A PL/SQLのソース・テキストのラップ
次の任意のストアドPL/SQLユニットのPL/SQLソース・テキストをラップすることによって、他のユーザーが静的データ・ディクショナリ・ビュー*_SOURCE
を使用して、他のユーザーがそのテキストを表示することを防止できます。
-
パッケージ仕様部
-
パッケージ本体
-
型仕様部
-
型本体
-
ファンクション
-
プロシージャ
注意:
テキストのラップのセキュリティは高くありません。高いセキュリティを確保するには、Oracle Database Vaultを使用してください(『Oracle Database Vault管理者ガイド』を参照)。
ラップされたPL/SQLソース・テキストが含まれるファイルは、ラップされたファイルと呼ばれます。ラップされたファイルは、SQL*Plusによって、またはインポート・ユーティリティおよびエクスポート・ユーティリティによって移動、バックアップまたは処理できます。
ラップされたファイルを生成するには、PL/SQLラッパー・ユーティリティまたはDBMS_DDL
サブプログラムを使用します。PL/SQLラッパー・ユーティリティは、指定のSQLファイルによって作成されたすべてのラップ可能PL/SQLユニットのソース・テキストをラップします。DBMS_DDL
サブプログラムは、動的に生成された単一のラップ可能PL/SQLユニットのソース・テキストをラップします。
PL/SQLラッパー・ユーティリティおよびDBMS_DDL
サブプログラムでは、トークン化エラー(文字列の欠落など)は検出されますが、構文エラーやセマンティック・エラー(表やビューが存在しないなど)は検出されません。
12.2 PL/SQLコンパイラは、デフォルトで、9.2 PL/SQLコンパイラでコンパイルされているラップされたパッケージを使用できます。12.2 PL/SQLコンパイラが9.2 PL/SQLコンパイラでコンパイルされているラップされたパッケージを使用できないようにするには、PL/SQLコンパイル・パラメータPERMIT_92_WRAP_FORMAT
をFALSE
に設定します。PERMIT_92_WRAP_FORMAT
の詳細は、『Oracle Databaseリファレンス』を参照してください。PL/SQLのコンパイル・パラメータの詳細は、「PL/SQLユニットおよびコンパイル・パラメータ」を参照してください。
ここでのトピック
A.1 PL/SQLソース・テキストのラップの制限
-
ラップされたファイルは、Oracle Databaseリリース間での下位互換性がありません。
たとえば、バージョンn.1 PL/SQL Wrapperユーティリティにより生成されたファイルをバージョン(n-1).2 Oracle Databaseにロードすることはできません。また、バージョンn.2 PL/SQL Wrapperユーティリティにより生成されたファイルをバージョンn.1 Oracle Databaseにロードすることもできません。ラップされたファイルは、パッチセット間で上位および下位の両方の互換性があります。
-
PL/SQLソース・テキストのラップは、パスワードや表名を隠すための安全な方法とはいえません。
高いセキュリティを確保するには、Oracle Database Vaultを使用してください(『Oracle Database Vault管理者ガイド』を参照)。
-
トリガーのPL/SQLソース・テキストは、ラップできません。
トリガーの実装の詳細を隠すには、実装の詳細をストアド・サブプログラムに配置し、そのサブプログラムをラップして、そのサブプログラムを起動する1行トリガーを記述します。
A.2 PL/SQLソース・テキストのラップのガイドライン
-
パッケージまたは型の仕様部ではなく、本体のみをラップします。
仕様部をラップしないことで、他の開発者は、パッケージまたは型を使用するために必要な情報を見ることができます(例A-5を参照)。本体はラップされているため、パッケージまたは型の実装は、他の開発者から隠されます。
-
ファイルの編集が完了した後にのみ、ファイルをラップします。
ラップされたファイルは、編集できません。ラップされたファイルの変更が必要な場合、ラップされていない元のファイルを編集し、再度ラップする必要があります。
-
ラップされたファイルを配布する前に、テキスト・エディタで表示して重要な部分がすべてラップされていることを確認します。
A.3 PL/SQLラッパー・ユーティリティによるPL/SQLソース・テキストのラップ
PL/SQLラッパー・ユーティリティは、単一のSQLファイル(SQL*Plusスクリプトなど)を取得して、各ラップ可能PL/SQLユニットのPL/SQLソース・テキストがラップされた同等のテキスト・ファイルを生成します。
注意:
PL/SQLラッパー・ユーティリティは、バージョン10以降を使用することをお薦めします。
ラップ可能PL/SQLユニットのリストは、「PL/SQLのソース・テキストのラップ」の概要を参照してください。
PL/SQLラッパー・ユーティリティは、Oracle Databaseに接続できません。PL/SQLラッパー・ユーティリティを実行するには、オペレーティング・システム・プロンプトで(等号の前後に空白を入れずに)次のコマンドを入力します。
wrap iname=input_file [ oname=output_file ] [ keep_comments=yes ]
input_file
は、複数のSQL文の任意の組合せを含む既存のファイルの名前です。output_file
は、PL/SQLラッパー・ユーティリティによって作成されるファイル(ラップされたファイル)の名前です。
注意:
output_file
は、SQL*PlusではなくPL/SQLコンパイラによって解析されるため、input_file
にSQL*PlusのDEFINE
表記法で指定された置換変数を含めることはできません。
PL/SQLラッパー・ユーティリティは、keep_comments=yes
が指定されていないかぎり、ラップされたファイルからすべてのコメントを削除します。keep_comments=yes
が指定されている場合、ソース外のコメントのみが維持されます。
注意:
input_file
がラップされたファイルの場合、input_file
とoutput_file
の内容は同じになります。
input_file
のデフォルトのファイル拡張子は、sql
です。output_file
のデフォルト名は、input_file
.plb
です。したがって、次のコマンドは同じ意味を持ちます。
wrap iname=/mydir/myfile wrap iname=/mydir/myfile.sql oname=/mydir/myfile.plb
次の例では、input_file
に異なるファイル拡張子を指定し、output_file
に異なる名前を指定します。
wrap iname=/mydir/myfile.src oname=/yourdir/yourfile.out keep_comments=yes
output_file
は、SQL*Plusのスクリプトとして実行できます。次に例を示します。
SQL> @myfile.plb;
例A-1 2つのラップ可能PL/SQLユニットを含むSQLファイル
この例では、2つのラップ可能PL/SQLユニット(プロシージャwraptest
およびファンクションfibonacci
)を含むSQLファイルwraptest2.sql
のテキストを示します。このファイルには、コメントのほか、SQLのSELECT
文も含まれます。
-- The following statement will not change. SELECT COUNT(*) FROM EMPLOYEES / /* The PL/SQL source text of the following two CREATE statements will be wrapped. */ CREATE PROCEDURE wraptest AUTHID CURRENT_USER /* C style comment in procedure declaration */ 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 /* C style in pl/sql source */ DBMS_OUTPUT.PUT_LINE('Emp Id: ' || all_emps(i).employee_id); END LOOP; END; / CREATE OR REPLACE FUNCTION fibonacci ( n PLS_INTEGER ) RETURN PLS_INTEGER AUTHID CURRENT_USER -- PL/SQL style comment inside fibonacci function spec IS fib_1 PLS_INTEGER := 0; fib_2 PLS_INTEGER := 1; BEGIN IF n = 1 THEN -- terminating condition RETURN fib_1; ELSIF n = 2 THEN RETURN fib_2; -- terminating condition ELSE RETURN fibonacci(n-2) + fibonacci(n-1); -- recursive invocations END IF; END; /
例A-2 PL/SQLラッパー・ユーティリティによるファイルのラップ
この例では、PL/SQLラッパー・ユーティリティを使用してwraptest2.sql
をラップし、そのラップされたファイルwraptest2.plb
を表示します。ラップされたファイルでは、ユーティリティによってコード内のコメントが削除され、プロシージャwraptest
およびファンクションfibonacci
のPL/SQLソース・テキストがラップされた(判読不可能にされた)ことがわかりますが、ラップされたソース外のコメントは維持されています。
オペレーティング・システム・プロンプトが>
であると仮定。ファイルwraptest.sql
のラップ:
> wrap keep_comments=yes iname=wraptest2.sql
結果:
Processing wraptest2.sql to wraptest2.plb
wraptest.plb
の内容:
-- The following statement will not change. SELECT COUNT(*) FROM EMPLOYEES / /* The PL/SQL source text of the following two CREATE statements will be wrapped. */ CREATE OR REPLACE PROCEDURE wraptest wrapped a000000 1 abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd 7 129 138 qf4HggDBeNMPlWAsPn6pGf+2LGwwg+nwJK5qZ3SVWE4+GayDZaL1bF7RwYm2/zr1qjZY3FrN 48M1bKc/MG5aY9YB+DrtT4SJN370Rpq7ck5D0sc1D5sKAwTyX13HYvRmjwkdXa0vEZ4q/mCU EQusX23UZbZjxha7CtlCDCx8guGw/M/oHZXc8wDHXL8V8OsqQMv/Hj7z68gINl7OstalRScr uSZ/l/W1YaaA9Lj8Fbx5/nJw96ZNy1SCY8VsB/G6O5f/65+EDxdThpnfU4e1vrrE9iB3/IpI +7fE1Tv29fwc+aZq3S7O / CREATE OR REPLACE FUNCTION fibonacci wrapped a000000 1 abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd 8 150 ff BFDvTL9OR04SJbx+qOy5H/h8IcwwgxDcAJnWZ3TNz51mjAmegdQcpNJfq8hUuQtv1Y5xg7Wd KqMH/HBANhnZ+E1mBWekavYjPxlqV9zIFqZAgB4SBqkqe42sai9Vb0cLEU02/ZCEyxDSfWf3 H1Lp6U9ztRXNy+oDZSNykWCUVLaZro0UmeFrNUBqzE6j9mI3AyRhPw1QbZX5oRMLgLOG3OtS SGJsz7M+bnhnp+xP4ww+SIlxx5LhDtnyPw== /
例A-3 ラップされたファイルの実行およびラップされたPL/SQLユニットの表示
この例では、ラップされたファイルwraptest.plb
をSQL*Plusで実行し、プロシージャwraptest
およびファンクションfibonacci
を作成します。各サブプログラムのテキスト(ラップされているため判読不可能)を選択し、その後、サブプログラムを起動します。
SQL> -- Run wrapped file: SQL> SQL> @wraptest2.plb SQL> -- The following statement will not change. SQL> SQL> SELECT COUNT(*) FROM EMPLOYEES 2 / COUNT(*) ---------- 107 1 row selected. SQL> /* The PL/SQL source text of the following two CREATE statements will be wrapped. */ SQL> CREATE PROCEDURE wraptest wrapped 2 a000000 3 1 4 abcd 5 abcd 6 abcd 7 abcd 8 abcd 9 abcd 10 abcd 11 abcd 12 abcd 13 abcd 14 abcd 15 abcd 16 abcd 17 abcd 18 abcd 19 7 20 129 138 21 qf4HggDBeNMPlWAsPn6pGf+2LGwwg+nwJK5qZ3SVWE4+GayDZaL1bF7RwYm2/zr1qjZY3FrN 22 48M1bKc/MG5aY9YB+DrtT4SJN370Rpq7ck5D0sc1D5sKAwTyX13HYvRmjwkdXa0vEZ4q/mCU 23 EQusX23UZbZjxha7CtlCDCx8guGw/M/oHZXc8wDHXL8V8OsqQMv/Hj7z68gINl7OstalRScr 24 uSZ/l/W1YaaA9Lj8Fbx5/nJw96ZNy1SCY8VsB/G6O5f/65+EDxdThpnfU4e1vrrE9iB3/IpI 25 +7fE1Tv29fwc+aZq3S7O 26 27 / Procedure created. SQL> CREATE OR REPLACE FUNCTION fibonacci wrapped 2 a000000 3 1 4 abcd 5 abcd 6 abcd 7 abcd 8 abcd 9 abcd 10 abcd 11 abcd 12 abcd 13 abcd 14 abcd 15 abcd 16 abcd 17 abcd 18 abcd 19 8 20 150 ff 21 BFDvTL9OR04SJbx+qOy5H/h8IcwwgxDcAJnWZ3TNz51mjAmegdQcpNJfq8hUuQtv1Y5xg7Wd 22 KqMH/HBANhnZ+E1mBWekavYjPxlqV9zIFqZAgB4SBqkqe42sai9Vb0cLEU02/ZCEyxDSfWf3 23 H1Lp6U9ztRXNy+oDZSNykWCUVLaZro0UmeFrNUBqzE6j9mI3AyRhPw1QbZX5oRMLgLOG3OtS 24 SGJsz7M+bnhnp+xP4ww+SIlxx5LhDtnyPw== 25 26 / Function created. SQL> SQL> -- Try to display procedure source text: SQL> SQL> SELECT text FROM USER_SOURCE WHERE name='WRAPTEST'; TEXT -------------------------------------------------------------------------------- PROCEDURE wraptest wrapped a000000 1 abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd 7 129 138 qf4HggDBeNMPlWAsPn6pGf+2LGwwg+nwJK5qZ3SVWE4+GayDZaL1bF7RwYm2/zr1qjZY3FrN 48M1bKc/MG5aY9YB+DrtT4SJN370Rpq7ck5D0sc1D5sKAwTyX13HYvRmjwkdXa0vEZ4q/mCU EQusX23UZbZjxha7CtlCDCx8guGw/M/oHZXc8wDHXL8V8OsqQMv/Hj7z68gINl7OstalRScr uSZ/l/W1YaaA9Lj8Fbx5/nJw96ZNy1SCY8VsB/G6O5f/65+EDxdThpnfU4e1vrrE9iB3/IpI +7fE1Tv29fwc+aZq3S7O 1 row selected. SQL> SQL> -- Try to display function source text: SQL> SQL> SELECT text FROM USER_SOURCE WHERE name='FIBONACCI'; TEXT -------------------------------------------------------------------------------- FUNCTION fibonacci wrapped a000000 1 abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd 8 150 ff BFDvTL9OR04SJbx+qOy5H/h8IcwwgxDcAJnWZ3TNz51mjAmegdQcpNJfq8hUuQtv1Y5xg7Wd KqMH/HBANhnZ+E1mBWekavYjPxlqV9zIFqZAgB4SBqkqe42sai9Vb0cLEU02/ZCEyxDSfWf3 H1Lp6U9ztRXNy+oDZSNykWCUVLaZro0UmeFrNUBqzE6j9mI3AyRhPw1QbZX5oRMLgLOG3OtS SGJsz7M+bnhnp+xP4ww+SIlxx5LhDtnyPw== 1 row selected. SQL> SQL> BEGIN 2 wraptest; -- invoke procedure 3 DBMS_OUTPUT.PUT_LINE('fibonacci(5) = ' || fibonacci(5)); 4 END; 5 / Emp Id: 100 Emp Id: 101 Emp Id: 102 Emp Id: 103 Emp Id: 104 Emp Id: 105 Emp Id: 106 Emp Id: 107 Emp Id: 108 Emp Id: 109 fibonacci(5) = 3 PL/SQL procedure successfully completed. SQL>
A.4 DBMS_DDLサブプログラムによるPL/SQLソース・テキストのラップ
DBMS_DDL
パッケージには、WRAP
ファンクションおよびCREATE_WRAPPED
プロシージャが含まれていて、各ファンクションおよびプロシージャは、動的に生成された単一のラップ可能PL/SQLユニットのPL/SQLソース・テキストをラップします。また、DBMS_DDL
パッケージには、WRAPまたはCREATE_WRAPPED
への入力が有効なラップ可能PL/SQLユニットでない場合に発生する、例外MALFORMED_WRAP_INPUT
(ORA-24230)も含まれます。(ラップ可能PL/SQLユニットのリストは、「PL/SQLのソース・テキストのラップ」の概要を参照してください。)
各WRAP
ファンクションは、ラップ可能PL/SQLユニットを作成する単一のCREATE
文を入力として取得し、PL/SQLソース・テキストがラップされた同等のCREATE
文を戻します。WRAP
ファンクションの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
注意:
DBMS_DDL
.WRAP
によって戻される文を、データ型がVARCHAR2A
の仮パラメータstatement
を含むDBMS_SQL
.PARSE
プロシージャに渡す場合、DBMS_SQL
.PARSE
のlfflg
パラメータをFALSE
に設定する必要があります。設定しないと、DBMS_SQL
.PARSE
によって、ラップされたPL/SQLユニットに行が追加され、ユニットが破損します。(DBMS_SQL
.PARSE
の構文は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。)
各CREATE_WRAPPED
プロシージャは、その対応するWRAP
ファンクションと同じ処理を行って、戻されたCREATE
文を実行し、指定されたPL/SQLユニットを作成します。CREATE_WRAPPED
プロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
ヒント:
DBMS_DDL
サブプログラムの起動時には、パッケージの完全修飾名SYS.DBMS_DDL
を使用し、他のユーザーがDBMS_DDL
という名前のローカル・パッケージを作成していたり、パブリック・シノニムDBMS_DDL
を定義している場合に発生する名前の競合を回避します。
注意:
WRAP
ファンクションまたはCREATE_WRAPPED
プロシージャに入力されるCREATE
文は、そのサブプログラムを起動したユーザーの権限で実行されます。
例A-4では、EXECUTE
IMMEDIATE
文を使用してパッケージ仕様部を、およびCREATE_WRAPPED
プロシージャを使用してラップされたパッケージ本体を動的に作成します。
例A-5では、例A-4で作成したパッケージemp_actions
のテキストを選択し、プロシージャemp_actions.raise_salary
を起動します。パッケージ仕様部がラップされている場合、プロシージャを起動するために必要な情報は、パッケージ本体のPL/SQLソース・テキストのように判読不可能になります。
例A-4 CREATE_WRAPPEDプロシージャによるラップされたパッケージ本体の作成
DECLARE
package_text VARCHAR2(32767); -- text for creating package spec and body
FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'CREATE PACKAGE ' || pkgname || ' AUTHID CURRENT_USER 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
package_text := generate_spec('emp_actions'); -- Generate package spec
EXECUTE IMMEDIATE package_text; -- Create package spec
package_text := generate_body('emp_actions'); -- Generate package body
SYS.DBMS_DDL.CREATE_WRAPPED(package_text); -- Create wrapped package body
END;
/
例A-5 ラップされた本体を含むパッケージの表示およびパッケージ・プロシージャの起動
パッケージのテキストの選択:
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
結果:
TEXT ------------------------------------------------------------------------ PACKAGE emp_actions AUTHID CURRENT_USER AS PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER); PROCEDURE fire_employee (emp_id NUMBER); END emp_actions; PACKAGE BODY emp_actions wrapped a000000 1f abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd b 180 113 1fOVodewm7j9dBOmBsiEQz0BKCgwg/BKoZ4VZy/pTBIYo8Uj1sjpbEz08Ck3HMjYq/Mf0XZn u9D0Kd+i89g9ZO61I6vZYjw2AuBidnLESyR63LHZpFD/7lyDTfF1eDY5vmNwLTXrFaxGy243 0lHKAzmOlwwfBWylkZZNi2UnpmSIe6z/BU2nhbwfpqd224p69FwYVXmFX2H5IMsdZ2/vWsK9 cDMCD1KEqOnPpbU2yXdpW3GIbGD8JFIbKAfpJLkoLfVxoRPXQfj0h1k=
raised_salary
の起動およびその影響の表示:
DECLARE
s employees.salary%TYPE;
BEGIN
SELECT salary INTO s FROM employees WHERE employee_id=130;
DBMS_OUTPUT.PUT_LINE('Old salary: ' || s);
emp_actions.raise_salary(130, 100);
SELECT salary INTO s FROM employees WHERE employee_id=130;
DBMS_OUTPUT.PUT_LINE('New salary: ' || s);
END;
/
結果:
Old salary: 3557.4 New salary: 3657.4 PL/SQL procedure successfully completed.