/* Copyright(C) 2004 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SENNA_H #define SENNA_H #ifdef __cplusplus extern "C" { #endif typedef unsigned sen_id; #define SEN_ID_NIL 0 #define SEN_ID_MAX 0x3fffffff typedef enum { sen_success = 0, sen_memory_exhausted, sen_invalid_format, sen_file_operation_error, sen_invalid_argument, sen_other_error, sen_external_error, sen_internal_error, sen_abnormal_error, sen_end_of_data } sen_rc; typedef enum { sen_enc_default = 0, sen_enc_none, sen_enc_euc_jp, sen_enc_utf8, sen_enc_sjis, sen_enc_latin1, sen_enc_koi8r } sen_encoding; typedef enum { sen_sel_or = 0, sen_sel_and, sen_sel_but, sen_sel_adjust } sen_sel_operator; typedef enum { sen_log_none = 0, sen_log_emerg, sen_log_alert, sen_log_crit, sen_log_error, sen_log_warning, sen_log_notice, sen_log_info, sen_log_debug, sen_log_dump } sen_log_level; typedef struct _sen_ctx sen_ctx; typedef struct _sen_ctx_info sen_ctx_info; typedef struct _sen_snip sen_snip; typedef struct _sen_query sen_query; typedef struct _sen_logger_info sen_logger_info; typedef struct _sen_snip_mapping sen_snip_mapping; typedef struct _sen_obj sen_obj; typedef struct _sen_obj_header sen_obj_header; typedef struct _sen_proc_ctx sen_proc_ctx; #define SEN_CTX_MSGSIZE 128 struct _sen_ctx { sen_rc rc; int flags; sen_encoding encoding; unsigned char ntrace; unsigned char errlvl; unsigned char stat; unsigned int seqno; unsigned int subno; unsigned int seqno2; unsigned int errline; sen_ctx *prev; sen_ctx *next; const char *errfile; const char *errfunc; struct _sen_ctx_impl *impl; void *trace[16]; char errbuf[SEN_CTX_MSGSIZE]; }; #define SEN_CTX_INITIALIZER \ { sen_success, 0, sen_enc_default, 0, sen_log_notice,\ SEN_CTX_FIN, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } #define SEN_CTX_CLOSED(ctx) ((ctx)->stat == SEN_CTX_FIN) struct _sen_ctx_info { int fd; unsigned int com_status; unsigned int com_info; sen_obj *outbuf; unsigned char stat; }; struct _sen_snip_mapping { void *dummy; }; #define SEN_LOG_TIME 1 #define SEN_LOG_TITLE 2 #define SEN_LOG_MESSAGE 4 #define SEN_LOG_LOCATION 8 struct _sen_logger_info { sen_log_level max_level; int flags; void (*func)(int, const char *, const char *, const char *, const char *, void *); void *func_arg; }; typedef int (*query_term_callback)(const char *, unsigned int, void *); /******** DB API ********/ typedef unsigned int sen_obj_flags; /* obj_flags */ #define SEN_OBJ_TABLE_TYPE_MASK (0x07L) #define SEN_OBJ_TABLE_HASH_KEY (0x00L) #define SEN_OBJ_TABLE_PAT_KEY (0x01L) #define SEN_OBJ_TABLE_NO_KEY (0x03L) #define SEN_OBJ_TABLE_ALIAS (0x04L) #define SEN_OBJ_KEY_MASK (0x07L<<3) #define SEN_OBJ_KEY_UINT (0x00L<<3) #define SEN_OBJ_KEY_INT (0x01L<<3) #define SEN_OBJ_KEY_FLOAT (0x02L<<3) #define SEN_OBJ_TOKEN_MASK (0x07L<<3) #define SEN_OBJ_TOKEN_MECAB (0x00L<<3) #define SEN_OBJ_TOKEN_NGRAM (0x01L<<3) #define SEN_OBJ_TOKEN_DELIMITED (0x02L<<3) #define SEN_OBJ_TOKEN_USER_DEFINED (0x07L<<3) #define SEN_OBJ_KEY_WITH_SIS (1L<<6) #define SEN_OBJ_KEY_NORMALIZE (1L<<7) #define SEN_OBJ_KEY_SPLIT_ALPHA (1L<<8) #define SEN_OBJ_KEY_SPLIT_DIGIT (1L<<9) #define SEN_OBJ_KEY_SPLIT_SYMBOL (1L<<10) #define SEN_OBJ_COLUMN_TYPE_MASK (0x07L) #define SEN_OBJ_COLUMN_SCALAR (0x00L) #define SEN_OBJ_COLUMN_ARRAY (0x01L) #define SEN_OBJ_COLUMN_VERSES (0x02L) #define SEN_OBJ_COLUMN_POSTINGS (0x03L) #define SEN_OBJ_COLUMN_INDEX (0x04L) #define SEN_OBJ_COMPRESS_MASK (0x07L<<4) #define SEN_OBJ_COMPRESS_NONE (0x00L<<4) #define SEN_OBJ_COMPRESS_ZLIB (0x01L<<4) #define SEN_OBJ_COMPRESS_LZO (0x02L<<4) #define SEN_OBJ_WITH_SECTION (0L<<7) #define SEN_OBJ_NO_SECTION (1L<<7) #define SEN_OBJ_WITH_SCORE (0L<<8) #define SEN_OBJ_NO_SCORE (1L<<8) #define SEN_OBJ_WITH_POSITION (0L<<9) #define SEN_OBJ_NO_POSITION (1L<<9) #define SEN_OBJ_UNIT_MASK (0x0fL<<8) #define SEN_OBJ_UNIT_DOCUMENT_NONE (0x00L<<8) #define SEN_OBJ_UNIT_DOCUMENT_SECTION (0x01L<<8) #define SEN_OBJ_UNIT_DOCUMENT_POSITION (0x02L<<8) #define SEN_OBJ_UNIT_SECTION_NONE (0x03L<<8) #define SEN_OBJ_UNIT_SECTION_POSITION (0x04L<<8) #define SEN_OBJ_UNIT_POSITION_NONE (0x05L<<8) #define SEN_OBJ_UNIT_USERDEF_DOCUMENT (0x06L<<8) #define SEN_OBJ_UNIT_USERDEF_SECTION (0x07L<<8) #define SEN_OBJ_UNIT_USERDEF_POSITION (0x08L<<8) #define SEN_OBJ_NO_SUBREC (0L<<13) #define SEN_OBJ_WITH_SUBREC (1L<<13) #define SEN_OBJ_COLUMN_INDEX_SCALAR (1L<<14) #define SEN_OBJ_KEY_VAR_SIZE (1L<<14) #define SEN_OBJ_DO_DEEP_COPY (0L<<14) #define SEN_OBJ_DO_SHALLOW_COPY (1L<<14) #define SEN_OBJ_TEMPORARY (0L<<15) #define SEN_OBJ_PERSISTENT (1L<<15) /* obj types */ #define SEN_VOID (0x00) #define SEN_BULK (0x01) #define SEN_VECTOR (0x02) #define SEN_VERSES (0x03) #define SEN_QUERY (0x08) #define SEN_ACCESSOR (0x09) #define SEN_SNIP (0x0a) #define SEN_PATSNIP (0x0b) #define SEN_CURSOR_TABLE_HASH_KEY (0x10) #define SEN_CURSOR_TABLE_PAT_KEY (0x11) #define SEN_CURSOR_TABLE_NO_KEY (0x13) #define SEN_CURSOR_COLUMN_INDEX (0x18) #define SEN_TYPE (0x20) #define SEN_PROC (0x21) #define SEN_TABLE_HASH_KEY (0x30) #define SEN_TABLE_PAT_KEY (0x31) #define SEN_TABLE_NO_KEY (0x33) #define SEN_SPACE (0x37) #define SEN_COLUMN_FIX_SIZE (0x40) #define SEN_COLUMN_VAR_SIZE (0x41) #define SEN_COLUMN_INDEX (0x48) typedef struct _sen_verse sen_verse; struct _sen_verse { char *str; unsigned int str_len; unsigned int weight; sen_id domain; }; struct _sen_obj_header { unsigned char type; unsigned char impl_flags; sen_obj_flags flags; sen_id domain; }; struct _sen_obj { sen_obj_header header; union { struct { char *head; char *curr; char *tail; } b; struct { sen_obj *src; sen_verse *verses; int n_verses; } v; } u; }; #define SEN_OBJ_INIT(obj,obj_type,obj_flags) {\ (obj)->header.type = (obj_type);\ (obj)->header.flags = (obj_flags);\ (obj)->header.impl_flags = 0;\ (obj)->header.domain = SEN_ID_NIL;\ (obj)->u.b.head = NULL;\ (obj)->u.b.curr = NULL;\ (obj)->u.b.tail = NULL;\ } #define SEN_OBJ_FIN(ctx,obj) (sen_obj_close((ctx), (obj))) /** * sen_ctx_init: * @ctx: 初期化するctx構造体へのポインタを指定します。 * @flags: 初期化するctxのオプションを指定します。 * SEN_CTX_NO_DBを指定すると、エラーハンドリングのみが行えるctxを初期化します。 * SEN_CTX_USE_DBを指定すると、全てのDBAPIが使用できるctxを初期化します。 * SEN_CTX_USE_QLを指定すると、senna qlインタプリタを実行可能なctxを初期化します。 * SEN_CTX_USE_QL|SEN_CTX_BATCH_MODEを指定すると、batchmodeでインタプリタを初期化します。 * @encoding: 初期化するctxでデフォルトとなるencoding。 * * ctxを初期化します。 **/ #define SEN_CTX_NO_DB (0x00) #define SEN_CTX_USE_DB (0x01) #define SEN_CTX_USE_QL (0x03) #define SEN_CTX_BATCH_MODE (0x04) sen_rc sen_ctx_init(sen_ctx *ctx, int flags, sen_encoding encoding); /** * sen_ctx_fin: * @ctx: 終了化するctx構造体へのポインタを指定します。 * * ctxの管理するメモリを解放し、使用を終了します。 **/ sen_rc sen_ctx_fin(sen_ctx *ctx); /** * sen_space_create: * @path: 作成するspaceを格納するファイルパス。NULLならtemporary spaceとなる。 * @encoding: 作成するspaceでデフォルトとなるencoding。 * * 新たなspaceを作成する。 **/ sen_obj *sen_space_create(sen_ctx *ctx, const char *path, sen_encoding encoding); /** * sen_space_open: * @path: 開こうとするspaceを格納するファイルパス。 * * 既存のspaceを開く。 **/ sen_obj *sen_space_open(sen_ctx *ctx, const char *path); /** * sen_ctx_use: * @space: ctxが使用するspaceを指定します。 * * ctxが操作対象とするspaceを指定します。NULLを指定した場合は、 * spaceを操作しない状態(init直後の状態)になります。 **/ sen_rc sen_ctx_use(sen_ctx *ctx, sen_obj *space); /** * sen_ctx_space: * * ctxが現在操作対象としているspaceを返します。 * spaceを使用していない場合はNULLを返します。 **/ sen_obj *sen_ctx_space(sen_ctx *ctx); /** * sen_ctx_lookup: * @name: 検索しようとするオブジェクトの名前。 * @name_size: @nameのbyte長。 * * ctxが使用するspaceからnameに対応するオブジェクトを検索して返す。 * nameに一致するオブジェクトが存在しなければNULLを返す。 **/ sen_obj *sen_ctx_lookup(sen_ctx *ctx, const char *name, unsigned name_size); /** * sen_ctx_get: * @id: 検索しようとするオブジェクトのid。 * * ctx、またはctxが使用するspaceからidに対応するオブジェクトを検索して返す。 * idに一致するオブジェクトが存在しなければNULLを返す。 **/ sen_obj *sen_ctx_get(sen_ctx *ctx, sen_id id); extern sen_obj *sen_type_any; /* 任意のtableのrecordを格納できる型 */ /** * sen_type_create: * @name: 作成するtypeの名前。 * @flags: SEN_OBJ_KEY_VAR_SIZE, SEN_OBJ_KEY_FLOAT, SEN_OBJ_KEY_INT, SEN_OBJ_KEY_UINT * のいずれかを指定 * @size: SEN_OBJ_KEY_VAR_SIZEの場合は最大長、 * それ以外の場合は長さを指定(単位:byte) * * nameに対応する新たなtype(型)をspaceに定義する。 * (todo: 複合keyを定義するための構造) **/ sen_obj *sen_type_create(sen_ctx *ctx, const char *name, unsigned name_size, sen_obj_flags flags, unsigned int size); /** * sen_proc_create: * @name: 作成するprocの名前。 * @type: procの種類。 * @init: 初期化関数のポインタ * @next: 実処理関数のポインタ * @fin: 終了関数のポインタ * * nameに対応する新たなproc(手続き)をctxが使用するspaceに定義する。 **/ typedef union { int int_value; sen_id id; void *ptr; } sen_proc_data; typedef sen_rc sen_proc_func(sen_ctx *ctx, sen_proc_ctx *pctx, int argc, sen_proc_data *argv); typedef sen_rc sen_proc_init_func(sen_ctx *ctx, const char *path); typedef enum { SEN_PROC_HOOK, SEN_PROC_RECALC, SEN_PROC_SCORE, SEN_PROC_COMPARE, SEN_PROC_GROUP } sen_proc_type; sen_obj *sen_proc_create(sen_ctx *ctx, const char *name, unsigned name_size, const char *path, sen_proc_type type, sen_proc_func *init, sen_proc_func *next, sen_proc_func *fin); /*------------------------------------------------------------- * table操作のための関数 */ #define SEN_TABLE_MAX_KEY_SIZE 4096 /** * sen_table_create: * @name: 作成するtableの名前。NULLなら無名tableとなる。 * @path: 作成するtableのファイルパス。 * flagsにSEN_OBJ_PERSISTENTが指定されている場合のみ有効。 * NULLなら自動的にファイルパスが付与される。 * @flags: SEN_OBJ_PERSISTENTを指定すると永続tableとなる。 * SEN_OBJ_TABLE_PAT_KEY,SEN_OBJ_TABLE_HASH_KEY,SEN_OBJ_TABLE_NO_KEY * のいずれかを指定する。 * SEN_OBJ_KEY_NORMALIZEを指定すると正規化された文字列がkeyとなる。 * SEN_OBJ_KEY_WITH_SISを指定するとkey文字列の全suffixが自動的に登録される。 * SEN_OBJ_TOKEN_MECAB,SEN_OBJ_TOKEN_NGRAM,SEN_OBJ_TOKEN_DELIMITEDは、 * 作成するtableを語彙表として用いる場合のtokenizeの方法を指定する。 * SEN_OBJ_TOKEN_NGRAMを指定した場合に限り、 * SEN_OBJ_KEY_SPLIT_ALPHA,SEN_OBJ_KEY_SPLIT_DIGIT,SEN_OBJ_KEY_SPLIT_SYMBOL * を指定して、文字列をN-GRAMに区切る際の方針を指定できる。 * @key_type: keyの型を指定する。SEN_OBJ_TABLE_NO_KEYが指定された場合は無効。 * 既存のtypeあるいはtableを指定できる。 * key_typeにtable Aを指定してtable Bを作成した場合、Bは必ずAのサブセットとなる。 * @value_size: keyに対応する値を格納する領域のサイズ(byte長)。tableはcolumnとは別に、 * keyに対応する値を格納する領域を一つだけ持つことができる。 * @encoding: 作成するtableでデフォルトとなるencoding。 * * nameに対応する新たなtableをctxが使用するspaceに定義する。 **/ sen_obj *sen_table_create(sen_ctx *ctx, const char *name, unsigned name_size, const char *path, sen_obj_flags flags, sen_obj *key_type, unsigned value_size, sen_encoding encoding); /** * sen_table_open: * @name: 開こうとするtableの名前。NULLなら無名tableとなる。 * @path: 開こうとするtableのファイルパス。 * * ctxが使用するspaceの中でnameに対応付けて既存のtableを開く。 **/ sen_obj *sen_table_open(sen_ctx *ctx, const char *name, unsigned name_size, const char *path); typedef unsigned char sen_search_flags; #define SEN_SEARCH_EXACT 0 #define SEN_SEARCH_LCP 1 #define SEN_SEARCH_SUFFIX 2 #define SEN_SEARCH_PREFIX 3 #define SEN_SEARCH_PARTIAL 4 #define SEN_SEARCH_NEAR 5 #define SEN_SEARCH_NEAR2 6 #define SEN_SEARCH_SIMILAR 7 #define SEN_SEARCH_TERM_EXTRACT 8 #define SEN_TABLE_ADD (1L<<6) #define SEN_TABLE_ADDED (1L<<7) /** * sen_table_lookup: * @table: 対象table * @key: 検索key * @flags: SEN_SEARCH_EXACTが指定された場合はkeyに完全一致するrecordを検索する。 * SEN_SEARCH_LCPが指定された場合はlongest common prefix searchを行う。 * 該当するkeyが存在せず、かつSEN_TABLE_ADDが指定された場合は、 * tableに該当レコードを追加する。(追加しない場合はSEN_ID_NILを返す) * SEN_TABLE_ADDが指定され、かつ実際にレコードが追加された場合は、 * flagsのSEN_TABLE_ADDED bitが立てられる。 * flagsにNULLが指定された場合は、SEN_SEARCH_EXACTのみが指定されたものと見なされる。 * * tableからkeyに対応するrecordを検索し、対応するIDを返す。 **/ sen_id sen_table_lookup(sen_ctx *ctx, sen_obj *table, const void *key, unsigned key_size, sen_search_flags *flags); /** * sen_table_add: * @table: 対象table * * 新しいレコードを追加し、そのIDを返す。 * SEN_OBJ_TABLE_NO_KEYが指定されたtableでのみ有効。 **/ sen_id sen_table_add(sen_ctx *ctx, sen_obj *table); /** * sen_table_get_key: * @table: 対象table * @id: 対象レコードのID * @keybuf: keyを格納するバッファ(呼出側で準備する) * @buf_size: keybufのサイズ(byte長) * * tableのIDに対応するレコードのkeyを取得する。対応するレコードが存在する場合はkey長を返す。 * 見つからない場合は0を返す。 * 対応するキーの検索に成功し、またbuf_sizeの長さがkey長以上であった場合は、 * keybufに該当するkeyをコピーする。 * **/ int sen_table_get_key(sen_ctx *ctx, sen_obj *table, sen_id id, void *keybuf, int buf_size); /** * sen_table_delete: * @table: 対象table * @key: 検索key * @key_size: 検索keyのサイズ * * tableのkeyに対応するレコードを削除する。 * 対応するレコードが存在しない場合はsen_invalid_argumentを返す。 **/ sen_rc sen_table_delete(sen_ctx *ctx, sen_obj *table, const void *key, unsigned key_size); /** * sen_table_delete_by_id: * @table: 対象table * @id: レコードID * * tableのkeyに対応するレコードを削除する。 * 対応するレコードが存在しない場合はsen_invalid_argumentを返す。 **/ sen_rc sen_table_delete_by_id(sen_ctx *ctx, sen_obj *table, sen_id id); /** * sen_table_truncate: * @table: 対象table * * tableの全レコードを一括して削除する。 **/ sen_rc sen_table_truncate(sen_ctx *ctx, sen_obj *table); typedef sen_obj sen_table_cursor; #define SEN_CURSOR_DESCENDING 0 #define SEN_CURSOR_ASCENDING 1 #define SEN_CURSOR_GE 0 #define SEN_CURSOR_GT 2 #define SEN_CURSOR_LE 0 #define SEN_CURSOR_LT 4 /** * sen_table_cursor_open: * @table: 対象table * @min: keyの下限 (NULLは下限なしと見なす) * @max: keyの上限 (NULLは上限なしと見なす) * @flags: SEN_CURSOR_ASCENDINGを指定すると昇順にkeyを取り出す。(指定しなければ降順) * SEN_CURSOR_GTを指定するとminに一致したkeyをcursorの範囲に含まない。 * SEN_CURSOR_LTを指定するとmaxに一致したkeyをcursorの範囲に含まない。 * * tableに登録されているレコードを順番に取り出すためのカーソルを生成して返す。 * SEN_OBJ_TABLE_PAT_KEYを指定したtableではkey順に、 * SEN_OBJ_TABLE_HASH_KEYを指定したtableではid順にレコードを取り出します。 **/ sen_table_cursor *sen_table_cursor_open(sen_ctx *ctx, sen_obj *table, const void *min, unsigned min_size, const void *max, unsigned max_size, int flags); /** * sen_table_cursor_close: * @tc: 対象cursor * * sen_table_cursor_openで生成したcursorを解放する。 **/ sen_rc sen_table_cursor_close(sen_ctx *ctx, sen_table_cursor *tc); /** * sen_table_cursor_next: * @tc: 対象cursor * * cursorのカレントレコードを一件進めてそのIDを返す。 * cursorの対象範囲の末尾に達するとSEN_ID_NILを返す。 **/ sen_id sen_table_cursor_next(sen_ctx *ctx, sen_table_cursor *tc); /** * sen_table_cursor_get_key: * @tc: 対象cursor * @key: カレントレコードのkeyへのポインタがセットされる。 * cursorのカレントレコードのkeyを@keyにセットし、その長さを返す。 **/ int sen_table_cursor_get_key(sen_ctx *ctx, sen_table_cursor *tc, void **key); /** * sen_table_cursor_get_value: * @tc: 対象cursor * @value: カレントレコードのvalueへのポインタがセットされる。 * cursorのカレントレコードのvalueを@valueにセットし、その長さを返す。 **/ int sen_table_cursor_get_value(sen_ctx *ctx, sen_table_cursor *tc, void **value); /** * sen_table_cursor_set_value: * @tc: 対象cursor * @value: 新しいvalueの値。 * @flags: sen_obj_set_valueのflagsと同様の値を指定できる。 * * cursorのカレントレコードのvalueを引数の内容に置き換える。 * cursorのカレントレコードが存在しない場合はsen_invalid_argumentを返す。 **/ sen_rc sen_table_cursor_set_value(sen_ctx *ctx, sen_table_cursor *tc, void *value, int flags); /** * sen_table_cursor_delete: * @tc: 対象cursor * * cursorのカレントレコードを削除する。 * cursorのカレントレコードが存在しない場合はsen_invalid_argumentを返す。 **/ sen_rc sen_table_cursor_delete(sen_ctx *ctx, sen_table_cursor *tc); #define SEN_TABLE_EACH(ctx,table,head,tail,id,key,key_size,value,block) { \ (ctx)->errlvl = SEN_OK;\ (ctx)->rc = sen_success;\ if ((ctx)->seqno & 1) {\ (ctx)->subno++;\ } else {\ (ctx)->seqno++;\ }\ if (table) {\ switch ((table)->header.type) {\ case SEN_TABLE_PAT_KEY :\ SEN_PAT_EACH((sen_pat *)(table), (id), (key), (key_size), (value), block);\ break;\ case SEN_TABLE_HASH_KEY :\ SEN_HASH_EACH((sen_hash *)(table), (id), (key), (key_size), (value), block);\ break;\ case SEN_TABLE_NO_KEY :\ SEN_ARRAY_EACH((sen_array *)(table), (head), (tail), (id), (value), block);\ break;\ }\ }\ if (ctx->subno) {\ ctx->subno--;\ } else {\ ctx->seqno++;\ }\ } /** * sen_table_sort: * @table: 対象table * @limit: resに格納するレコードの上限 * @result: 結果を格納するtable * @keys: ソートキー配列へのポインタ * @n_keys: ソートキー配列のサイズ * * table内のレコードをソートし、上位limit個の要素をresultに格納する。 * keysには、tableのcolumn,accessor,procのいずれかが指定できる。 **/ typedef struct _sen_table_sort_key sen_table_sort_key; typedef unsigned char sen_table_sort_flags; #define SEN_TABLE_SORT_DESC 0 #define SEN_TABLE_SORT_ASC (1L<<0) struct _sen_table_sort_key { sen_obj *key; sen_table_sort_flags flags; int offset; }; int sen_table_sort(sen_ctx *ctx, sen_obj *table, int limit, sen_obj *result, sen_table_sort_key *keys, int n_keys); /** * sen_table_group: * @table: 対象table * @keys: group化キー構造体の配列へのポインタ * @n_keys: group化キー構造体の配列のサイズ * @results: group化の結果を格納する構造体の配列へのポインタ * @n_results:group化の結果を格納する構造体の配列のサイズ * * tableのレコードを特定の条件でグループ化する **/ typedef struct _sen_table_group_result sen_table_group_result; typedef unsigned int sen_table_group_flags; #define SEN_TABLE_GROUP_CALC_COUNT (1L<<3) #define SEN_TABLE_GROUP_CALC_MAX (1L<<4) #define SEN_TABLE_GROUP_CALC_MIN (1L<<5) #define SEN_TABLE_GROUP_CALC_SUM (1L<<6) #define SEN_TABLE_GROUP_CALC_AVG (1L<<7) struct _sen_table_group_result { sen_obj *table; unsigned char key_begin; unsigned char key_end; int limit; sen_table_group_flags flags; sen_sel_operator op; }; sen_rc sen_table_group(sen_ctx *ctx, sen_obj *table, sen_table_sort_key *keys, int n_keys, sen_table_group_result *results, int n_results); /** * sen_table_setoperation: * @table1: 対象table1 * @table2: 対象table2 * @res: 結果を格納するtable * * table1とtable2をopの指定に従って集合演算した結果をresに格納する。 * resにtable1あるいはtable2そのものを指定した場合を除けば、table1, table2は破壊されない。 **/ sen_rc sen_table_setoperation(sen_ctx *ctx, sen_obj *table1, sen_obj *table2, sen_obj *res, sen_sel_operator op); /** * sen_table_difference: * @table1: 対象table1 * @table2: 対象table2 * @res1: 結果を格納するtable * @res2: 結果を格納するtable * * table1とtable2から重複するレコードを取り除いた結果をそれぞれres1, res2に格納する。 **/ sen_rc sen_table_difference(sen_ctx *ctx, sen_obj *table1, sen_obj *table2, sen_obj *res1, sen_obj *res2); /** * sen_table_column: * @table: 対象table * @name: カラム名 * * nameに対応するtableのカラムを返す。対応するカラムが存在しなければNULLを返す。 **/ sen_obj *sen_table_column(sen_ctx *ctx, sen_obj *table, const char *name, unsigned name_size); /** * sen_table_size: * @table: 対象table * * tableに登録されているレコードの件数を返す。 **/ unsigned int sen_table_size(sen_ctx *ctx, sen_obj *table); /*------------------------------------------------------------- * column操作のための関数 */ /** * sen_column_create: * @table: 対象table * @name: カラム名 * @path: カラムを格納するファイルパス。 * flagsにSEN_OBJ_PERSISTENTが指定されている場合のみ有効。 * NULLなら自動的にファイルパスが付与される。 * @flags: SEN_OBJ_PERSISTENTを指定すると永続columnとなる。 * SEN_OBJ_COLUMN_INDEXを指定すると転置インデックスとなる。 * @type: カラム値の型。定義済みのtypeあるいはtableを指定できる。 * * tableに新たなカラムを定義する。nameは省略できない。 * 一つのtableに同一のnameのcolumnを複数定義することはできない。 **/ sen_obj *sen_column_create(sen_ctx *ctx, sen_obj *table, const char *name, unsigned name_size, const char *path, sen_obj_flags flags, sen_obj *type); /** * sen_column_open: * @table: 対象table * @name: カラム名 * @path: カラムを格納するファイルパス。 * @type: カラム値の型。 * * 既存の永続的なcolumnを、tableのnameに対応するcolumnとして開く **/ sen_obj *sen_column_open(sen_ctx *ctx, sen_obj *table, const char *name, unsigned name_size, const char *path, sen_obj *type); /** * sen_column_index_update * @column: 対象column * @id: 対象レコードのID * @section: 対象レコードのセクション番号 * @oldvalue: 更新前の値 * @newvalue: 更新後の値 * * oldvalue, newvalueの値から得られるキーに対応するcolumnの値の中の、 * id, sectionに対応するエントリを更新する。 * columnはSEN_OBJ_COLUMN_INDEX型のカラムでなければならない。 **/ sen_rc sen_column_index_update(sen_ctx *ctx, sen_obj *column, sen_id id, unsigned int section, sen_obj *oldvalue, sen_obj *newvalue); /** * sen_column_table: * @column: 対象column * * columnが属するtableを返す。 **/ sen_obj *sen_column_table(sen_ctx *ctx, sen_obj *column); /*------------------------------------------------------------- * space, table, columnの全てまたは幾つかで共通に使用できる関数 */ #define SEN_PROC_MAX_ARGS 256 typedef enum { SEN_INFO_ENCODING = 0, SEN_INFO_SOURCE, SEN_INFO_ELEMENT_SIZE, SEN_INFO_CURR_MAX, SEN_INFO_MAX_ELEMENT_SIZE, SEN_INFO_SEG_SIZE, SEN_INFO_CHUNK_SIZE, SEN_INFO_INITIAL_N_SEGMENTS, SEN_INFO_MAX_SECTION, SEN_INFO_HOOK_LOCAL_DATA, SEN_INFO_ELEMENT_A, SEN_INFO_ELEMENT_CHUNK, SEN_INFO_ELEMENT_CHUNK_SIZE, SEN_INFO_ELEMENT_BUFFER_FREE, SEN_INFO_ELEMENT_NTERMS, SEN_INFO_ELEMENT_NTERMS_VOID, SEN_INFO_ELEMENT_SIZE_IN_CHUNK, SEN_INFO_ELEMENT_POS_IN_CHUNK, SEN_INFO_ELEMENT_SIZE_IN_BUFFER, SEN_INFO_ELEMENT_POS_IN_BUFFER, SEN_INFO_ELEMENT_ESTIMATE_SIZE, SEN_INFO_NGRAM_UNIT_SIZE } sen_info_type; /** * sen_obj_get_info: * @obj: 対象obj * @type: 取得する情報の種類 * @valuebuf: 値を格納するバッファ(呼出側で準備) * * objのtypeに対応する情報をvaluebufに格納する。 **/ sen_obj *sen_obj_get_info(sen_ctx *ctx, sen_obj *obj, sen_info_type type, sen_obj *valuebuf); /** * sen_obj_set_info: * @obj: 対象obj * @type: 設定する情報の種類 * @value: 設定しようとする値 * * objのtypeに対応する情報をvalueの内容に更新する。 **/ sen_rc sen_obj_set_info(sen_ctx *ctx, sen_obj *obj, sen_info_type type, sen_obj *value); /** * sen_obj_get_element_info: * @obj: 対象obj * @id: 対象ID * @type: 取得する情報の種類 * @value: 値を格納するバッファ(呼出側で準備) * * objのidに対応するレコードの、typeに対応する情報をvaluebufに格納する。 * 呼出側ではtypeに応じて十分なサイズのバッファを確保しなければならない。 **/ sen_obj *sen_obj_get_element_info(sen_ctx *ctx, sen_obj *obj, sen_id id, sen_info_type type, sen_obj *value); /** * sen_obj_set_element_info: * @obj: 対象object * @id: 対象ID * @type: 設定する情報の種類 * @value: 設定しようとする値 * * objのidに対応するレコードのtypeに対応する情報をvalueの内容に更新する。 **/ sen_rc sen_obj_set_element_info(sen_ctx *ctx, sen_obj *obj, sen_id id, sen_info_type type, sen_obj *value); /** * sen_obj_get_value: * @obj: 対象object * @id: 対象レコードのID * @value: 値を格納するバッファ(呼出側で準備する) * * tableのIDに対応するレコードのvalueを取得する。 * 対応するレコードが存在する場合はvalue長を返す。見つからない場合は0を返す。 **/ sen_obj *sen_obj_get_value(sen_ctx *ctx, sen_obj *obj, sen_id id, sen_obj *value); /** * sen_obj_set_value: * @obj: 対象object * @id: 対象レコードのID * @value: 格納する値 * @flags: 以下の値を指定できる * SEN_OBJ_SET: レコードの値をvalueと置き換える。 * SEN_OBJ_INCR: レコードの値にvalueを加算する。 * SEN_OBJ_DECR: レコードの値にvalueを減算する。 * SEN_OBJ_APPEND: レコードの値の末尾にvalueを追加する。 * SEN_OBJ_PREPEND: レコードの値の先頭にvalueを追加する。 * SEN_OBJ_GET: 新しいレコードの値をvalueにセットする。 * SEN_OBJ_COMPARE: レコードの値とvalueが等しいか調べる。 * SEN_OBJ_LOCK: 当該レコードをロックする。SEN_OBJ_COMPAREと共に指定された場合は、 * レコードの値とvalueが等しい場合に限ってロックする。 * SEN_OBJ_UNLOCK: 当該レコードのロックを解除する。 * * objのIDに対応するレコードの値を更新する。 * 対応するレコードが存在しない場合はsen_invalid_argumentを返す。 **/ #define SEN_OBJ_SET_MASK (0x07L) #define SEN_OBJ_SET (0x01L) #define SEN_OBJ_INCR (0x02L) #define SEN_OBJ_DECR (0x03L) #define SEN_OBJ_APPEND (0x04L) #define SEN_OBJ_PREPEND (0x05L) #define SEN_OBJ_GET (1L<<4) #define SEN_OBJ_COMPARE (1L<<5) #define SEN_OBJ_LOCK (1L<<6) #define SEN_OBJ_UNLOCK (1L<<7) sen_rc sen_obj_set_value(sen_ctx *ctx, sen_obj *obj, sen_id id, sen_obj *value, int flags); /** * sen_obj_remove: * @path: objectに該当するファイルパス * * pathに該当するオブジェクトのファイル一式を削除する。 **/ sen_rc sen_obj_remove(sen_ctx *ctx, const char *path); /** * sen_obj_rename: * @old_path: 旧ファイルパス * @new_path: 新ファイルパス * * old_pathに該当するオブジェクトのファイル名をnew_pathに変更する。 **/ sen_rc sen_obj_rename(sen_ctx *ctx, const char *old_path, const char *new_path); /** * sen_obj_close: * @obj: 対象object * * objをメモリから解放する。objに属するobjectも再帰的にメモリから解放される。 **/ sen_rc sen_obj_close(sen_ctx *ctx, sen_obj *obj); /** * sen_obj_path: * @obj: 対象object * * objに対応するファイルパスを返す。一時objectならNULLを返す。 **/ const char *sen_obj_path(sen_ctx *ctx, sen_obj *obj); /** * sen_obj_name: * @obj: 対象object * @namebuf: nameを格納するバッファ(呼出側で準備する) * @buf_size: namebufのサイズ(byte長) * * objの名前を返す。無名objectなら0を返す。 * 名前付きのobjectであり、buf_sizeの長さがname長以上であった場合は、 * namebufに該当するnameをコピーする。 **/ int sen_obj_name(sen_ctx *ctx, sen_obj *obj, char *namebuf, int buf_size); /** * sen_obj_expire: * @obj: 対象object * * objの占有するメモリのうち、可能な領域をthresholdを指標として解放する。 **/ int sen_obj_expire(sen_ctx *ctx, sen_obj *obj, int threshold); /** * sen_obj_check: * @obj: 対象object * * objに対応するファイルの整合性を検査する。 **/ int sen_obj_check(sen_ctx *ctx, sen_obj *obj); /** * sen_obj_lock: * @obj: 対象object * * objをlockする。timeout(秒)経過してもlockを取得できない場合はsen_other_errorを返す。 **/ sen_rc sen_obj_lock(sen_ctx *ctx, sen_obj *obj, sen_id id, int timeout); /** * sen_obj_unlock: * @obj: 対象object * * objをunlockする。 **/ sen_rc sen_obj_unlock(sen_ctx *ctx, sen_obj *obj, sen_id id); /** * sen_obj_clear_lock: * @obj: 対象object * * 強制的にロックをクリアする。 **/ sen_rc sen_obj_clear_lock(sen_ctx *ctx, sen_obj *obj); /** * sen_obj_is_locked; * @obj: 対象object * * objが現在lockされていれば0以外の値を返す。 **/ unsigned int sen_obj_is_locked(sen_ctx *ctx, sen_obj *obj); /** * sen_obj_space: * @obj: 対象object * * objの属するspaceを返す。 **/ sen_obj *sen_obj_space(sen_ctx *ctx, sen_obj *obj); /** * sen_obj_search: * @obj: 検索対象のobject * @query: 検索クエリ * @res: 検索結果を格納するテーブル * @op: sen_sel_or, sen_sel_and, sen_sel_but, sen_sel_adjustのいずれかを指定する * @optargs: 詳細検索条件 * * objを対象としてqueryにマッチするレコードを検索し、 * opの指定に従ってresにレコードを追加あるいは削除する。 **/ typedef struct _sen_search_optarg sen_search_optarg; struct _sen_search_optarg { sen_search_flags flags; int similarity_threshold; int max_interval; int *weight_vector; int vector_size; sen_obj *proc; int max_size; }; sen_rc sen_obj_search(sen_ctx *ctx, sen_obj *obj, sen_obj *query, sen_obj *res, sen_sel_operator op, sen_search_optarg *optarg); sen_rc sen_verses_add(sen_ctx *ctx, sen_obj *verses, const char *str, unsigned int str_len, unsigned int weight, sen_id lang); /*------------------------------------------------------------- * hook操作のための関数 */ int sen_proc_call_next(sen_ctx *ctx, sen_obj *exec_info, sen_obj *in, sen_obj *out); void *sen_proc_get_ctx_local_data(sen_ctx *ctx, sen_obj *exec_info); void *sen_proc_get_hook_local_data(sen_ctx *ctx, sen_obj *exec_info); typedef enum { SEN_HOOK_SET = 0, SEN_HOOK_GET, SEN_HOOK_INSERT, SEN_HOOK_DELETE, SEN_HOOK_SELECT } sen_hook_entry; /** * sen_obj_add_hook: * @obj: 対象object * @entry: SEN_HOOK_GETは、objectの参照時に呼び出されるhookを定義する。 SEN_HOOK_SETは、objectの更新時に呼び出されるhookを定義する。 SEN_HOOK_SELECTは、検索処理の実行中に適時呼び出され、 処理の実行状況を調べたり、実行の中断を指示することができる。 * @offset: hookの実行順位。offsetに対応するhookの直前に新たなhookを挿入する。 0を指定した場合は先頭に挿入される。-1を指定した場合は末尾に挿入される。 objectに複数のhookが定義されている場合は順位の順に呼び出される。 * @proc: 手続き * @data: hook固有情報 * * objに対してhookを追加する。 **/ sen_rc sen_obj_add_hook(sen_ctx *ctx, sen_obj *obj, sen_hook_entry entry, int offset, sen_obj *proc, sen_obj *data); /** * sen_obj_get_hook: * @obj: 対象object * @entry: hookタイプ * @offset: 実行順位 * @data: hook固有情報格納バッファ * * objに定義されているhookの手続き(proc)を返す。hook固有情報が定義されている場合は、 * その内容をdataにコピーして返す。 **/ sen_obj *sen_obj_get_hook(sen_ctx *ctx, sen_obj *obj, sen_hook_entry entry, int offset, sen_obj *data); /** * sen_obj_delete_hook: * @obj: 対象object * @entry: hookタイプ * @offset: 実行順位 * * objに定義されているhookを削除する。 **/ sen_rc sen_obj_delete_hook(sen_ctx *ctx, sen_obj *obj, sen_hook_entry entry, int offset); sen_obj *sen_obj_open(sen_ctx *ctx, unsigned char type, sen_obj_flags flags); sen_obj *sen_obj_graft(sen_ctx *ctx, sen_obj *obj); /******** query language API ********/ typedef sen_obj sen_db; sen_db *sen_db_create(const char *path, int flags, sen_encoding encoding); sen_db *sen_db_open(const char *path); sen_rc sen_db_close(sen_db *s); #define SEN_CTX_MORE 0x01 #define SEN_CTX_TAIL 0x02 #define SEN_CTX_HEAD 0x04 #define SEN_CTX_QUIET 0x08 #define SEN_CTX_QUIT 0x10 #define SEN_CTX_FIN 0xff sen_ctx *sen_ctx_open(sen_db *db, int flags); sen_ctx *sen_ctx_connect(const char *host, int port, int flags); sen_rc sen_ctx_load(sen_ctx *c, const char *path); sen_rc sen_ctx_send(sen_ctx *c, char *str, unsigned int str_len, int flags); sen_rc sen_ctx_recv(sen_ctx *c, char **str, unsigned int *str_len, int *flags); sen_rc sen_ctx_close(sen_ctx *c); sen_rc sen_ctx_info_get(sen_ctx *c, sen_ctx_info *info); /******** basic API ********/ sen_rc sen_init(void); sen_rc sen_fin(void); sen_rc sen_info(char **version, char **configure_options, char **config_path, sen_encoding *default_encoding, unsigned int *initial_n_segments, unsigned int *partial_match_threshold); /******** advanced API ********/ #ifndef SEN_QUERY_AND #define SEN_QUERY_AND '+' #endif /* SEN_QUERY_AND */ #ifndef SEN_QUERY_BUT #define SEN_QUERY_BUT '-' #endif /* SEN_QUERY_BUT */ #ifndef SEN_QUERY_ADJ_INC #define SEN_QUERY_ADJ_INC '>' #endif /* SEN_QUERY_ADJ_POS2 */ #ifndef SEN_QUERY_ADJ_DEC #define SEN_QUERY_ADJ_DEC '<' #endif /* SEN_QUERY_ADJ_POS1 */ #ifndef SEN_QUERY_ADJ_NEG #define SEN_QUERY_ADJ_NEG '~' #endif /* SEN_QUERY_ADJ_NEG */ #ifndef SEN_QUERY_PREFIX #define SEN_QUERY_PREFIX '*' #endif /* SEN_QUERY_PREFIX */ #ifndef SEN_QUERY_PARENL #define SEN_QUERY_PARENL '(' #endif /* SEN_QUERY_PARENL */ #ifndef SEN_QUERY_PARENR #define SEN_QUERY_PARENR ')' #endif /* SEN_QUERY_PARENR */ #ifndef SEN_QUERY_QUOTEL #define SEN_QUERY_QUOTEL '"' #endif /* SEN_QUERY_QUOTEL */ #ifndef SEN_QUERY_QUOTER #define SEN_QUERY_QUOTER '"' #endif /* SEN_QUERY_QUOTER */ #ifndef SEN_QUERY_ESCAPE #define SEN_QUERY_ESCAPE '\\' #endif /* SEN_QUERY_ESCAPE */ sen_query *sen_query_open(const char *str, unsigned int str_len, sen_sel_operator default_op, int max_exprs, sen_encoding encoding); unsigned int sen_query_rest(sen_query *q, const char ** const rest); sen_rc sen_query_close(sen_query *q); void sen_query_term(sen_query *q, query_term_callback func, void *func_arg); sen_rc sen_query_scan(sen_query *q, const char **strs, unsigned int *str_lens, unsigned int nstrs, int flags, int *found, int *score); sen_snip *sen_query_snip(sen_query *query, int flags, unsigned int width, unsigned int max_results, unsigned int n_tags, const char **opentags, unsigned int *opentag_lens, const char **closetags, unsigned int *closetag_lens, sen_snip_mapping *mapping); /******** utility API ********/ #define SEN_SNIP_NORMALIZE 0x0001 #define SEN_SNIP_COPY_TAG 0x0002 #define SEN_SNIP_SKIP_LEADING_SPACES 0x0004 #define SEN_QUERY_SCAN_NORMALIZE SEN_SNIP_NORMALIZE sen_snip *sen_snip_open(sen_encoding encoding, int flags, unsigned int width, unsigned int max_results, const char *defaultopentag, unsigned int defaultopentag_len, const char *defaultclosetag, unsigned int defaultclosetag_len, sen_snip_mapping *mapping); sen_rc sen_snip_close(sen_snip *snip); sen_rc sen_snip_add_cond(sen_snip *snip, const char *keyword, unsigned int keyword_len, const char *opentag, unsigned int opentag_len, const char *closetag, unsigned int closetag_len); sen_rc sen_snip_exec(sen_snip *snip, const char *string, unsigned int string_len, unsigned int *nresults, unsigned int *max_tagged_len); sen_rc sen_snip_get_result(sen_snip *snip, const unsigned int index, char *result, unsigned int *result_len); /* flags for sen_str_normalize */ #define SEN_STR_REMOVEBLANK 1 #define SEN_STR_WITH_CTYPES 2 #define SEN_STR_WITH_CHECKS 4 int sen_str_normalize(const char *str, unsigned int str_len, sen_encoding encoding, int flags, char *nstrbuf, int buf_size); unsigned int sen_str_charlen(const char *str, sen_encoding encoding); /* misc */ sen_rc sen_logger_info_set(const sen_logger_info *info); void sen_logger_put(sen_log_level level, const char *file, int line, const char *func, char *fmt, ...); int sen_logger_pass(sen_log_level level); #define SEN_LOG(level,...) \ if (sen_logger_pass(level)) {\ sen_logger_put((level), __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);\ } #ifndef SEN_LOG_DEFAULT_LEVEL #define SEN_LOG_DEFAULT_LEVEL sen_log_notice #endif /* SEN_LOG_DEFAULT_LEVEL */ #define sen_log(...) \ if (sen_logger_pass(SEN_LOG_DEFAULT_LEVEL)) {\ sen_logger_put(SEN_LOG_DEFAULT_LEVEL, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);\ } sen_rc sen_bulk_init(sen_ctx *ctx, sen_obj *bulk, unsigned int size); sen_rc sen_bulk_reinit(sen_ctx *ctx, sen_obj *bulk, unsigned int size); sen_rc sen_bulk_resize(sen_ctx *ctx, sen_obj *bulk, unsigned int newsize); sen_rc sen_bulk_write(sen_ctx *ctx, sen_obj *bulk, const char *str, unsigned int len); sen_rc sen_bulk_reserve(sen_ctx *ctx, sen_obj *bulk, unsigned int len); sen_rc sen_bulk_space(sen_ctx *ctx, sen_obj *bulk, unsigned int len); sen_rc sen_bulk_itoa(sen_ctx *ctx, sen_obj *bulk, int i); sen_rc sen_bulk_lltoa(sen_ctx *ctx, sen_obj *bulk, long long int i); sen_rc sen_bulk_ftoa(sen_ctx *ctx, sen_obj *bulk, double d); sen_rc sen_bulk_itoh(sen_ctx *ctx, sen_obj *bulk, int i, unsigned int len); sen_rc sen_bulk_itob(sen_ctx *ctx, sen_obj *bulk, sen_id id); sen_rc sen_bulk_lltob32h(sen_ctx *ctx, sen_obj *bulk, long long int i); sen_rc sen_bulk_fin(sen_ctx *ctx, sen_obj *bulk); sen_rc sen_bulk_benc(sen_ctx *ctx, sen_obj *bulk, unsigned int v); sen_rc sen_bulk_esc(sen_ctx *ctx, sen_obj *bulk, const char *s, unsigned int len, sen_encoding encoding); sen_rc sen_bulk_urlenc(sen_ctx *ctx, sen_obj *buf, const char *str, unsigned int len); #define SEN_BULK_PUTS(ctx,bulk,str) (sen_bulk_write((ctx), (bulk), (str), strlen(str))) #define SEN_BULK_PUTC(ctx,bulk,c) { char _c = (c); sen_bulk_write((ctx), (bulk), &_c, 1); } #define SEN_BULK_REWIND(bulk) ((bulk)->u.b.curr = (bulk)->u.b.head) #define SEN_BULK_WSIZE(bulk) ((bulk)->u.b.tail - (bulk)->u.b.head) #define SEN_BULK_REST(bulk) ((bulk)->u.b.tail - (bulk)->u.b.curr) #define SEN_BULK_VSIZE(bulk) ((bulk)->u.b.curr - (bulk)->u.b.head) #define SEN_BULK_EMPTYP(bulk) ((bulk)->u.b.curr == (bulk)->u.b.head) #define SEN_BULK_HEAD(bulk) ((bulk)->u.b.head) #ifdef __cplusplus } #endif #ifndef SENNA_OLD_H #include "senna_old.h" #endif /* SENNA_OLD_H */ #endif /* SENNA_H */