]> granicus.if.org Git - postgresql/commitdiff
Add array_contains_nulls() function in arrayfuncs.c.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 9 Jan 2011 01:24:08 +0000 (20:24 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 9 Jan 2011 01:26:14 +0000 (20:26 -0500)
This will support fixing contrib/intarray (and probably other places)
so that they don't have to fail on arrays that contain a null bitmap
but no live null entries.

src/backend/utils/adt/arrayfuncs.c
src/include/utils/array.h

index fb4cbce23cc03b4306c26b36d58221b439352707..a1bcbe687fdc13e44917ad58cbc790f612090d6c 100644 (file)
@@ -2998,7 +2998,7 @@ deconstruct_array(ArrayType *array,
        nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
        *elemsp = elems = (Datum *) palloc(nelems * sizeof(Datum));
        if (nullsp)
-               *nullsp = nulls = (bool *) palloc(nelems * sizeof(bool));
+               *nullsp = nulls = (bool *) palloc0(nelems * sizeof(bool));
        else
                nulls = NULL;
        *nelemsp = nelems;
@@ -3023,8 +3023,6 @@ deconstruct_array(ArrayType *array,
                else
                {
                        elems[i] = fetch_att(p, elmbyval, elmlen);
-                       if (nulls)
-                               nulls[i] = false;
                        p = att_addlength_pointer(p, elmlen, p);
                        p = (char *) att_align_nominal(p, elmalign);
                }
@@ -3042,6 +3040,49 @@ deconstruct_array(ArrayType *array,
        }
 }
 
+/*
+ * array_contains_nulls --- detect whether an array has any null elements
+ *
+ * This gives an accurate answer, whereas testing ARR_HASNULL only tells
+ * if the array *might* contain a null.
+ */
+bool
+array_contains_nulls(ArrayType *array)
+{
+       int                     nelems;
+       bits8      *bitmap;
+       int                     bitmask;
+
+       /* Easy answer if there's no null bitmap */
+       if (!ARR_HASNULL(array))
+               return false;
+
+       nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
+
+       bitmap = ARR_NULLBITMAP(array);
+
+       /* check whole bytes of the bitmap byte-at-a-time */
+       while (nelems >= 8)
+       {
+               if (*bitmap != 0xFF)
+                       return true;
+               bitmap++;
+               nelems -= 8;
+       }
+
+       /* check last partial byte */
+       bitmask = 1;
+       while (nelems > 0)
+       {
+               if ((*bitmap & bitmask) == 0)
+                       return true;
+               bitmask <<= 1;
+               nelems--;
+       }
+
+       return false;
+}
+
 
 /*
  * array_eq :
index 78a4c8a72f3f078e6411c3524b460ff6323b771f..7f7e744cb12bc872f628f90dad99dfdf074eb314 100644 (file)
@@ -244,6 +244,7 @@ extern void deconstruct_array(ArrayType *array,
                                  Oid elmtype,
                                  int elmlen, bool elmbyval, char elmalign,
                                  Datum **elemsp, bool **nullsp, int *nelemsp);
+extern bool array_contains_nulls(ArrayType *array);
 extern ArrayBuildState *accumArrayResult(ArrayBuildState *astate,
                                 Datum dvalue, bool disnull,
                                 Oid element_type,