Commit e9452463 authored by Tom Lane's avatar Tom Lane

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
parent de9c553f
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -1620,16 +1620,18 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
ArrayType *result; ArrayType *result;
List *element; List *element;
Oid element_type = arrayExpr->element_typeid; Oid element_type = arrayExpr->element_typeid;
int ndims = arrayExpr->ndims; int ndims = 0;
int dims[MAXDIM]; int dims[MAXDIM];
int lbs[MAXDIM]; int lbs[MAXDIM];
if (ndims == 1) if (!arrayExpr->multidims)
{ {
/* Elements are presumably of scalar type */
int nelems; int nelems;
Datum *dvalues; Datum *dvalues;
int i = 0; int i = 0;
ndims = 1;
nelems = length(astate->elements); nelems = length(astate->elements);
/* Shouldn't happen here, but if length is 0, return NULL */ /* Shouldn't happen here, but if length is 0, return NULL */
...@@ -1667,6 +1669,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, ...@@ -1667,6 +1669,7 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
} }
else else
{ {
/* Must be nested array expressions */
char *dat = NULL; char *dat = NULL;
Size ndatabytes = 0; Size ndatabytes = 0;
int nbytes; int nbytes;
...@@ -1677,12 +1680,6 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, ...@@ -1677,12 +1680,6 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
bool firstone = true; bool firstone = true;
int i; 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 */ /* loop through and get data area from each element */
foreach(element, astate->elements) foreach(element, astate->elements)
{ {
...@@ -1701,14 +1698,32 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, ...@@ -1701,14 +1698,32 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
array = DatumGetArrayTypeP(arraydatum); 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) if (firstone)
{ {
/* Get sub-array details from first member */ /* Get sub-array details from first member */
elem_ndims = ARR_NDIM(array); 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)); elem_dims = (int *) palloc(elem_ndims * sizeof(int));
memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)); memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));
elem_lbs = (int *) palloc(elem_ndims * sizeof(int)); elem_lbs = (int *) palloc(elem_ndims * sizeof(int));
memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int)); memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));
firstone = false; firstone = false;
} }
else else
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -947,7 +947,7 @@ _copyArrayExpr(ArrayExpr *from)
COPY_SCALAR_FIELD(array_typeid); COPY_SCALAR_FIELD(array_typeid);
COPY_SCALAR_FIELD(element_typeid); COPY_SCALAR_FIELD(element_typeid);
COPY_NODE_FIELD(elements); COPY_NODE_FIELD(elements);
COPY_SCALAR_FIELD(ndims); COPY_SCALAR_FIELD(multidims);
return newnode; return newnode;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -409,7 +409,7 @@ _equalArrayExpr(ArrayExpr *a, ArrayExpr *b)
COMPARE_SCALAR_FIELD(array_typeid); COMPARE_SCALAR_FIELD(array_typeid);
COMPARE_SCALAR_FIELD(element_typeid); COMPARE_SCALAR_FIELD(element_typeid);
COMPARE_NODE_FIELD(elements); COMPARE_NODE_FIELD(elements);
COMPARE_SCALAR_FIELD(ndims); COMPARE_SCALAR_FIELD(multidims);
return true; return true;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -785,7 +785,7 @@ _outArrayExpr(StringInfo str, ArrayExpr *node) ...@@ -785,7 +785,7 @@ _outArrayExpr(StringInfo str, ArrayExpr *node)
WRITE_OID_FIELD(array_typeid); WRITE_OID_FIELD(array_typeid);
WRITE_OID_FIELD(element_typeid); WRITE_OID_FIELD(element_typeid);
WRITE_NODE_FIELD(elements); WRITE_NODE_FIELD(elements);
WRITE_INT_FIELD(ndims); WRITE_BOOL_FIELD(multidims);
} }
static void static void
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
...@@ -659,7 +659,7 @@ _readArrayExpr(void) ...@@ -659,7 +659,7 @@ _readArrayExpr(void)
READ_OID_FIELD(array_typeid); READ_OID_FIELD(array_typeid);
READ_OID_FIELD(element_typeid); READ_OID_FIELD(element_typeid);
READ_NODE_FIELD(elements); READ_NODE_FIELD(elements);
READ_INT_FIELD(ndims); READ_BOOL_FIELD(multidims);
READ_DONE(); READ_DONE();
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -1515,7 +1515,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns) ...@@ -1515,7 +1515,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
newarray->array_typeid = arrayexpr->array_typeid; newarray->array_typeid = arrayexpr->array_typeid;
newarray->element_typeid = arrayexpr->element_typeid; newarray->element_typeid = arrayexpr->element_typeid;
newarray->elements = FastListValue(&newelems); newarray->elements = FastListValue(&newelems);
newarray->ndims = arrayexpr->ndims; newarray->multidims = arrayexpr->multidims;
if (all_const) if (all_const)
return (Node *) evaluate_expr((Expr *) newarray, return (Node *) evaluate_expr((Expr *) newarray,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -748,7 +748,6 @@ transformExpr(ParseState *pstate, Node *expr)
List *element; List *element;
Oid array_type; Oid array_type;
Oid element_type; Oid element_type;
int ndims;
/* Transform the element expressions */ /* Transform the element expressions */
foreach(element, a->elements) foreach(element, a->elements)
...@@ -781,11 +780,13 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -781,11 +780,13 @@ transformExpr(ParseState *pstate, Node *expr)
if (array_type != InvalidOid) if (array_type != InvalidOid)
{ {
/* Elements are presumably of scalar type */ /* Elements are presumably of scalar type */
ndims = 1; newa->multidims = false;
} }
else else
{ {
/* Must be nested array expressions */ /* Must be nested array expressions */
newa->multidims = true;
array_type = element_type; array_type = element_type;
element_type = get_element_type(array_type); element_type = get_element_type(array_type);
if (!OidIsValid(element_type)) if (!OidIsValid(element_type))
...@@ -793,47 +794,11 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -793,47 +794,11 @@ transformExpr(ParseState *pstate, Node *expr)
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for datatype %s", errmsg("could not find array type for datatype %s",
format_type_be(array_type)))); 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->array_typeid = array_type;
newa->element_typeid = element_type; newa->element_typeid = element_type;
newa->elements = newcoercedelems; newa->elements = newcoercedelems;
newa->ndims = ndims;
result = (Node *) newa; result = (Node *) newa;
break; break;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2003, PostgreSQL Global Development Group * Copyright (c) 2003, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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) ...@@ -132,7 +132,7 @@ array_push(PG_FUNCTION_ARGS)
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
* array_cat : * 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 * push an (n-1)D array onto the end of an nD array
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
*/ */
...@@ -154,6 +154,7 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -154,6 +154,7 @@ array_cat(PG_FUNCTION_ARGS)
*lbs2, *lbs2,
ndims2, ndims2,
ndatabytes2; ndatabytes2;
int i;
char *dat1, char *dat1,
*dat2; *dat2;
Oid element_type; Oid element_type;
...@@ -164,11 +165,14 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -164,11 +165,14 @@ array_cat(PG_FUNCTION_ARGS)
v1 = PG_GETARG_ARRAYTYPE_P(0); v1 = PG_GETARG_ARRAYTYPE_P(0);
v2 = PG_GETARG_ARRAYTYPE_P(1); v2 = PG_GETARG_ARRAYTYPE_P(1);
/* /*----------
* We must have one of the following combinations of inputs: 1) one * We must have one of the following combinations of inputs:
* empty array, and one non-empty array 2) both arrays empty 3) two * 1) one empty array, and one non-empty array
* arrays with ndims1 == ndims2 4) ndims1 == ndims2 - 1 5) ndims1 == * 2) both arrays empty
* ndims2 + 1 * 3) two arrays with ndims1 == ndims2
* 4) ndims1 == ndims2 - 1
* 5) ndims1 == ndims2 + 1
*----------
*/ */
ndims1 = ARR_NDIM(v1); ndims1 = ARR_NDIM(v1);
ndims2 = ARR_NDIM(v2); ndims2 = ARR_NDIM(v2);
...@@ -185,8 +189,10 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -185,8 +189,10 @@ array_cat(PG_FUNCTION_ARGS)
if (ndims2 == 0) if (ndims2 == 0)
PG_RETURN_ARRAYTYPE_P(v1); PG_RETURN_ARRAYTYPE_P(v1);
/* the rest fall into combo 2, 3, or 4 */ /* the rest fall under rule 3, 4, or 5 */
if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1) if (ndims1 != ndims2 &&
ndims1 != ndims2 - 1 &&
ndims1 != ndims2 + 1)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("cannot concatenate incompatible arrays"), errmsg("cannot concatenate incompatible arrays"),
...@@ -197,7 +203,7 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -197,7 +203,7 @@ array_cat(PG_FUNCTION_ARGS)
element_type1 = ARR_ELEMTYPE(v1); element_type1 = ARR_ELEMTYPE(v1);
element_type2 = ARR_ELEMTYPE(v2); element_type2 = ARR_ELEMTYPE(v2);
/* Do we have a matching element types */ /* Check we have matching element types */
if (element_type1 != element_type2) if (element_type1 != element_type2)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
...@@ -223,29 +229,27 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -223,29 +229,27 @@ array_cat(PG_FUNCTION_ARGS)
if (ndims1 == ndims2) if (ndims1 == ndims2)
{ {
/* /*
* resulting array has two element outer array made up of input * resulting array is made up of the elements (possibly arrays
* argument arrays * themselves) of the input argument arrays
*/ */
int i; ndims = ndims1;
ndims = ndims1 + 1;
dims = (int *) palloc(ndims * sizeof(int)); dims = (int *) palloc(ndims * sizeof(int));
lbs = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int));
dims[0] = 2; /* outer array made up of two input arrays */ dims[0] = dims1[0] + dims2[0];
lbs[0] = 1; /* start lower bound at 1 */ 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]) if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i])
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("cannot concatenate incompatible arrays"), errmsg("cannot concatenate incompatible arrays"),
errdetail("Arrays with differing dimensions are not " errdetail("Arrays with differing element dimensions are "
"compatible for concatenation."))); "not compatible for concatenation.")));
dims[i + 1] = dims1[i]; dims[i] = dims1[i];
lbs[i + 1] = lbs1[i]; lbs[i] = lbs1[i];
} }
} }
else if (ndims1 == ndims2 - 1) else if (ndims1 == ndims2 - 1)
...@@ -255,15 +259,18 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -255,15 +259,18 @@ array_cat(PG_FUNCTION_ARGS)
* with the first argument appended to the front of the outer * with the first argument appended to the front of the outer
* dimension * dimension
*/ */
int i;
ndims = ndims2; ndims = ndims2;
dims = dims2; dims = (int *) palloc(ndims * sizeof(int));
lbs = lbs2; 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 */ /* increment number of elements in outer array */
dims[0] += 1; dims[0] += 1;
/* decrement outer array lower bound */
lbs[0] -= 1;
/* make sure the added element matches our existing elements */ /* make sure the added element matches our existing elements */
for (i = 0; i < ndims1; i++) for (i = 0; i < ndims1; i++)
{ {
...@@ -276,17 +283,18 @@ array_cat(PG_FUNCTION_ARGS) ...@@ -276,17 +283,18 @@ array_cat(PG_FUNCTION_ARGS)
} }
} }
else else
/* (ndims1 == ndims2 + 1) */
{ {
/* /*
* (ndims1 == ndims2 + 1)
*
* resulting array has the first argument as the outer array, with * resulting array has the first argument as the outer array, with
* the second argument appended to the end of the outer dimension * the second argument appended to the end of the outer dimension
*/ */
int i;
ndims = ndims1; ndims = ndims1;
dims = dims1; dims = (int *) palloc(ndims * sizeof(int));
lbs = lbs1; 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 */ /* increment number of elements in outer array */
dims[0] += 1; dims[0] += 1;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200308171 #define CATALOG_VERSION_NO 200308172
#endif #endif
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -587,16 +587,18 @@ typedef struct CaseWhen
/* /*
* ArrayExpr - an ARRAY[] expression * ArrayExpr - an ARRAY[] expression
* *
* Note: if ndims > 1, then the array elements are all ArrayExprs of the * Note: if multidims is false, the constituent expressions all yield the
* same type and ndims one less. * 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 typedef struct ArrayExpr
{ {
Expr xpr; Expr xpr;
Oid array_typeid; /* type of expression result */ Oid array_typeid; /* type of expression result */
Oid element_typeid; /* common type of expression elements */ Oid element_typeid; /* common type of array elements */
List *elements; /* the array elements */ List *elements; /* the array elements or sub-arrays */
int ndims; /* number of array dimensions */ bool multidims; /* true if elements are sub-arrays */
} ArrayExpr; } ArrayExpr;
/* /*
......
...@@ -190,10 +190,10 @@ SELECT array_prepend(6, array[42]) AS "{6,42}"; ...@@ -190,10 +190,10 @@ SELECT array_prepend(6, array[42]) AS "{6,42}";
{6,42} {6,42}
(1 row) (1 row)
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}";
{{1,2},{3,4}} {1,2,3,4}
--------------- -----------
{{1,2},{3,4}} {1,2,3,4}
(1 row) (1 row)
SELECT array_cat(ARRAY[1,2], ARRAY[[3,4],[5,6]]) AS "{{1,2},{3,4},{5,6}}"; 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}"; ...@@ -233,16 +233,16 @@ SELECT 0 || ARRAY[1,2] AS "{0,1,2}";
{0,1,2} {0,1,2}
(1 row) (1 row)
SELECT ARRAY[1,2] || ARRAY[3,4] AS "{{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,2},{3,4}} {1,2,3,4}
(1 row) (1 row)
SELECT ARRAY[[['hello','world']]] || ARRAY[[['happy','birthday']]] AS "ARRAY"; SELECT ARRAY[[['hello','world']]] || ARRAY[[['happy','birthday']]] AS "ARRAY";
ARRAY ARRAY
------------------------------------------ --------------------------------------
{{{{hello,world}}},{{{happy,birthday}}}} {{{hello,world}},{{happy,birthday}}}
(1 row) (1 row)
SELECT ARRAY[[1,2],[3,4]] || ARRAY[5,6] AS "{{1,2},{3,4},{5,6}}"; 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}}"; ...@@ -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,2},{3,4},{5,6}}
(1 row) (1 row)
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}";
{{0,0},{1,1},{2,2}} {0,0,1,1,2,2}
--------------------- ---------------
{{0,0},{1,1},{2,2}} {0,0,1,1,2,2}
(1 row) (1 row)
SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}"; SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
......
...@@ -132,7 +132,7 @@ SELECT ARRAY(select f2 from arrtest_f order by f2) AS "ARRAY"; ...@@ -132,7 +132,7 @@ SELECT ARRAY(select f2 from arrtest_f order by f2) AS "ARRAY";
-- functions -- functions
SELECT array_append(array[42], 6) AS "{42,6}"; SELECT array_append(array[42], 6) AS "{42,6}";
SELECT array_prepend(6, array[42]) AS "{6,42}"; 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[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}}"; 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]]]; ...@@ -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 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 ARRAY[1,2] || 3 AS "{1,2,3}";
SELECT 0 || ARRAY[1,2] AS "{0,1,2}"; 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[[['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[[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}"; SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
-- array casts -- array casts
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment