Kouhei Sutou
null+****@clear*****
Mon Feb 22 00:20:59 JST 2016
Kouhei Sutou 2016-02-22 00:20:59 +0900 (Mon, 22 Feb 2016) New Revision: f673eb505376258df24ad75f25141edf561aace2 https://github.com/pgroonga/pgroonga/commit/f673eb505376258df24ad75f25141edf561aace2 Message: Add &` operator It enables script syntax but it's not useful on seqscan... Added files: expected/full-text-search/text/single/script-v2/bitmapscan.out expected/full-text-search/text/single/script-v2/indexscan.out expected/full-text-search/text/single/script-v2/seqscan.out sql/full-text-search/text/single/script-v2/bitmapscan.sql sql/full-text-search/text/single/script-v2/indexscan.sql sql/full-text-search/text/single/script-v2/seqscan.sql Modified files: pgroonga.sql src/pgroonga.c src/pgroonga.h Added: expected/full-text-search/text/single/script-v2/bitmapscan.out (+22 -0) 100644 =================================================================== --- /dev/null +++ expected/full-text-search/text/single/script-v2/bitmapscan.out 2016-02-22 00:20:59 +0900 (6594e30) @@ -0,0 +1,22 @@ +CREATE TABLE memos ( + id integer, + content text +); +INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.'); +INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.'); +INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.'); +CREATE INDEX grnindex ON memos + USING pgroonga (content pgroonga.text_full_text_search_ops_v2); +SET enable_seqscan = off; +SET enable_indexscan = off; +SET enable_bitmapscan = on; +SELECT id, content + FROM memos + WHERE content &` 'content @ "rdbms" || content @ "engine"'; + id | content +----+------------------------------------------ + 1 | PostgreSQL is a RDBMS. + 2 | Groonga is fast full text search engine. +(2 rows) + +DROP TABLE memos; Added: expected/full-text-search/text/single/script-v2/indexscan.out (+22 -0) 100644 =================================================================== --- /dev/null +++ expected/full-text-search/text/single/script-v2/indexscan.out 2016-02-22 00:20:59 +0900 (cd0d49f) @@ -0,0 +1,22 @@ +CREATE TABLE memos ( + id integer, + content text +); +INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.'); +INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.'); +INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.'); +CREATE INDEX grnindex ON memos + USING pgroonga (content pgroonga.text_full_text_search_ops_v2); +SET enable_seqscan = off; +SET enable_indexscan = on; +SET enable_bitmapscan = off; +SELECT id, content + FROM memos + WHERE content &` 'content @ "rdbms" || content @ "engine"'; + id | content +----+------------------------------------------ + 1 | PostgreSQL is a RDBMS. + 2 | Groonga is fast full text search engine. +(2 rows) + +DROP TABLE memos; Added: expected/full-text-search/text/single/script-v2/seqscan.out (+20 -0) 100644 =================================================================== --- /dev/null +++ expected/full-text-search/text/single/script-v2/seqscan.out 2016-02-22 00:20:59 +0900 (3012904) @@ -0,0 +1,20 @@ +CREATE TABLE memos ( + id integer, + text text +); +INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.'); +INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.'); +INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.'); +SET enable_seqscan = on; +SET enable_indexscan = off; +SET enable_bitmapscan = off; +SELECT id, text + FROM memos + WHERE text &` 'text @ "rdbms" || text @ "engine"'; + id | text +----+------------------------------------------ + 1 | PostgreSQL is a RDBMS. + 2 | Groonga is fast full text search engine. +(2 rows) + +DROP TABLE memos; Modified: pgroonga.sql (+17 -3) =================================================================== --- pgroonga.sql 2016-02-18 00:10:37 +0900 (d082421) +++ pgroonga.sql 2016-02-22 00:20:59 +0900 (3207764) @@ -206,7 +206,7 @@ CREATE FUNCTION pgroonga.options(internal) DELETE FROM pg_catalog.pg_am WHERE amname = 'pgroonga'; INSERT INTO pg_catalog.pg_am VALUES( 'pgroonga', -- amname - 15, -- amstrategies + 16, -- amstrategies 0, -- amsupport true, -- amcanorder true, -- amcanorderbyop @@ -401,6 +401,19 @@ CREATE OPERATOR &? ( RIGHTARG = text ); +CREATE FUNCTION pgroonga.script_text(text, text) + RETURNS bool + AS 'MODULE_PATHNAME', 'pgroonga_script_text' + LANGUAGE C + IMMUTABLE + STRICT; + +CREATE OPERATOR &` ( + PROCEDURE = pgroonga.script_text, + LEFTARG = text, + RIGHTARG = text +); + CREATE FUNCTION pgroonga.match_contain_text(text, text[]) RETURNS bool AS 'MODULE_PATHNAME', 'pgroonga_match_contain_text' @@ -433,5 +446,6 @@ CREATE OPERATOR CLASS pgroonga.text_full_text_search_ops_v2 FOR TYPE text OPERATOR 7 pg_catalog.~~*, OPERATOR 12 &@, OPERATOR 13 &?, - OPERATOR 14 &@> (text, text[]), - OPERATOR 15 &?> (text, text[]); + OPERATOR 14 &`, + OPERATOR 15 &@> (text, text[]), + OPERATOR 16 &?> (text, text[]); Added: sql/full-text-search/text/single/script-v2/bitmapscan.sql (+21 -0) 100644 =================================================================== --- /dev/null +++ sql/full-text-search/text/single/script-v2/bitmapscan.sql 2016-02-22 00:20:59 +0900 (505d66b) @@ -0,0 +1,21 @@ +CREATE TABLE memos ( + id integer, + content text +); + +INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.'); +INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.'); +INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.'); + +CREATE INDEX grnindex ON memos + USING pgroonga (content pgroonga.text_full_text_search_ops_v2); + +SET enable_seqscan = off; +SET enable_indexscan = off; +SET enable_bitmapscan = on; + +SELECT id, content + FROM memos + WHERE content &` 'content @ "rdbms" || content @ "engine"'; + +DROP TABLE memos; Added: sql/full-text-search/text/single/script-v2/indexscan.sql (+21 -0) 100644 =================================================================== --- /dev/null +++ sql/full-text-search/text/single/script-v2/indexscan.sql 2016-02-22 00:20:59 +0900 (cca62ae) @@ -0,0 +1,21 @@ +CREATE TABLE memos ( + id integer, + content text +); + +INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.'); +INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.'); +INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.'); + +CREATE INDEX grnindex ON memos + USING pgroonga (content pgroonga.text_full_text_search_ops_v2); + +SET enable_seqscan = off; +SET enable_indexscan = on; +SET enable_bitmapscan = off; + +SELECT id, content + FROM memos + WHERE content &` 'content @ "rdbms" || content @ "engine"'; + +DROP TABLE memos; Added: sql/full-text-search/text/single/script-v2/seqscan.sql (+18 -0) 100644 =================================================================== --- /dev/null +++ sql/full-text-search/text/single/script-v2/seqscan.sql 2016-02-22 00:20:59 +0900 (78bc983) @@ -0,0 +1,18 @@ +CREATE TABLE memos ( + id integer, + text text +); + +INSERT INTO memos VALUES (1, 'PostgreSQL is a RDBMS.'); +INSERT INTO memos VALUES (2, 'Groonga is fast full text search engine.'); +INSERT INTO memos VALUES (3, 'PGroonga is a PostgreSQL extension that uses Groonga.'); + +SET enable_seqscan = on; +SET enable_indexscan = off; +SET enable_bitmapscan = off; + +SELECT id, text + FROM memos + WHERE text &` 'text @ "rdbms" || text @ "engine"'; + +DROP TABLE memos; Modified: src/pgroonga.c (+150 -0) =================================================================== --- src/pgroonga.c 2016-02-18 00:10:37 +0900 (e754c77) +++ src/pgroonga.c 2016-02-22 00:20:59 +0900 (913c6c2) @@ -142,6 +142,7 @@ PG_FUNCTION_INFO_V1(pgroonga_match_regexp_varchar); /* v2 */ PG_FUNCTION_INFO_V1(pgroonga_match_text); PG_FUNCTION_INFO_V1(pgroonga_query_text); +PG_FUNCTION_INFO_V1(pgroonga_script_text); PG_FUNCTION_INFO_V1(pgroonga_match_contain_text); PG_FUNCTION_INFO_V1(pgroonga_query_contain_text); @@ -605,6 +606,38 @@ PGrnIsQueryContainStrategyIndex(Relation index, int nthAttribute) } static bool +PGrnIsScriptStrategyIndex(Relation index, int nthAttribute) +{ + Oid strategyOID; + Oid leftType; + Oid rightType; + + leftType = index->rd_opcintype[nthAttribute]; + + switch (leftType) + { + case VARCHARARRAYOID: + rightType = VARCHAROID; + break; + case TEXTARRAYOID: + rightType = TEXTOID; + break; + default: + rightType = leftType; + break; + } + + strategyOID = get_opfamily_member(index->rd_opfamily[nthAttribute], + leftType, + rightType, + PGrnScriptStrategyV2Number); + if (OidIsValid(strategyOID)) + return true; + + return false; +} + +static bool PGrnIsForFullTextSearchIndex(Relation index, int nthAttribute) { if (PGrnIsQueryStrategyIndex(index, nthAttribute)) @@ -613,6 +646,9 @@ PGrnIsForFullTextSearchIndex(Relation index, int nthAttribute) if (PGrnIsQueryContainStrategyIndex(index, nthAttribute)) return true; + if (PGrnIsScriptStrategyIndex(index, nthAttribute)) + return true; + return false; } @@ -1514,6 +1550,83 @@ pgroonga_query_text(PG_FUNCTION_ARGS) PG_RETURN_BOOL(matched); } +static grn_bool +pgroonga_script_raw(const char *target, unsigned int targetSize, + const char *script, unsigned int scriptSize) +{ + grn_obj *expression; + grn_obj *variable; + grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT; + grn_rc rc; + grn_obj *result; + bool matched = false; + + GRN_EXPR_CREATE_FOR_QUERY(ctx, + sequentialSearchData.table, + expression, + variable); + if (!expression) + { + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("pgroonga: failed to create expression: %s", + ctx->errbuf))); + } + + rc = grn_expr_parse(ctx, + expression, + script, scriptSize, + sequentialSearchData.textColumn, + GRN_OP_MATCH, GRN_OP_AND, + flags); + if (rc != GRN_SUCCESS) + { + char message[GRN_CTX_MSGSIZE]; + grn_strncpy(message, GRN_CTX_MSGSIZE, + ctx->errbuf, GRN_CTX_MSGSIZE); + + grn_obj_close(ctx, expression); + ereport(ERROR, + (errcode(PGrnRCToPgErrorCode(rc)), + errmsg("pgroonga: failed to parse expression: %s", + message))); + } + + grn_obj_reinit(ctx, &(buffers->general), GRN_DB_TEXT, 0); + GRN_TEXT_SET(ctx, &(buffers->general), target, targetSize); + grn_obj_set_value(ctx, + sequentialSearchData.textColumn, + sequentialSearchData.recordID, + &(buffers->general), + GRN_OBJ_SET); + GRN_RECORD_SET(ctx, variable, sequentialSearchData.recordID); + + result = grn_expr_exec(ctx, expression, 0); + GRN_OBJ_IS_TRUE(ctx, result, matched); + + grn_obj_close(ctx, expression); + + return matched; +} + +/** + * pgroonga.script_text(target text, script text) : bool + */ +Datum +pgroonga_script_text(PG_FUNCTION_ARGS) +{ + text *target = PG_GETARG_TEXT_PP(0); + text *script = PG_GETARG_TEXT_PP(1); + bool matched = false; + + matched = pgroonga_script_raw(VARDATA_ANY(target), + VARSIZE_ANY_EXHDR(target), + VARDATA_ANY(script), + VARSIZE_ANY_EXHDR(script)); + + PG_RETURN_BOOL(matched); +} + /** * pgroonga.match_contain_text(target text, keywords text[]) : bool */ @@ -2103,6 +2216,35 @@ PGrnSearchBuildConditionQuery(PGrnScanOpaque so, } static void +PGrnSearchBuildConditionScript(PGrnScanOpaque so, + PGrnSearchData *data, + grn_obj *targetColumn, + const char *script, + unsigned int scriptSize) +{ + grn_rc rc; + grn_obj *matchTarget, *matchTargetVariable; + grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT; + + GRN_EXPR_CREATE_FOR_QUERY(ctx, so->sourcesTable, + matchTarget, matchTargetVariable); + GRN_PTR_PUT(ctx, &(data->matchTargets), matchTarget); + grn_expr_append_obj(ctx, matchTarget, targetColumn, GRN_OP_PUSH, 1); + + rc = grn_expr_parse(ctx, data->expression, + script, scriptSize, + matchTarget, GRN_OP_MATCH, GRN_OP_AND, + flags); + if (rc != GRN_SUCCESS) + { + ereport(ERROR, + (errcode(PGrnRCToPgErrorCode(rc)), + errmsg("pgroonga: failed to parse expression: %s", + ctx->errbuf))); + } +} + +static void PGrnSearchBuildConditionBinaryOperation(PGrnSearchData *data, grn_obj *targetColumn, grn_obj *value, @@ -2182,6 +2324,7 @@ PGrnSearchBuildCondition(IndexScanDesc scan, break; case PGrnQueryStrategyNumber: case PGrnQueryStrategyV2Number: + case PGrnScriptStrategyV2Number: break; case PGrnRegexpStrategyNumber: operator = GRN_OP_REGEXP; @@ -2230,6 +2373,13 @@ PGrnSearchBuildCondition(IndexScanDesc scan, GRN_TEXT_VALUE(&(buffers->general)), GRN_TEXT_LEN(&(buffers->general))); break; + case PGrnScriptStrategyV2Number: + PGrnSearchBuildConditionScript(so, + data, + targetColumn, + GRN_TEXT_VALUE(&(buffers->general)), + GRN_TEXT_LEN(&(buffers->general))); + break; case PGrnQueryContainStrategyNumber: { grn_obj *queries = &(buffers->general); Modified: src/pgroonga.h (+3 -2) =================================================================== --- src/pgroonga.h 2016-02-18 00:10:37 +0900 (c915668) +++ src/pgroonga.h 2016-02-22 00:20:59 +0900 (a5d8918) @@ -26,8 +26,9 @@ #define PGrnMatchStrategyV2Number 12 /* operator &@ (@ in Groonga) */ #define PGrnQueryStrategyV2Number 13 /* operator &? (query in Groonga) */ -#define PGrnMatchContainStrategyNumber 14 /* operator &@> (@ in Groonga) */ -#define PGrnQueryContainStrategyNumber 15 /* operator &?> (query in Groonga) */ +#define PGrnScriptStrategyV2Number 14 /* operator &` (script in Groonga) */ +#define PGrnMatchContainStrategyNumber 15 /* operator &@> (@ in Groonga) */ +#define PGrnQueryContainStrategyNumber 16 /* operator &?> (query in Groonga) */ /* file and table names */ #define PGrnLogBasename "pgroonga.log" -------------- next part -------------- HTML����������������������������... Download