この付録では、ラップの概要、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によって、ラップされたユニットに改行が追加されるため、ユニットが破損します。