aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/intarray/expected/_int.out42
-rw-r--r--contrib/intarray/sql/_int.sql7
-rw-r--r--src/backend/access/gin/ginlogic.c20
3 files changed, 64 insertions, 5 deletions
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
index 09ab23483f7..64d88787632 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -473,6 +473,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
SET enable_seqscan = off; -- not all of these would use index by default
CREATE INDEX text_idx on test__int using gist ( a gist__int_ops );
SELECT count(*) from test__int WHERE a && '{23,50}';
@@ -547,6 +553,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail
ERROR: input array is too big (199 maximum allowed, 1001 current), use gist__intbig_ops opclass instead
DROP INDEX text_idx;
@@ -629,6 +641,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 0));
ERROR: value 0 out of bounds for option "siglen"
@@ -709,6 +727,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops );
SELECT count(*) from test__int WHERE a && '{23,50}';
@@ -783,6 +807,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gin ( a gin__int_ops );
SELECT count(*) from test__int WHERE a && '{23,50}';
@@ -857,6 +887,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
DROP INDEX text_idx;
-- Repeat the same queries with an extended data set. The data set is the
-- same that we used before, except that each element in the array is
@@ -949,4 +985,10 @@ SELECT count(*) from more__int WHERE a @@ '!20 & !21';
6344
(1 row)
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
+ count
+-------
+ 12
+(1 row)
+
RESET enable_seqscan;
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql
index 95eec96c14e..ba4c298151a 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -92,6 +92,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from test__int WHERE a @@ '20 | !21';
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
SET enable_seqscan = off; -- not all of these would use index by default
@@ -109,6 +110,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from test__int WHERE a @@ '20 | !21';
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail
@@ -129,6 +131,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from test__int WHERE a @@ '20 | !21';
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 0));
@@ -147,6 +150,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from test__int WHERE a @@ '20 | !21';
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops );
@@ -163,6 +167,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from test__int WHERE a @@ '20 | !21';
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
DROP INDEX text_idx;
CREATE INDEX text_idx on test__int using gin ( a gin__int_ops );
@@ -179,6 +184,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from test__int WHERE a @@ '20 | !21';
SELECT count(*) from test__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
DROP INDEX text_idx;
@@ -214,6 +220,7 @@ SELECT count(*) from more__int WHERE a @> '{20,23}' or a @> '{50,68}';
SELECT count(*) from more__int WHERE a @@ '(20&23)|(50&68)';
SELECT count(*) from more__int WHERE a @@ '20 | !21';
SELECT count(*) from more__int WHERE a @@ '!20 & !21';
+SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
RESET enable_seqscan;
diff --git a/src/backend/access/gin/ginlogic.c b/src/backend/access/gin/ginlogic.c
index bcbc26efdb6..81fc4e67515 100644
--- a/src/backend/access/gin/ginlogic.c
+++ b/src/backend/access/gin/ginlogic.c
@@ -146,7 +146,9 @@ shimBoolConsistentFn(GinScanKey key)
* every combination is O(n^2), so this is only feasible for a small number of
* MAYBE inputs.
*
- * NB: This function modifies the key->entryRes array!
+ * NB: This function modifies the key->entryRes array. For now that's okay
+ * so long as we restore the entry-time contents before returning. This may
+ * need revisiting if we ever invent multithreaded GIN scans, though.
*/
static GinTernaryValue
shimTriConsistentFn(GinScanKey key)
@@ -155,7 +157,7 @@ shimTriConsistentFn(GinScanKey key)
int maybeEntries[MAX_MAYBE_ENTRIES];
int i;
bool boolResult;
- bool recheck = false;
+ bool recheck;
GinTernaryValue curResult;
/*
@@ -175,8 +177,8 @@ shimTriConsistentFn(GinScanKey key)
}
/*
- * If none of the inputs were MAYBE, so we can just call consistent
- * function as is.
+ * If none of the inputs were MAYBE, we can just call the consistent
+ * function as-is.
*/
if (nmaybe == 0)
return directBoolConsistentFn(key);
@@ -185,6 +187,7 @@ shimTriConsistentFn(GinScanKey key)
for (i = 0; i < nmaybe; i++)
key->entryRes[maybeEntries[i]] = GIN_FALSE;
curResult = directBoolConsistentFn(key);
+ recheck = key->recheckCurItem;
for (;;)
{
@@ -206,13 +209,20 @@ shimTriConsistentFn(GinScanKey key)
recheck |= key->recheckCurItem;
if (curResult != boolResult)
- return GIN_MAYBE;
+ {
+ curResult = GIN_MAYBE;
+ break;
+ }
}
/* TRUE with recheck is taken to mean MAYBE */
if (curResult == GIN_TRUE && recheck)
curResult = GIN_MAYBE;
+ /* We must restore the original state of the entryRes array */
+ for (i = 0; i < nmaybe; i++)
+ key->entryRes[maybeEntries[i]] = GIN_MAYBE;
+
return curResult;
}