CodeZine(コードジン)

特集ページ一覧

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

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

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/10/27 00:00

if... then... else呼び出しの繰り返しがパフォーマンスに与える悪影響を心配しているOracle PL/SQL開発者には、条件付きコンパイルをお勧めします。条件付きコンパイルによって、if... then... else呼び出しを運用コードから消し去ることができます。しかも、できることはそれだけではありません。

目次

はじめに

 Oracle PL/SQL開発者の多くは、次の2つの要望を持っています。

  1. コードを運用環境で実行したときにパフォーマンスを低下させることなく、できるだけ多くのデバッグコードを挿入したい。
  2. Oracleデータベースの最新バージョンの新しい機能を活用しつつ、以前のバージョンでも動作するコードを作成したい。ただし、データベースのバージョンごとに異なるコードをすべて詰め込んだ「ブロートウェア」(無意味に肥大化したソフトウェア)になることは避けたい。

 他の言語の開発者たちは、以前からこれらの要望に応える手軽な解決手段を手に入れています。プリプロセッサとプリコンパイラです。例えば、C++のプリプロセッサでは条件付きコンパイルディレクティブと文字列置換を処理できるので、開発、運用、バージョンの異なるデータベースなど、目的に合わせてソースコードの別々のサブセットをコンパイルすることができます。残念ながらOracle PL/SQLにはこの機能がありませんでした。しかし、それも過去の話となりました。

 最新リリースのOracle Database 10g R2には、これらの要望を簡単に満たすことができるPL/SQL条件付きコンパイル(Conditional Compilation)という新しい機能が備わっています。PL/SQL条件付きコンパイルは、厳密にはプリコンパイラやプリプロセッサではありません。Oracleが既存のPL/SQLコンパイル処理の初期ステージに追加した機能です。同じエンジンによって他のステージと一緒に実行されます。それでも、DBMS_PREPROCESSORパッケージ(これについては後で説明します)という名前に見られるように、PL/SQLはプリプロセッサと呼ばれることがあります。

 本稿では、Oracle 10g R2の新しい条件付きコンパイル機能の使い方、DBMS_PREPROCESSORで条件付きコンパイルの結果を確認する方法、DBMS_DB_VERSIONでこの新しい機能を活用し、バージョンに依存しないコードを作成する方法、および条件付きコンパイルを使って軽量のデバッグフレームワークを作成する方法について説明します。

PL/SQL条件付きコンパイルの使い方

 PL/SQL条件付きコンパイルの使い方はとても簡単です。必要なのは次の2種類の新しいセマンティック構造を覚えることだけです。

  1. コンパイラディレクティブ
  2. 条件付きコンパイルフラグ(ccflag)
  3. 条件付きコンパイラにとって、これはシステム、セッション、または個々のコンパイルレベルで設定できる「定数」のようなものです(いくつかのデフォルトのフラグが用意されており、独自のフラグを指定することもできます)。

 条件付きコンパイルの最も基本的な原則は、コードを「条件付きで」コンパイルできる必要があることです。つまり、もし(IF)特定の条件が満たされた場合は特定のコードをコンパイルし、それ以外の場合は(ELSE)別のコードをコンパイルします。従って、条件付きコンパイルの最も基本的な構成要素は、if... then... else構造のような働きをするコンパイラディレクティブということになります。

 PL/SQL条件付きコンパイルでは、この構成要素を「選択ディレクティブ」と呼びます。選択ディレクティブは、PL/SQLのif... then... else構造と非常によく似た働きをします。構文は次のとおりです。

$IF condition $THEN .....
[$ELSIF condition $THEN.... ]
[$ELSE .....]
$END

 ご想像どおり、PL/SQL条件付きコンパイルのトークンの先頭には常にドル記号($)が付きます。

 条件付きコンパイルの選択ディレクティブと、標準のPL/SQLのif... then... else構造には、次の2つの大きな違いがあります。

  1. 条件付きコンパイルの選択ディレクティブは、$END $IFではなく$ENDで終了します。
  2. 条件付きコンパイルのIFテストの条件式(condition)には、大きな制限があります。コンパイラはコンパイル時にconditionを評価する必要があるので、conditionには変数を使用できません。conditionはコンパイル時に定数値になっている必要があります。具体的には、静的なブール式である必要があります。この概念にとても近いのは、コンパイル時に静的になる式です(詳細については、コラム「静的なブール式」を参照してください)。

 例えば、次の条件式は有効です。

$IF -4 = 8 $THEN
...
$END

 しかし、次のような条件式は指定できません。-4=TRUNC(sysdate,'MM')は静的なブール式ではないからです。

$IF -4=TRUNC(sysdate,'MM') $THEN
...
$END

 IFテスト式には、それ自体が静的なブール式であれば、パッケージ定数を含めることができます(もちろん、この定数は他のパッケージのどこかで設定しておく必要があります)。次に例を示します。

create or replace package PayrollApp_CC_Constants is
    c_SpecialNumber constant PLS_INTEGER := 8;
    c_DebugOn constant BOOLEAN := false;
end PayrollApp_CC_Constants;

....
$IF PayrollApp_CC_Constants.c_DebugOn $THEN
    debug('Debug On');
$ELSIF PayrollApp_CC_Constants.c_SpecialNumber = -4 $THEN
    raise;
$END
....
著者注
 この例および以降のすべての例に出てくるdebug('X')は、PL/SQLの言語要素を示すものではありません。特に明記しない限り、これは例で使われている仮想のパッケージのどこか別の場所にある仮想のプロシージャを示しています。このプロシージャは、デバッグメッセージを引数に取り、それを出力するか、どこかに記録するという想定です。

 条件付きコンパイルのIFテスト式で静的な式の定数を使うときは、それらの定数を分離して、定数のみが含まれるパッケージにすべてまとめることをお勧めします。このようにすると、コンパイルの結果を左右する定数の値が一目で分かるようになります。また、PL/SQLコードの通常のアプリケーション定数と混同しにくくなるので、例えば定数が誤って静的でない値や式に設定されるのを防ぐことができます。さらに、定数を分離すると、コンパイルの循環依存関係に陥るおそれもなくなります。

 次の例は、残りのコードがコンパイルどころか解析さえされないうちに、条件付きコンパイルの選択ディレクティブが処理されることを非常に明確に示しています。この簡単なプロシージャを見てください。

create or replace procedure testproc is
begin
$if TRUE $then
  dbms_output.put_line('We got here');
$else
  RANDOM BAD STUFF, NOT EVEN SYNTACTICALLY CORRECT
$end
null;
end testproc;

 このプロシージャのテキストには、大きな構文上の誤り("RANDOM BAD STUFF, NOT EVEN SYNTACTICALLY CORRECT")が含まれていますが、この誤りは決して評価されることのない$IF - $THEN - $ELSEの分岐内にあります。そのため、プロシージャは問題なくコンパイルされます。

SQL> create or replace procedure testproc is
  2  begin
  3  $if TRUE $then
  4     dbms_output.put_line('We got here');
  5  $else
  6     RANDOM BAD STUFF, NOT EVEN SYNTACTICALLY CORRECT
  7  $end
  8  null;
  9  end testproc;
10 /

Procedure created.

SQL> show errors procedure testproc
No errors.
静的なブール式
 「静的なブール式」とは、値が変わらないブール(TRUE/FALSE)式です。いつ誰が式を評価しても、結果は常に同じでなければなりません。静的なブール式の評価値を変更する唯一の方法は、そのブール式が定数に基づいて定義されている場合に、定数値を変更することです。分かりやすいようにいくつかの例を示します。
次に示すのは、「静的な式」の例です。
18
'Pashmina'
TRUE
静的な式は、別の静的な式に基づいて定義することができます。例えば、c_mynumberを次のように定義するとします。
c_myNumber constant pls_integer := 42;
この場合、c_myNumberは静的な式になります。次の式も同様です。
c_myNumber*12
to_char(c_myNumber) || 'Pashmina'
「静的なブール式」は、次のようにTRUEまたはFALSEに評価される静的な式です。
c_myNumber = 43
-4 >= 8
ここで注意しておきたいのは、すべての定数が静的な式であるとは限らないということです。静的な式に基づかないPL/SQL定数を定義することができます。例えば、次の式は静的な式ではありません。いつ評価されるかによって値が変わるからです。
c_myNumber CONSTANT PLS_INTEGER := trunc(sysdate,'MM') ;
この場合は、次のような式も静的な式になりません。
c_myNumber*12
c_myNumber != 9

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

あなたにオススメ

著者プロフィール

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

    japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.c...

  • Natalka Roshak(Natalka Roshak)

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

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5