mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Merge Resdom nodes into TargetEntry nodes to simplify code and save a
few palloc's. I also chose to eliminate the restype and restypmod fields entirely, since they are redundant with information stored in the node's contained expression; re-examining the expression at need seems simpler and more reliable than trying to keep restype/restypmod up to date. initdb forced due to change in contents of stored rules.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.316 2005/03/10 23:21:23 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.317 2005/04/06 16:34:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -438,15 +438,12 @@ transformViewStmt(ParseState *pstate, ViewStmt *stmt,
|
||||
foreach(targetList, stmt->query->targetList)
|
||||
{
|
||||
TargetEntry *te = (TargetEntry *) lfirst(targetList);
|
||||
Resdom *rd;
|
||||
|
||||
Assert(IsA(te, TargetEntry));
|
||||
rd = te->resdom;
|
||||
Assert(IsA(rd, Resdom));
|
||||
/* junk columns don't get aliases */
|
||||
if (rd->resjunk)
|
||||
if (te->resjunk)
|
||||
continue;
|
||||
rd->resname = pstrdup(strVal(lfirst(alist_item)));
|
||||
te->resname = pstrdup(strVal(lfirst(alist_item)));
|
||||
alist_item = lnext(alist_item);
|
||||
if (alist_item == NULL)
|
||||
break; /* done assigning aliases */
|
||||
@@ -507,7 +504,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
{
|
||||
Query *qry = makeNode(Query);
|
||||
Query *selectQuery = NULL;
|
||||
bool copy_up_hack = false;
|
||||
List *sub_rtable;
|
||||
List *sub_namespace;
|
||||
List *icolumns;
|
||||
@@ -615,7 +611,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
* separate from the subquery's tlist because we may add columns,
|
||||
* insert datatype coercions, etc.)
|
||||
*
|
||||
* HACK: unknown-type constants and params in the INSERT's targetlist
|
||||
* HACK: unknown-type constants and params in the SELECT's targetlist
|
||||
* are copied up as-is rather than being referenced as subquery
|
||||
* outputs. This is to ensure that when we try to coerce them to
|
||||
* the target column's datatype, the right things happen (see
|
||||
@@ -627,28 +623,25 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
foreach(tl, selectQuery->targetList)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resnode = tle->resdom;
|
||||
Expr *expr;
|
||||
|
||||
if (resnode->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue;
|
||||
if (tle->expr &&
|
||||
(IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
|
||||
exprType((Node *) tle->expr) == UNKNOWNOID)
|
||||
{
|
||||
expr = tle->expr;
|
||||
copy_up_hack = true;
|
||||
}
|
||||
else
|
||||
expr = (Expr *) makeVar(rtr->rtindex,
|
||||
resnode->resno,
|
||||
resnode->restype,
|
||||
resnode->restypmod,
|
||||
tle->resno,
|
||||
exprType((Node *) tle->expr),
|
||||
exprTypmod((Node *) tle->expr),
|
||||
0);
|
||||
resnode = copyObject(resnode);
|
||||
resnode->resno = (AttrNumber) pstate->p_next_resno++;
|
||||
qry->targetList = lappend(qry->targetList,
|
||||
makeTargetEntry(resnode, expr));
|
||||
tle = makeTargetEntry(expr,
|
||||
(AttrNumber) pstate->p_next_resno++,
|
||||
tle->resname,
|
||||
false);
|
||||
qry->targetList = lappend(qry->targetList, tle);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -690,7 +683,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
col = (ResTarget *) lfirst(icols);
|
||||
Assert(IsA(col, ResTarget));
|
||||
|
||||
Assert(!tle->resdom->resjunk);
|
||||
Assert(!tle->resjunk);
|
||||
updateTargetListEntry(pstate, tle, col->name, lfirst_int(attnos),
|
||||
col->indirection);
|
||||
|
||||
@@ -708,28 +701,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("INSERT has more target columns than expressions")));
|
||||
|
||||
/*
|
||||
* If we copied up any unknown Params (see HACK above) then their
|
||||
* resolved types need to be propagated into the Resdom nodes of
|
||||
* the sub-INSERT's tlist. One hack begets another :-(
|
||||
*/
|
||||
if (copy_up_hack)
|
||||
{
|
||||
foreach(tl, selectQuery->targetList)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resnode = tle->resdom;
|
||||
|
||||
if (resnode->resjunk)
|
||||
continue;
|
||||
if (resnode->restype == UNKNOWNOID)
|
||||
{
|
||||
resnode->restype = exprType((Node *) tle->expr);
|
||||
resnode->restypmod = exprTypmod((Node *) tle->expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* done building the range table and jointree */
|
||||
qry->rtable = pstate->p_rtable;
|
||||
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
|
||||
@@ -2007,26 +1978,23 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
foreach(dtlist, sostmt->colTypes)
|
||||
{
|
||||
Oid colType = lfirst_oid(dtlist);
|
||||
Resdom *leftResdom;
|
||||
TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
|
||||
char *colName;
|
||||
Resdom *resdom;
|
||||
TargetEntry *tle;
|
||||
Expr *expr;
|
||||
|
||||
leftResdom = ((TargetEntry *) lfirst(left_tlist))->resdom;
|
||||
Assert(!leftResdom->resjunk);
|
||||
colName = pstrdup(leftResdom->resname);
|
||||
resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
|
||||
colType,
|
||||
-1,
|
||||
colName,
|
||||
false);
|
||||
Assert(!lefttle->resjunk);
|
||||
colName = pstrdup(lefttle->resname);
|
||||
expr = (Expr *) makeVar(leftmostRTI,
|
||||
leftResdom->resno,
|
||||
lefttle->resno,
|
||||
colType,
|
||||
-1,
|
||||
0);
|
||||
qry->targetList = lappend(qry->targetList,
|
||||
makeTargetEntry(resdom, expr));
|
||||
tle = makeTargetEntry(expr,
|
||||
(AttrNumber) pstate->p_next_resno++,
|
||||
colName,
|
||||
false);
|
||||
qry->targetList = lappend(qry->targetList, tle);
|
||||
targetvars = lappend(targetvars, expr);
|
||||
targetnames = lappend(targetnames, makeString(colName));
|
||||
left_tlist = lnext(left_tlist);
|
||||
@@ -2284,11 +2252,10 @@ getSetColTypes(ParseState *pstate, Node *node)
|
||||
foreach(tl, selectQuery->targetList)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resnode = tle->resdom;
|
||||
|
||||
if (resnode->resjunk)
|
||||
if (tle->resjunk)
|
||||
continue;
|
||||
result = lappend_oid(result, resnode->restype);
|
||||
result = lappend_oid(result, exprType((Node *) tle->expr));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -2324,8 +2291,8 @@ applyColumnNames(List *dst, List *src)
|
||||
TargetEntry *d = (TargetEntry *) lfirst(dst_item);
|
||||
ColumnDef *s = (ColumnDef *) lfirst(src_item);
|
||||
|
||||
Assert(d->resdom && !d->resdom->resjunk);
|
||||
d->resdom->resname = pstrdup(s->colname);
|
||||
Assert(!d->resjunk);
|
||||
d->resname = pstrdup(s->colname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2383,10 +2350,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
foreach(tl, qry->targetList)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resnode = tle->resdom;
|
||||
ResTarget *origTarget;
|
||||
|
||||
if (resnode->resjunk)
|
||||
if (tle->resjunk)
|
||||
{
|
||||
/*
|
||||
* Resjunk nodes need no additional processing, but be sure
|
||||
@@ -2394,8 +2360,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
* rewriter or planner might get confused. They don't need a
|
||||
* resname either.
|
||||
*/
|
||||
resnode->resno = (AttrNumber) pstate->p_next_resno++;
|
||||
resnode->resname = NULL;
|
||||
tle->resno = (AttrNumber) pstate->p_next_resno++;
|
||||
tle->resname = NULL;
|
||||
continue;
|
||||
}
|
||||
if (origTargetList == NULL)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.138 2004/12/31 22:00:27 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.139 2005/04/06 16:34:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1161,10 +1161,9 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
|
||||
foreach(tl, *tlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resnode = tle->resdom;
|
||||
|
||||
if (!resnode->resjunk &&
|
||||
strcmp(resnode->resname, name) == 0)
|
||||
if (!tle->resjunk &&
|
||||
strcmp(tle->resname, name) == 0)
|
||||
{
|
||||
if (target_result != NULL)
|
||||
{
|
||||
@@ -1204,9 +1203,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
|
||||
foreach(tl, *tlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resnode = tle->resdom;
|
||||
|
||||
if (!resnode->resjunk)
|
||||
if (!tle->resjunk)
|
||||
{
|
||||
if (++targetlist_pos == target_pos)
|
||||
return tle; /* return the unique match */
|
||||
@@ -1282,7 +1280,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
continue;
|
||||
|
||||
/* if tlist item is an UNKNOWN literal, change it to TEXT */
|
||||
restype = tle->resdom->restype;
|
||||
restype = exprType((Node *) tle->expr);
|
||||
|
||||
if (restype == UNKNOWNOID)
|
||||
{
|
||||
@@ -1290,8 +1288,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
restype, TEXTOID, -1,
|
||||
COERCION_IMPLICIT,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
restype = tle->resdom->restype = TEXTOID;
|
||||
tle->resdom->restypmod = -1;
|
||||
restype = TEXTOID;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1304,7 +1301,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
|
||||
*/
|
||||
if (sortItem &&
|
||||
((SortClause *) lfirst(sortItem))->tleSortGroupRef ==
|
||||
tle->resdom->ressortgroupref)
|
||||
tle->ressortgroupref)
|
||||
{
|
||||
ordering_op = ((SortClause *) lfirst(sortItem))->sortop;
|
||||
sortItem = lnext(sortItem);
|
||||
@@ -1405,7 +1402,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
SortClause *scl = (SortClause *) lfirst(slitem);
|
||||
TargetEntry *tle = get_sortgroupclause_tle(scl, *targetlist);
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
if (tle->resjunk)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("for SELECT DISTINCT, ORDER BY expressions must appear in select list")));
|
||||
@@ -1445,7 +1442,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
{
|
||||
SortClause *scl = (SortClause *) lfirst(nextsortlist);
|
||||
|
||||
if (tle->resdom->ressortgroupref != scl->tleSortGroupRef)
|
||||
if (tle->ressortgroupref != scl->tleSortGroupRef)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("SELECT DISTINCT ON expressions must match initial ORDER BY expressions")));
|
||||
@@ -1466,7 +1463,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
||||
{
|
||||
SortClause *scl = (SortClause *) lfirst(slitem);
|
||||
|
||||
if (tle->resdom->ressortgroupref == scl->tleSortGroupRef)
|
||||
if (tle->ressortgroupref == scl->tleSortGroupRef)
|
||||
{
|
||||
result = lappend(result, copyObject(scl));
|
||||
break;
|
||||
@@ -1501,7 +1498,7 @@ addAllTargetsToSortList(ParseState *pstate, List *sortlist,
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (!tle->resdom->resjunk)
|
||||
if (!tle->resjunk)
|
||||
sortlist = addTargetToSortList(pstate, tle,
|
||||
sortlist, targetlist,
|
||||
SORTBY_ASC, NIL,
|
||||
@@ -1533,7 +1530,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
|
||||
if (!targetIsInSortList(tle, sortlist))
|
||||
{
|
||||
SortClause *sortcl = makeNode(SortClause);
|
||||
Oid restype = tle->resdom->restype;
|
||||
Oid restype = exprType((Node *) tle->expr);
|
||||
|
||||
/* if tlist item is an UNKNOWN literal, change it to TEXT */
|
||||
if (restype == UNKNOWNOID && resolveUnknown)
|
||||
@@ -1542,8 +1539,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
|
||||
restype, TEXTOID, -1,
|
||||
COERCION_IMPLICIT,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
restype = tle->resdom->restype = TEXTOID;
|
||||
tle->resdom->restypmod = -1;
|
||||
restype = TEXTOID;
|
||||
}
|
||||
|
||||
sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
|
||||
@@ -1586,20 +1582,20 @@ assignSortGroupRef(TargetEntry *tle, List *tlist)
|
||||
Index maxRef;
|
||||
ListCell *l;
|
||||
|
||||
if (tle->resdom->ressortgroupref) /* already has one? */
|
||||
return tle->resdom->ressortgroupref;
|
||||
if (tle->ressortgroupref) /* already has one? */
|
||||
return tle->ressortgroupref;
|
||||
|
||||
/* easiest way to pick an unused refnumber: max used + 1 */
|
||||
maxRef = 0;
|
||||
foreach(l, tlist)
|
||||
{
|
||||
Index ref = ((TargetEntry *) lfirst(l))->resdom->ressortgroupref;
|
||||
Index ref = ((TargetEntry *) lfirst(l))->ressortgroupref;
|
||||
|
||||
if (ref > maxRef)
|
||||
maxRef = ref;
|
||||
}
|
||||
tle->resdom->ressortgroupref = maxRef + 1;
|
||||
return tle->resdom->ressortgroupref;
|
||||
tle->ressortgroupref = maxRef + 1;
|
||||
return tle->ressortgroupref;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1613,7 +1609,7 @@ assignSortGroupRef(TargetEntry *tle, List *tlist)
|
||||
bool
|
||||
targetIsInSortList(TargetEntry *tle, List *sortList)
|
||||
{
|
||||
Index ref = tle->resdom->ressortgroupref;
|
||||
Index ref = tle->ressortgroupref;
|
||||
ListCell *l;
|
||||
|
||||
/* no need to scan list if tle has no marker */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.180 2005/01/19 23:45:24 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.181 2005/04/06 16:34:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -960,13 +960,13 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
* resjunk targets).
|
||||
*/
|
||||
if (tlist_item == NULL ||
|
||||
((TargetEntry *) lfirst(tlist_item))->resdom->resjunk)
|
||||
((TargetEntry *) lfirst(tlist_item))->resjunk)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("subquery must return a column")));
|
||||
while ((tlist_item = lnext(tlist_item)) != NULL)
|
||||
{
|
||||
if (!((TargetEntry *) lfirst(tlist_item))->resdom->resjunk)
|
||||
if (!((TargetEntry *) lfirst(tlist_item))->resjunk)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("subquery must return only one column")));
|
||||
@@ -1045,7 +1045,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
Operator optup;
|
||||
Form_pg_operator opform;
|
||||
|
||||
if (tent->resdom->resjunk)
|
||||
if (tent->resjunk)
|
||||
continue;
|
||||
|
||||
if (ll_item == NULL)
|
||||
@@ -1417,18 +1417,16 @@ exprType(Node *expr)
|
||||
elog(ERROR, "cannot get type for untransformed sublink");
|
||||
tent = (TargetEntry *) linitial(qtree->targetList);
|
||||
Assert(IsA(tent, TargetEntry));
|
||||
Assert(!tent->resdom->resjunk);
|
||||
if (sublink->subLinkType == EXPR_SUBLINK)
|
||||
type = tent->resdom->restype;
|
||||
else
|
||||
Assert(!tent->resjunk);
|
||||
type = exprType((Node *) tent->expr);
|
||||
if (sublink->subLinkType == ARRAY_SUBLINK)
|
||||
{
|
||||
/* ARRAY_SUBLINK */
|
||||
type = get_array_type(tent->resdom->restype);
|
||||
type = get_array_type(type);
|
||||
if (!OidIsValid(type))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(tent->resdom->restype))));
|
||||
format_type_be(exprType((Node *) tent->expr)))));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1456,18 +1454,16 @@ exprType(Node *expr)
|
||||
|
||||
tent = (TargetEntry *) linitial(subplan->plan->targetlist);
|
||||
Assert(IsA(tent, TargetEntry));
|
||||
Assert(!tent->resdom->resjunk);
|
||||
if (subplan->subLinkType == EXPR_SUBLINK)
|
||||
type = tent->resdom->restype;
|
||||
else
|
||||
Assert(!tent->resjunk);
|
||||
type = exprType((Node *) tent->expr);
|
||||
if (subplan->subLinkType == ARRAY_SUBLINK)
|
||||
{
|
||||
/* ARRAY_SUBLINK */
|
||||
type = get_array_type(tent->resdom->restype);
|
||||
type = get_array_type(type);
|
||||
if (!OidIsValid(type))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("could not find array type for data type %s",
|
||||
format_type_be(tent->resdom->restype))));
|
||||
format_type_be(exprType((Node *) tent->expr)))));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.103 2005/03/31 22:46:13 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.104 2005/04/06 16:34:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -910,15 +910,15 @@ addRangeTableEntryForSubquery(ParseState *pstate,
|
||||
{
|
||||
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
|
||||
|
||||
if (te->resdom->resjunk)
|
||||
if (te->resjunk)
|
||||
continue;
|
||||
varattno++;
|
||||
Assert(varattno == te->resdom->resno);
|
||||
Assert(varattno == te->resno);
|
||||
if (varattno > numaliases)
|
||||
{
|
||||
char *attrname;
|
||||
|
||||
attrname = pstrdup(te->resdom->resname);
|
||||
attrname = pstrdup(te->resname);
|
||||
eref->colnames = lappend(eref->colnames, makeString(attrname));
|
||||
}
|
||||
}
|
||||
@@ -1260,10 +1260,10 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
|
||||
{
|
||||
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
|
||||
|
||||
if (te->resdom->resjunk)
|
||||
if (te->resjunk)
|
||||
continue;
|
||||
varattno++;
|
||||
Assert(varattno == te->resdom->resno);
|
||||
Assert(varattno == te->resno);
|
||||
|
||||
if (colnames)
|
||||
{
|
||||
@@ -1279,8 +1279,8 @@ expandRTE(List *rtable, int rtindex, int sublevels_up,
|
||||
Var *varnode;
|
||||
|
||||
varnode = makeVar(rtindex, varattno,
|
||||
te->resdom->restype,
|
||||
te->resdom->restypmod,
|
||||
exprType((Node *) te->expr),
|
||||
exprTypmod((Node *) te->expr),
|
||||
sublevels_up);
|
||||
|
||||
*colvars = lappend(*colvars, varnode);
|
||||
@@ -1532,14 +1532,12 @@ expandRelAttrs(ParseState *pstate, List *rtable, int rtindex, int sublevels_up)
|
||||
{
|
||||
char *label = strVal(lfirst(name));
|
||||
Node *varnode = (Node *) lfirst(var);
|
||||
TargetEntry *te = makeNode(TargetEntry);
|
||||
TargetEntry *te;
|
||||
|
||||
te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
|
||||
exprType(varnode),
|
||||
exprTypmod(varnode),
|
||||
label,
|
||||
false);
|
||||
te->expr = (Expr *) varnode;
|
||||
te = makeTargetEntry((Expr *) varnode,
|
||||
(AttrNumber) pstate->p_next_resno++,
|
||||
label,
|
||||
false);
|
||||
te_list = lappend(te_list, te);
|
||||
}
|
||||
|
||||
@@ -1641,11 +1639,11 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||
TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
|
||||
attnum);
|
||||
|
||||
if (te == NULL || te->resdom->resjunk)
|
||||
if (te == NULL || te->resjunk)
|
||||
elog(ERROR, "subquery %s does not have attribute %d",
|
||||
rte->eref->aliasname, attnum);
|
||||
*vartype = te->resdom->restype;
|
||||
*vartypmod = te->resdom->restypmod;
|
||||
*vartype = exprType((Node *) te->expr);
|
||||
*vartypmod = exprTypmod((Node *) te->expr);
|
||||
}
|
||||
break;
|
||||
case RTE_FUNCTION:
|
||||
@@ -1856,7 +1854,7 @@ get_tle_by_resno(List *tlist, AttrNumber resno)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
if (tle->resdom->resno == resno)
|
||||
if (tle->resno == resno)
|
||||
return tle;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.130 2005/03/26 06:28:59 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.131 2005/04/06 16:34:06 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "utils/typcache.h"
|
||||
|
||||
|
||||
static void markTargetListOrigin(ParseState *pstate, Resdom *res,
|
||||
static void markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
|
||||
Var *var, int levelsup);
|
||||
static Node *transformAssignmentIndirection(ParseState *pstate,
|
||||
Node *basenode,
|
||||
@@ -65,17 +65,10 @@ transformTargetEntry(ParseState *pstate,
|
||||
char *colname,
|
||||
bool resjunk)
|
||||
{
|
||||
Oid type_id;
|
||||
int32 type_mod;
|
||||
Resdom *resnode;
|
||||
|
||||
/* Transform the node if caller didn't do it already */
|
||||
if (expr == NULL)
|
||||
expr = transformExpr(pstate, node);
|
||||
|
||||
type_id = exprType(expr);
|
||||
type_mod = exprTypmod(expr);
|
||||
|
||||
if (colname == NULL && !resjunk)
|
||||
{
|
||||
/*
|
||||
@@ -85,13 +78,10 @@ transformTargetEntry(ParseState *pstate,
|
||||
colname = FigureColname(node);
|
||||
}
|
||||
|
||||
resnode = makeResdom((AttrNumber) pstate->p_next_resno++,
|
||||
type_id,
|
||||
type_mod,
|
||||
colname,
|
||||
resjunk);
|
||||
|
||||
return makeTargetEntry(resnode, (Expr *) expr);
|
||||
return makeTargetEntry((Expr *) expr,
|
||||
(AttrNumber) pstate->p_next_resno++,
|
||||
colname,
|
||||
resjunk);
|
||||
}
|
||||
|
||||
|
||||
@@ -176,13 +166,13 @@ markTargetListOrigins(ParseState *pstate, List *targetlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
markTargetListOrigin(pstate, tle->resdom, (Var *) tle->expr, 0);
|
||||
markTargetListOrigin(pstate, tle, (Var *) tle->expr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* markTargetListOrigin()
|
||||
* If 'var' is a Var of a plain relation, mark 'res' with its origin
|
||||
* If 'var' is a Var of a plain relation, mark 'tle' with its origin
|
||||
*
|
||||
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
|
||||
*
|
||||
@@ -190,7 +180,8 @@ markTargetListOrigins(ParseState *pstate, List *targetlist)
|
||||
* do not drill down into views, but report the view as the column owner.
|
||||
*/
|
||||
static void
|
||||
markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
|
||||
markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
|
||||
Var *var, int levelsup)
|
||||
{
|
||||
int netlevelsup;
|
||||
RangeTblEntry *rte;
|
||||
@@ -206,20 +197,20 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
|
||||
{
|
||||
case RTE_RELATION:
|
||||
/* It's a table or view, report it */
|
||||
res->resorigtbl = rte->relid;
|
||||
res->resorigcol = attnum;
|
||||
tle->resorigtbl = rte->relid;
|
||||
tle->resorigcol = attnum;
|
||||
break;
|
||||
case RTE_SUBQUERY:
|
||||
{
|
||||
/* Subselect-in-FROM: copy up from the subselect */
|
||||
TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
|
||||
attnum);
|
||||
TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
|
||||
attnum);
|
||||
|
||||
if (te == NULL || te->resdom->resjunk)
|
||||
if (ste == NULL || ste->resjunk)
|
||||
elog(ERROR, "subquery %s does not have attribute %d",
|
||||
rte->eref->aliasname, attnum);
|
||||
res->resorigtbl = te->resdom->resorigtbl;
|
||||
res->resorigcol = te->resdom->resorigcol;
|
||||
tle->resorigtbl = ste->resorigtbl;
|
||||
tle->resorigcol = ste->resorigcol;
|
||||
}
|
||||
break;
|
||||
case RTE_JOIN:
|
||||
@@ -229,7 +220,7 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
|
||||
|
||||
Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
|
||||
aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
|
||||
markTargetListOrigin(pstate, res, aliasvar, netlevelsup);
|
||||
markTargetListOrigin(pstate, tle, aliasvar, netlevelsup);
|
||||
}
|
||||
break;
|
||||
case RTE_SPECIAL:
|
||||
@@ -264,7 +255,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
Oid type_id; /* type of value provided */
|
||||
Oid attrtype; /* type of target column */
|
||||
int32 attrtypmod;
|
||||
Resdom *resnode = tle->resdom;
|
||||
Relation rd = pstate->p_target_relation;
|
||||
|
||||
Assert(rd != NULL);
|
||||
@@ -368,13 +358,6 @@ updateTargetListEntry(ParseState *pstate,
|
||||
errhint("You will need to rewrite or cast the expression.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* The result of the target expression should now match the
|
||||
* destination column's type.
|
||||
*/
|
||||
resnode->restype = attrtype;
|
||||
resnode->restypmod = attrtypmod;
|
||||
|
||||
/*
|
||||
* Set the resno to identify the target column --- the rewriter and
|
||||
* planner depend on this. We also set the resname to identify the
|
||||
@@ -382,8 +365,8 @@ updateTargetListEntry(ParseState *pstate,
|
||||
* not be relied on. (In particular, it might be out of date in a
|
||||
* stored rule.)
|
||||
*/
|
||||
resnode->resno = (AttrNumber) attrno;
|
||||
resnode->resname = colname;
|
||||
tle->resno = (AttrNumber) attrno;
|
||||
tle->resname = colname;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -881,13 +864,10 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
||||
fieldnode = (Node *) fselect;
|
||||
}
|
||||
|
||||
te = makeNode(TargetEntry);
|
||||
te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
|
||||
att->atttypid,
|
||||
att->atttypmod,
|
||||
pstrdup(NameStr(att->attname)),
|
||||
false);
|
||||
te->expr = (Expr *) fieldnode;
|
||||
te = makeTargetEntry((Expr *) fieldnode,
|
||||
(AttrNumber) pstate->p_next_resno++,
|
||||
pstrdup(NameStr(att->attname)),
|
||||
false);
|
||||
te_list = lappend(te_list, te);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user