]> granicus.if.org Git - postgresql/commitdiff
Fix longstanding error in contrib/intarray's int[] & int[] operator.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 17 Feb 2012 01:00:17 +0000 (20:00 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 17 Feb 2012 01:00:17 +0000 (20:00 -0500)
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
contrib/intarray/expected/_int.out
contrib/intarray/sql/_int.sql

index bfc55501dbcdd6f9ba361808b69a712207cb0031..94df98608de09ddd9c4200cdcf1b3e99ad3b2163 100644 (file)
@@ -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
index 6ed3cc6ced096e2e97665e76ceba7fc139415029..4080b9633fe98a91861684e0d82f1297c21b91af 100644 (file)
@@ -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 
index b60e936dc520d8308bd16e50681f061dc86e2dfe..216c5c58d615a7cd1a5fe3714c9a5c91fb255138 100644 (file)
@@ -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