From f0395d50e9486e1a5691fe4bfab92d4800460c83 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 6 Nov 2006 18:21:31 +0000
Subject: [PATCH] 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, 34 insertions(+), 5 deletions(-)

diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 943ae62d3d4..6559947bf1e 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.196 2006/10/06 17:13:59 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.197 2006/11/06 18:21:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2280,6 +2280,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 		int		   *elem_lbs = NULL;
 		bool		firstone = true;
 		bool		havenulls = false;
+		bool		haveempty = false;
 		char	  **subdata;
 		bits8	  **subbitmaps;
 		int		   *subbytes;
@@ -2302,11 +2303,15 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 			bool		eisnull;
 			Datum		arraydatum;
 			ArrayType  *array;
+			int			this_ndims;
 
 			arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
-			/* ignore null subarrays */
+			/* temporarily ignore null subarrays */
 			if (eisnull)
+			{
+				haveempty = true;
 				continue;
+			}
 
 			array = DatumGetArrayTypeP(arraydatum);
 
@@ -2320,10 +2325,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,
@@ -2341,7 +2354,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),
@@ -2356,13 +2369,29 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 			subbitmaps[outer_nelems] = ARR_NULLBITMAP(array);
 			subbytes[outer_nelems] = ARR_SIZE(array) - ARR_DATA_OFFSET(array);
 			nbytes += subbytes[outer_nelems];
-			subnitems[outer_nelems] = ArrayGetNItems(ARR_NDIM(array),
+			subnitems[outer_nelems] = ArrayGetNItems(this_ndims,
 													 ARR_DIMS(array));
 			nitems += subnitems[outer_nelems];
 			havenulls |= ARR_HASNULL(array);
 			outer_nelems++;
 		}
 
+		/*
+		 * If all items were null or 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 */
+				return PointerGetDatum(construct_empty_array(element_type));
+			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;
-- 
GitLab