aboutsummaryrefslogtreecommitdiff
path: root/contrib/intarray/_int_gin.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/intarray/_int_gin.c')
-rw-r--r--contrib/intarray/_int_gin.c122
1 files changed, 68 insertions, 54 deletions
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
index b5ad69eba35..3ef5c4635a1 100644
--- a/contrib/intarray/_int_gin.c
+++ b/contrib/intarray/_int_gin.c
@@ -3,6 +3,7 @@
*/
#include "postgres.h"
+#include "access/gin.h"
#include "access/gist.h"
#include "access/skey.h"
@@ -16,66 +17,90 @@ 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 = (QUERYTYPE *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
ITEM *items = GETQUERY(query);
int i;
- if (query->size == 0)
+ /* empty query must fail */
+ 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);
-
+ /*
+ * 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);
- int4 *arr;
- uint32 i;
CHECKARRVALID(query);
*nentries = ARRNELEMS(query);
if (*nentries > 0)
{
+ int4 *arr;
+ int32 i;
+
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 */
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ break;
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ /* empty set is contained in everything */
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
break;
- default: /* require fullscan: GIN can't find void
- * arrays */
+ 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);
}
}
@@ -90,16 +115,11 @@ ginint4_consistent(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
-
- /* int32 nkeys = PG_GETARG_INT32(3); */
+ 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
- */
+ int32 i;
switch (strategy)
{
@@ -117,47 +137,41 @@ ginint4_consistent(PG_FUNCTION_ARGS)
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++)
{
- 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;
- }
+ 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++)
{
- 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;
- }
+ if (!check[i])
+ {
+ res = FALSE;
+ break;
+ }
}
break;
case BooleanSearchStrategy:
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(2));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2);
/* result is not lossy */
*recheck = false;
- res = ginconsistent(query, check);
+ res = gin_bool_consistent(query, check);
}
break;
default: