1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-13 18:28:01 +03:00

Support assignment to subfields of composite columns in UPDATE and INSERT.

As a side effect, cause subscripts in INSERT targetlists to do something
more or less sensible; previously we evaluated such subscripts and then
effectively ignored them.  Another side effect is that UPDATE-ing an
element or slice of an array value that is NULL now produces a non-null
result, namely an array containing just the assigned-to positions.
This commit is contained in:
Tom Lane
2004-06-09 19:08:20 +00:00
parent 3a0df651da
commit 7e64dbc6b5
27 changed files with 1468 additions and 574 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.172 2004/05/30 23:40:35 neilc Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.173 2004/06/09 19:08:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -100,7 +100,6 @@ transformExpr(ParseState *pstate, Node *expr)
int paramno = pref->number;
ParseState *toppstate;
Param *param;
ListCell *fields;
/*
* Find topmost ParseState, which is where paramtype info
@@ -148,18 +147,6 @@ transformExpr(ParseState *pstate, Node *expr)
param->paramid = (AttrNumber) paramno;
param->paramtype = toppstate->p_paramtypes[paramno - 1];
result = (Node *) param;
/* handle qualification, if any */
foreach(fields, pref->fields)
{
result = ParseFuncOrColumn(pstate,
list_make1(lfirst(fields)),
list_make1(result),
false, false, true);
}
/* handle subscripts, if any */
result = transformIndirection(pstate, result,
pref->indirection);
break;
}
case T_A_Const:
@@ -173,23 +160,13 @@ transformExpr(ParseState *pstate, Node *expr)
con->typename);
break;
}
case T_ExprFieldSelect:
case T_A_Indirection:
{
ExprFieldSelect *efs = (ExprFieldSelect *) expr;
ListCell *fields;
A_Indirection *ind = (A_Indirection *) expr;
result = transformExpr(pstate, efs->arg);
/* handle qualification, if any */
foreach(fields, efs->fields)
{
result = ParseFuncOrColumn(pstate,
list_make1(lfirst(fields)),
list_make1(result),
false, false, true);
}
/* handle subscripts, if any */
result = transformExpr(pstate, ind->arg);
result = transformIndirection(pstate, result,
efs->indirection);
ind->indirection);
break;
}
case T_TypeCast:
@@ -961,6 +938,7 @@ transformExpr(ParseState *pstate, Node *expr)
case T_NullIfExpr:
case T_BoolExpr:
case T_FieldSelect:
case T_FieldStore:
case T_RelabelType:
case T_CaseTestExpr:
case T_CoerceToDomain:
@@ -983,15 +961,55 @@ transformExpr(ParseState *pstate, Node *expr)
static Node *
transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
{
if (indirection == NIL)
return basenode;
return (Node *) transformArraySubscripts(pstate,
basenode,
exprType(basenode),
exprTypmod(basenode),
indirection,
false,
NULL);
Node *result = basenode;
List *subscripts = NIL;
ListCell *i;
/*
* We have to split any field-selection operations apart from
* subscripting. Adjacent A_Indices nodes have to be treated
* as a single multidimensional subscript operation.
*/
foreach(i, indirection)
{
Node *n = lfirst(i);
if (IsA(n, A_Indices))
{
subscripts = lappend(subscripts, n);
}
else
{
Assert(IsA(n, String));
/* process subscripts before this field selection */
if (subscripts)
result = (Node *) transformArraySubscripts(pstate,
result,
exprType(result),
InvalidOid,
-1,
subscripts,
NULL);
subscripts = NIL;
result = ParseFuncOrColumn(pstate,
list_make1(n),
list_make1(result),
false, false, true);
}
}
/* process trailing subscripts, if any */
if (subscripts)
result = (Node *) transformArraySubscripts(pstate,
result,
exprType(result),
InvalidOid,
-1,
subscripts,
NULL);
return result;
}
static Node *
@@ -1051,17 +1069,15 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
}
/*
* Try to find the name as a relation ... but not if
* subscripts appear. Note also that only relations
* already entered into the rangetable will be
* Try to find the name as a relation. Note that only
* relations already entered into the rangetable will be
* recognized.
*
* This is a hack for backwards compatibility with
* PostQUEL-inspired syntax. The preferred form now
* is "rel.*".
*/
if (cref->indirection == NIL &&
refnameRangeTblEntry(pstate, NULL, name,
if (refnameRangeTblEntry(pstate, NULL, name,
&levels_up) != NULL)
node = transformWholeRowRef(pstate, NULL, name);
else
@@ -1172,7 +1188,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
break;
}
return transformIndirection(pstate, node, cref->indirection);
return node;
}
/*
@@ -1385,6 +1401,9 @@ exprType(Node *expr)
case T_FieldSelect:
type = ((FieldSelect *) expr)->resulttype;
break;
case T_FieldStore:
type = ((FieldStore *) expr)->resulttype;
break;
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;