summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2012-02-17 01:00:11 +0000
committerTom Lane2012-02-17 01:00:11 +0000
commit06d9afa6f93ec08a45da4de7afd97bbf16738739 (patch)
tree2c9776a5c070be13f4a3a0c4c61c0c935c620449
parent4767bc8ff2edc1258cf4d8a83155d4cedd724231 (diff)
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 79f018d333..132d153160 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 6ed3cc6ced..4080b9633f 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 b60e936dc5..216c5c58d6 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