アプリケーション開発の手引き


UDF とメソッドの登録例

次に、UDF やメソッドを登録できるさまざまな代表的な場合を具体例を挙げて説明します。

これらの例では、以下のことに注意してください。

例: べき乗

たとえば、浮動小数点値をべき乗するために外部 UDF を作成し、それを MATH スキーマに登録したい場合を考えます。このとき DBADM 権限を持っているものとします。関数を広範囲にわたってテストした結果、保全性が損なわれることがないと分かっているので、この関数を NOT FENCED として定義します。 DBADM 権限を持っているので、 CREATE_NOT_FENCED というデータベース権限を持つことになります。これは、関数を NOT FENCED として定義するために必要になります。

     CREATE FUNCTION MATH.EXPON (DOUBLE, DOUBLE)
       RETURNS DOUBLE
       EXTERNAL NAME '/common/math/exponent'
       LANGUAGE C
       PARAMETER STYLE DB2SQL
       NO SQL
       DETERMINISTIC
       NO EXTERNAL ACTION
       NOT FENCED

この例では、システムは NOT NULL CALL という省略時値を使用します。いずれか一方の引き数が NULL である場合、結果は NULL でなければならないため、これは要求を満たします。また、スクラッチパッドが必要なく、最終呼び出しを行う必要がないので、 NO SCRATCHPAD および NO FINAL CALL という省略時値が使用されます。 EXPON が並列にしてはいけない理由がないので、ALLOW PARALLELISM 省略時値が使用されます。

例: ストリングの検索

Willie という人が UDF を作成して、引き数として渡される所定の短いストリングを同じく引き数として渡される所定の CLOB 値内で検索すると仮定します。 UDF は、そのストリングを検出すると CLOB 内のそのストリングの位置を戻し、検出しないとゼロを戻します。 UDF が完全にはテストされていない恐れがあると、この関数に対するデータベースの保全性にかかわるため、この関数を FENCED として定義します。

さらに、Willie は FLOAT の結果を戻す関数を作成しています。このとき、SQL で使用されると必ず INTEGER を戻すことが分かっているものとします。すると、次の関数を作成することができます。

     CREATE FUNCTION FINDSTRING (CLOB(500K), VARCHAR(200))
       RETURNS INTEGER
       CAST FROM FLOAT
       SPECIFIC "willie_find_feb95"
       EXTERNAL NAME '/u/willie/testfunc/testmod!findstr'
       LANGUAGE C
       PARAMETER STYLE DB2SQL
       NO SQL
       DETERMINISTIC
       NO EXTERNAL ACTION
       FENCED

CAST FROM 文節を使用しているのは、 UDF 本体から実際に戻される FLOAT 値を INTEGER にキャストして、それからその値を、UDF を使用するステートメントに戻すよう指定するためです。 SQL 解説書 に説明されているように、 INTEGER 組み込み関数はこのキャストを実行できます。また、関数に対してユーザー指定の名前を付け、後に DDL (例: UDT のストリング検索を参照) で参照することもできます。 NULL 値を処理する UDF は作成されなかったので、 NOT NULL CALL という省略時値を使用します。また、スクラッチパッドがないので、 NO SCRATCHPAD および NO FINAL CALL という省略時値を使用します。 FINDSTRING を並列にしてはいけない理由がないので、 ALLOW PARALLELISM 省略時値が使用されます。

例: BLOB ストリング検索

この関数は、CLOB だけでなく BLOB 上でも実行できるようにしたいので、最初のパラメーターとして BLOB を指定する FINDSTRING をもう 1 つ定義します。

     CREATE FUNCTION FINDSTRING (BLOB(500K), VARCHAR(200))
       RETURNS INTEGER
       CAST FROM FLOAT
       SPECIFIC "willie_fblob_feb95"
       EXTERNAL NAME '/u/willie/testfunc/testmod!findstr'
       LANGUAGE C
       PARAMETER STYLE DB2SQL
       NO SQL
       DETERMINISTIC
       NO EXTERNAL ACTION
       FENCED

この例は、UDF 名の多重定義を具体的に説明し、複数の UDF やメソッドが同じ本体を共用できることを示しています。なお、BLOB は CLOB に割り当てることはできませんが、同じソース・コードを使用できます。 DB2 と UDF の間で BLOB と CLOB のプログラミング・インターフェースが同じ (長さの次にデータがある) なので、上の例ではプログラミング上の問題はありません。 DB2 は、特別な関数本体を使用する UDF が同じ本体を使用する別の UDF と一貫しているかどうか検査しません。

例: UDT のストリング検索

この例は、前述の例に続くものです。 例: BLOB ストリング検索の FINDSTRING 関数には満足していますが、ここでソース・タイプを BLOB とする特殊タイプ BOAT を定義したとしましょう。すると、BOAT というデータ・タイプを持つ値の演算を行う FINDSTRING も必要になるので、 FINDSTRING をもう 1 つ作成します。この関数は、例: BLOB ストリング検索で BLOB 値に対して演算を行った FINDSTRING をソースとします。この例では、FINDSTRING をさらに多重定義する点に注目してください。

     CREATE FUNCTION FINDSTRING (BOAT, VARCHAR(200))
       RETURNS INT
       SPECIFIC "slick_fboat_mar95"
       SOURCE SPECIFIC "willie_fblob_feb95"

この FINDSTRING 関数は 例: BLOB ストリング検索の FINDSTRING 関数とはシグニチャーが異なるので、名前を多重定義しても問題はありません。ユーザー独自の名前を付けて、後で DDL で参照できるようにしたいとします。 SOURCE 文節を使用しているので、EXTERNAL NAME 文節または、関数の属性を指定する関連したキーワードは使用できません。これらの属性は、ソース関数から取り出されます。最後に、例: BLOB ストリング検索では、ご使用のソース関数を識別する際に特定の関数名が明示的に示されていることに注意してください。これは修飾されない参照であるので、このソース関数が常駐するスキーマは関数パスにあるはずで、そうでなければ参照は分析されません。

例: UDT パラメーターを指定した外部関数

BOAT を入手し、その設計属性を調べ、そのボートのコストをカナダドルで生成する、別の UDF を作成しました。労働コストはユーロ、円、または US ドルで内部的に計算されるとしても、この関数は、ボートを作成するのに必要なコストを、要求された通貨であるカナダドルで出す必要があります。これは、関数が 為替相場の Web ページから現在の為替相場の情報を取り入れなければならないということを意味し、その答えは、Web ページ内で検出するものによって決まります。このため、関数は NOT DETERMINISTIC (または VARIANT) になります。

     CREATE FUNCTION BOAT_COST (BOAT)
       RETURNS INTEGER
       EXTERNAL NAME '/u/marine/funcdir/costs!boatcost'
       LANGUAGE C
       PARAMETER STYLE DB2SQL
       NO SQL
       NOT DETERMINISTIC
       NO EXTERNAL ACTION
       FENCED

CAST FROM および SPECIFIC は指定されておらず、 NOT DETERMINISTIC が指定されていることに注意してください。ここでも、安全のために FENCED が選択されます。

例: UDT での AVG

この例は、CANADIAN_DOLLAR 特殊タイプで AVG 列関数をインプリメントします。 CANADIAN_DOLLAR の定義については、 例: 通貨を参照してください。強力タイピングは、特殊タイプ上で AVG 組み込み関数を使用しないようにします。 CANADIAN_DOLLAR のソース・タイプが DECIMAL であったと分かるので、 AVG を、AVG (DECIMAL) 組み込み関数をソースとしてインプリメントします。これができるかどうかは、DECIMAL から CANADIAN_DOLLAR へ、またその逆方向にキャストできるかどうかによりますが、 DECIMAL は CANADIAN_DOLLAR のソース・タイプであるので、これらのキャストは実行できるということが分かります。

     CREATE FUNCTION AVG (CANADIAN_DOLLAR)
       RETURNS CANADIAN_DOLLAR
       SOURCE "SYSIBM".AVG(DECIMAL(9,2))

なお、別の AVG 関数がご使用の関数パスに潜在する場合に備えて SOURCE 文節中で関数名を修飾しています。

例: 計算

単純な計算関数は、最初に 1 を戻し、呼び出されるたびに結果を 1 ずつ増分します。この関数は SQL 引き数を取らず、応答が呼び出しごとに変化するので、 NOT DETERMINISTIC 関数として定義されています。これは、戻される最後の値を保管するためにスクラッチパッドを使用し、呼び出されるたびにこの値を増分して戻します。このとき、この関数を厳密にテストした結果、データベース上で DBADM 権限を持っているので、これを NOT FENCED と定義します。 (DBADM は、CREATE_NOT_FENCED を暗黙指定します。)

     CREATE FUNCTION COUNTER ()
       RETURNS INT
       EXTERNAL NAME '/u/roberto/myfuncs/util!ctr'
       LANGUAGE C
       PARAMETER STYLE DB2SQL
       NO SQL
       NOT DETERMINISTIC
       NOT FENCED
       SCRATCHPAD
       DISALLOW PARALLEL

パラメーターは定義されず、空括弧のみとなります。上記の関数は SCRATCHPAD を指定し、省略時指定の NO FINAL CALL を使用します。この場合、スクラッチパッドの省略時サイズ (100 バイト) は十分大きく、最後の呼び出しによって記憶域を解放する必要はないので、 NO FINAL CALL が指定されています。 COUNTER 関数が正しく動作するためには、単一のスクラッチパッドを使う必要があるので、 DISALLOW PARALLEL を追加して、DB2 がこの関数を並列に実行しないようにします。この COUNTER 関数のインプリメンテーションについては、 例: カウンターを参照してください。

例: OLE オートメーション・オブジェクトを使った計算

この例では、前に挙げた計算例を OLE (オブジェクトのリンクと埋め込み) オートメーション・オブジェクト counter としてインプリメントします。これには、呼び出しの数を記録するためのインスタンス変数 nbrOfInvoke があります。 UDF が呼び出されるたびに、オブジェクトの increment メソッドは、 nbrOfInvoke インスタンスを増分し、その時点での状態を戻します。オートメーション・オブジェクトは、 OLE プログラマティック識別子 (progID) bert.bcounter を指定して Windows レジストリーに登録されます。

     CREATE FUNCTION bcounter ()
       RETURNS integer
       EXTERNAL NAME 'bert.bcounter!increment'
       LANGUAGE OLE
       PARAMETER STYLE DB2SQL
       SCRATCHPAD
       NOT DETERMINISTIC
       FENCED
       NULL CALL
       NO SQL
       NO EXTERNAL ACTION
       DISALLOW PARALLEL;

クラス counter のインプリメンテーションは、 例: BASIC でのカウンター OLE オートメーション UDF例: C++ でのカウンター OLE オートメーション UDFに示されています。 DB2 による OLE サポートの詳細については、OLE オートメーション UDF の作成を参照してください。

例: 文書 ID を戻す表関数

特定の対象域 (最初のパラメーター) と一致し、特定のストリング (2 番目のパラメーター) を含む、テキスト管理システム内の各文書について単一の文書識別子列を戻す、表関数を作成しました。この UDF は、テキスト管理システムの関数を使用して、即座に文書を識別します。

     CREATE FUNCTION DOCMATCH (VARCHAR(30), VARCHAR(255))
       RETURNS TABLE (DOC_ID CHAR(16))
       EXTERNAL NAME '/common/docfuncs/rajiv/udfmatch'
       LANGUAGE C
       PARAMETER STYLE DB2SQL
       NO SQL
       DETERMINISTIC
       NO EXTERNAL ACTION
       NOT FENCED
       SCRATCHPAD
       NO FINAL CALL
       DISALLOW PARALLEL
       CARDINALITY 20

この UDF は、単一セッションの文脈内では常に同じ表を戻すので、 DETERMINISTIC として定義されています。 RETURNS 文節で、列名 DOC_ID を含む、DOCMATCH の出力が定義されることに注意してください。 FINAL CALL は、各表関数ごとに指定する必要はありません。さらに、表関数は並列に実行できないので、DISALLOW PARALLEL キーワードが追加されています。 DOCMATCH の出力のサイズはよく変化しますが、 CARDINALITY 20 を代表値として指定し、DB2 最適化プログラムが優れた決定を行えるようにしています。

通常、この表関数は、次のように文書テキストを含む表と組み合わせて使用されます。

  SELECT T.AUTHOR, T.DOCTEXT
  FROM DOCS as T, TABLE(DOCMATCH('MATHEMATICS', 'ZORN''S LEMMA')) as F
  WHERE T.DOCID = F.DOC_ID

FROM 文節で表関数を指定するための特殊な構文 (TABLE キーワード) に注意してください。この呼び出しでは、docmatch() 表関数は、 Zorn's Lemma を参照する各 mathematics 文書について、単一行 DOC_ID を含む行を戻します。これらの DOC_ID 値が結合し、作成者の名前と文書テキストを取得して、マスター文書表になります。


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]