mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
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
This commit is contained in:
@ -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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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 @@
|
|||||||
* 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)
|
|||||||
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 @@
|
|||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
(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 @@
|
|||||||
* 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)
|
|||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
* 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)
|
|||||||
*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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200308171
|
#define CATALOG_VERSION_NO 200308172
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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
|
|||||||
/*
|
/*
|
||||||
* 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}";
|
|||||||
{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}";
|
|||||||
{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}}";
|
|||||||
{{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";
|
|||||||
-- 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]]];
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user