前回の投稿で、テーブルの作成やオープン操作を解説しました。
今回は、一歩進んでテーブルに登録されているレコードのアクセス方法を紹介します。
レコードを一意に表す値がレコードIDで、これを取得できれば、
カラムに格納されている特定のデータを参照することが出来ます。
主キー値によるレコードID取得
grn_table_get() 関数を使います。
assert(grn_table_get(ctx, table, "test_record", strlen("test_record")) == record_id);
ちなみに、キー値がテキスト型以外の場合は char ポインタ型にキャストしましょう。
逆に、レコードIDから主キー値を取得したいときは grn_table_get_key() 関数を使います。
char keybuf[16];
int keylen = grn_table_get_key(ctx, table, record_id, keybuf, 16);
assert(keylen == strlen("test_record"));
assert(strncmp("test_record", keybuf, keylen) == 0);
grn_table_get_key() 関数ですが、
指定された ID のレコードが見つからない場合は 0 を返します。
レコードが見つかった場合は、パラメータに指定されたバッファに主キー値をコピーして、
主キー値の長さを返却値として返します。(コピーした長さではありません。)
文字列の末尾に NULL を追加するような処理は行いませんので、
返却される文字列長を使って適宜処理してください。
こちらも同様に、キー値がテキスト型以外の場合は char ポインタ型にキャストして受け取りましょう。
テーブルカーソルによる巡回参照
特定のキー値やレコードIDを取得せずに、テーブルに含まれるレコードをなめたい場合には、
テーブルカーソルを使うことで実現可能です。
テーブルカーソルは、特定条件のレコードを特定の順番で参照できる機能です。
ちなみに、テーブルに存在するレコードは ID がすべて連番で揃っているという訳ではないので、
grn_table_size() で存在するレコードの総数を取得して、
レコードIDを 1 から順番になめるというアプローチは、
正しい結果が保障されませんのでご注意下さい。
####テーブルカーソルのオープン
grn_table_cursor *table_cursor = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1,
GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING);
カーソルのオープンには grn_table_cursor_open() 関数を使います。
grn_table_cursor_open() 関数にはパラメータが複数ありますが、
今回の投稿では単純な巡回で必要になるものに絞って説明します。
GRN_API grn_table_cursor *grn_table_cursor_open(grn_ctx *ctx, grn_obj *table,
const void *min, unsigned int min_size,
const void *max, unsigned int max_size,
int offset, int limit, int flags);
min, min_size, max, max_size パラメータは、単純に巡回するだけであれば不要なので NULL や 0 を指定します。
offset パラメータに、カーソルの開始位置を指定します。
limit パラメータに、レコードの最大取得数を指定します。取得数の制限が不要であれば -1 を指定します。
flags パラメータに、GRN_CURSOR_* をフラグ指定して取り出すレコードを制限します。特に指定がなければ 0 でも構いません。フラグによってはサポートされるテーブルが限定されます。
- GRN_CURSOR_BY_ID: レコードIDでソートして取り出す
- GRN_CURSOR_BY_KEY: 主キー値でソートして取り出す(パトリシアトライ、ダブル配列トライでサポート)
- GRN_CURSOR_ASCENDING: 昇順で取り出す
- GRN_CURSOR_DESCENDING: 降順で取り出す
####テーブルカーソルを進める
assert(grn_table_cursor_next(ctx, table_cursor) == record_id);
// レコードの巡回が完了した
assert(grn_table_cursor_next(ctx, table_cursor) == GRN_ID_NIL);
grn_table_cursor_next() 関数を使ってカーソルを次の位置に進めます。
そして、同時に次の位置のレコードIDを取得します。
ただし、巡回が完了している場合には GRN_ID_NIL が返されます。
注意点として、カーソルをオープン直後は現在位置は何も指しておりません。
現在位置を一つ目のレコードに進めるには、
grn_table_cursor_next() 関数を一度呼び出す必要があります。
grn_table_cursor_get_key() などの現在位置を参照する関数使う場合には、
気を付けましょう。
####テーブルカーソルのクローズ
assert(grn_table_cursor_close(ctx, table_cursor) == GRN_SUCCESS);
grn_table_cursor_close() 関数を使います。
必ずしも巡回が完了している必要はありません。
後書き
以上です。
紹介した機能を利用したプログラムのソースコードを Gist にて公開しております。
投稿内で掲載しているサンプルコードは、このプログラムから切り出したものです。
掲載している情報に関しましては、十分な検証を行っておりますが、
もし誤りがございましたら、コメントにてご指摘ください。