mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.183.2.3 2006/03/10 01:51:34 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.183.2.4 2006/11/06 18:21:38 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -2131,6 +2131,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 | 
				
			|||||||
		int		   *elem_dims = NULL;
 | 
							int		   *elem_dims = NULL;
 | 
				
			||||||
		int		   *elem_lbs = NULL;
 | 
							int		   *elem_lbs = NULL;
 | 
				
			||||||
		bool		firstone = true;
 | 
							bool		firstone = true;
 | 
				
			||||||
 | 
							bool		haveempty = false;
 | 
				
			||||||
		int			i;
 | 
							int			i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* loop through and get data area from each element */
 | 
							/* loop through and get data area from each element */
 | 
				
			||||||
@@ -2140,6 +2141,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 | 
				
			|||||||
			bool		eisnull;
 | 
								bool		eisnull;
 | 
				
			||||||
			Datum		arraydatum;
 | 
								Datum		arraydatum;
 | 
				
			||||||
			ArrayType  *array;
 | 
								ArrayType  *array;
 | 
				
			||||||
 | 
								int			this_ndims;
 | 
				
			||||||
			int			elem_ndatabytes;
 | 
								int			elem_ndatabytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
 | 
								arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);
 | 
				
			||||||
@@ -2161,10 +2163,18 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 | 
				
			|||||||
								   format_type_be(ARR_ELEMTYPE(array)),
 | 
													   format_type_be(ARR_ELEMTYPE(array)),
 | 
				
			||||||
								   format_type_be(element_type))));
 | 
													   format_type_be(element_type))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this_ndims = ARR_NDIM(array);
 | 
				
			||||||
 | 
								/* temporarily ignore zero-dimensional subarrays */
 | 
				
			||||||
 | 
								if (this_ndims <= 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									haveempty = true;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (firstone)
 | 
								if (firstone)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/* Get sub-array details from first member */
 | 
									/* Get sub-array details from first member */
 | 
				
			||||||
				elem_ndims = ARR_NDIM(array);
 | 
									elem_ndims = this_ndims;
 | 
				
			||||||
				ndims = elem_ndims + 1;
 | 
									ndims = elem_ndims + 1;
 | 
				
			||||||
				if (ndims <= 0 || ndims > MAXDIM)
 | 
									if (ndims <= 0 || ndims > MAXDIM)
 | 
				
			||||||
					ereport(ERROR,
 | 
										ereport(ERROR,
 | 
				
			||||||
@@ -2182,7 +2192,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 | 
				
			|||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/* Check other sub-arrays are compatible */
 | 
									/* Check other sub-arrays are compatible */
 | 
				
			||||||
				if (elem_ndims != ARR_NDIM(array) ||
 | 
									if (elem_ndims != this_ndims ||
 | 
				
			||||||
					memcmp(elem_dims, ARR_DIMS(array),
 | 
										memcmp(elem_dims, ARR_DIMS(array),
 | 
				
			||||||
						   elem_ndims * sizeof(int)) != 0 ||
 | 
											   elem_ndims * sizeof(int)) != 0 ||
 | 
				
			||||||
					memcmp(elem_lbs, ARR_LBOUND(array),
 | 
										memcmp(elem_lbs, ARR_LBOUND(array),
 | 
				
			||||||
@@ -2205,6 +2215,29 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 | 
				
			|||||||
				   elem_ndatabytes);
 | 
									   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 */
 | 
							/* setup for multi-D array */
 | 
				
			||||||
		dims[0] = outer_nelems;
 | 
							dims[0] = outer_nelems;
 | 
				
			||||||
		lbs[0] = 1;
 | 
							lbs[0] = 1;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user