summaryrefslogtreecommitdiff
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 b39ab82d43d..d0e68d0447f 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -492,6 +492,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}';
@@ -566,6 +572,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;
@@ -648,6 +660,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"
@@ -728,6 +746,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}';
@@ -802,6 +826,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}';
@@ -876,6 +906,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
@@ -968,4 +1004,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 2d4ed1c9ae2..5668ab40704 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -107,6 +107,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
@@ -124,6 +125,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
@@ -144,6 +146,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));
@@ -162,6 +165,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 );
@@ -178,6 +182,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 );
@@ -194,6 +199,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;
@@ -229,6 +235,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 665ff9b9810..ff456247cef 100644
--- a/src/backend/access/gin/ginlogic.c
+++ b/src/backend/access/gin/ginlogic.c
@@ -140,7 +140,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)
@@ -149,7 +151,7 @@ shimTriConsistentFn(GinScanKey key)
int maybeEntries[MAX_MAYBE_ENTRIES];
int i;
bool boolResult;
- bool recheck = false;
+ bool recheck;
GinTernaryValue curResult;
/*
@@ -169,8 +171,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);
@@ -179,6 +181,7 @@ shimTriConsistentFn(GinScanKey key)
for (i = 0; i < nmaybe; i++)
key->entryRes[maybeEntries[i]] = GIN_FALSE;
curResult = directBoolConsistentFn(key);
+ recheck = key->recheckCurItem;
for (;;)
{
@@ -200,13 +203,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;
}