diff options
Diffstat (limited to 'contrib/tsearch2/ginidx.c')
-rw-r--r-- | contrib/tsearch2/ginidx.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/contrib/tsearch2/ginidx.c b/contrib/tsearch2/ginidx.c new file mode 100644 index 00000000000..0a4e04e64a9 --- /dev/null +++ b/contrib/tsearch2/ginidx.c @@ -0,0 +1,145 @@ +#include "postgres.h" + +#include <float.h> + +#include "access/gist.h" +#include "access/itup.h" +#include "access/tuptoaster.h" +#include "storage/bufpage.h" +#include "utils/array.h" +#include "utils/builtins.h" + +#include "tsvector.h" +#include "query.h" +#include "query_cleanup.h" + +PG_FUNCTION_INFO_V1(gin_extract_tsvector); +Datum gin_extract_tsvector(PG_FUNCTION_ARGS); + +Datum +gin_extract_tsvector(PG_FUNCTION_ARGS) { + tsvector *vector = (tsvector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(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 ); + + VARATT_SIZEP(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); +} + + +PG_FUNCTION_INFO_V1(gin_extract_tsquery); +Datum gin_extract_tsquery(PG_FUNCTION_ARGS); + +Datum +gin_extract_tsquery(PG_FUNCTION_ARGS) { + QUERYTYPE *query = (QUERYTYPE*) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + uint32 *nentries = (uint32*)PG_GETARG_POINTER(1); + StrategyNumber strategy = DatumGetUInt16( PG_GETARG_DATUM(2) ); + Datum *entries = NULL; + + *nentries = 0; + if ( query->size > 0 ) { + int4 i, j=0, len; + ITEM *item; + + item = clean_NOT_v2(GETQUERY(query), &len); + if ( !item ) + elog(ERROR,"Query requires full scan, GIN doesn't support it"); + + 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 ); + + VARATT_SIZEP(txt) = VARHDRSZ + item[i].length; + memcpy( VARDATA(txt), GETOPERAND( query ) + item[i].distance, item[i].length ); + + entries[j++] = PointerGetDatum( txt ); + + if ( strategy == 1 && item[i].weight != 0 ) + elog(ERROR,"With class of lexeme restrictions use @@@ operation"); + } + + } + + PG_FREE_IF_COPY(query, 0); + PG_RETURN_POINTER(entries); +} + +typedef struct { + ITEM *frst; + bool *mapped_check; +} GinChkVal; + +static bool +checkcondition_gin(void *checkval, ITEM * val) { + GinChkVal *gcv = (GinChkVal*)checkval; + + return gcv->mapped_check[ val - gcv->frst ]; +} + +PG_FUNCTION_INFO_V1(gin_ts_consistent); +Datum gin_ts_consistent(PG_FUNCTION_ARGS); + +Datum +gin_ts_consistent(PG_FUNCTION_ARGS) { + bool *check = (bool*)PG_GETARG_POINTER(0); + QUERYTYPE *query = (QUERYTYPE*) PG_DETOAST_DATUM(PG_GETARG_DATUM(2)); + bool res = FALSE; + + if ( query->size > 0 ) { + int4 i, j=0; + ITEM *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_FREE_IF_COPY(query, 2); + PG_RETURN_BOOL(res); +} + + |