postgresql/contrib/pg_trgm/trgm_gin.c

110 lines
2.6 KiB
C

/*
* $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gin.c,v 1.6 2008/11/12 13:43:54 teodor Exp $
*/
#include "trgm.h"
#include "access/gin.h"
#include "access/itup.h"
#include "access/tuptoaster.h"
#include "storage/bufpage.h"
#include "utils/array.h"
#include "utils/builtins.h"
PG_FUNCTION_INFO_V1(gin_extract_trgm);
Datum gin_extract_trgm(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gin_trgm_consistent);
Datum gin_trgm_consistent(PG_FUNCTION_ARGS);
Datum
gin_extract_trgm(PG_FUNCTION_ARGS)
{
text *val = (text *) PG_GETARG_TEXT_P(0);
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
Datum *entries = NULL;
TRGM *trg;
int4 trglen;
*nentries = 0;
trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
trglen = ARRNELEM(trg);
if (trglen > 0)
{
trgm *ptr;
int4 i = 0,
item;
*nentries = (int32) trglen;
entries = (Datum *) palloc(sizeof(Datum) * trglen);
ptr = GETARR(trg);
while (ptr - GETARR(trg) < ARRNELEM(trg))
{
item = trgm2int(ptr);
entries[i++] = Int32GetDatum(item);
ptr++;
}
}
PG_RETURN_POINTER(entries);
}
/*
* Per call strage for consistent functions to
* cache computed value from query
*/
typedef struct PerCallConsistentStorage {
int trglen;
text data[1]; /* query */
} PerCallConsistentStorage;
#define PCCSHDR_SZ offsetof(PerCallConsistentStorage, data)
Datum
gin_trgm_consistent(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
/* StrategyNumber strategy = PG_GETARG_UINT16(1); */
text *query = PG_GETARG_TEXT_P(2);
bool *recheck = (bool *) PG_GETARG_POINTER(3);
bool res = FALSE;
int4 i,
trglen,
ntrue = 0;
PerCallConsistentStorage *pccs = (PerCallConsistentStorage*) fcinfo->flinfo->fn_extra;
/* All cases served by this function are inexact */
*recheck = true;
if ( pccs == NULL || VARSIZE(pccs->data) != VARSIZE(query) || memcmp( pccs->data, query, VARSIZE(query) ) !=0 )
{
TRGM *trg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
if ( pccs )
pfree(pccs);
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
VARSIZE(query) + PCCSHDR_SZ);
pccs = (PerCallConsistentStorage*) fcinfo->flinfo->fn_extra;
pccs->trglen = ARRNELEM(trg);
memcpy( pccs->data, query, VARSIZE(query) );
}
trglen = pccs->trglen;
for (i = 0; i < trglen; i++)
if (check[i])
ntrue++;
#ifdef DIVUNION
res = (trglen == ntrue) ? true : ((((((float4) ntrue) / ((float4) (trglen - ntrue)))) >= trgm_limit) ? true : false);
#else
res = (trglen == 0) ? false : ((((((float4) ntrue) / ((float4) trglen))) >= trgm_limit) ? true : false);
#endif
PG_RETURN_BOOL(res);
}