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.
REL8_4_STABLE
Tom Lane 14 years ago
parent a2c2bbcd28
commit 81b4e5ceb6
  1. 15
      contrib/intarray/_int_tool.c
  2. 6
      contrib/intarray/expected/_int.out
  3. 1
      contrib/intarray/sql/_int.sql

@ -146,7 +146,8 @@ inner_int_inter(ArrayType *a, ArrayType *b)
*db, *db,
*dr; *dr;
int i, int i,
j; j,
k;
CHECKARRVALID(a); CHECKARRVALID(a);
CHECKARRVALID(b); CHECKARRVALID(b);
@ -161,27 +162,29 @@ inner_int_inter(ArrayType *a, ArrayType *b)
r = new_intArrayType(Min(na, nb)); r = new_intArrayType(Min(na, nb));
dr = ARRPTR(r); dr = ARRPTR(r);
i = j = 0; i = j = k = 0;
while (i < na && j < nb) while (i < na && j < nb)
{
if (da[i] < db[j]) if (da[i] < db[j])
i++; i++;
else if (da[i] == db[j]) else if (da[i] == db[j])
{ {
if (i + j == 0 || (i + j > 0 && *(dr - 1) != db[j])) if (k == 0 || dr[k - 1] != db[j])
*dr++ = db[j]; dr[k++] = db[j];
i++; i++;
j++; j++;
} }
else else
j++; j++;
}
if ((dr - ARRPTR(r)) == 0) if (k == 0)
{ {
pfree(r); pfree(r);
return new_intArrayType(0); return new_intArrayType(0);
} }
else else
return resize_intArrayType(r, dr - ARRPTR(r)); return resize_intArrayType(r, k);
} }
void void

@ -143,6 +143,12 @@ SELECT '{123,623,445}'::int[] & '{1623,623}';
{623} {623}
(1 row) (1 row)
SELECT '{-1,3,1}'::int[] & '{1,2}';
?column?
----------
{1}
(1 row)
--test query_int --test query_int
SELECT '1'::query_int; SELECT '1'::query_int;
query_int query_int

@ -32,6 +32,7 @@ SELECT '{123,623,445}'::int[] | 623;
SELECT '{123,623,445}'::int[] | 1623; SELECT '{123,623,445}'::int[] | 1623;
SELECT '{123,623,445}'::int[] | '{1623,623}'; SELECT '{123,623,445}'::int[] | '{1623,623}';
SELECT '{123,623,445}'::int[] & '{1623,623}'; SELECT '{123,623,445}'::int[] & '{1623,623}';
SELECT '{-1,3,1}'::int[] & '{1,2}';
--test query_int --test query_int

Loading…
Cancel
Save