diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index fb4cbce23c..a1bcbe687f 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -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 : diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 78a4c8a72f..7f7e744cb1 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -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,