mirror of
https://github.com/postgres/postgres.git
synced 2025-11-21 00:42:43 +03:00
Tsearch2 functionality migrates to core. The bulk of this work is by
Oleg Bartunov and Teodor Sigaev, but I did a lot of editorializing, so anything that's broken is probably my fault. Documentation is nonexistent as yet, but let's land the patch so we can get some portability testing done.
This commit is contained in:
157
src/backend/utils/adt/tsginidx.c
Normal file
157
src/backend/utils/adt/tsginidx.c
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user