short (SQL_CALLBACK *get_value) ( void * arg_handle, a_sql_uint32 arg_num, an_extfn_value *value ); |
Mit der get_value-Callback-Funktion können Sie den Wert eines Parameters abfragen, der an die gespeicherte Prozedur oder Funktion übergeben wurde, die als Schnittstelle zu der externen Funktion agiert. Wenn die Funktion nicht erfolgreich ist, wird 0 zurückgegeben, andernfalls ist der Rückgabewert Nicht-Null. Nach dem Aufruf von get_value enthält das Feld total_len der Struktur an_extfn_value die Länge des gesamten Werts. Das Feld piece_len enthält die Länge des Teils, der als Ergebnis des Aufrufs von get_value abgerufen wurde. Beachten Sie, dass piece_len immer kleiner oder gleich total_len ist. Wenn piece_len kleiner ist, kann als zweite Funktion get_piece aufgerufen werden, um die übrigen Teile abzurufen. Beachten Sie, dass das Feld total_len erst nach dem ersten Aufruf von get_value gültig ist. Dieses Feld wird vom Feld remain_len überlagert, das von Aufrufen von get_piece geändert wird. Der Wert des Felds total_len unmittelbar nach dem Aufruf von get_value muss bewahrt werden, wenn geplant wird, den Wert zu einem späteren Zeitpunkt zu verwenden.
short (SQL_CALLBACK *get_piece) ( void * arg_handle, a_sql_uint32 arg_num, an_extfn_value *value, a_sql_uint32 offset ); |
Wenn es nicht möglich ist, den gesamten Parameterwert in einem Stück zurückzugeben, kann die get_piece-Funktion wiederholt aufgerufen werden, um die übrigen Teile des Parameterwerts abzurufen.
Die Summe aller von den beiden Aufrufen von get_value und get_piece zurückgegebenen piece_len-Werte wird zum Ausgangswert addiert, der im Feld total_len nach dem Aufruf von get_value zurückgegeben wurde. Nach dem Aufruf von get_piece repräsentiert das Feld remain_len, das total_len überlagert, die noch nicht erhaltene Länge.
Im folgenden Beispiel wird gezeigt, wie Sie mit get_value und get_piece den Wert eines Zeichenfolgeparameters wie z.B. eines long varchar-Parameters erhalten.
Angenommen, der Wrapper für eine externe Funktion wurde folgendermaßen deklariert:
CREATE PROCEDURE mystring( IN instr LONG VARCHAR ) EXTERNAL NAME 'mystring@mystring.dll'; |
Um die externe Funktion aus SQL aufzurufen, verwenden Sie eine Anweisung ähnlich der folgenden.
call mystring('Hello world!'); |
Im Folgenden wird eine in C geschriebene Beispielimplementierung der Funktion mystring für Windows gezeigt:
#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 ); |
Mit der Callback-Funktion set_value können die Werte von OUT-Parametern und das RETURNS-Ergebnis einer gespeicherten Funktion festgelegt werden. Legen Sie den RETURNS-Wert mit dem arg_num-Wert 0 fest. Im Folgenden finden Sie ein Beispiel.
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 ); |
Das append-Argument von set_value legt fest, ob die gelieferten Daten die bestehenden Daten ersetzen (FALSE) oder ergänzen
(TRUE). Sie müssen set_value mit append=FALSE
aufrufen, bevor Sie es mit append=TRUE
für dasselbe Argument aufrufen. Das append-Argument wird bei Datentypen mit fester Länge ignoriert.
Damit NULL zurückgegeben wird, setzen Sie das Datenfeld der Struktur an_extfn_value auf NULL.
void (SQL_CALLBACK *set_cancel) ( void *arg_handle, void *cancel_handle ); |
Externe Funktionen können die Werte von IN- oder INOUT-Parametern erhalten und können die Werte von OUT-Parametern und das RETURNS-Ergebnis einer gespeicherten Funktion festlegen. In einem bestimmten Fall sind die erhaltenen Parameterwerte jedoch möglicherweise nicht mehr gültig oder die Einstellung der Werte ist nicht mehr erforderlich. Dieser Fall tritt ein, wenn eine ausführende SQL-Anweisung abgebrochen wird. Der Grund hierfür kann sein, dass eine Anwendung plötzlich vom Datenbankserver getrennt wird. Sie können für diese Situation einen speziellen Eintrittspunkt in der Bibliothek mit dem Namen extfn_cancel definieren. Wenn diese Funktion definiert wurde, wird sie vom Server immer dann aufgerufen, wenn eine laufende SQL-Anweisung abgebrochen wird.
Die Funktion extfn_cancel wird mit einem Handle aufgerufen, das auf jede gewünschte Weise verwendet werden kann. Eine typische Verwendung des Handles ist das indirekte Setzen eines Parameters, der anzeigt, dass die aufrufende SQL-Anweisung abgebrochen wurde.
Der übergebene Wert des Handles kann von Funktionen in der externen Bibliothek mit der Callback-Funktion set_cancel festgelegt werden. Dieser Vorgang wird im folgenden Codefragment veranschaulicht.
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 ) |
Beachten Sie, dass das Festlegen einer statischen globalen canceled-Variablen ungeeignet ist, da dies als Abbruch aller SQL-Anweisungen auf allen Verbindungen interpretiert würde, was normalerweise nicht der Fall ist. Aus diesem Grund wird die set_cancel-Callback-Funktion bereitgestellt. Stellen Sie sicher, dass die canceled-Variable vor dem Aufruf von set_cancel initialisiert wurde.
Es ist wichtig, die Einstellung der canceled-Variablen an strategischen Punkten der externen Funktion zu überprüfen. Zu den strategischen Punkten zählen Punkte vor und nach dem Aufruf von Schnittstellenfunktionen für externe Bibliotheksaufrufe wie get_value und set_value. Wenn die Variable festgelegt wird (als Ergebnis des Aufrufs von extfn_cancel), kann die externe Funktion entsprechende Beendigungsaktionen ausführen. Im Folgenden wird der Vorgang durch ein Codefragment basierend auf dem obigen Beispiel veranschaulicht:
if( canceled ) { free( string ); return; } |
Die get_piece-Funktion für ein bestimmtes Argument kann nur sofort nach der get_value-Funktion für dasselbe Argument aufgerufen werden.
Der Aufruf eines OUT-Parameter gibt das Feld type der Struktur an_extfn_value zurück, das den Datentyp des Arguments enthält, sowie das Feld data der Struktur an_extfn_value, das auf NULL gesetzt ist.
Die Header-Datei extfnapi.h im SQL Anywhere-Installationsverzeichnis SDK\Include enthält einige zusätzliche Hinweise.
In der folgenden Tabelle werden die Bedingungen aufgeführt, unter welchen die in an_extfn_api definierten Funktionen den Wert FALSE zurückgeben:
Funktion | Gibt 0 zurück, wenn das Folgende zutrifft, andernfalls 1 |
---|---|
get_value() |
|
get_piece() |
|
set_value() |
|
![]() |
Kommentieren Sie diese Seite in DocCommentXchange.
|
Copyright © 2012, iAnywhere Solutions, Inc. - SQL Anywhere 12.0.1 |