summaryrefslogtreecommitdiffstats
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.c180
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);
+}