summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/tsginidx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/tsginidx.c')
-rw-r--r--src/backend/utils/adt/tsginidx.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c
new file mode 100644
index 00000000000..491dd21aa81
--- /dev/null
+++ b/src/backend/utils/adt/tsginidx.c
@@ -0,0 +1,157 @@
+/*-------------------------------------------------------------------------
+ *
+ * tsginidx.c
+ * GIN support functions for tsvector_ops
+ *
+ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/utils/adt/tsginidx.c,v 1.1 2007/08/21 01:11:19 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/skey.h"
+#include "tsearch/ts_type.h"
+#include "tsearch/ts_utils.h"
+
+
+Datum
+gin_extract_tsvector(PG_FUNCTION_ARGS)
+{
+ TSVector vector = PG_GETARG_TSVECTOR(0);
+ uint32 *nentries = (uint32 *) PG_GETARG_POINTER(1);
+ Datum *entries = NULL;
+
+ *nentries = 0;
+ if (vector->size > 0)
+ {
+ int i;
+ WordEntry *we = ARRPTR(vector);
+
+ *nentries = (uint32) vector->size;
+ entries = (Datum *) palloc(sizeof(Datum) * vector->size);
+
+ for (i = 0; i < vector->size; i++)
+ {
+ text *txt = (text *) palloc(VARHDRSZ + we->len);
+
+ SET_VARSIZE(txt, VARHDRSZ + we->len);
+ memcpy(VARDATA(txt), STRPTR(vector) + we->pos, we->len);
+
+ entries[i] = PointerGetDatum(txt);
+
+ we++;
+ }
+ }
+
+ PG_FREE_IF_COPY(vector, 0);
+ PG_RETURN_POINTER(entries);
+}
+
+Datum
+gin_extract_query(PG_FUNCTION_ARGS)
+{
+ TSQuery query = PG_GETARG_TSQUERY(0);
+ uint32 *nentries = (uint32 *) PG_GETARG_POINTER(1);
+ StrategyNumber strategy = PG_GETARG_UINT16(2);
+ Datum *entries = NULL;
+
+ *nentries = 0;
+
+ if (query->size > 0)
+ {
+ int4 i,
+ j = 0,
+ len;
+ QueryItem *item;
+
+ item = clean_NOT(GETQUERY(query), &len);
+ if (!item)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("query requires full scan, which is not supported by GIN indexes")));
+
+ item = GETQUERY(query);
+
+ for (i = 0; i < query->size; i++)
+ if (item[i].type == VAL)
+ (*nentries)++;
+
+ entries = (Datum *) palloc(sizeof(Datum) * (*nentries));
+
+ for (i = 0; i < query->size; i++)
+ if (item[i].type == VAL)
+ {
+ text *txt;
+
+ txt = (text *) palloc(VARHDRSZ + item[i].length);
+
+ SET_VARSIZE(txt, VARHDRSZ + item[i].length);
+ memcpy(VARDATA(txt), GETOPERAND(query) + item[i].distance, item[i].length);
+
+ entries[j++] = PointerGetDatum(txt);
+
+ if (strategy != TSearchWithClassStrategyNumber && item[i].weight != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("@@ operator does not support lexeme class restrictions"),
+ errhint("Use the @@@ operator instead.")));
+ }
+ }
+ else
+ *nentries = -1; /* nothing can be found */
+
+ PG_FREE_IF_COPY(query, 0);
+
+ PG_RETURN_POINTER(entries);
+}
+
+typedef struct
+{
+ QueryItem *frst;
+ bool *mapped_check;
+} GinChkVal;
+
+static bool
+checkcondition_gin(void *checkval, QueryItem * val)
+{
+ GinChkVal *gcv = (GinChkVal *) checkval;
+
+ return gcv->mapped_check[val - gcv->frst];
+}
+
+Datum
+gin_ts_consistent(PG_FUNCTION_ARGS)
+{
+ bool *check = (bool *) PG_GETARG_POINTER(0);
+ /* StrategyNumber strategy = PG_GETARG_UINT16(1); */
+ TSQuery query = PG_GETARG_TSQUERY(2);
+ bool res = FALSE;
+
+ if (query->size > 0)
+ {
+ int4 i,
+ j = 0;
+ QueryItem *item;
+ GinChkVal gcv;
+
+ gcv.frst = item = GETQUERY(query);
+ gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
+
+ for (i = 0; i < query->size; i++)
+ if (item[i].type == VAL)
+ gcv.mapped_check[i] = check[j++];
+
+ res = TS_execute(
+ GETQUERY(query),
+ &gcv,
+ true,
+ checkcondition_gin
+ );
+ }
+
+ PG_RETURN_BOOL(res);
+}