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,