これを公開するに至るまでには裏話がありまして、別件で特定の目的専用のモジュールを作ったことがきっかけでした。
それではこんな関数を使っています。
/* {{{ proto array t_search(resource sary_res_searcher res_searcher, string pattern); */ PHP_FUNCTION(t_search) { zval *searcher = NULL; SarySearcher *res_searcher; const char *pattern = NULL; int pattern_len = 0; gchar *line = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &searcher, &pattern, &pattern_len) == FAILURE) { return; } ZEND_FETCH_RESOURCE(res_searcher, SarySearcher *, &searcher, -1, "sary_res_searcher", le_sary_searcher); if (!sary_res_searcher_search2(res_searcher, (const gchar *)pattern, (SaryInt)pattern_len)) { RETURN_FALSE; } array_init(return_value); sary_res_searcher_sort_occurrences(res_searcher); while ((line = sary_res_searcher_get_next_line(res_searcher))) { zval *info = NULL; long tid, bid, cid; if (sscanf((const char *)line, "%5lx%3lx%2lx", &tid, &bid, &cid) != 3) { g_free(line); php_error(E_NOTICE, "t_search(): invalid format of line."); continue; } g_free(line); MAKE_STD_ZVAL(info); array_init(info); add_next_index_long(info, tid); add_next_index_long(info, bid); add_next_index_long(info, cid); add_next_index_zval(return_value, info); } } /* }}} t_search */
各行の先頭の10バイトをスキップしてインデックスした Suffix Array の検索結果から、そのスキップした箇所をパースして各種情報を取得するというものです。
検索対象のテキストはNFKCで正規化+全角半角/大文字小文字を統一してあり、DB に入っているデータは生のままっちゅー寸法ですわ。