diff options
Diffstat (limited to 'src/backend/utils/adt/tsginidx.c')
-rw-r--r-- | src/backend/utils/adt/tsginidx.c | 157 |
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); +} |