mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
First phase of work on array improvements. ARRAY[x,y,z] constructor
expressions, ARRAY(sub-SELECT) expressions, some array functions. Polymorphic functions using ANYARRAY/ANYELEMENT argument and return types. Some regression tests in place, documentation is lacking. Joe Conway, with some kibitzing from Tom Lane.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.146 2003/02/16 02:30:38 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.147 2003/04/08 23:20:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -395,7 +395,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
sublink->operOids = NIL;
|
||||
sublink->useOr = FALSE;
|
||||
}
|
||||
else if (sublink->subLinkType == EXPR_SUBLINK)
|
||||
else if (sublink->subLinkType == EXPR_SUBLINK ||
|
||||
sublink->subLinkType == ARRAY_SUBLINK)
|
||||
{
|
||||
List *tlist = qtree->targetList;
|
||||
|
||||
@ -413,8 +414,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
}
|
||||
|
||||
/*
|
||||
* EXPR needs no lefthand or combining operator. These
|
||||
* fields should be NIL already, but make sure.
|
||||
* EXPR and ARRAY need no lefthand or combining operator.
|
||||
* These fields should be NIL already, but make sure.
|
||||
*/
|
||||
sublink->lefthand = NIL;
|
||||
sublink->operName = NIL;
|
||||
@ -633,6 +634,98 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
break;
|
||||
}
|
||||
|
||||
case T_ArrayExpr:
|
||||
{
|
||||
ArrayExpr *a = (ArrayExpr *) expr;
|
||||
ArrayExpr *newa = makeNode(ArrayExpr);
|
||||
List *newelems = NIL;
|
||||
List *newcoercedelems = NIL;
|
||||
List *typeids = NIL;
|
||||
List *element;
|
||||
Oid array_type;
|
||||
Oid element_type;
|
||||
int ndims;
|
||||
|
||||
/* Transform the element expressions */
|
||||
foreach(element, a->elements)
|
||||
{
|
||||
Node *e = (Node *) lfirst(element);
|
||||
Node *newe;
|
||||
|
||||
newe = transformExpr(pstate, e);
|
||||
newelems = lappend(newelems, newe);
|
||||
typeids = lappendo(typeids, exprType(newe));
|
||||
}
|
||||
|
||||
/* Select a common type for the elements */
|
||||
element_type = select_common_type(typeids, "ARRAY");
|
||||
|
||||
/* Coerce arguments to common type if necessary */
|
||||
foreach(element, newelems)
|
||||
{
|
||||
Node *e = (Node *) lfirst(element);
|
||||
Node *newe;
|
||||
|
||||
newe = coerce_to_common_type(e, element_type, "ARRAY");
|
||||
newcoercedelems = lappend(newcoercedelems, newe);
|
||||
}
|
||||
|
||||
/* Do we have an array type to use? */
|
||||
array_type = get_array_type(element_type);
|
||||
if (array_type != InvalidOid)
|
||||
{
|
||||
/* Elements are presumably of scalar type */
|
||||
ndims = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Must be nested array expressions */
|
||||
array_type = element_type;
|
||||
element_type = get_element_type(array_type);
|
||||
if (!OidIsValid(element_type))
|
||||
elog(ERROR, "Cannot 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))
|
||||
elog(ERROR, "Multi-dimensional ARRAY[] must be built from nested array expressions");
|
||||
if (ndims == 0)
|
||||
ndims = e->ndims;
|
||||
else if (e->ndims != ndims)
|
||||
elog(ERROR, "Nested array expressions must have "
|
||||
"common number of dimensions");
|
||||
if (e->element_typeid != element_type)
|
||||
elog(ERROR, "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)
|
||||
elog(ERROR, "Number of array dimensions, %d, "
|
||||
"exceeds the maximum allowed %d",
|
||||
ndims, MAXDIM);
|
||||
}
|
||||
|
||||
newa->array_typeid = array_type;
|
||||
newa->element_typeid = element_type;
|
||||
newa->elements = newcoercedelems;
|
||||
newa->ndims = ndims;
|
||||
|
||||
result = (Node *) newa;
|
||||
break;
|
||||
}
|
||||
|
||||
case T_CoalesceExpr:
|
||||
{
|
||||
CoalesceExpr *c = (CoalesceExpr *) expr;
|
||||
@ -1018,7 +1111,8 @@ exprType(Node *expr)
|
||||
{
|
||||
SubLink *sublink = (SubLink *) expr;
|
||||
|
||||
if (sublink->subLinkType == EXPR_SUBLINK)
|
||||
if (sublink->subLinkType == EXPR_SUBLINK ||
|
||||
sublink->subLinkType == ARRAY_SUBLINK)
|
||||
{
|
||||
/* get the type of the subselect's first target column */
|
||||
Query *qtree = (Query *) sublink->subselect;
|
||||
@ -1029,7 +1123,15 @@ exprType(Node *expr)
|
||||
tent = (TargetEntry *) lfirst(qtree->targetList);
|
||||
Assert(IsA(tent, TargetEntry));
|
||||
Assert(!tent->resdom->resjunk);
|
||||
type = tent->resdom->restype;
|
||||
if (sublink->subLinkType == EXPR_SUBLINK)
|
||||
type = tent->resdom->restype;
|
||||
else /* ARRAY_SUBLINK */
|
||||
{
|
||||
type = get_array_type(tent->resdom->restype);
|
||||
if (!OidIsValid(type))
|
||||
elog(ERROR, "Cannot find array type for datatype %s",
|
||||
format_type_be(tent->resdom->restype));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1047,7 +1149,8 @@ exprType(Node *expr)
|
||||
*/
|
||||
SubPlan *subplan = (SubPlan *) expr;
|
||||
|
||||
if (subplan->subLinkType == EXPR_SUBLINK)
|
||||
if (subplan->subLinkType == EXPR_SUBLINK ||
|
||||
subplan->subLinkType == ARRAY_SUBLINK)
|
||||
{
|
||||
/* get the type of the subselect's first target column */
|
||||
TargetEntry *tent;
|
||||
@ -1055,7 +1158,15 @@ exprType(Node *expr)
|
||||
tent = (TargetEntry *) lfirst(subplan->plan->targetlist);
|
||||
Assert(IsA(tent, TargetEntry));
|
||||
Assert(!tent->resdom->resjunk);
|
||||
type = tent->resdom->restype;
|
||||
if (subplan->subLinkType == EXPR_SUBLINK)
|
||||
type = tent->resdom->restype;
|
||||
else /* ARRAY_SUBLINK */
|
||||
{
|
||||
type = get_array_type(tent->resdom->restype);
|
||||
if (!OidIsValid(type))
|
||||
elog(ERROR, "Cannot find array type for datatype %s",
|
||||
format_type_be(tent->resdom->restype));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1076,6 +1187,9 @@ exprType(Node *expr)
|
||||
case T_CaseWhen:
|
||||
type = exprType((Node *) ((CaseWhen *) expr)->result);
|
||||
break;
|
||||
case T_ArrayExpr:
|
||||
type = ((ArrayExpr *) expr)->array_typeid;
|
||||
break;
|
||||
case T_CoalesceExpr:
|
||||
type = ((CoalesceExpr *) expr)->coalescetype;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user