diff options
Diffstat (limited to 'contrib/intarray/_int_gin.c')
-rw-r--r-- | contrib/intarray/_int_gin.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c new file mode 100644 index 0000000..b7958d8 --- /dev/null +++ b/contrib/intarray/_int_gin.c @@ -0,0 +1,180 @@ +/* + * contrib/intarray/_int_gin.c + */ +#include "postgres.h" + +#include "_int.h" +#include "access/gin.h" +#include "access/stratnum.h" + +PG_FUNCTION_INFO_V1(ginint4_queryextract); + +Datum +ginint4_queryextract(PG_FUNCTION_ARGS) +{ + int32 *nentries = (int32 *) PG_GETARG_POINTER(1); + StrategyNumber strategy = PG_GETARG_UINT16(2); + int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); + Datum *res = NULL; + + *nentries = 0; + + if (strategy == BooleanSearchStrategy) + { + QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0); + ITEM *items = GETQUERY(query); + int i; + + /* empty query must fail */ + if (query->size <= 0) + PG_RETURN_POINTER(NULL); + + /* + * If the query doesn't have any required primitive values (for + * instance, it's something like '! 42'), we have to do a full index + * scan. + */ + if (query_has_required_values(query)) + *searchMode = GIN_SEARCH_MODE_DEFAULT; + else + *searchMode = GIN_SEARCH_MODE_ALL; + + /* + * Extract all the VAL items as things we want GIN to check for. + */ + 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); + + CHECKARRVALID(query); + *nentries = ARRNELEMS(query); + if (*nentries > 0) + { + int32 *arr; + int32 i; + + res = (Datum *) palloc(sizeof(Datum) * (*nentries)); + + arr = ARRPTR(query); + for (i = 0; i < *nentries; i++) + res[i] = Int32GetDatum(arr[i]); + } + + switch (strategy) + { + case RTOverlapStrategyNumber: + *searchMode = GIN_SEARCH_MODE_DEFAULT; + break; + case RTContainedByStrategyNumber: + case RTOldContainedByStrategyNumber: + /* empty set is contained in everything */ + *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; + break; + case RTSameStrategyNumber: + if (*nentries > 0) + *searchMode = GIN_SEARCH_MODE_DEFAULT; + else + *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; + break; + case RTContainsStrategyNumber: + case RTOldContainsStrategyNumber: + if (*nentries > 0) + *searchMode = GIN_SEARCH_MODE_DEFAULT; + else /* everything contains the empty set */ + *searchMode = GIN_SEARCH_MODE_ALL; + break; + default: + elog(ERROR, "ginint4_queryextract: unknown strategy number: %d", + strategy); + } + } + + PG_RETURN_POINTER(res); +} + +PG_FUNCTION_INFO_V1(ginint4_consistent); + +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; + int32 i; + + 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: + /* we will need recheck */ + *recheck = true; + /* Must have all elements in check[] true */ + res = true; + for (i = 0; i < nkeys; i++) + { + if (!check[i]) + { + res = false; + break; + } + } + break; + case RTContainsStrategyNumber: + case RTOldContainsStrategyNumber: + /* result is not lossy */ + *recheck = false; + /* Must have all elements in check[] true */ + res = true; + for (i = 0; i < nkeys; i++) + { + if (!check[i]) + { + res = false; + break; + } + } + break; + case BooleanSearchStrategy: + { + QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2); + + /* result is not lossy */ + *recheck = false; + res = gin_bool_consistent(query, check); + } + break; + default: + elog(ERROR, "ginint4_consistent: unknown strategy number: %d", + strategy); + } + + PG_RETURN_BOOL(res); +} |