この付録では、ラップの概要、PL/SQLコードをラップする理由およびその方法について説明します。
ここでのトピック:
ラップとは、PL/SQLソース・コードを隠す処理のことです。ラップは、競合他社やソース・コードを間違って使用する可能性のあるユーザーからソース・コードを保護する際に役立ちます。
PL/SQLソース・コードをラップするには、wrap
ユーティリティまたはDBMS_DDL
サブプログラムのいずれかを使用します。wrap
ユーティリティによって、SQL*Plusスクリプトなどの単一のソース・ファイルがラップされます。 DBMS_DDL
サブプログラムでは、単一のCREATE
PROCEDURE
文などの動的に生成された単一のPL/SQLユニットがラップされます。
ラップされたソース・ファイルは、SQL*Plus、インポート・ユーティリティおよびエクスポート・ユーティリティによって移動、バックアップおよび処理することはできますが、静的データ・ディクショナリ・ビュー*_SOURCE
から参照されません。
注意: すでにラップされたファイルをラップしてもそのファイルに影響はありません。 |
パッケージまたはオブジェクト型の仕様部ではなく、本体のみをラップします。
こうすると、他の開発者は、パッケージまたは型を使用するのに必要な情報を見ることができますが、その実装は見えません。
コードの編集が完了した後、コードをラップします。
ラップされたファイル内のPL/SQLソース・コードは編集できません。出荷可能な状態になったコードをラップするか、またはビルド環境の一部としてラッピング操作を行います。
ラップされたPL/SQLコードを変更するには、元のソース・ファイルを編集し、再度ラップします。
ラップされたファイルを配布する前に、テキスト・エディタで表示して重要な部分がすべてラップされていることを確認します。
ラップはパスワードや表名を隠すためには安全な方法とはいえません。
PL/SQLユニットをラップすると、ほとんどのユーザーはソース・コードを確認できなくなりますが、すべてのユーザーに対して隠されるわけではありません。
ラップでは、トリガー用のソース・コードは隠されません。
トリガーの動作を隠すには、ラップされたサブプログラムを起動する1行トリガーを記述します。
ラップでは、構文エラーやセマンティック・エラーは検出されません。
ラップでは、構文エラーやセマンティック・エラー(表やビューが存在しないなど)ではなく、トークン化エラー(文字列の欠落など)のみが検出されます。構文エラーやセマンティック・エラーは、PL/SQLのコンパイル時またはSQL*Plusでの出力ファイルの実行時に検出されます。
ラップされたPL/SQLユニットは、下位互換性がありません。
ラップされたPL/SQLユニットは、Oracle Databaseリリース間での上位互換性はありますが、下位互換性はありません。たとえば、リリース8.1.5のwrap
ユーティリティで処理されたファイルは、リリース8.1.6のOracle Databaseにロードできますが、リリース8.1.6のwrap
ユーティリティで処理されたファイルは、リリース8.1.5のOracle Databaseにロードできません。
wrap
ユーティリティでは、入力SQLファイルが処理されて、パッケージ仕様部、パッケージ本体、ファンクション、プロシージャ、型仕様部、型本体など、ファイル内のPL/SQLユニットのみがラップされます。無名ブロックのPL/SQLコンテンツ、トリガーまたはPL/SQL以外のコードはラップされません。
wrapユーティリティを実行するには、次の構文を(等号の前後に空白を入れずに)使用して、オペレーティング・システム・プロンプトでwrap
コマンドを入力します。
wrap iname=input_file [ oname=output_file ]
input_file
は、通常、SQL*Plusを使用して実行する、SQL文を含むファイルの名前です。ファイル拡張子を省略すると、拡張子は.sql
であるとみなされます。たとえば、次のコマンドは同じ意味を持ちます。
wrap iname=/mydir/myfile wrap iname=/mydir/myfile.sql
次のように、異なるファイル拡張子を指定することもできます。
wrap iname=/mydir/myfile.src
output_file
は、作成するファイル(ラップされたファイル)の名前です。これがデフォルトで入力ファイルの名前となり、拡張子はデフォルトで.plb
となります。たとえば、次のコマンドは同じ意味を持ちます。
wrap iname=/mydir/myfile wrap iname=/mydir/myfile.sql oname=/mydir/myfile.plb
次に示すように、oname
オプションを使用して、異なるファイル名と拡張子を指定できます。
wrap iname=/mydir/myfile oname=/yourdir/yourfile.out
注意: input_file がすでにラップされている場合、output_file はinput_file と同じです。 |
ここでのトピック:
入力ファイルでは、SQL文を任意に組み合せることができます。ほとんどの文はそのままの形で渡されます。サブプログラム、パッケージまたはオブジェクト型を定義するCREATE
文は、ラップされます。これらの文の本体は、隠された(ただしPL/SQLコンパイラが理解可能な)形式に置き換えられます。
次のCREATE
文はラップされています。
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
CREATE
[OR
REPLACE]
TRIGGER
文および[DECLARE]
BEGIN-END
無名ブロックはラップされません。その他のSQL文はすべて、そのままの形で出力ファイルに渡されます。
CREATE
OR
REPLACE
ヘッダー内のコメント行およびC形式のコメント(/* */
で区切られる)を除いて、ラップされるユニットのすべてのコメント行が削除されます。
出力ファイルはテキスト・ファイルです。このファイルをSQL*Plusでスクリプトとして実行し、PL/SQLサブプログラムおよびパッケージを設定できます。ラップされたファイルは、次のように実行します。
SQL> @wrapped_file_name.plb;
たとえば、wrap_test.sql
ファイルの内容が次のとおりであるとします。
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; /
ファイルをラップするには、オペレーティング・システム・プロンプトで次のように実行します。
wrap iname=wrap_test.sql
wrap
ユーティリティの出力は、次のようになります。
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 wrap_test.sql to wrap_test.plb
wrap_test.plb
テキスト・ファイルの内容を確認すると、1行目にCREATE
PROCEDURE
wraptest
wrapped
が表示され、ファイルの残りの内容は表示されません。
SQL*Plusでwrap_test.plb
を実行し、ファイルのSQL文を実行するには、次のように入力します。
SQL> @wrap_test.plb
wrap_test.plb
を実行した後、作成されたプロシージャを実行できます。
SQL> CALL wraptest();
ラップされるPL/SQLコードにSQL*PlusのDEFINE
表記法を使用して置換変数を含めることはできません。
ラップされたソース・コードは、SQL*Plusではなく、PL/SQLコンパイラによって解析されます。
wrapユーティリティによって、ラップされたファイルからほとんどのコメントが削除されます。
「PL/SQLのwrapユーティリティの入力ファイルと出力ファイル」を参照してください。
DBMS_DDL
パッケージには、パッケージ仕様部、パッケージ本体、ファンクション、プロシージャ、型仕様部、型本体などの単一のPL/SQLユニットをラップするプロシージャが含まれています。 オーバーロードされるこれらのサブプログラムには、データベースに作成される動的生成PL/SQLユニットをラップするメカニズムが備えられています。
DBMS_DDL
パッケージには、WRAP
ファンクションおよびCREATE_WRAPPED
プロシージャが含まれます。CREATE_WRAPPED
では、テキストのラップおよびPL/SQLユニットの作成の両方が行われます。 名前の競合および他のユーザーがDBMS_DDL
というローカル・パッケージを作成していたり、DBMS_DDL
パブリック・シノニムを定義している場合の危険性を回避するために、ラップ・プロシージャを起動する場合は、パッケージの完全修飾名SYS.DBMS_DDL
を使用してください。入力CREATE
OR
REPLACE
文は、DBMS_DDL
.WRAP
またはDBMS_DDL
.CREATE_WRAPPED
を起動するユーザーの権限で実行されます。
また、DBMS_DDL
パッケージには、ラップ・プロシージャへの入力が有効なPL/SQLユニットでない場合に発生するMALFORMED_WRAP_INPUT
例外(ORA-24230)も含まれます。
注意: すでにラップされているPL/SQLユニットをラップしても、そのユニットに影響はありません。 |
ここでのトピック:
参照: DBMS_DDL パッケージの詳細は『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
例A-1では、CREATE_WRAPPED
を使用して、データベースにパッケージ仕様部およびパッケージ本体を動的に作成し、ラップしています。
例A-1 DBMS_DDL.CREATE_WRAPPEDプロシージャを使用したパッケージのラップ
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);
静的データ・ディクショナリ・ビュー*_SOURCE
を表示しても、ソースがラップされている(表示されない)ため、他のユーザーはコードの詳細を参照できません。次に例を示します。
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
出力結果は、次のようになります。
TEXT -------------------------------------------------------------------- PACKAGE emp_actions WRAPPED a000000 1f abcd ...
DBMS_DDL
.WRAP
の出力でDBMS_SQL
.PARSE
を起動する場合(32767バイトを超えるテキストに対する文の仮パラメータのデータ型がVARCHAR2A
またはVARCHAR2S
であるオーバーロードを使用するとき)は、LFFLG
パラメータにFALSE
を設定する必要があります。設定しないと、DBMS_SQL
.PARSE
によって、ラップされたユニットに改行が追加されるため、ユニットが破損します。