内部関数が足りない? それならUDFだ!
アナハイムテクノロジー
はやしつとむ
2009/6/9
UDFに文字を渡す
次に、UDFに文字型のデータを渡すコードを見てみましょう。同じくIB_UDFのソースコードからです。
ib_udf.cpp(81) ISC_LONG EXPORT IB_UDF_ascii_val( const char *a) { // NULL is treated as ASCII(0). return ((ISC_LONG) (*a)); }
IB_UDF_ascii_val()関数は、引数で指定されたASCII文字の文字コードを返す関数です。char型のポインタaで参照される文字をint型にキャストして返しているだけです。シンプルですね。
同じことをDelphiで書くと以下のようになります。
function tomneko_ascii_val(var a:char):Integer;stdcall; begin result := Ord(a); end;
●登録用スクリプト:
/* External Function declarations */ DECLARE EXTERNAL FUNCTION TOMNEKO_ASCII_VAL CHAR(1) CHARACTER SET ASCII RETURNS INTEGER BY VALUE ENTRY_POINT 'tomneko_ascii_val' MODULE_NAME 'UDF_sample';
●使用例:
SQL> SELECT TOMNEKO_ASCII_VAL('a') FROM RDB$DATABASE; TOMNEKO_ASCII_VAL ============= 97
UDFに文字列を渡す
ascii_val()関数のように、文字列を引数として受け取るような場合は問題とならないのですが、文字列を戻り値として返すために、関数の内部で文字列処理のメモリ領域を用意するような場合は注意が必要です。
ご存じのように、Firebirdのスーパーサーバ版はマルチスレッド化されているため、複数の接続に対して、1プロセスのFirebirdサーバが複数のスレッドを生成して処理を行っています。このとき、各スレッドはメモリ空間を共有しているため、UDFの呼び出しにおいて同じ関数が別のスレッドから同時に呼ばれてしまった場合、静的変数の内容が上書きされてしまうなどの再入問題が発生する可能性があります。
ところが、動的にメモリ領域を確保するとなると、誰がそれを解放するのかという問題が生じます。UDF内部で確保されたメモリ領域を使って、戻り値をFirebirdへ渡す場合、Firebirdがそのメモリ領域を解放しなくてはならないからです。
この問題の解決方法として、Firebirdには、ib_util.dll(Linuxではib_util.so)というライブラリが付属しています。これはUDF内で動的にメモリを確保するために使用されます。このライブラリを使用することで、呼び出し側であるFirebirdがUDF側で確保したメモリを解放することが可能となります。
この場合、UDF登録用スクリプトのREURNS句の最後にFREE ITキーワードを指定します。このFREE IT指定によって、FirebirdはUDFの呼び出しが終了した時点で、不要となったメモリ領域をib_util_malloc()と同じメモリマネージャを利用して解放します。
しかし、ib_util_malloc()関数とFREE ITキーワードを利用する方法は、あまりスマートとはいえません。そこで、もう1つ方法を紹介します。
DECLARE EXTERNAL FUNCTION文のRETURNS句で戻り値のデータ型を指定する代わりに、PARAMETER句を指定することで、引数として渡すデータの中から戻り値を指定することができます。具体的には、以下のようにします。
procedure tomneko_ascii_char2(var a:Integer; b:PChar);stdcall; begin b^ := Char(a); (b+1)^ := #0; end;
●登録用スクリプト:
DECLARE EXTERNAL FUNCTION tomneko_ascii_char2 INTEGER, CSTRING(1) CHARACTER SET ASCII RETURNS PARAMETER 2 ENTRY_POINT 'tomneko_ascii_char2' MODULE_NAME 'UDF_sample';
●使用例:
SQL> select tomneko_ascii_char2(97) from rdb$database; TOMNEKO_ASCII_CHAR2 =============== a
この場合、戻り値のために必要なメモリ領域は、Firebirdが管理しているので、FREE ITキーワードもib_util_malloc()関数も必要ありません。
3/4 |
Index | |
内部関数が足りない? それならUDFだ! | |
Page 1 内部関数で物足りないあなたに UDFの仕組み 標準UDFのコード |
|
Page 2 引数を取らないUDF 数値型の引数を取るUDF |
|
Page 3 UDFに文字を渡す UDFに文字列を渡す |
|
Page 4 最後に |
Yet another OSS DB:Firebird |
- Oracleライセンス「SE2」検証 CPUスレッド数制限はどんな仕組みで制御されるのか (2017/7/26)
データベース管理システムの運用でトラブルが発生したらどうするか。DBサポートスペシャリストが現場目線の解決Tipsをお届けします。今回は、Oracle SE2の「CPUスレッド数制限」がどんな仕組みで行われるのかを検証します - ドメイン参加後、SQL Serverが起動しなくなった (2017/7/24)
本連載では、「SQL Server」で発生するトラブルを「どんな方法で」「どのように」解決していくか、正しい対処のためのノウハウを紹介します。今回は、「ドメイン参加後にSQL Serverが起動しなくなった場合の対処方法」を解説します - さらに高度なSQL実行計画の取得」のために理解しておくべきこと (2017/7/21)
日本オラクルのデータベーススペシャリストが「DBAがすぐ実践できる即効テクニック」を紹介する本連載。今回は「より高度なSQL実行計画を取得するために、理解しておいてほしいこと」を解説します - データベースセキュリティが「各種ガイドライン」に記載され始めている事実 (2017/7/20)
本連載では、「データベースセキュリティに必要な対策」を学び、DBMSでの「具体的な実装方法」や「Tips」などを紹介していきます。今回は、「各種ガイドラインが示すコンプライアンス要件に、データベースのセキュリティはどのように記載されているのか」を解説します
|
|