その1では拡張ライブラリのビルドをしてみたけど、今回は実際に自分で関数を作ってみる。
複数の引数を渡されるとそれらの積を返すスカラー関数を作ってみよう。
動作イメージ
productfunctions.c
ポイントは以下な感じ。
An Introduction To The SQLite C/C++ Interface
C-language Interface Specification for SQLite
これをその1でやったsqlite-extensionと同じ要領でビルドする。
product関数が動作したね!
複数の引数を渡されるとそれらの積を返すスカラー関数を作ってみよう。
動作イメージ
> select product(2, 3, 4); 24
productfunctions.c
#include <stddef.h> #include "sqlite3ext.h" // 1. SQLITE_EXTENSION_INIT1 // 2. // 3. static void productFunc(sqlite3_context *context, int argc, sqlite3_value **argv) { if (argc == 0) { sqlite3_result_int64(context, 0); return; } sqlite_int64 product = 1; int i; for (i = 0; i < argc; i++) { if (sqlite3_value_type(argv[i]) == SQLITE_NULL) return; product *= sqlite3_value_int64(argv[i]); } sqlite3_result_int64(context, product); } // 4. int sqlite3_extension_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){ SQLITE_EXTENSION_INIT2(pApi); int res = sqlite3_create_function( db, "product", -1, SQLITE_ANY, NULL, productFunc, NULL, NULL); if (res != SQLITE_OK) { *pzErrMsg = sqlite3_mprintf("Can't create product function."); return 1; } return 0; }
ポイントは以下な感じ。
- "sqlite3ext.h"をインクルードする。
- SQLITE_EXTENSION_INIT1マクロを宣言する。
これはSQLiteの拡張モジュールを作成するときの決まりごとなので、はじめに書こう。
実際はこの中でグローバル変数が定義されていて、後で使うSQLITE_EXTENSION_INIT2で値が代入される。 - 今回、実装するproduct関数の本体だね。
Cのmain関数と同様に引数はargcとargvで渡ってくる。
今回はsqlite_int64型が渡ってくることを前提として、型チェックは最小限しかしていない。
引数からの値の取り出しは型に応じたsqlite3_value_*関数で行う。
関数からの戻り値も型に応じたsqlite3_result_*関数で設定する。 - 作成した関数をSQLiteの関数として登録する。
最初にSQLITE_EXTENSION_INIT2を呼び出す。
sqlite3_create_functionを使って、関数を登録する。
第2引数にSQLでの関数名、第3引数に期待する引数の数、第6引数に実行される関数を指定する。
今回は引数の数は可変のため-1を指定する。
An Introduction To The SQLite C/C++ Interface
C-language Interface Specification for SQLite
これをその1でやったsqlite-extensionと同じ要領でビルドする。
$ gcc -I../sqlite-amalgamation-3150000gcc -I../sqlite-amalgamation-3150000 -L../sqlite-amalgamation-3150000 -fPIC -shared -Os productfunctions.c -o libproductfunctions.so -L../sqlite-amalgamation-3150000 $ LD_LIBRARY_PATH=./../sqlite-amalgamation-3150000/ ../sqlite-amalgamation-3150000/sqlite3 SQLite version 3.15.0 2016-10-14 10:20:30 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite> .load libproductfunctions sqlite> select product(2, 3, 4); 24 sqlite>
product関数が動作したね!
0 件のコメント:
コメントを投稿