aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-02-16 20:00:11 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2012-02-16 20:00:11 -0500
commit06d9afa6f93ec08a45da4de7afd97bbf16738739 (patch)
tree2c9776a5c070be13f4a3a0c4c61c0c935c620449
parent4767bc8ff2edc1258cf4d8a83155d4cedd724231 (diff)
downloadpostgresql-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.c13
-rw-r--r--contrib/intarray/expected/_int.out6
-rw-r--r--contrib/intarray/sql/_int.sql1
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