Imaginemos un escenario en el cual hemos desarrollado un procedimiento almacenado en PL/SQL y deseamos evitar que alguien, incluido el DBA, pueda ver y/o modificar el código fuente. ¿Es eso posible?, definitivamente sí: Oracle provee el utilitario WRAP para lograrlo, pero implicaba invocarlo desde el Sistema Operativo; a partir de 10g es posible invocarlo desde dentro de la base de datos.
Veamos cómo hacer uso de ambas modalidades, empezando por un vistazo al código que nos interesa ocultar:
[oracle@caliope ~]$ cat salary.sql
CREATE OR REPLACE
FUNCTION salary (
empno emp.empno%TYPE )
RETURN NUMBER
IS
sal emp.sal%TYPE;
BEGIN
SELECT sal INTO salary.sal
FROM emp
WHERE empno = salary.empno;
RETURN ( salary.sal );
END;
La primera alternativa es usar wrap desde el Sistema Operativo.
1. Hay que invocarlo referenciando al archivo que contiene el código fuente.
[oracle@caliope ~]$ wrap iname=salary.sql
PL/SQL Wrapper: Release 10.2.0.4.0- Production on Sat Nov 01 14:21:47 2008
Copyright (c) 1993, 2004, Oracle. All rights reserved.
Processing salary.sql to salary.plb
[oracle@caliope ~]$ cat salary.plb
CREATE OR REPLACE
FUNCTION salary wrapped
a000000
367
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
8
cc d6
+/IgG5qcUWhn5W4aX1Z1gJbmalUwgy5KLcvWfHSi2sHVSCY2DKrK4KYn8hQGyrdN4JG7orD5
ELaEY9EXT7sxm8hT0NF8GQX2BSRNdGc/i2nS6FUq4oJr3+Z/vda3u1pli6dW3SXcl4vlGtfr
ShxK0Ikb/IzmSgsWLtX2Nyo5Ob28iiwzrfFQOmdO1j2jRP8s5Z3aTTuovLrHOuGA3Hyl
/
[oracle@caliope ~]$ sqlplus scott/tiger @salary.plb
SQL*Plus: Release 10.2.0.4.0 - Production on Sat Nov 1 14:23:59 2008
Copyright (c) 1982, 2007, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Function created.
SCOTT@orcl> select salary( 7654 ) from dual;
SALARY(7654)
------------
1312.5
SCOTT@orcl>
Como resultado tenemos ahora un procedimiento almacenado cuyo código fuente es ininteligible a simple vista.
¿Qué hacer si el código ya está en la base de datos? Pues podemos extraerlo a un archivo y seguir el procedimiento previo, pero también es posible hacer uso del mejorado package DBMS_DDL; entonces manos a la obra.
1. Usaremos la siguiente rutina para transformar el código fuente.
[oracle@caliope ~]$ cat wrapped.sql
DECLARE
v_source DBMS_SQL.VARCHAR2A;
BEGIN
v_source(1) := 'CREATE OR REPLACE ';
FOR s IN ( SELECT line, text
FROM user_source
WHERE name = 'SALARY'
ORDER BY line )
LOOP
v_source(s.line+1) := s.text;
END LOOP;
dbms_ddl.create_wrapped(
ddl => v_source,
lb => 1,
ub => v_source.count );
END;
SCOTT@orcl> @wrapped
PL/SQL procedure successfully completed.
SCOTT@orcl> select text from user_source
2 where name = 'SALARY' order by line;
TEXT
--------------------------------------------------------------------------------
FUNCTION salary wrapped
a000000
369
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
8
c3 d2
NL5qz7Eyn6/UUHrpUacIYXrnSkQwgy7wLcsVfHSiWHOUxMoNmSQvf6CVAlrwXr70aca5WXwI
/nAKWlYzkLkxeCuI8kessTO0QSAhNtwDkRNJ6sbC/1+niQxcN3d3A9MG5qanSMCbmJCZRkFk
zHqG9AcGWonxLvVFqyc+fCfcn4q5PwtD7ZLkhFU52f6bi7u9g2dWnLjOpqUrlos=
SCOTT@orcl> select salary( 7654 ) from dual;
SALARY(7654)
------------
1312.5
Nuevamente el objetivo se ha cumplido!
En conclusión, hemos visto dos formas de transformar nuestro código fuente en un texto indescifrable apoyados de WRAP.
El código mostrado no está libre de errores ni está optimizado, pero les puede servir como una base. Ah!, y no olviden darle una ojeada a la documentación, para que tengan un panorama completo de las posibilidades existentes.