条件付きコンパイルフラグの使い方
条件付きコンパイルのIFテスト、およびコード内のその他の場所で、PL/SQLコード内で設定する式ではなく、コンパイル時にコンパイラに直接渡される静的な式を使うこともできます。次の3つのオプションがあります。
- NLS_Length_SemanticsなどのPL/SQLコンパイラ初期化パラメータ
- ユーザー定義の条件付きコンパイルフラグ(ccflag)
- Oracleによって事前定義された2つのccflag(PLSQL_UnitとPLSQL_Line)
これらのPL/SQL以外の式を参照するには、「問合せディレクティブ」($$)を使います。つまり、ccflagまたはPL/SQLコンパイラ初期化パラメータの前に$$を付けます。これにより、条件付きコンパイルエンジンがその式の値をコンパイル時に読み込むようになります。次に例を示します。
$IF $$PLSQL_LINE=15 $THEN
debug('That was line 15');
$END ;
ユーザー定義のccflagを設定するには、OracleパラメータのPLSQL_CCFLAGSに名前/値ペアの文字列をname:value[,name:value][,name:value]...の形式で割り当てます。例えば、"set_debug_on"、"use_10g_features"、および"compile_w_extras"という名前のccflagの値を設定するには、PLSQL_CCFLAGSを次のように設定します。
PLSQL_CCFLAGS ='set_debug_on:true,use_10g_features:false,compile_w_extras:false' ;
PLSQL_CCFLAGSは、ALTER SESSIONまたはALTER SYSTEMを使って、セッションレベルまたはシステムレベルで設定することができます。あるいは、個々のパッケージまたはプロシージャコンパイルで、コンパイル時にPLSQL_CCFLAGSを設定することもできます。
次の例では、ユーザー定義のccflagをコンパイル時に設定しています。
SQL> alter package PAYROLL_CALC compile 2> plsql_ccflags = 3> 'no_commit_trans:true,print_debug_msg:true' 4> reuse settings ;
次の例では、PLSQL_CCFLAGSの値をALTER SESSIONレベルで設定しています。
SQL> alter session set PLSQL_CCFLAGS = 2> 'set_debug_on:true' ;
そして次の例では、PLSQL_CCFLAGSの値をALTER SYSTEMレベルで設定しています。
SQL> alter system set PLSQL_CCFLAGS = 2> 'use_10g_features:false' ;
条件付きコンパイルのIFテストで、パッケージ定数とccflagを組み合わせて使うことができます。次に例を示します。
$IF $$DEBUG_ON or PayrollConstants.c_Debug $THEN debug('Error'); $END
開発時にはパッケージ定数をTRUEに設定し、それ以降はFALSEに設定します。開発の終了後に、デバッグが必要になったときはいつでもccflagのDEBUG_ONをTRUEに設定してパッケージを再コンパイルすることができます。次のケーススタディで、この概念を詳しく見ていきます。
ケーススタディ:軽量のデバッグフレームワーク
次の軽量のデバッグフレームワークの例では、専用のパッケージで設定されたPL/SQL定数によって、デバッグ機能を有効にしてコードをコンパイルするかどうかを制御しています。この定数をFALSEに設定した場合に、単独のccflagをTRUEに設定して定数の設定を無効にすることができます。
create or replace package DebugConstants is c_debug constant boolean := true; end; / create or replace package debugpkg is procedure debug (p_msg in varchar2, p_lineNum in number,p_plsUnit in varchar2); end debugpkg; / create or replace package debugpkg is procedure debug (p_msg in varchar2, p_lineNum in number,
p_plsUnit in varchar2) is v_error_string varchar2(32767); begin $IF $$DEBUG_ON or DebugConstants.c_debug $THEN v_error_string := 'ERROR in ' || p_plsUnit ||
', at line ' || p_lineNum || ': ' || p_msg; dbms_output.put_line(substr(v_error_string,1,255)); $ELSE null; $END end debug; end debugpkg; /
お分かりのように、DebugConstants.c_debugがFALSEでccflagのdebug_onがFALSEの場合、DebugPkg.debugの呼び出しは単純にnullの呼び出しとなります。これは非常に軽量です。このデバッグフレームワークを使った簡単なパッケージを作成してみましょう。
create or replace package testpkg is procedure run; end; / create or replace package body testpkg is procedure run is v_dummy varchar2(1); begin dbms_output.put_line('Beginning test run...'); select * into v_dummy from dual; if v_dummy = 'X' then debug('Dummy is X!', $$plsql_line, $$plsql_unit); end if; end run; end testpkg;
DebugPkg.debugの呼び出しで、Oracleが定義した新しいccflagの$$plsql_lineと$$plsql_unitが使われています。DebugConstants.c_debugをTRUEに設定している場合は、debugの呼び出しにより、デバッグメッセージとそれに関連するユニットおよび行が出力されます。
SQL> set serverout on SQL> exec testpkg.run ; Beginning test run... ERROR in TESTPKG, at line 19: Dummy is X! PL/SQL procedure successfully completed.
ここで、格納された定数c_debugを変更してみます。
create or replace package DebugConstants is c_debug constant boolean := false; end;
格納された定数c_debugをFALSEに設定した後でテストプロシージャを実行すると、デバッグ情報は出力されません。
SQL> exec testPkg.run ; Beginning test run... PL/SQL procedure successfully completed.
デバッグ情報が出力されなくなるのは、パッケージDebugConstantsが再コンパイルされたときに、Oracleが依存関係を記憶し、デバッグコードなしでDebugPkgを再コンパイルしたからです。
エラーディレクティブ
PL/SQL条件付きコンパイルには、3つのディレクティブしかありません。そのうちの2つは、既に出てきた選択ディレクティブ($IF... $END)と問合せディレクティブ($$)です。残りの1つがエラーディレクティブで、これは困っている開発者の強い味方になる構文要素です。未完成のセクションに関するエラーをコンパイラに報告させることで、未完のコードがコンパイルされるのを防ぎ、仕上げなければならない部分を思い出すことができます。
エラーディレクティブの構文はとても単純です。
$ERROR varchar2_string $END
エラーディレクティブを含むコードをコンパイルすると、PL/SQLコンパイラは$ERROR行でPLS-00179エラーを報告し、varchar2_stringの値をエラーテキストとして表示します。次に例を示します。
create or replace package testErrDirective is procedure run; end; / create or replace package body testErrDirective is procedure run is begin dbms_output.put_line('Beginning test run...'); $ERROR 'Oh No! There''s no code at line ' || $$plsql_line || ' in ' || $$plsql_unit $END end run; end testpkg; /
このパッケージ本体をコンパイルするとエラーが発生し、エラーテキストがエラーディレクティブのメッセージとして表示されます。
SQL> show errors Errors for PACKAGE BODY TESTERRDIRECTIVE: LINE/COL ERROR -------- ------------------------------------------ 5/3 PLS-00179: $ERROR: Oh No! There's no code at line 6 in TESTERRDIRECTIVE
古いコードに目を通していて、次のようなコメントに次々と出くわして途方にくれた経験はないでしょうか。
--Joe: これではうまくいかない ; 運用環境に導入する前に修正すること!!!
実際にこういう経験をしたことがある人ならば、エラーディレクティブの有用性がすぐに分かるでしょう。
