シェアードライブラリを使用してSQLiteに独自関数を追加する方法SQLiteはBLOB(Binary Large Object)を扱えるので、アプリケーション固有のデータをそのままDBに保存することができる。しかし、アプリケーションにとって意味のある演算をBLOBに対して行うことができるSQL関数はほとんどない。そのため、BLOBを操作する場合、コードをゴリゴリ書かなければならない。しかし、BLOBを操作するSQL関数を一揃え用意しておけば、コードをゴリゴリ書かなくても、SQLだけである程度の処理を記述できるようになる。 例えば、BLOBに保存されたJPEGイメージから、撮影されたGPS位置情報を取り出す関数を用意しておけば、SQLを書くだけである場所の近隣で撮影された画像を検索できる。 SQLiteは簡単にSQL関数を拡張(追加)することができる。ここでは、例として2次元の2点間の距離を求める関数distanceを追加してみる。関数の使い方は以下のとおり。
この関数をシェアードライブラリ(共有ライブラリ、動的リンクライブラリ)として実装しておくと、SQLiteのSQL関数load_extensionを使用して、実行時に読み込むことができる。このように実装することで、自作のアプリケーション以外の、例えばコマンドラインツールsqlite3のような既存のプログラムに対しても、SQL関数を追加できる。 実装実際のプログラムは下記のようになる。
SQLiteのwikiに書いてあるように、まず、次のように記述する。これは、シェアードライブラリ内ではSQLiteの名前解決の方法が通常と異なるためで、sqlite3ext.hの中身を見れば、何を行っているかすぐにわかる。
関数sqlite3_extension_initは、この拡張のエントリーポイントである。任意の名前でよいがsqlite3_extension_initと言う名前にしておけば、load_extensionでこの拡張をロードする際に、エントリーポイント名を省略できる。 エントリーポイントのシグネチャは、上記のとおりでなければならない。正常終了の場合は0を返す。エラーの場合は、第二引数にsqlite3_mprintfを使用してエラーメッセージを設定して、0以外を返す。 エントリーポイントの関数内では、sqlite3_create_function_v2を使用して関数を登録する。 distanceFunc関数が、今回追加するSQL関数の実装となる。引数のいずれかがNULLなら、結果もNULLとする。 sqlite3_value_numeric_typeの結果、数値型に変換できない引数を含む場合は、エラーとする。 正常に処理できたら、sqlite3_result_doubleを使用して、戻り値を設定する。 コンパイル、リンクここでは、Linuxでシェアードライブラリとしてコンパイル、リンクする方法を示す(詳細はこちらを参照)。
-Lオプションの直後には、sqlite3のライブラリが置いてあるディレクトリを指定する。 実行カレントディレクトリに上記で作成したlibsqlite_ext.so.1.0.0があるとすると、次のようにしてロード、実行できる。 環境変数LD_LIBRARY_PATHで、シェアードライブラリの検索パスにカレントディレクトリを指定している。
|