[Groonga-commit] pgroonga/pgroonga at 0c2dad7 [master] pgroonga.query_expand: support find data from PostgreSQL table

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index