short (SQL_CALLBACK *get_value) ( void * arg_handle, a_sql_uint32 arg_num, an_extfn_value *value ); |
get_value コールバック関数は、外部関数とのインターフェイスとして動作するストアドプロシージャーまたはファンクションに渡されたパラメーターの値を取得するために使用します。失敗した場合は 0 を返し、それ以外の場合は 0 以外の結果を返します。get_value を呼び出した後、an_extfn_value 構造体の total_len フィールドには値全体の長さが入ります。piece_len フィールドには、get_value を呼び出して取得された部分の長さが入ります。piece_len は必ず total_len 以下の値になります。piece_len が total_len よりも小さい場合は、2 番目の関数 get_piece を呼び出して残りの部分を取得できます。total_len フィールドが有効になるのは、最初の get_value が呼び出された後です。このフィールドは、get_piece の呼び出しによって変更される remain_len フィールドでオーバーレイされます。したがって、total_len フィールドの値を後で使用する場合は、get_value を呼び出した直後にこのフィールドの値を保存しておく必要があります。
short (SQL_CALLBACK *get_piece) ( void * arg_handle, a_sql_uint32 arg_num, an_extfn_value *value, a_sql_uint32 offset ); |
パラメーター全体の値を一度に返せない場合は、get_piece 関数を繰り返し呼び出して、パラメーター値の残りの部分を取得できます。
get_value と get_piece の両方を呼び出して返されたすべての piece_len 値の合計が、get_value を呼び出した後で total_len フィールドに返された初期値に加算されます。get_piece の呼び出し後、total_len をオーバーレイする remain_len フィールドには未取得分の長さ (値) が示されます。
次に示すのは、get_value と get_piece を使用して、LONG VARCHAR パラメーターなどの文字列パラメーターの値を取得する例です。
外部関数のラッパーが次のように宣言されているとします。
CREATE PROCEDURE mystring( IN instr LONG VARCHAR ) EXTERNAL NAME 'mystring@mystring.dll'; |
外部関数を SQL から呼び出すには、次のような文を使用します。
call mystring('Hello world!'); |
C で記述された mystring 関数を Windows オペレーティングシステムに実装する例を次に示します。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> #include "extfnapi.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } extern "C" __declspec( dllexport ) a_sql_uint32 extfn_use_new_api( void ) { return( EXTFN_API_VERSION ); } extern "C" __declspec( dllexport ) void mystring( an_extfn_api *extapi, void *arg_handle ) { short result; an_extfn_value arg; unsigned offset; char *string; result = extapi->get_value( arg_handle, 1, &arg ); if( result == 0 || arg.data == NULL ) { return; // no parameter or parameter is NULL } string = (char *)malloc( arg.len.total_len + 1 ); offset = 0; for( ; result != 0; ) { if( arg.data == NULL ) break; memcpy( &string[offset], arg.data, arg.piece_len ); offset += arg.piece_len; string[offset] = '\0'; if( arg.piece_len == 0 ) break; result = extapi->get_piece( arg_handle, 1, &arg, offset ); } MessageBoxA( NULL, string, "SQL Anywhere", MB_OK | MB_TASKMODAL ); free( string ); return; } |
short (SQL_CALLBACK *set_value) ( void * arg_handle, a_sql_uint32 arg_num, an_extfn_value *value short append ); |
set_value コールバック関数は、OUT パラメーターおよびストアド関数の RETURNS 結果の値を設定するために使用します。RETURNS 値を設定するには、arg_num 値を 0 にします。次はその例です。
an_extfn_value retval; retval.type = DT_LONGVARCHAR; retval.data = result; retval.piece_len = retval.len.total_len = (a_sql_uint32) strlen( result ); extapi->set_value( arg_handle, 0, &retval, 0 ); |
set_value の append 引数は、指定されたデータを既存のデータと置き換えるか (false)、または既存のデータに追加するか (true) を指定します。append=FALSE
を指定して set_value を呼び出してから、同じ引数に対して append=TRUE
を指定して呼び出してください。固定長データ型の場合、append 引数は無視されます。
NULL を返すには、an_extfn_value 構造体の data フィールドを NULL に設定します。
void (SQL_CALLBACK *set_cancel) ( void *arg_handle, void *cancel_handle ); |
外部関数では、IN または INOUT パラメーターの値を取得し、OUT パラメーターおよびストアド関数の RETURNS 結果の値を設定することができます。ただし、取得したパラメーター値が無効になっていたり、値を設定する必要がなくなっている場合があります。これは、SQL 文の実行が取り消された場合に発生します。また、アプリケーションがデータベースサーバーから不意に切断された場合に発生することもあります。この問題を処理するには、extfn_cancel という特別なエントリポイントをライブラリに定義します。この関数が定義されていると、サーバーは実行中の SQL 文が取り消される場合に必ずこの関数を呼び出します。
extfn_cancel 関数は、適切と思われるさまざまな方法で使用できるハンドルを指定して呼び出されます。一般的にこのハンドルは、SQL 文の呼び出しが取り消されたことを示すフラグを間接的に設定する場合に使用します。
渡されるハンドルの値は、set_cancel コールバック関数を使用して、外部ライブラリの関数で設定することができます。次のコードフラグメントがその例です。
extern "C" __declspec( dllexport ) void extfn_cancel( void *cancel_handle ) { *(short *)cancel_handle = 1; } extern "C" __declspec( dllexport ) void mystring( an_extfn_api *api, void *arg_handle ) { . . . short canceled = 0; extapi->set_cancel( arg_handle, &canceled ); . . . if( canceled ) |
静的なグローバル "canceled" 変数を設定することは不適切です。これは、通常はありえない、すべての接続のすべての SQL 文が取り消されると誤って解釈されることがあるためです。そのために、set_cancel コールバック関数が提供されています。set_cancel を呼び出す前に、"canceled" 変数を必ず初期化してください。
外部関数の重要ポイントにある "canceled" 変数の設定を確認しておく必要があります。たとえば、get_value や set_value などの外部ライブラリ呼び出しインターフェイス関数の呼び出し前や後などが重要ポイントです。extfn_cancel が呼び出された結果、変数が設定されると、外部関数は適切な終了アクションを実行することができます。前述の例に基づいたコードフラグメントを次に示します。
if( canceled ) { free( string ); return; } |
任意の引数の get_piece 関数は、同じ引数の get_value 関数の直後にのみ呼び出すことができます。
OUT パラメーターで get_value を呼び出すと、an_extfn_value 構造体の type フィールドに引数のデータ型が設定されて返され、an_extfn_value 構造体の data フィールドに NULL が設定されて返されます。
SQL Anywhere インストールディレクトリの SDK\Include フォルダーのヘッダーファイル extfnapi.h に、詳細な注意事項が記載されています。
次の表に、an_extfn_api に定義されている関数が false を返す条件を示します。
関数 | true の場合は 0 を返し、それ以外の場合は 1 を返す条件 |
---|---|
get_value() |
|
get_piece() |
|
set_value() |
|
![]() |
DocCommentXchange で意見交換できます
|
Copyright © 2012, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.1 |