diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 4ecae71cd68c1f7c45d71433b4ab4e0fbd7f0867..d05eedceecf01aa51612c02c911c103bf705cdb5 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 55076ec48d34550b31e86b6ada8f98acf7f5cf4f..17b32cd4ab85d93802ca97ccce8fd89229512105 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 e3a59f4739a674a4b23ee072dba33b85caed2283..5066a556e4551cb9a15c17ae9d27e3593e23fcf4 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 b7c1a37069598e3a05223130dd365a2fa9033ea1..97d9aed24078a3e6f69173b03a764069c4ccd3ed 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 d261ac7f862ad26b580f76d42208dcfb8d8615bc..74d25c7db1b3b1bb3d3097a931dda7efce536b5d 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 b95002ef43e0ba428fb04a088b365b1247898995..5de4d19a5b831c7e00bd008082dcc412b1add0a2 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 64718a486991f1b6a08b3b05eb581a216010a72d..06f8917db60f9784f2184c5dbd166a7aa0798b91 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 a32ea871b58a2305e17065ed6b0469fa874bb45e..ced3233d21860d53bc0fe5478f5cc1efd776137a 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 9d4f80b727bfe67f8887078e5c4a7e8619241dad..ffc48a300a72a7f8804751e6742d7165224458ab 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 f6e4436d95078e059be3185636f5fca5aa7bef9a..2d86b48c4118d7cf2985f9c940b2b91c6e513a74 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 ee08082d5bd4bdec25aca7436ad1f3119f3785d4..219ac0262958a138afe459fcfa426d298a1ca652 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 c3bcdd5e3a66e6441ca0c3ac87519aeb105942c3..3bc800cef21c99b3a8cff41578202522d4630c46 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