PostgreSQLのユーザー定義型を利用して、
内部で暗号化されたカラムを作成したので、その過程でハマったことを
覚書も兼ねて投稿しておきます。
1. 可変長データのサイズ設定
可変長データは、内部的に
/************************/
typedef struct
{
int4 sz; // 構造体の総サイズ
char val[1]; // データ格納位置(ダミー)
} EncryptedText
/************************/
のように表現されているのですが、
/************************/
EncryptedText a;
a.sz = 100;
/************************/
のように書くとNG。
この場合、専用のマクロを使って
/************************/
SET_VARSIZE(a, 100);
/************************/
としなければいけません。
また、ここで設定した値を取り出す場合も
/************************/
VARSIZE(a);
/************************/
とする必要があり、実際のデータ(val部分)にアクセスする場合も
/************************/
VARDATA(a);
/************************/
とします。全てマクロ経由でアクセスしないとダメということです。
2. 他で定義されている関数の呼び出し
今回は暗号化するということで、pg_cryptoモジュールで定義されている
pgp_sym_encrypt/decryptを使用しましたが、これらのプロトタイプ宣言は
/************************/
Datum pgp_sym_encrypt(PG_FUNCTION_ARGS)
/************************/
となっています。pgp_sym_encryptの内部では
/************************/
bytea* pgp_sym_encrypt(const char *str, const char *pass, const char *cipher_algo);
/************************/
と同等なのですが、この形式で呼び出すことはできません。
なんとかして暗号化対象文字列をPG_FUNCTION_ARGS形式に変換する必要があるのですが、、
仕方なく、PostgreSQLのソースコードに潜ると・・・
こんなものがありました。
/************************/
Datum DirectFunctionCall3(関数ポインタ, Datum, Datum, Datum);
/************************/
Call3の部分は、渡す引数の数に応じて1~5まであります。
これを使えば、引数がPG_FUNCTION_ARGSで定義されている関数を呼び出すことができます。
3.メモリリーク対策
PostgreSQLのメモリ確保は、pallocを使用します。
これを使うと、1回のクエリ(トランザクション)終了時に使用していたメモリを解放してくれるので
基本的にメモリリークはありません。
ただし、戻り値以外の変数領域確保にpallocを使った場合は、ちゃんとpfreeで解放する必要があり ます。
次回は、作成したC言語関数を登録する際にハマったことを書く予定です。