diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c index ea79c4bb51..5d46b6bc13 100644 --- a/contrib/intarray/_int_gist.c +++ b/contrib/intarray/_int_gist.c @@ -296,8 +296,7 @@ g_int_decompress(PG_FUNCTION_ARGS) ArrayType *in; int lenin; int *din; - int i, - j; + int i; in = DatumGetArrayTypeP(entry->key); @@ -341,9 +340,12 @@ g_int_decompress(PG_FUNCTION_ARGS) dr = ARRPTR(r); for (i = 0; i < lenin; i += 2) - for (j = din[i]; j <= din[i + 1]; j++) + { + /* use int64 for j in case din[i + 1] is INT_MAX */ + for (int64 j = din[i]; j <= din[i + 1]; j++) if ((!i) || *(dr - 1) != j) - *dr++ = j; + *dr++ = (int) j; + } if (in != (ArrayType *) DatumGetPointer(entry->key)) pfree(in); diff --git a/contrib/intarray/data/test__int.data b/contrib/intarray/data/test__int.data index b3903d0f33..0a7fac3c08 100644 --- a/contrib/intarray/data/test__int.data +++ b/contrib/intarray/data/test__int.data @@ -6998,3 +6998,4 @@ {173,208,229} {6,22,142,267,299} {22,122,173,245,293} +{1,2,101,102,201,202,2147483647} diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out index 2f33c7e18d..09ab23483f 100644 --- a/contrib/intarray/expected/_int.out +++ b/contrib/intarray/expected/_int.out @@ -464,13 +464,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from test__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) SET enable_seqscan = off; -- not all of these would use index by default @@ -538,13 +538,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from test__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail @@ -620,13 +620,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from test__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) DROP INDEX text_idx; @@ -700,13 +700,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from test__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) DROP INDEX text_idx; @@ -774,13 +774,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from test__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) DROP INDEX text_idx; @@ -848,13 +848,13 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from test__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) DROP INDEX text_idx; @@ -870,9 +870,10 @@ DROP INDEX text_idx; -- core that would reach the same codepaths. CREATE TABLE more__int AS SELECT -- Leave alone NULLs, empty arrays and the one row that we use to test - -- equality + -- equality; also skip INT_MAX CASE WHEN a IS NULL OR a = '{}' OR a = '{73,23,20}' THEN a ELSE - (select array_agg(u) || array_agg(u + 1000) || array_agg(u + 2000) from (select unnest(a) u) x) + (select array_agg(u) || array_agg(u + 1000) || array_agg(u + 2000) + from unnest(a) u where u < 2000000000) END AS a, a as b FROM test__int; CREATE INDEX ON more__int using gist (a gist__int_ops(numranges = 252)); @@ -939,13 +940,13 @@ SELECT count(*) from more__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from more__int WHERE a @@ '20 | !21'; count ------- - 6566 + 6567 (1 row) SELECT count(*) from more__int WHERE a @@ '!20 & !21'; count ------- - 6343 + 6344 (1 row) RESET enable_seqscan; diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql index bd3e01208d..95eec96c14 100644 --- a/contrib/intarray/sql/_int.sql +++ b/contrib/intarray/sql/_int.sql @@ -194,9 +194,10 @@ DROP INDEX text_idx; -- core that would reach the same codepaths. CREATE TABLE more__int AS SELECT -- Leave alone NULLs, empty arrays and the one row that we use to test - -- equality + -- equality; also skip INT_MAX CASE WHEN a IS NULL OR a = '{}' OR a = '{73,23,20}' THEN a ELSE - (select array_agg(u) || array_agg(u + 1000) || array_agg(u + 2000) from (select unnest(a) u) x) + (select array_agg(u) || array_agg(u + 1000) || array_agg(u + 2000) + from unnest(a) u where u < 2000000000) END AS a, a as b FROM test__int; CREATE INDEX ON more__int using gist (a gist__int_ops(numranges = 252));