From e945246321506732ac9d2cab74b49782e12c4768 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 17 Aug 2003 23:43:27 +0000
Subject: [PATCH] Fix ARRAY[] construct so that in multidimensional case,
 elements can be anything yielding an array of the proper kind, not only
 sub-ARRAY[] constructs; do subscript checking at runtime not parse time. 
 Also, adjust array_cat to make array || array comply with the SQL99 spec.

Joe Conway
---
 src/backend/executor/execQual.c         | 33 ++++++++----
 src/backend/nodes/copyfuncs.c           |  4 +-
 src/backend/nodes/equalfuncs.c          |  4 +-
 src/backend/nodes/outfuncs.c            |  4 +-
 src/backend/nodes/readfuncs.c           |  4 +-
 src/backend/optimizer/util/clauses.c    |  4 +-
 src/backend/parser/parse_expr.c         | 43 ++-------------
 src/backend/utils/adt/array_userfuncs.c | 70 ++++++++++++++-----------
 src/include/catalog/catversion.h        |  4 +-
 src/include/nodes/primnodes.h           | 14 ++---
 src/test/regress/expected/arrays.out    | 30 +++++------
 src/test/regress/sql/arrays.sql         |  6 +--
 12 files changed, 105 insertions(+), 115 deletions(-)

diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 4ecae71cd68..d05eedceecf 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.141 2003/08/08 21:41:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.142 2003/08/17 23:43:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1620,16 +1620,18 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 	ArrayType  *result;
 	List	   *element;
 	Oid			element_type = arrayExpr->element_typeid;
-	int			ndims = arrayExpr->ndims;
+	int			ndims = 0;
 	int			dims[MAXDIM];
 	int			lbs[MAXDIM];
 
-	if (ndims == 1)
+	if (!arrayExpr->multidims)
 	{
+		/* Elements are presumably of scalar type */
 		int			nelems;
 		Datum	   *dvalues;
 		int			i = 0;
 
+		ndims = 1;
 		nelems = length(astate->elements);
 
 		/* Shouldn't happen here, but if length is 0, return NULL */
@@ -1667,6 +1669,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 	}
 	else
 	{
+		/* Must be nested array expressions */
 		char	   *dat = NULL;
 		Size		ndatabytes = 0;
 		int			nbytes;
@@ -1677,12 +1680,6 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 		bool		firstone = true;
 		int			i;
 
-		if (ndims <= 0 || ndims > MAXDIM)
-			ereport(ERROR,
-					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
-					 errmsg("number of array dimensions exceeds the maximum allowed, %d",
-							MAXDIM)));
-
 		/* loop through and get data area from each element */
 		foreach(element, astate->elements)
 		{
@@ -1701,14 +1698,32 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
 
 			array = DatumGetArrayTypeP(arraydatum);
 
+			/* run-time double-check on element type */
+			if (element_type != ARR_ELEMTYPE(array))
+				ereport(ERROR,
+						(errcode(ERRCODE_DATATYPE_MISMATCH),
+						 errmsg("cannot merge incompatible arrays"),
+						 errdetail("Array with element type %s cannot be "
+								   "included in ARRAY construct with element type %s.",
+								   format_type_be(ARR_ELEMTYPE(array)),
+								   format_type_be(element_type))));
+
 			if (firstone)
 			{
 				/* Get sub-array details from first member */
 				elem_ndims = ARR_NDIM(array);
+				ndims = elem_ndims + 1;
+				if (ndims <= 0 || ndims > MAXDIM)
+					ereport(ERROR,
+							(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+							 errmsg("number of array dimensions exceeds " \
+									"the maximum allowed, %d", MAXDIM)));
+
 				elem_dims = (int *) palloc(elem_ndims * sizeof(int));
 				memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
 				elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
 				memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
+
 				firstone = false;
 			}
 			else
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 55076ec48d3..17b32cd4ab8 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.264 2003/08/17 19:58:05 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.265 2003/08/17 23:43:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -947,7 +947,7 @@ _copyArrayExpr(ArrayExpr *from)
 	COPY_SCALAR_FIELD(array_typeid);
 	COPY_SCALAR_FIELD(element_typeid);
 	COPY_NODE_FIELD(elements);
-	COPY_SCALAR_FIELD(ndims);
+	COPY_SCALAR_FIELD(multidims);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e3a59f4739a..5066a556e45 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.208 2003/08/17 19:58:05 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.209 2003/08/17 23:43:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -409,7 +409,7 @@ _equalArrayExpr(ArrayExpr *a, ArrayExpr *b)
 	COMPARE_SCALAR_FIELD(array_typeid);
 	COMPARE_SCALAR_FIELD(element_typeid);
 	COMPARE_NODE_FIELD(elements);
-	COMPARE_SCALAR_FIELD(ndims);
+	COMPARE_SCALAR_FIELD(multidims);
 
 	return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index b7c1a370695..97d9aed2407 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.217 2003/08/08 21:41:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.218 2003/08/17 23:43:26 tgl Exp $
  *
  * NOTES
  *	  Every node type that can appear in stored rules' parsetrees *must*
@@ -785,7 +785,7 @@ _outArrayExpr(StringInfo str, ArrayExpr *node)
 	WRITE_OID_FIELD(array_typeid);
 	WRITE_OID_FIELD(element_typeid);
 	WRITE_NODE_FIELD(elements);
-	WRITE_INT_FIELD(ndims);
+	WRITE_BOOL_FIELD(multidims);
 }
 
 static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index d261ac7f862..74d25c7db1b 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.161 2003/08/04 02:39:59 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.162 2003/08/17 23:43:26 tgl Exp $
  *
  * NOTES
  *	  Path and Plan nodes do not have any readfuncs support, because we
@@ -659,7 +659,7 @@ _readArrayExpr(void)
 	READ_OID_FIELD(array_typeid);
 	READ_OID_FIELD(element_typeid);
 	READ_NODE_FIELD(elements);
-	READ_INT_FIELD(ndims);
+	READ_BOOL_FIELD(multidims);
 
 	READ_DONE();
 }
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index b95002ef43e..5de4d19a5b8 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.152 2003/08/08 21:41:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.153 2003/08/17 23:43:26 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1515,7 +1515,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
 		newarray->array_typeid = arrayexpr->array_typeid;
 		newarray->element_typeid = arrayexpr->element_typeid;
 		newarray->elements = FastListValue(&newelems);
-		newarray->ndims = arrayexpr->ndims;
+		newarray->multidims = arrayexpr->multidims;
 
 		if (all_const)
 			return (Node *) evaluate_expr((Expr *) newarray,
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 64718a48699..06f8917db60 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.160 2003/08/04 02:40:01 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.161 2003/08/17 23:43:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -748,7 +748,6 @@ transformExpr(ParseState *pstate, Node *expr)
 				List	   *element;
 				Oid			array_type;
 				Oid			element_type;
-				int			ndims;
 
 				/* Transform the element expressions */
 				foreach(element, a->elements)
@@ -781,11 +780,13 @@ transformExpr(ParseState *pstate, Node *expr)
 				if (array_type != InvalidOid)
 				{
 					/* Elements are presumably of scalar type */
-					ndims = 1;
+					newa->multidims = false;
 				}
 				else
 				{
 					/* Must be nested array expressions */
+					newa->multidims = true;
+
 					array_type = element_type;
 					element_type = get_element_type(array_type);
 					if (!OidIsValid(element_type))
@@ -793,47 +794,11 @@ transformExpr(ParseState *pstate, Node *expr)
 								(errcode(ERRCODE_UNDEFINED_OBJECT),
 								 errmsg("could not find array type for datatype %s",
 										format_type_be(array_type))));
-
-					/*
-					 * make sure the element expressions all have the same
-					 * number of dimensions
-					 */
-					ndims = 0;
-					foreach(element, newcoercedelems)
-					{
-						ArrayExpr  *e = (ArrayExpr *) lfirst(element);
-
-						if (!IsA(e, ArrayExpr))
-							ereport(ERROR,
-									(errcode(ERRCODE_SYNTAX_ERROR),
-									 errmsg("multidimensional ARRAY[] must be built from nested array expressions")));
-						if (ndims == 0)
-							ndims = e->ndims;
-						else if (e->ndims != ndims)
-							ereport(ERROR,
-									(errcode(ERRCODE_SYNTAX_ERROR),
-									 errmsg("nested array expressions must have common number of dimensions")));
-						if (e->element_typeid != element_type)
-							ereport(ERROR,
-									(errcode(ERRCODE_SYNTAX_ERROR),
-									 errmsg("nested array expressions must have common element type")));
-
-					}
-					/* increment the number of dimensions */
-					ndims++;
-
-					/* make sure we don't have too many dimensions now */
-					if (ndims > MAXDIM)
-						ereport(ERROR,
-								(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
-								 errmsg("number of array dimensions exceeds the maximum allowed, %d",
-										MAXDIM)));
 				}
 
 				newa->array_typeid = array_type;
 				newa->element_typeid = element_type;
 				newa->elements = newcoercedelems;
-				newa->ndims = ndims;
 
 				result = (Node *) newa;
 				break;
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index a32ea871b58..ced3233d218 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -6,7 +6,7 @@
  * Copyright (c) 2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.7 2003/08/04 00:43:25 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.8 2003/08/17 23:43:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -132,7 +132,7 @@ array_push(PG_FUNCTION_ARGS)
 
 /*-----------------------------------------------------------------------------
  * array_cat :
- *		concatenate two nD arrays to form an (n+1)D array, or
+ *		concatenate two nD arrays to form an nD array, or
  *		push an (n-1)D array onto the end of an nD array
  *----------------------------------------------------------------------------
  */
@@ -154,6 +154,7 @@ array_cat(PG_FUNCTION_ARGS)
 			   *lbs2,
 				ndims2,
 				ndatabytes2;
+	int			i;
 	char	   *dat1,
 			   *dat2;
 	Oid			element_type;
@@ -164,11 +165,14 @@ array_cat(PG_FUNCTION_ARGS)
 	v1 = PG_GETARG_ARRAYTYPE_P(0);
 	v2 = PG_GETARG_ARRAYTYPE_P(1);
 
-	/*
-	 * We must have one of the following combinations of inputs: 1) one
-	 * empty array, and one non-empty array 2) both arrays empty 3) two
-	 * arrays with ndims1 == ndims2 4) ndims1 == ndims2 - 1 5) ndims1 ==
-	 * ndims2 + 1
+	/*----------
+	 * We must have one of the following combinations of inputs:
+	 * 1) one empty array, and one non-empty array
+	 * 2) both arrays empty
+	 * 3) two arrays with ndims1 == ndims2
+	 * 4) ndims1 == ndims2 - 1
+	 * 5) ndims1 == ndims2 + 1
+	 *----------
 	 */
 	ndims1 = ARR_NDIM(v1);
 	ndims2 = ARR_NDIM(v2);
@@ -185,8 +189,10 @@ array_cat(PG_FUNCTION_ARGS)
 	if (ndims2 == 0)
 		PG_RETURN_ARRAYTYPE_P(v1);
 
-	/* the rest fall into combo 2, 3, or 4 */
-	if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1)
+	/* the rest fall under rule 3, 4, or 5 */
+	if (ndims1 != ndims2 &&
+		ndims1 != ndims2 - 1 &&
+		ndims1 != ndims2 + 1)
 		ereport(ERROR,
 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 				 errmsg("cannot concatenate incompatible arrays"),
@@ -197,7 +203,7 @@ array_cat(PG_FUNCTION_ARGS)
 	element_type1 = ARR_ELEMTYPE(v1);
 	element_type2 = ARR_ELEMTYPE(v2);
 
-	/* Do we have a matching element types */
+	/* Check we have matching element types */
 	if (element_type1 != element_type2)
 		ereport(ERROR,
 				(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -223,29 +229,27 @@ array_cat(PG_FUNCTION_ARGS)
 	if (ndims1 == ndims2)
 	{
 		/*
-		 * resulting array has two element outer array made up of input
-		 * argument arrays
+		 * resulting array is made up of the elements (possibly arrays
+		 * themselves) of the input argument arrays
 		 */
-		int			i;
-
-		ndims = ndims1 + 1;
+		ndims = ndims1;
 		dims = (int *) palloc(ndims * sizeof(int));
 		lbs = (int *) palloc(ndims * sizeof(int));
 
-		dims[0] = 2;			/* outer array made up of two input arrays */
-		lbs[0] = 1;				/* start lower bound at 1 */
+		dims[0] = dims1[0] + dims2[0];
+		lbs[0] = lbs1[0];
 
-		for (i = 0; i < ndims1; i++)
+		for (i = 1; i < ndims; i++)
 		{
 			if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i])
 				ereport(ERROR,
 						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 						 errmsg("cannot concatenate incompatible arrays"),
-					errdetail("Arrays with differing dimensions are not "
-							  "compatible for concatenation.")));
+					errdetail("Arrays with differing element dimensions are "
+							  "not compatible for concatenation.")));
 
-			dims[i + 1] = dims1[i];
-			lbs[i + 1] = lbs1[i];
+			dims[i] = dims1[i];
+			lbs[i] = lbs1[i];
 		}
 	}
 	else if (ndims1 == ndims2 - 1)
@@ -255,15 +259,18 @@ array_cat(PG_FUNCTION_ARGS)
 		 * with the first argument appended to the front of the outer
 		 * dimension
 		 */
-		int			i;
-
 		ndims = ndims2;
-		dims = dims2;
-		lbs = lbs2;
+		dims = (int *) palloc(ndims * sizeof(int));
+		lbs = (int *) palloc(ndims * sizeof(int));
+		memcpy(dims, dims2, ndims * sizeof(int));
+		memcpy(lbs, lbs2, ndims * sizeof(int));
 
 		/* increment number of elements in outer array */
 		dims[0] += 1;
 
+		/* decrement outer array lower bound */
+		lbs[0] -= 1;
+
 		/* make sure the added element matches our existing elements */
 		for (i = 0; i < ndims1; i++)
 		{
@@ -276,17 +283,18 @@ array_cat(PG_FUNCTION_ARGS)
 		}
 	}
 	else
-/* (ndims1 == ndims2 + 1) */
 	{
 		/*
+		 * (ndims1 == ndims2 + 1)
+		 *
 		 * resulting array has the first argument as the outer array, with
 		 * the second argument appended to the end of the outer dimension
 		 */
-		int			i;
-
 		ndims = ndims1;
-		dims = dims1;
-		lbs = lbs1;
+		dims = (int *) palloc(ndims * sizeof(int));
+		lbs = (int *) palloc(ndims * sizeof(int));
+		memcpy(dims, dims1, ndims * sizeof(int));
+		memcpy(lbs, lbs1, ndims * sizeof(int));
 
 		/* increment number of elements in outer array */
 		dims[0] += 1;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 9d4f80b727b..ffc48a300a7 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.207 2003/08/17 19:58:06 tgl Exp $
+ * $Id: catversion.h,v 1.208 2003/08/17 23:43:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200308171
+#define CATALOG_VERSION_NO	200308172
 
 #endif
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index f6e4436d950..2d86b48c411 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.91 2003/08/11 23:04:50 tgl Exp $
+ * $Id: primnodes.h,v 1.92 2003/08/17 23:43:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -587,16 +587,18 @@ typedef struct CaseWhen
 /*
  * ArrayExpr - an ARRAY[] expression
  *
- * Note: if ndims > 1, then the array elements are all ArrayExprs of the
- * same type and ndims one less.
+ * Note: if multidims is false, the constituent expressions all yield the
+ * scalar type identified by element_typeid.  If multidims is true, the
+ * constituent expressions all yield arrays of element_typeid (ie, the same
+ * type as array_typeid); at runtime we must check for compatible subscripts.
  */
 typedef struct ArrayExpr
 {
 	Expr		xpr;
 	Oid			array_typeid;	/* type of expression result */
-	Oid			element_typeid; /* common type of expression elements */
-	List	   *elements;		/* the array elements */
-	int			ndims;			/* number of array dimensions */
+	Oid			element_typeid; /* common type of array elements */
+	List	   *elements;		/* the array elements or sub-arrays */
+	bool		multidims;		/* true if elements are sub-arrays */
 } ArrayExpr;
 
 /*
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index ee08082d5bd..219ac026295 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -190,10 +190,10 @@ SELECT array_prepend(6, array[42]) AS "{6,42}";
  {6,42}
 (1 row)
 
-SELECT array_cat(ARRAY[1,2], ARRAY[3,4]) AS "{{1,2},{3,4}}";
- {{1,2},{3,4}} 
----------------
- {{1,2},{3,4}}
+SELECT array_cat(ARRAY[1,2], ARRAY[3,4]) AS "{1,2,3,4}";
+ {1,2,3,4} 
+-----------
+ {1,2,3,4}
 (1 row)
 
 SELECT array_cat(ARRAY[1,2], ARRAY[[3,4],[5,6]]) AS "{{1,2},{3,4},{5,6}}";
@@ -233,16 +233,16 @@ SELECT 0 || ARRAY[1,2] AS "{0,1,2}";
  {0,1,2}
 (1 row)
 
-SELECT ARRAY[1,2] || ARRAY[3,4] AS "{{1,2},{3,4}}";
- {{1,2},{3,4}} 
----------------
- {{1,2},{3,4}}
+SELECT ARRAY[1,2] || ARRAY[3,4] AS "{1,2,3,4}";
+ {1,2,3,4} 
+-----------
+ {1,2,3,4}
 (1 row)
 
 SELECT ARRAY[[['hello','world']]] || ARRAY[[['happy','birthday']]] AS "ARRAY";
-                  ARRAY                   
-------------------------------------------
- {{{{hello,world}}},{{{happy,birthday}}}}
+                ARRAY                 
+--------------------------------------
+ {{{hello,world}},{{happy,birthday}}}
 (1 row)
 
 SELECT ARRAY[[1,2],[3,4]] || ARRAY[5,6] AS "{{1,2},{3,4},{5,6}}";
@@ -251,10 +251,10 @@ SELECT ARRAY[[1,2],[3,4]] || ARRAY[5,6] AS "{{1,2},{3,4},{5,6}}";
  {{1,2},{3,4},{5,6}}
 (1 row)
 
-SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{{0,0},{1,1},{2,2}}";
- {{0,0},{1,1},{2,2}} 
----------------------
- {{0,0},{1,1},{2,2}}
+SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{0,0,1,1,2,2}";
+ {0,0,1,1,2,2} 
+---------------
+ {0,0,1,1,2,2}
 (1 row)
 
 SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index c3bcdd5e3a6..3bc800cef21 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -132,7 +132,7 @@ SELECT ARRAY(select f2 from arrtest_f order by f2) AS "ARRAY";
 -- functions
 SELECT array_append(array[42], 6) AS "{42,6}";
 SELECT array_prepend(6, array[42]) AS "{6,42}";
-SELECT array_cat(ARRAY[1,2], ARRAY[3,4]) AS "{{1,2},{3,4}}";
+SELECT array_cat(ARRAY[1,2], ARRAY[3,4]) AS "{1,2,3,4}";
 SELECT array_cat(ARRAY[1,2], ARRAY[[3,4],[5,6]]) AS "{{1,2},{3,4},{5,6}}";
 SELECT array_cat(ARRAY[[3,4],[5,6]], ARRAY[1,2]) AS "{{3,4},{5,6},{1,2}}";
 
@@ -141,10 +141,10 @@ SELECT a FROM arrtest WHERE b = ARRAY[[[113,142],[1,147]]];
 SELECT NOT ARRAY[1.1,1.2,1.3] = ARRAY[1.1,1.2,1.3] AS "FALSE";
 SELECT ARRAY[1,2] || 3 AS "{1,2,3}";
 SELECT 0 || ARRAY[1,2] AS "{0,1,2}";
-SELECT ARRAY[1,2] || ARRAY[3,4] AS "{{1,2},{3,4}}";
+SELECT ARRAY[1,2] || ARRAY[3,4] AS "{1,2,3,4}";
 SELECT ARRAY[[['hello','world']]] || ARRAY[[['happy','birthday']]] AS "ARRAY";
 SELECT ARRAY[[1,2],[3,4]] || ARRAY[5,6] AS "{{1,2},{3,4},{5,6}}";
-SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{{0,0},{1,1},{2,2}}";
+SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{0,0,1,1,2,2}";
 SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
 
 -- array casts
-- 
GitLab