SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

条件付きコンパイルを使ってOracleの運用コードを効率化する

パフォーマンスを低下させることなく可能な限りデバッグコードを挿入する方法

条件付きコンパイルフラグの使い方

 条件付きコンパイルの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: これではうまくいかない ; 運用環境に導入する前に修正すること!!!

 実際にこういう経験をしたことがある人ならば、エラーディレクティブの有用性がすぐに分かるでしょう。

次のページ
バージョン依存の条件付きコンパイル

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Natalka Roshak(Natalka Roshak)

カナダのオンタリオ州在住のデータベース管理者、アナリスト、およびアーキテクト。toolkit.rdbms-insight.comにも記事を執筆している。連絡先はwww.rdbms-insight.com/contact.php

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/647 2010/01/05 11:05

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー