From 06d9afa6f93ec08a45da4de7afd97bbf16738739 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 16 Feb 2012 20:00:11 -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 | 13 +++++++------ contrib/intarray/expected/_int.out | 6 ++++++ 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 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