Oracle® Database PL/SQL Language Reference 11g Release 2 (11.2) Part Number E10472-02 |
|
|
View PDF |
This appendix explains what wrapping is, why you wrap PL/SQL code, and how to do it.
Topics:
Wrapping is the process of hiding PL/SQL source code. Wrapping helps to protect your source code by making it more difficult for others to view it.
You can wrap PL/SQL source code with either the wrap
utility or DBMS_DDL
subprograms. The wrap
utility wraps a single source file, such as a SQL*Plus script. The DBMS_DDL
subprograms wrap a single dynamically generated PL/SQL unit, such as a single CREATE
PROCEDURE
statement.
Wrapped source files can be moved, backed up, and processed by SQL*Plus and the Import and Export utilities, but they are not visible through the static data dictionary views *_SOURCE
.
Note:
Wrapping a file that is already wrapped has no effect on the file.Wrap only the body of a package or ADT, not the specification.
This allows other developers to see the information they must use the package or type, but prevents them from seeing its implementation.
Wrap code only after you have finished editing it.
You cannot edit PL/SQL source code inside wrapped files. Either wrap your code after it is ready to ship to users or include the wrapping operation as part of your build environment.
To change wrapped PL/SQL code, edit the original source file and then wrap it again.
Before distributing a wrapped file, view it in a text editor to be sure that all important parts are wrapped.
Wrapping is not a secure method for hiding passwords or table names.
Wrapping a PL/SQL unit helps prevent most users from examining the source code, but might not stop all of them.
Wrapping does not hide the source code for triggers.
To hide the workings of a trigger, write a one-line trigger that invokes a wrapped subprogram.
Wrapping does not detect syntax or semantic errors.
Wrapping detects only tokenization errors (for example, runaway strings), not syntax or semantic errors (for example, nonexistent tables or views). Syntax or semantic errors are detected during PL/SQL compilation or when running the output file in SQL*Plus.
Wrapped PL/SQL units are not downward-compatible.
Wrapped PL/SQL units are upward-compatible between Oracle Database releases, but are not downward-compatible. For example, you can load files processed by the V8.1.5 wrap
utility into a V8.1.6 Oracle Database, but you cannot load files processed by the V8.1.6 wrap
utility into a V8.1.5 Oracle Database.
The wrap
utility processes an input SQL file and wraps only the PL/SQL units in the file, such as a package specification, package body, function, procedure, type specification, or type body. It does not wrap PL/SQL content in anonymous blocks or triggers or non-PL/SQL code.
The wrap
utility does not need to connect to Oracle Database (in fact, it cannot connect to Oracle Database).
To run the wrap utility, enter the wrap
command at your operating system prompt using this syntax (with no spaces around the equal signs):
wrap iname=input_file [ oname=output_file ]
input_file
is the name of a file containing SQL statements, which you typically run using SQL*Plus. If you omit the file extension, .sql
is assumed. For example, these commands are equivalent:
wrap iname=/mydir/myfile wrap iname=/mydir/myfile.sql
You can specify a different file extension. For example:
wrap iname=/mydir/myfile.src
output_file
is the name of the wrapped file to be created. If you omit the oname
option, output_file
has the same name as input_file
, but with the extension .plb
. For example, these commands are equivalent:
wrap iname=/mydir/myfile wrap iname=/mydir/myfile.sql oname=/mydir/myfile.plb
You can specify a different output file name and extension. For example:
wrap iname=/mydir/myfile oname=/yourdir/yourfile.out
Note:
Ifinput_file
is already wrapped, output_file
is identical to input_file
.Topics:
The input file can contain any combination of SQL statements. Most statements are passed through unchanged. CREATE
statements that define subprograms, packages, or ADTs are wrapped; their bodies are replaced by a scrambled form that the PL/SQL compiler understands.
These CREATE
statements are wrapped:
CREATE [OR REPLACE] FUNCTION function_name CREATE [OR REPLACE] PROCEDURE procedure_name CREATE [OR REPLACE] PACKAGE package_name CREATE [OR REPLACE] PACKAGE BODY package_name CREATE [OR REPLACE] TYPE type_name AS OBJECT CREATE [OR REPLACE] TYPE type_name UNDER type_name CREATE [OR REPLACE] TYPE BODY type_name
The CREATE
[OR
REPLACE]
TRIGGER
statement, and [DECLARE]
BEGIN
END
anonymous blocks, are not wrapped. All other SQL statements are passed unchanged to the output file.
All comment lines in the unit being wrapped are deleted, except for those in a CREATE
OR
REPLACE
header and C-style comments (delimited by /* */
).
The output file is a text file, which you can run as a script in SQL*Plus to set up your PL/SQL subprograms and packages. Run a wrapped file as follows:
SQL> @wrapped_file_name.plb;
For example, assume that the wraptest.sql
file contains:
CREATE PROCEDURE wraptest IS TYPE emp_tab IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER; all_emps emp_tab; BEGIN SELECT * BULK COLLECT INTO all_emps FROM employees; FOR i IN 1..10 LOOP DBMS_OUTPUT.PUT_LINE('Emp Id: ' || all_emps(i).employee_id); END LOOP; END; /
To wrap the file, run this command from the operating system prompt:
wrap iname=wraptest.sql
The output of the wrap
utility is similar to:
PL/SQL Wrapper: Release 10.2.0.0.0 on Tue Apr 26 16:47:39 2005 Copyright (c) 1993, 2005, Oracle. All rights reserved. Processing wraptest.sql to wraptest.plb
If you view the contents of the wraptest.plb
text file, the first line is CREATE
PROCEDURE
wraptest
wrapped
and the rest of the file contents is hidden.
You can run wraptest.plb
in SQL*Plus to run the SQL statements in the file:
SQL> @wraptest.plb
After the wraptest.plb
is run, you can run the procedure that was created:
SQL> CALL wraptest();
The DBMS_DDL
package contains procedures for wrapping a single PL/SQL unit, such as a package specification, package body, function, procedure, type specification, or type body. These overloaded subprograms provide a mechanism for wrapping dynamically generated PL/SQL units that are created in a database.
The DBMS_DDL
package contains the WRAP
functions and the CREATE_WRAPPED
procedures. The CREATE_WRAPPED
both wraps the text and creates the PL/SQL unit. When invoking the wrap procedures, use the fully qualified package name, SYS.DBMS_DDL
, to avoid any naming conflicts and the possibility that someone might create a local package called DBMS_DDL
or define the DBMS_DDL
public synonym. The input CREATE
OR
REPLACE
statement runs with the privileges of the user who invokes DBMS_DDL
.WRAP
or DBMS_DDL
.CREATE_WRAPPED
.
The DBMS_DDL
package also provides the MALFORMED_WRAP_INPUT
exception (ORA-24230) which is raised if the input to the wrap procedures is not a valid PL/SQL unit.
Note:
Wrapping a PL/SQL unit that is already wrapped has no effect on the unit.Topics:
See Also:
Oracle Database PL/SQL Packages and Types Reference for information about theDBMS_DDL
packageIn Example A-1 CREATE_WRAPPED
is used to dynamically create and wrap a package specification and a package body in a database.
Example A-1 Wrapping Package with DBMS_DDL.CREATE_WRAPPED Procedure
DECLARE package_text VARCHAR2(32767); -- text for creating package spec & body FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN 'CREATE PACKAGE ' || pkgname || ' AS PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER); PROCEDURE fire_employee (emp_id NUMBER); END ' || pkgname || ';'; END generate_spec; FUNCTION generate_body (pkgname VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN 'CREATE PACKAGE BODY ' || pkgname || ' AS PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS BEGIN UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id; END raise_salary; PROCEDURE fire_employee (emp_id NUMBER) IS BEGIN DELETE FROM employees WHERE employee_id = emp_id; END fire_employee; END ' || pkgname || ';'; END generate_body; BEGIN -- Generate package spec package_text := generate_spec('emp_actions'); -- Create wrapped package spec DBMS_DDL.CREATE_WRAPPED(package_text); -- Generate package body package_text := generate_body('emp_actions'); -- Create wrapped package body DBMS_DDL.CREATE_WRAPPED(package_text); END; / -- Invoke procedure from wrapped package CALL emp_actions.raise_salary(120, 100);
When you check the static data dictionary views *_SOURCE
, the source is wrapped, or hidden, so that others cannot view the code details. For example:
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
Result is similar to:
TEXT -------------------------------------------------------------------- PACKAGE emp_actions WRAPPED a000000 1f abcd ... 2 rows selected.
If you invoke DBMS_SQL
.PARSE
(when using an overload where the statement formal has data type VARCHAR2A
or VARCHAR2S
for text which exceeds 32767 bytes) on the output of DBMS_DDL
.WRAP
, then you must set the LFFLG
parameter to FALSE
. Otherwise DBMS_SQL
.PARSE
adds lines to the wrapped unit which corrupts the unit.