Kouhei Sutou
null+****@clear*****
Thu Jun 29 11:36:56 JST 2017
Kouhei Sutou 2017-06-29 11:36:56 +0900 (Thu, 29 Jun 2017) New Revision: 0c2dad7b2c59b7a620da9e0f8a4e09db03f2c47e https://github.com/pgroonga/pgroonga/commit/0c2dad7b2c59b7a620da9e0f8a4e09db03f2c47e Message: pgroonga.query_expand: support find data from PostgreSQL table Modified files: data/pgroonga.sql expected/function/query-expand/one.out sql/function/query-expand/one.sql src/pgroonga.c Modified: data/pgroonga.sql (+4 -1) =================================================================== --- data/pgroonga.sql 2017-06-27 09:38:32 +0900 (48691c2) +++ data/pgroonga.sql 2017-06-29 11:36:56 +0900 (95d913c) @@ -30,7 +30,10 @@ CREATE FUNCTION pgroonga.command(groongaCommand text, arguments text[]) VOLATILE STRICT; -CREATE FUNCTION pgroonga.query_expand(term text) +CREATE FUNCTION pgroonga.query_expand(tableName cstring, + termColumnName text, + synonymsColumnName text, + term text) RETURNS text AS 'MODULE_PATHNAME', 'pgroonga_query_expand' LANGUAGE C Modified: expected/function/query-expand/one.out (+9 -4) =================================================================== --- expected/function/query-expand/one.out 2017-06-27 09:38:32 +0900 (133ef0e) +++ expected/function/query-expand/one.out 2017-06-29 11:36:56 +0900 (63b96d5) @@ -1,6 +1,11 @@ -SELECT pgroonga.query_expand('Groonga'); - query_expand --------------- - Groonga +CREATE TABLE synonyms ( + term text PRIMARY KEY, + synonyms text[] +); +INSERT INTO synonyms VALUES ('Groonga', ARRAY['Groonga', 'Senna']); +SELECT pgroonga.query_expand('synonyms', 'term', 'synonyms', 'Groonga'); + query_expand +------------------ + Groonga OR Senna (1 row) Modified: sql/function/query-expand/one.sql (+8 -1) =================================================================== --- sql/function/query-expand/one.sql 2017-06-27 09:38:32 +0900 (dd08c3f) +++ sql/function/query-expand/one.sql 2017-06-29 11:36:56 +0900 (c1deb03) @@ -1 +1,8 @@ -SELECT pgroonga.query_expand('Groonga'); +CREATE TABLE synonyms ( + term text PRIMARY KEY, + synonyms text[] +); + +INSERT INTO synonyms VALUES ('Groonga', ARRAY['Groonga', 'Senna']); + +SELECT pgroonga.query_expand('synonyms', 'term', 'synonyms', 'Groonga'); Modified: src/pgroonga.c (+170 -4) =================================================================== --- src/pgroonga.c 2017-06-27 09:38:32 +0900 (f69d661) +++ src/pgroonga.c 2017-06-29 11:36:56 +0900 (452c396) @@ -1419,15 +1419,181 @@ pgroonga_command(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } +static Relation +PGrnFindTargetIndex(Relation table, + const char *columnName, + size_t columnNameSize) +{ + Relation index = InvalidRelation; + List *indexOIDList; + ListCell *cell; + + indexOIDList = RelationGetIndexList(table); + foreach(cell, indexOIDList) + { + Oid indexOID = lfirst_oid(cell); + bool isTargetIndex = false; + int i; + + index = index_open(indexOID, NoLock); + for (i = 1; i <= index->rd_att->natts; i++) + { + const char *name = index->rd_att->attrs[i - 1]->attname.data; + if (strlen(name) == columnNameSize && + memcmp(name, columnName, columnNameSize) == 0) + { + isTargetIndex = true; + break; + } + } + + if (isTargetIndex) + break; + + index_close(index, NoLock); + index = InvalidRelation; + } + list_free(indexOIDList); + + return index; +} + /** -* pgroonga.query_expand(term text) : text -*/ + * pgroonga.query_expand(tableName cstring, + * termColumnName text, + * synonymsColumnName text, + * query text) : text + */ Datum pgroonga_query_expand(PG_FUNCTION_ARGS) { - text *term = PG_GETARG_TEXT_PP(0); + Datum tableNameDatum = PG_GETARG_DATUM(0); + text *termColumnName = PG_GETARG_TEXT_PP(1); + text *synonymsColumnName = PG_GETARG_TEXT_PP(2); + Datum queryDatum = PG_GETARG_DATUM(3); + Datum tableOIDDatum; + Oid tableOID; + Relation table; + TupleDesc desc; + int i; + Form_pg_attribute synonymsAttribute = NULL; + Relation index; + grn_obj expandedQuery; + + tableOIDDatum = DirectFunctionCall1(regclassin, tableNameDatum); + if (!OidIsValid(tableOIDDatum)) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("pgroonga: query_expand: unknown table name: <%s>", + DatumGetCString(tableNameDatum)))); + } + tableOID = DatumGetObjectId(tableOIDDatum); - PG_RETURN_TEXT_P(term); + table = RelationIdGetRelation(tableOID); + desc = RelationGetDescr(table); + for (i = 1; i <= desc->natts; i++) + { + Form_pg_attribute attribute = desc->attrs[i - 1]; + if (strlen(attribute->attname.data) == + VARSIZE_ANY_EXHDR(synonymsColumnName) && + strncmp(attribute->attname.data, + VARDATA_ANY(synonymsColumnName), + VARSIZE_ANY_EXHDR(synonymsColumnName)) == 0) + { + synonymsAttribute = attribute; + break; + } + } + if (!synonymsAttribute) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("pgroonga: query_expand: " + "synonyms column doesn't exist: <%s>.<%.*s>", + DatumGetCString(tableNameDatum), + (int)VARSIZE_ANY_EXHDR(synonymsColumnName), + VARDATA_ANY(synonymsColumnName)))); + } + + index = PGrnFindTargetIndex(table, + VARDATA_ANY(termColumnName), + VARSIZE_ANY_EXHDR(termColumnName)); + if (!index) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("pgroonga: query_expand: " + "index for term column doesn't exist: <%s>.<%.*s>", + DatumGetCString(tableNameDatum), + (int)VARSIZE_ANY_EXHDR(termColumnName), + VARDATA_ANY(termColumnName)))); + } + + GRN_TEXT_INIT(&expandedQuery, 0); + { + Snapshot snapshot; + IndexScanDesc scan; + ScanKeyData scanKeys[1]; + HeapTuple tuple; + Datum synonymsDatum; + ArrayType *synonymsArray; + bool isNULL; + + snapshot = GetActiveSnapshot(); + scan = index_beginscan(table, index, snapshot, 1, 0); + ScanKeyInit(&(scanKeys[0]), + 1, + BTEqualStrategyNumber, + 67, // F_TEXTEQ + queryDatum); + index_rescan(scan, scanKeys, 1, NULL, 0); + tuple = index_getnext(scan, ForwardScanDirection); + synonymsDatum = heap_getattr(tuple, + synonymsAttribute->attnum, + desc, + &isNULL); + synonymsArray = DatumGetArrayTypeP(synonymsDatum); + { + int i, n; + + n = ARR_DIMS(synonymsArray)[0]; + for (i = 1; i <= n; i++) + { + Datum synonymDatum; + bool isNULL; + text *synonym; + + synonymDatum = array_ref(synonymsArray, 1, &i, -1, + synonymsAttribute->attlen, + synonymsAttribute->attbyval, + synonymsAttribute->attalign, + &isNULL); + synonym = DatumGetTextP(synonymDatum); + if (GRN_TEXT_LEN(&expandedQuery) > 0) + GRN_TEXT_PUTS(ctx, &expandedQuery, " OR "); + GRN_TEXT_PUT(ctx, &expandedQuery, + VARDATA_ANY(synonym), + VARSIZE_ANY_EXHDR(synonym)); + } + } + index_endscan(scan); + + index_close(index, NoLock); + } + + RelationClose(table); + + { + text *expandedQueryText; + + expandedQueryText = + cstring_to_text_with_len(GRN_TEXT_VALUE(&expandedQuery), + GRN_TEXT_LEN(&expandedQuery)); + GRN_OBJ_FIN(ctx, &expandedQuery); + + PG_RETURN_TEXT_P(expandedQueryText); + } } static void -------------- next part -------------- HTML����������������������������...Download