Kouhei Sutou
null+****@clear*****
Sun Feb 15 00:48:12 JST 2015
Kouhei Sutou 2015-02-15 00:48:12 +0900 (Sun, 15 Feb 2015) New Revision: 9fd2e0d4ca9b9d9d2c6b78d5783f5f7070096d1b https://github.com/pgroonga/pgroonga/commit/9fd2e0d4ca9b9d9d2c6b78d5783f5f7070096d1b Message: Support text[] Added files: expected/array/text/single/contain/bitmapscan.out expected/array/text/single/contain/indexscan.out expected/array/text/single/contain/seqscan.out sql/array/text/single/contain/indexscan.sql Modified files: Makefile pgroonga.c pgroonga.h pgroonga.sql pgroonga_types.c Modified: Makefile (+3 -0) =================================================================== --- Makefile 2015-02-14 22:50:50 +0900 (9fa78f6) +++ Makefile 2015-02-15 00:48:12 +0900 (4265960) @@ -40,6 +40,7 @@ installcheck: results/compare/integer/single/between installcheck: results/compare/integer/multiple/greater-than-equal installcheck: results/compare/integer/order_by_limit installcheck: results/compare/timestamp/single/between +installcheck: results/array/text/single/contain installcheck: results/groonga results/full-text-search/text/single/contain: @@ -72,5 +73,7 @@ results/compare/integer/order_by_limit: @mkdir -p $@ results/compare/timestamp/single/between: @mkdir -p $@ +results/array/text/single/contain: + @mkdir -p $@ results/groonga: @mkdir -p $@ Added: expected/array/text/single/contain/bitmapscan.out (+21 -0) 100644 =================================================================== --- /dev/null +++ expected/array/text/single/contain/bitmapscan.out 2015-02-15 00:48:12 +0900 (d2df0e2) @@ -0,0 +1,21 @@ +CREATE TABLE memos ( + title text, + tags text[] +); +INSERT INTO memos VALUES ('PostgreSQL', ARRAY['PostgreSQL']); +INSERT INTO memos VALUES ('Groonga', ARRAY['Groonga']); +INSERT INTO memos VALUES ('PGroonga', ARRAY['PostgreSQL', 'Groonga']); +CREATE INDEX pgroonga_memos_index ON memos USING pgroonga (tags); +SET enable_seqscan = off; +SET enable_indexscan = off; +SET enable_bitmapscan = on; +SELECT title, tags + FROM memos + WHERE tags %% 'Groonga'; + title | tags +----------+---------------------- + Groonga | {Groonga} + PGroonga | {PostgreSQL,Groonga} +(2 rows) + +DROP TABLE memos; Added: expected/array/text/single/contain/indexscan.out (+21 -0) 100644 =================================================================== --- /dev/null +++ expected/array/text/single/contain/indexscan.out 2015-02-15 00:48:12 +0900 (4359d48) @@ -0,0 +1,21 @@ +CREATE TABLE memos ( + title text, + tags text[] +); +INSERT INTO memos VALUES ('PostgreSQL', ARRAY['PostgreSQL']); +INSERT INTO memos VALUES ('Groonga', ARRAY['Groonga']); +INSERT INTO memos VALUES ('PGroonga', ARRAY['PostgreSQL', 'Groonga']); +CREATE INDEX pgroonga_memos_index ON memos USING pgroonga (tags); +SET enable_seqscan = off; +SET enable_indexscan = on; +SET enable_bitmapscan = off; +SELECT title, tags + FROM memos + WHERE tags %% 'Groonga'; + title | tags +----------+---------------------- + Groonga | {Groonga} + PGroonga | {PostgreSQL,Groonga} +(2 rows) + +DROP TABLE memos; Added: expected/array/text/single/contain/seqscan.out (+21 -0) 100644 =================================================================== --- /dev/null +++ expected/array/text/single/contain/seqscan.out 2015-02-15 00:48:12 +0900 (d8b3ced) @@ -0,0 +1,21 @@ +CREATE TABLE memos ( + title text, + tags text[] +); +INSERT INTO memos VALUES ('PostgreSQL', ARRAY['PostgreSQL']); +INSERT INTO memos VALUES ('Groonga', ARRAY['Groonga']); +INSERT INTO memos VALUES ('PGroonga', ARRAY['PostgreSQL', 'Groonga']); +CREATE INDEX pgroonga_memos_index ON memos USING pgroonga (tags); +SET enable_seqscan = on; +SET enable_indexscan = off; +SET enable_bitmapscan = off; +SELECT title, tags + FROM memos + WHERE tags %% 'Groonga'; + title | tags +----------+---------------------- + Groonga | {Groonga} + PGroonga | {PostgreSQL,Groonga} +(2 rows) + +DROP TABLE memos; Modified: pgroonga.c (+109 -25) =================================================================== --- pgroonga.c 2015-02-14 22:50:50 +0900 (af953b3) +++ pgroonga.c 2015-02-15 00:48:12 +0900 (b3a97f8) @@ -16,6 +16,7 @@ #include <miscadmin.h> #include <storage/ipc.h> #include <storage/lmgr.h> +#include <utils/array.h> #include <utils/builtins.h> #include <utils/lsyscache.h> #include <utils/selfuncs.h> @@ -47,6 +48,7 @@ typedef struct PGrnCreateData Oid relNode; bool forFullTextSearch; grn_id attributeTypeID; + unsigned char attributeFlags; } PGrnCreateData; typedef struct PGrnBuildStateData @@ -93,6 +95,7 @@ PG_FUNCTION_INFO_V1(pgroonga_table_name); PG_FUNCTION_INFO_V1(pgroonga_command); PG_FUNCTION_INFO_V1(pgroonga_contain_text); +PG_FUNCTION_INFO_V1(pgroonga_contain_text_array); PG_FUNCTION_INFO_V1(pgroonga_contain_bpchar); PG_FUNCTION_INFO_V1(pgroonga_match); @@ -368,16 +371,16 @@ PGrnCheck(const char *message) } static grn_id -PGrnGetType(Relation index, AttrNumber n) +PGrnGetType(Relation index, AttrNumber n, unsigned char *flags) { TupleDesc desc = RelationGetDescr(index); Form_pg_attribute attr; grn_id typeID = GRN_ID_NIL; + unsigned char typeFlags = 0; int32 maxlen; attr = desc->attrs[n]; - /* TODO: support array and record types. */ switch (attr->atttypid) { case BOOLOID: @@ -425,6 +428,10 @@ PGrnGetType(Relation index, AttrNumber n) typeID = GRN_DB_TOKYO_GEO_POINT or GRN_DB_WGS84_GEO_POINT; break; #endif + case TEXTARRAYOID: + typeID = GRN_DB_SHORT_TEXT; + typeFlags |= GRN_OBJ_VECTOR; + break; default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -432,6 +439,11 @@ PGrnGetType(Relation index, AttrNumber n) break; } + if (flags) + { + *flags = typeFlags; + } + return typeID; } @@ -446,6 +458,17 @@ PGrnGetValue(Relation index, AttrNumber n, grn_obj *buffer, Datum value) value); } +static void +PGrnGetQuery(Relation index, AttrNumber n, grn_obj *buffer, Datum value) +{ + FmgrInfo *function; + + function = index_getprocinfo(index, n + 1, PGrnGetQueryProc); + FunctionCall3(function, + PointerGetDatum(ctx), PointerGetDatum(buffer), + value); +} + static grn_obj * PGrnLookup(const char *name, int errorLevel) { @@ -516,28 +539,37 @@ PGrnCreateColumn(grn_obj *table, static bool PGrnIsForFullTextSearchIndex(Relation index) { - Oid containStrategyOID; - containStrategyOID = get_opfamily_member(index->rd_opfamily[0], - index->rd_opcintype[0], - index->rd_opcintype[0], - PGrnContainStrategyNumber); - return (containStrategyOID != InvalidOid); + Oid queryStrategyOID; + queryStrategyOID = get_opfamily_member(index->rd_opfamily[0], + index->rd_opcintype[0], + index->rd_opcintype[0], + PGrnQueryStrategyNumber); + return (queryStrategyOID != InvalidOid); } static void PGrnCreateDataColumn(PGrnCreateData *data) { - grn_obj_flags flags = GRN_OBJ_COLUMN_SCALAR; + grn_obj_flags flags = 0; - if (PGrnIsLZ4Available) + if (data->attributeFlags & GRN_OBJ_VECTOR) + { + flags |= GRN_OBJ_COLUMN_VECTOR; + } + else { - switch (data->attributeTypeID) + flags |= GRN_OBJ_COLUMN_SCALAR; + + if (PGrnIsLZ4Available) { - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: - flags |= GRN_OBJ_COMPRESS_LZ4; - break; + switch (data->attributeTypeID) + { + case GRN_DB_SHORT_TEXT: + case GRN_DB_TEXT: + case GRN_DB_LONG_TEXT: + flags |= GRN_OBJ_COMPRESS_LZ4; + break; + } } } @@ -634,7 +666,8 @@ PGrnCreate(Relation index, grn_obj **idsTable, grn_obj *lexicons) for (data.i = 0; data.i < data.desc->natts; data.i++) { - data.attributeTypeID = PGrnGetType(index, data.i); + data.attributeTypeID = PGrnGetType(index, data.i, + &(data.attributeFlags)); PGrnCreateDataColumn(&data); PGrnCreateIndexColumn(&data); } @@ -891,6 +924,49 @@ pgroonga_contain_text(PG_FUNCTION_ARGS) } /** + * pgroonga.contain(target text[], query text) : bool + */ +Datum +pgroonga_contain_text_array(PG_FUNCTION_ARGS) +{ + ArrayType *target = PG_GETARG_ARRAYTYPE_P(0); + text *query = PG_GETARG_TEXT_PP(1); + bool contained = false; + grn_obj elementBuffer; + int i, n; + + grn_obj_reinit(ctx, &buffer, GRN_DB_TEXT, 0); + GRN_TEXT_SET(ctx, &buffer, VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query)); + + GRN_TEXT_INIT(&elementBuffer, GRN_OBJ_DO_SHALLOW_COPY); + + n = ARR_DIMS(target)[0]; + for (i = 1; i <= n; i++) + { + Datum elementDatum; + text *element; + bool isNULL; + + elementDatum = array_ref(target, 1, &i, -1, -1, false, 'i', &isNULL); + if (isNULL) + continue; + + element = DatumGetTextPP(elementDatum); + GRN_TEXT_SET(ctx, &elementBuffer, + VARDATA_ANY(element), VARSIZE_ANY_EXHDR(element)); + if (grn_operator_exec_equal(ctx, &buffer, &elementBuffer)) + { + contained = true; + break; + } + } + + GRN_OBJ_FIN(ctx, &elementBuffer); + + PG_RETURN_BOOL(contained); +} + +/** * pgroonga.contain(doc bpchar, key bpchar) : bool */ Datum @@ -943,13 +1019,16 @@ PGrnInsert(grn_ctx *ctx, { grn_obj *dataColumn; NameData *name = &(desc->attrs[i]->attname); + grn_id domain; + unsigned char flags; if (isnull[i]) continue; dataColumn = grn_obj_column(ctx, idsTable, name->data, strlen(name->data)); - grn_obj_reinit(ctx, &buffer, PGrnGetType(index, i), 0); + domain = PGrnGetType(index, i, &flags); + grn_obj_reinit(ctx, &buffer, domain, flags); PGrnGetValue(index, i, &buffer, values[i]); grn_obj_set_value(ctx, dataColumn, id, &buffer, GRN_OBJ_SET); grn_obj_unlink(ctx, dataColumn); @@ -1151,8 +1230,13 @@ PGrnSearchBuildConditions(IndexScanDesc scan, grn_expr_append_op(ctx, matchTarget, GRN_OP_GET_MEMBER, 2); - grn_obj_reinit(ctx, &buffer, PGrnGetType(index, key->sk_attno - 1), 0); - PGrnGetValue(index, key->sk_attno - 1, &buffer, key->sk_argument); + { + grn_id domain; + unsigned char flags = 0; + domain = PGrnGetType(index, key->sk_attno - 1, NULL); + grn_obj_reinit(ctx, &buffer, domain, flags); + } + PGrnGetQuery(index, key->sk_attno - 1, &buffer, key->sk_argument); switch (key->sk_strategy) { @@ -1396,7 +1480,7 @@ PGrnFillBorder(IndexScanDesc scan, grn_id domain; attrNumber = key->sk_attno - 1; - domain = PGrnGetType(index, attrNumber); + domain = PGrnGetType(index, attrNumber, NULL); switch (key->sk_strategy) { case PGrnLessStrategyNumber: @@ -1404,7 +1488,7 @@ PGrnFillBorder(IndexScanDesc scan, if (maxBorderValue->header.type != GRN_DB_VOID) { grn_obj_reinit(ctx, &buffer, domain, 0); - PGrnGetValue(index, attrNumber, &buffer, key->sk_argument); + PGrnGetQuery(index, attrNumber, &buffer, key->sk_argument); if (!PGrnIsMeaningfullMaxBorderValue(maxBorderValue, &buffer, *flags, @@ -1414,7 +1498,7 @@ PGrnFillBorder(IndexScanDesc scan, } } grn_obj_reinit(ctx, maxBorderValue, domain, 0); - PGrnGetValue(index, attrNumber, maxBorderValue, key->sk_argument); + PGrnGetQuery(index, attrNumber, maxBorderValue, key->sk_argument); *max = GRN_BULK_HEAD(maxBorderValue); *maxSize = GRN_BULK_VSIZE(maxBorderValue); *flags &= ~(GRN_CURSOR_LT | GRN_CURSOR_LE); @@ -1432,7 +1516,7 @@ PGrnFillBorder(IndexScanDesc scan, if (minBorderValue->header.type != GRN_DB_VOID) { grn_obj_reinit(ctx, &buffer, domain, 0); - PGrnGetValue(index, attrNumber, &buffer, + PGrnGetQuery(index, attrNumber, &buffer, key->sk_argument); if (!PGrnIsMeaningfullMinBorderValue(minBorderValue, &buffer, @@ -1443,7 +1527,7 @@ PGrnFillBorder(IndexScanDesc scan, } } grn_obj_reinit(ctx, minBorderValue, domain, 0); - PGrnGetValue(index, attrNumber, minBorderValue, key->sk_argument); + PGrnGetQuery(index, attrNumber, minBorderValue, key->sk_argument); *min = GRN_BULK_HEAD(minBorderValue); *minSize = GRN_BULK_VSIZE(minBorderValue); *flags &= ~(GRN_CURSOR_GT | GRN_CURSOR_GE); Modified: pgroonga.h (+3 -0) =================================================================== --- pgroonga.h 2015-02-14 22:50:50 +0900 (a1c6399) +++ pgroonga.h 2015-02-15 00:48:12 +0900 (e9bdf06) @@ -33,6 +33,7 @@ /* Groonga support functions */ #define PGrnGetValueProc 1 +#define PGrnGetQueryProc 2 /* file and table names */ #define PGrnDatabaseBasename "pgrn" @@ -49,6 +50,7 @@ extern Datum PGDLLEXPORT pgroonga_table_name(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_command(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_contain_text(PG_FUNCTION_ARGS); +extern Datum PGDLLEXPORT pgroonga_contain_text_array(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_contain_bpchar(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_match(PG_FUNCTION_ARGS); @@ -69,6 +71,7 @@ extern Datum PGDLLEXPORT pgroonga_options(PG_FUNCTION_ARGS); int pgroonga_bpchar_size(const BpChar *bpchar); extern Datum PGDLLEXPORT pgroonga_get_text(PG_FUNCTION_ARGS); +extern Datum PGDLLEXPORT pgroonga_get_text_array(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_get_bpchar(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_get_bool(PG_FUNCTION_ARGS); extern Datum PGDLLEXPORT pgroonga_get_int2(PG_FUNCTION_ARGS); Modified: pgroonga.sql (+67 -12) =================================================================== --- pgroonga.sql 2015-02-14 22:50:50 +0900 (5baaee4) +++ pgroonga.sql 2015-02-15 00:48:12 +0900 (cea4a69) @@ -30,6 +30,13 @@ CREATE FUNCTION pgroonga.contain(text, text) IMMUTABLE STRICT; +CREATE FUNCTION pgroonga.contain(target text[], query text) + RETURNS bool + AS 'MODULE_PATHNAME', 'pgroonga_contain_text_array' + LANGUAGE C + IMMUTABLE + STRICT; + CREATE FUNCTION pgroonga.contain(bpchar, bpchar) RETURNS bool AS 'MODULE_PATHNAME', 'pgroonga_contain_bpchar' @@ -45,6 +52,12 @@ CREATE OPERATOR %% ( CREATE OPERATOR %% ( PROCEDURE = pgroonga.contain, + LEFTARG = text[], + RIGHTARG = text +); + +CREATE OPERATOR %% ( + PROCEDURE = pgroonga.contain, LEFTARG = bpchar, RIGHTARG = bpchar ); @@ -57,6 +70,13 @@ CREATE FUNCTION pgroonga.match(text, text) IMMUTABLE STRICT; +CREATE FUNCTION pgroonga.match(text[], text) + RETURNS bool + AS 'MODULE_PATHNAME', 'pgroonga_match' + LANGUAGE C + IMMUTABLE + STRICT; + CREATE FUNCTION pgroonga.match(bpchar, bpchar) RETURNS bool AS 'MODULE_PATHNAME', 'pgroonga_match' @@ -72,6 +92,12 @@ CREATE OPERATOR @@ ( CREATE OPERATOR @@ ( PROCEDURE = pgroonga.match, + LEFTARG = text[], + RIGHTARG = text +); + +CREATE OPERATOR @@ ( + PROCEDURE = pgroonga.match, LEFTARG = bpchar, RIGHTARG = bpchar ); @@ -130,6 +156,10 @@ CREATE FUNCTION pgroonga.get_text(internal, internal, text) RETURNS void AS 'MODULE_PATHNAME', 'pgroonga_get_text' LANGUAGE C; +CREATE FUNCTION pgroonga.get_text_array(internal, internal, text[]) + RETURNS void + AS 'MODULE_PATHNAME', 'pgroonga_get_text_array' + LANGUAGE C; CREATE FUNCTION pgroonga.get_bpchar(internal, internal, bpchar) RETURNS void AS 'MODULE_PATHNAME', 'pgroonga_get_bpchar' @@ -206,7 +236,8 @@ CREATE OPERATOR CLASS pgroonga.full_text_search_text_ops DEFAULT FOR TYPE text OPERATOR 6 pg_catalog.~~, OPERATOR 7 %%, OPERATOR 8 @@, - FUNCTION 1 pgroonga.get_text(internal, internal, text); + FUNCTION 1 pgroonga.get_text(internal, internal, text), + FUNCTION 2 pgroonga.get_text(internal, internal, text); CREATE OPERATOR CLASS pgroonga.text_ops FOR TYPE text USING pgroonga AS @@ -215,13 +246,28 @@ CREATE OPERATOR CLASS pgroonga.text_ops FOR TYPE text OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_text(internal, internal, text); + FUNCTION 1 pgroonga.get_text(internal, internal, text), + FUNCTION 2 pgroonga.get_text(internal, internal, text); + +CREATE OPERATOR CLASS pgroonga.full_text_search_text_array_ops FOR TYPE text[] + USING pgroonga AS + OPERATOR 7 %% (text[], text), + OPERATOR 8 @@ (text[], text), + FUNCTION 1 pgroonga.get_text_array(internal, internal, text[]), + FUNCTION 2 pgroonga.get_text(internal, internal, text); + +CREATE OPERATOR CLASS pgroonga.text_array_ops DEFAULT FOR TYPE text[] + USING pgroonga AS + OPERATOR 7 %% (text[], text), + FUNCTION 1 pgroonga.get_text_array(internal, internal, text[]), + FUNCTION 2 pgroonga.get_text(internal, internal, text); CREATE OPERATOR CLASS pgroonga.full_text_search_bpchar_ops DEFAULT FOR TYPE bpchar USING pgroonga AS OPERATOR 7 %%, OPERATOR 8 @@, - FUNCTION 1 pgroonga.get_bpchar(internal, internal, bpchar); + FUNCTION 1 pgroonga.get_bpchar(internal, internal, bpchar), + FUNCTION 2 pgroonga.get_bpchar(internal, internal, bpchar); CREATE OPERATOR CLASS pgroonga.bpchar_ops FOR TYPE bpchar USING pgroonga AS @@ -230,7 +276,8 @@ CREATE OPERATOR CLASS pgroonga.bpchar_ops FOR TYPE bpchar OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_bpchar(internal, internal, bpchar); + FUNCTION 1 pgroonga.get_bpchar(internal, internal, bpchar), + FUNCTION 2 pgroonga.get_bpchar(internal, internal, bpchar); CREATE OPERATOR CLASS pgroonga.bool_ops DEFAULT FOR TYPE bool USING pgroonga AS @@ -239,7 +286,8 @@ CREATE OPERATOR CLASS pgroonga.bool_ops DEFAULT FOR TYPE bool OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_bool(internal, internal, bool); + FUNCTION 1 pgroonga.get_bool(internal, internal, bool), + FUNCTION 2 pgroonga.get_bool(internal, internal, bool); CREATE OPERATOR CLASS pgroonga.int2_ops DEFAULT FOR TYPE int2 USING pgroonga AS @@ -248,7 +296,8 @@ CREATE OPERATOR CLASS pgroonga.int2_ops DEFAULT FOR TYPE int2 OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_int2(internal, internal, int2); + FUNCTION 1 pgroonga.get_int2(internal, internal, int2), + FUNCTION 2 pgroonga.get_int2(internal, internal, int2); CREATE OPERATOR CLASS pgroonga.int4_ops DEFAULT FOR TYPE int4 USING pgroonga AS @@ -257,7 +306,8 @@ CREATE OPERATOR CLASS pgroonga.int4_ops DEFAULT FOR TYPE int4 OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_int4(internal, internal, int4); + FUNCTION 1 pgroonga.get_int4(internal, internal, int4), + FUNCTION 2 pgroonga.get_int4(internal, internal, int4); CREATE OPERATOR CLASS pgroonga.int8_ops DEFAULT FOR TYPE int8 USING pgroonga AS @@ -266,7 +316,8 @@ CREATE OPERATOR CLASS pgroonga.int8_ops DEFAULT FOR TYPE int8 OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_int8(internal, internal, int8); + FUNCTION 1 pgroonga.get_int8(internal, internal, int8), + FUNCTION 2 pgroonga.get_int8(internal, internal, int8); CREATE OPERATOR CLASS pgroonga.float4_ops DEFAULT FOR TYPE float4 USING pgroonga AS @@ -275,7 +326,8 @@ CREATE OPERATOR CLASS pgroonga.float4_ops DEFAULT FOR TYPE float4 OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_float4(internal, internal, float4); + FUNCTION 1 pgroonga.get_float4(internal, internal, float4), + FUNCTION 2 pgroonga.get_float4(internal, internal, float4); CREATE OPERATOR CLASS pgroonga.float8_ops DEFAULT FOR TYPE float8 USING pgroonga AS @@ -284,7 +336,8 @@ CREATE OPERATOR CLASS pgroonga.float8_ops DEFAULT FOR TYPE float8 OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_float8(internal, internal, float8); + FUNCTION 1 pgroonga.get_float8(internal, internal, float8), + FUNCTION 2 pgroonga.get_float8(internal, internal, float8); CREATE OPERATOR CLASS pgroonga.timestamp_ops DEFAULT FOR TYPE timestamp USING pgroonga AS @@ -293,7 +346,8 @@ CREATE OPERATOR CLASS pgroonga.timestamp_ops DEFAULT FOR TYPE timestamp OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_timestamp(internal, internal, timestamp); + FUNCTION 1 pgroonga.get_timestamp(internal, internal, timestamp), + FUNCTION 2 pgroonga.get_timestamp(internal, internal, timestamp); CREATE OPERATOR CLASS pgroonga.timestamptz_ops DEFAULT FOR TYPE timestamptz USING pgroonga AS @@ -302,4 +356,5 @@ CREATE OPERATOR CLASS pgroonga.timestamptz_ops DEFAULT FOR TYPE timestamptz OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, - FUNCTION 1 pgroonga.get_timestamptz(internal, internal, timestamptz); + FUNCTION 1 pgroonga.get_timestamptz(internal, internal, timestamptz), + FUNCTION 2 pgroonga.get_timestamptz(internal, internal, timestamptz); Modified: pgroonga_types.c (+33 -0) =================================================================== --- pgroonga_types.c 2015-02-14 22:50:50 +0900 (243f1cf) +++ pgroonga_types.c 2015-02-15 00:48:12 +0900 (e8221c8) @@ -6,6 +6,7 @@ #include "pgroonga.h" #include <catalog/pg_type.h> +#include <utils/array.h> #include <utils/builtins.h> #include <utils/timestamp.h> @@ -30,6 +31,7 @@ pgroonga_bpchar_size(const BpChar *arg) } PG_FUNCTION_INFO_V1(pgroonga_get_text); +PG_FUNCTION_INFO_V1(pgroonga_get_text_array); PG_FUNCTION_INFO_V1(pgroonga_get_bpchar); PG_FUNCTION_INFO_V1(pgroonga_get_bool); PG_FUNCTION_INFO_V1(pgroonga_get_int2); @@ -62,6 +64,37 @@ pgroonga_get_text(PG_FUNCTION_ARGS) } Datum +pgroonga_get_text_array(PG_FUNCTION_ARGS) +{ + grn_ctx *ctx = (grn_ctx *) PG_GETARG_POINTER(0); + grn_obj *obj = (grn_obj *) PG_GETARG_POINTER(1); + ArrayType *value = PG_GETARG_ARRAYTYPE_P(2); + int i, n; + + n = ARR_DIMS(value)[0]; + for (i = 1; i <= n; i++) + { + int weight = 0; + Datum elementDatum; + text *element; + bool isNULL; + + elementDatum = array_ref(value, 1, &i, -1, -1, false, 'i', &isNULL); + if (isNULL) + continue; + + element = DatumGetTextPP(elementDatum); + grn_vector_add_element(ctx, obj, + VARDATA_ANY(element), + VARSIZE_ANY_EXHDR(element), + weight, + obj->header.domain); + } + + PG_RETURN_VOID(); +} + +Datum pgroonga_get_bpchar(PG_FUNCTION_ARGS) { grn_ctx *ctx = (grn_ctx *) PG_GETARG_POINTER(0); Added: sql/array/text/single/contain/indexscan.sql (+20 -0) 100644 =================================================================== --- /dev/null +++ sql/array/text/single/contain/indexscan.sql 2015-02-15 00:48:12 +0900 (9cb0a1e) @@ -0,0 +1,20 @@ +CREATE TABLE memos ( + title text, + tags text[] +); + +INSERT INTO memos VALUES ('PostgreSQL', ARRAY['PostgreSQL']); +INSERT INTO memos VALUES ('Groonga', ARRAY['Groonga']); +INSERT INTO memos VALUES ('PGroonga', ARRAY['PostgreSQL', 'Groonga']); + +CREATE INDEX pgroonga_memos_index ON memos USING pgroonga (tags); + +SET enable_seqscan = off; +SET enable_indexscan = on; +SET enable_bitmapscan = off; + +SELECT title, tags + FROM memos + WHERE tags %% 'Groonga'; + +DROP TABLE memos; -------------- next part -------------- HTML����������������������������... Descargar