postgresql/contrib/intarray/_int_gin.c
Tom Lane 87b8db3774 Adjust the APIs for GIN opclass support functions to allow the extractQuery()
method to pass extra data to the consistent() and comparePartial() methods.
This is the core infrastructure needed to support the soon-to-appear
contrib/btree_gin module.  The APIs are still upward compatible with the
definitions used in 8.3 and before, although *not* with the previous 8.4devel
function definitions.

catversion bump for changes in pg_proc entries (although these are just
cosmetic, since GIN doesn't actually look at the function signature before
calling it...)

Teodor Sigaev and Oleg Bartunov
2009-03-25 22:19:02 +00:00

169 lines
3.6 KiB
C

/*
* $PostgreSQL: pgsql/contrib/intarray/_int_gin.c,v 1.9 2009/03/25 22:19:01 tgl Exp $
*/
#include "postgres.h"
#include "access/gist.h"
#include "access/skey.h"
#include "_int.h"
PG_FUNCTION_INFO_V1(ginint4_queryextract);
Datum ginint4_queryextract(PG_FUNCTION_ARGS);
Datum
ginint4_queryextract(PG_FUNCTION_ARGS)
{
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
StrategyNumber strategy = PG_GETARG_UINT16(2);
Datum *res = NULL;
*nentries = 0;
if (strategy == BooleanSearchStrategy)
{
QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
ITEM *items = GETQUERY(query);
int i;
if (query->size == 0)
PG_RETURN_POINTER(NULL);
if (shorterquery(items, query->size) == 0)
elog(ERROR, "Query requires full scan, GIN doesn't support it");
pfree(query);
query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
items = GETQUERY(query);
res = (Datum *) palloc(sizeof(Datum) * query->size);
*nentries = 0;
for (i = 0; i < query->size; i++)
if (items[i].type == VAL)
{
res[*nentries] = Int32GetDatum(items[i].val);
(*nentries)++;
}
}
else
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
int4 *arr;
uint32 i;
CHECKARRVALID(query);
*nentries = ARRNELEMS(query);
if (*nentries > 0)
{
res = (Datum *) palloc(sizeof(Datum) * (*nentries));
arr = ARRPTR(query);
for (i = 0; i < *nentries; i++)
res[i] = Int32GetDatum(arr[i]);
}
}
if (nentries == 0)
{
switch (strategy)
{
case BooleanSearchStrategy:
case RTOverlapStrategyNumber:
*nentries = -1; /* nobody can be found */
break;
default: /* require fullscan: GIN can't find void
* arrays */
break;
}
}
PG_RETURN_POINTER(res);
}
PG_FUNCTION_INFO_V1(ginint4_consistent);
Datum ginint4_consistent(PG_FUNCTION_ARGS);
Datum
ginint4_consistent(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
/* int32 nkeys = PG_GETARG_INT32(3); */
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
bool *recheck = (bool *) PG_GETARG_POINTER(5);
bool res = FALSE;
/*
* we need not check array carefully, it's done by previous
* ginarrayextract call
*/
switch (strategy)
{
case RTOverlapStrategyNumber:
/* result is not lossy */
*recheck = false;
/* at least one element in check[] is true, so result = true */
res = TRUE;
break;
case RTContainedByStrategyNumber:
case RTOldContainedByStrategyNumber:
/* we will need recheck */
*recheck = true;
/* at least one element in check[] is true, so result = true */
res = TRUE;
break;
case RTSameStrategyNumber:
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
int i,
nentries = ARRNELEMS(query);
/* we will need recheck */
*recheck = true;
res = TRUE;
for (i = 0; i < nentries; i++)
if (!check[i])
{
res = FALSE;
break;
}
}
break;
case RTContainsStrategyNumber:
case RTOldContainsStrategyNumber:
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
int i,
nentries = ARRNELEMS(query);
/* result is not lossy */
*recheck = false;
res = TRUE;
for (i = 0; i < nentries; i++)
if (!check[i])
{
res = FALSE;
break;
}
}
break;
case BooleanSearchStrategy:
{
QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(2));
/* result is not lossy */
*recheck = false;
res = ginconsistent(query, check);
}
break;
default:
elog(ERROR, "ginint4_consistent: unknown strategy number: %d",
strategy);
}
PG_RETURN_BOOL(res);
}