From fc8c5fbf5d7763b070f50b1afa85c7f955a83d77 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 6 Nov 2006 18:21:47 +0000 Subject: Repair bug #2694 concerning an ARRAY[] construct whose inputs are empty sub-arrays. Per discussion, if all inputs are empty arrays then result must be an empty array too, whereas a mix of empty and nonempty arrays should (and already did) draw an error. In the back branches, the construct was strict: any NULL input immediately yielded a NULL output; so I left that behavior alone. HEAD was simply ignoring NULL sub-arrays, which doesn't seem very sensible. For lack of a better idea it now treats NULL sub-arrays the same as empty ones. --- src/backend/executor/execQual.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 5ff95e1087..91271423b0 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.171.4.1 2005/10/19 22:51:26 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.171.4.2 2006/11/06 18:21:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2170,6 +2170,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, int *elem_dims = NULL; int *elem_lbs = NULL; bool firstone = true; + bool haveempty = false; int i; /* loop through and get data area from each element */ @@ -2179,6 +2180,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, bool eisnull; Datum arraydatum; ArrayType *array; + int this_ndims; int elem_ndatabytes; arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL); @@ -2200,10 +2202,18 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, format_type_be(ARR_ELEMTYPE(array)), format_type_be(element_type)))); + this_ndims = ARR_NDIM(array); + /* temporarily ignore zero-dimensional subarrays */ + if (this_ndims <= 0) + { + haveempty = true; + continue; + } + if (firstone) { /* Get sub-array details from first member */ - elem_ndims = ARR_NDIM(array); + elem_ndims = this_ndims; ndims = elem_ndims + 1; if (ndims <= 0 || ndims > MAXDIM) ereport(ERROR, @@ -2221,7 +2231,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, else { /* Check other sub-arrays are compatible */ - if (elem_ndims != ARR_NDIM(array) || + if (elem_ndims != this_ndims || memcmp(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)) != 0 || memcmp(elem_lbs, ARR_LBOUND(array), @@ -2244,6 +2254,29 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, elem_ndatabytes); } + /* + * If all items were empty arrays, return an empty array; + * otherwise, if some were and some weren't, raise error. (Note: + * we must special-case this somehow to avoid trying to generate + * a 1-D array formed from empty arrays. It's not ideal...) + */ + if (haveempty) + { + if (ndims == 0) /* didn't find any nonempty array */ + { + result = (ArrayType *) palloc(sizeof(ArrayType)); + result->size = sizeof(ArrayType); + result->ndim = 0; + result->flags = 0; + result->elemtype = element_type; + return PointerGetDatum(result); + } + ereport(ERROR, + (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), + errmsg("multidimensional arrays must have array " + "expressions with matching dimensions"))); + } + /* setup for multi-D array */ dims[0] = outer_nelems; lbs[0] = 1; -- cgit v1.2.1