diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-02-16 20:00:11 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-02-16 20:00:11 -0500 |
commit | 06d9afa6f93ec08a45da4de7afd97bbf16738739 (patch) | |
tree | 2c9776a5c070be13f4a3a0c4c61c0c935c620449 | |
parent | 4767bc8ff2edc1258cf4d8a83155d4cedd724231 (diff) | |
download | postgresql-06d9afa6f93ec08a45da4de7afd97bbf16738739.tar.gz postgresql-06d9afa6f93ec08a45da4de7afd97bbf16738739.zip |
Fix longstanding error in contrib/intarray's int[] & int[] operator.
The array intersection code would give wrong results if the first entry of
the correct output array would be "1". (I think only this value could be
at risk, since the previous word would always be a lower-bound entry with
that fixed value.)
Problem spotted by Julien Rouhaud, initial patch by Guillaume Lelarge,
cosmetic improvements by me.
-rw-r--r-- | contrib/intarray/_int_tool.c | 13 | ||||
-rw-r--r-- | contrib/intarray/expected/_int.out | 6 | ||||
-rw-r--r-- | contrib/intarray/sql/_int.sql | 1 |
3 files changed, 14 insertions, 6 deletions
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c index 79f018d333b..132d1531605 100644 --- a/contrib/intarray/_int_tool.c +++ b/contrib/intarray/_int_tool.c @@ -140,7 +140,8 @@ inner_int_inter(ArrayType *a, ArrayType *b) *db, *dr; int i, - j; + j, + k; if (ARRISEMPTY(a) || ARRISEMPTY(b)) return new_intArrayType(0); @@ -152,15 +153,15 @@ inner_int_inter(ArrayType *a, ArrayType *b) r = new_intArrayType(Min(na, nb)); dr = ARRPTR(r); - i = j = 0; + i = j = k = 0; while (i < na && j < nb) { if (da[i] < db[j]) i++; else if (da[i] == db[j]) { - if (i + j == 0 || (i + j > 0 && *(dr - 1) != db[j])) - *dr++ = db[j]; + if (k == 0 || dr[k - 1] != db[j]) + dr[k++] = db[j]; i++; j++; } @@ -168,13 +169,13 @@ inner_int_inter(ArrayType *a, ArrayType *b) j++; } - if ((dr - ARRPTR(r)) == 0) + if (k == 0) { pfree(r); return new_intArrayType(0); } else - return resize_intArrayType(r, dr - ARRPTR(r)); + return resize_intArrayType(r, k); } void diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out index 6ed3cc6ced0..4080b9633fe 100644 --- a/contrib/intarray/expected/_int.out +++ b/contrib/intarray/expected/_int.out @@ -137,6 +137,12 @@ SELECT '{123,623,445}'::int[] & '{1623,623}'; {623} (1 row) +SELECT '{-1,3,1}'::int[] & '{1,2}'; + ?column? +---------- + {1} +(1 row) + --test query_int SELECT '1'::query_int; query_int diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql index b60e936dc52..216c5c58d61 100644 --- a/contrib/intarray/sql/_int.sql +++ b/contrib/intarray/sql/_int.sql @@ -24,6 +24,7 @@ SELECT '{123,623,445}'::int[] | 623; SELECT '{123,623,445}'::int[] | 1623; SELECT '{123,623,445}'::int[] | '{1623,623}'; SELECT '{123,623,445}'::int[] & '{1623,623}'; +SELECT '{-1,3,1}'::int[] & '{1,2}'; --test query_int |