| /* |
| * 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); |
| } |