From b0e1a4bd5e1d2057d0ddab9b93f2cccb538989dc Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 16 Feb 2012 20:00:34 -0500 Subject: [PATCH] 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. --- contrib/intarray/_int_tool.c | 15 +++++++++------ contrib/intarray/expected/_int.out | 6 ++++++ contrib/intarray/sql/_int.sql | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c index fead4ff30dc..1c6b7301a2b 100644 --- a/contrib/intarray/_int_tool.c +++ b/contrib/intarray/_int_tool.c @@ -139,7 +139,8 @@ inner_int_inter(ArrayType *a, ArrayType *b) *db, *dr; int i, - j; + j, + k; CHECKARRVALID(a); CHECKARRVALID(b); @@ -154,27 +155,29 @@ 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++; } else 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 596439d3149..ab28ad33de1 100644 --- a/contrib/intarray/expected/_int.out +++ b/contrib/intarray/expected/_int.out @@ -143,6 +143,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 1588e3b5145..d020c5fa8e3 100644 --- a/contrib/intarray/sql/_int.sql +++ b/contrib/intarray/sql/_int.sql @@ -32,6 +32,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