From ad161bcc8a3792d18ef2f3ebe66bb1e22d42b6f2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 6 Apr 2005 16:34:07 +0000 Subject: [PATCH] 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. --- src/backend/access/common/printtup.c | 10 +- src/backend/commands/view.c | 14 +-- src/backend/executor/execJunk.c | 23 ++-- src/backend/executor/execMain.c | 4 +- src/backend/executor/execQual.c | 10 +- src/backend/executor/execTuples.c | 11 +- src/backend/executor/execUtils.c | 4 +- src/backend/executor/functions.c | 8 +- src/backend/executor/nodeSubplan.c | 22 ++-- src/backend/nodes/copyfuncs.c | 32 ++---- src/backend/nodes/equalfuncs.c | 27 ++--- src/backend/nodes/makefuncs.c | 63 +++++------ src/backend/nodes/outfuncs.c | 27 ++--- src/backend/nodes/print.c | 10 +- src/backend/nodes/readfuncs.c | 31 ++---- src/backend/optimizer/path/allpaths.c | 11 +- src/backend/optimizer/path/pathkeys.c | 10 +- src/backend/optimizer/plan/createplan.c | 56 +++++----- src/backend/optimizer/plan/planner.c | 27 +++-- src/backend/optimizer/plan/setrefs.c | 65 +++++------ src/backend/optimizer/plan/subselect.c | 27 ++--- src/backend/optimizer/prep/prepjointree.c | 4 +- src/backend/optimizer/prep/preptlist.c | 68 +++++------- src/backend/optimizer/prep/prepunion.c | 126 ++++++++++------------ src/backend/optimizer/util/clauses.c | 14 +-- src/backend/optimizer/util/pathnode.c | 4 +- src/backend/optimizer/util/plancat.c | 19 ++-- src/backend/optimizer/util/tlist.c | 99 +++-------------- src/backend/parser/analyze.c | 96 ++++++----------- src/backend/parser/parse_clause.c | 42 ++++---- src/backend/parser/parse_expr.c | 32 +++--- src/backend/parser/parse_relation.c | 38 ++++--- src/backend/parser/parse_target.c | 68 +++++------- src/backend/rewrite/rewriteDefine.c | 16 +-- src/backend/rewrite/rewriteHandler.c | 30 +++--- src/backend/utils/adt/ruleutils.c | 27 +++-- src/include/catalog/catversion.h | 4 +- src/include/nodes/makefuncs.h | 13 ++- src/include/nodes/nodes.h | 5 +- src/include/nodes/parsenodes.h | 6 +- src/include/nodes/primnodes.h | 125 ++++++++++----------- src/include/optimizer/tlist.h | 7 +- src/tools/backend/index.html | 5 +- 43 files changed, 539 insertions(+), 801 deletions(-) diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index 6f44533822..e78dc19a03 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.87 2005/03/16 21:38:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.88 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -190,14 +190,14 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats) { /* Do we have a non-resjunk tlist item? */ while (tlist_item && - ((TargetEntry *) lfirst(tlist_item))->resdom->resjunk) + ((TargetEntry *) lfirst(tlist_item))->resjunk) tlist_item = lnext(tlist_item); if (tlist_item) { - Resdom *res = ((TargetEntry *) lfirst(tlist_item))->resdom; + TargetEntry *tle = (TargetEntry *) lfirst(tlist_item); - pq_sendint(&buf, res->resorigtbl, 4); - pq_sendint(&buf, res->resorigcol, 2); + pq_sendint(&buf, tle->resorigtbl, 4); + pq_sendint(&buf, tle->resorigcol, 2); tlist_item = lnext(tlist_item); } else diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 10caef1375..21609e063f 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.87 2005/02/02 06:36:00 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.88 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" +#include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteManip.h" @@ -106,18 +107,17 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace) attrList = NIL; foreach(t, tlist) { - TargetEntry *entry = lfirst(t); - Resdom *res = entry->resdom; + TargetEntry *tle = lfirst(t); - if (!res->resjunk) + if (!tle->resjunk) { ColumnDef *def = makeNode(ColumnDef); TypeName *typename = makeNode(TypeName); - def->colname = pstrdup(res->resname); + def->colname = pstrdup(tle->resname); - typename->typeid = res->restype; - typename->typmod = res->restypmod; + typename->typeid = exprType((Node *) tle->expr); + typename->typmod = exprTypmod((Node *) tle->expr); def->typename = typename; def->inhcount = 0; diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index 2dfd90b51f..1cf403f88d 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.48 2005/03/16 21:38:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.49 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,8 +31,8 @@ * of some system attributes like "ctid" or rule locks. * * The general idea is the following: A target list consists of a list of - * Resdom nodes & expression pairs. Each Resdom node has an attribute - * called 'resjunk'. If the value of this attribute is true then the + * TargetEntry nodes containing expressions. Each TargetEntry has a field + * called 'resjunk'. If the value of this field is true then the * corresponding attribute is a "junk" attribute. * * When we initialize a plan we call 'ExecInitJunkFilter' to create @@ -101,11 +101,10 @@ ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot) foreach(t, targetList) { TargetEntry *tle = lfirst(t); - Resdom *resdom = tle->resdom; - if (!resdom->resjunk) + if (!tle->resjunk) { - cleanMap[cleanResno - 1] = resdom->resno; + cleanMap[cleanResno - 1] = tle->resno; cleanResno++; } } @@ -177,12 +176,11 @@ ExecInitJunkFilterConversion(List *targetList, for (;;) { TargetEntry *tle = lfirst(t); - Resdom *resdom = tle->resdom; t = lnext(t); - if (!resdom->resjunk) + if (!tle->resjunk) { - cleanMap[i] = resdom->resno; + cleanMap[i] = tle->resno; break; } } @@ -228,13 +226,12 @@ ExecGetJunkAttribute(JunkFilter *junkfilter, foreach(t, junkfilter->jf_targetList) { TargetEntry *tle = lfirst(t); - Resdom *resdom = tle->resdom; - if (resdom->resjunk && resdom->resname && - (strcmp(resdom->resname, attrName) == 0)) + if (tle->resjunk && tle->resname && + (strcmp(tle->resname, attrName) == 0)) { /* We found it ! */ - *value = slot_getattr(slot, resdom->resno, isNull); + *value = slot_getattr(slot, tle->resno, isNull); return true; } } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 304f1ba6b1..0ba6104422 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.244 2005/03/25 21:57:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.245 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -640,7 +640,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly) { TargetEntry *tle = (TargetEntry *) lfirst(tlist); - if (tle->resdom->resjunk) + if (tle->resjunk) { junk_filter_needed = true; break; diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 9d915af91a..67c962398e 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.175 2005/03/29 00:16:59 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.176 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3467,7 +3467,7 @@ ExecCleanTargetListLength(List *targetlist) TargetEntry *curTle = (TargetEntry *) lfirst(tl); Assert(IsA(curTle, TargetEntry)); - if (!curTle->resdom->resjunk) + if (!curTle->resjunk) len++; } return len; @@ -3516,7 +3516,7 @@ ExecTargetList(List *targetlist, { GenericExprState *gstate = (GenericExprState *) lfirst(tl); TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr; - AttrNumber resind = tle->resdom->resno - 1; + AttrNumber resind = tle->resno - 1; values[resind] = ExecEvalExpr(gstate->arg, econtext, @@ -3568,7 +3568,7 @@ ExecTargetList(List *targetlist, { GenericExprState *gstate = (GenericExprState *) lfirst(tl); TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr; - AttrNumber resind = tle->resdom->resno - 1; + AttrNumber resind = tle->resno - 1; if (itemIsDone[resind] == ExprEndResult) { @@ -3602,7 +3602,7 @@ ExecTargetList(List *targetlist, { GenericExprState *gstate = (GenericExprState *) lfirst(tl); TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr; - AttrNumber resind = tle->resdom->resno - 1; + AttrNumber resind = tle->resno - 1; while (itemIsDone[resind] == ExprMultipleResult) { diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 7941cebad6..1c82a3b64b 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.86 2005/03/17 15:25:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.87 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -784,15 +784,14 @@ ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk) foreach(l, targetList) { TargetEntry *tle = lfirst(l); - Resdom *resdom = tle->resdom; - if (skipjunk && resdom->resjunk) + if (skipjunk && tle->resjunk) continue; TupleDescInitEntry(typeInfo, cur_resno++, - resdom->resname, - resdom->restype, - resdom->restypmod, + tle->resname, + exprType((Node *) tle->expr), + exprTypmod((Node *) tle->expr), 0); } diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index b1840b45cf..820c042913 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.119 2005/03/21 01:24:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.120 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -561,7 +561,7 @@ ExecBuildProjectionInfo(List *targetList, Var *variable = (Var *) gstate->arg->expr; AttrNumber attnum = variable->varattno; TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr; - AttrNumber resind = tle->resdom->resno - 1; + AttrNumber resind = tle->resno - 1; Assert(resind >= 0 && resind < len); varNumbers[resind] = attnum; diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index d2e101a2d6..521d656ff1 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.95 2005/03/31 22:46:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.96 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -935,7 +935,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, format_type_be(rettype)), errdetail("Final SELECT must return exactly one column."))); - restype = ((TargetEntry *) linitial(tlist))->resdom->restype; + restype = exprType((Node *) ((TargetEntry *) linitial(tlist))->expr); if (!IsBinaryCoercible(restype, rettype)) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), @@ -961,7 +961,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, */ if (tlistlen == 1) { - restype = ((TargetEntry *) linitial(tlist))->resdom->restype; + restype = exprType((Node *) ((TargetEntry *) linitial(tlist))->expr); if (IsBinaryCoercible(restype, rettype)) return false; /* NOT returning whole tuple */ } @@ -996,7 +996,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, Oid tletype; Oid atttype; - if (tle->resdom->resjunk) + if (tle->resjunk) continue; do diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 7d40fe8b1e..de3187e247 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.67 2005/03/16 21:38:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.68 2005/04/06 16:34:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -828,12 +828,10 @@ ExecInitSubPlan(SubPlanState *node, EState *estate) /* Process lefthand argument */ exstate = (ExprState *) linitial(fstate->args); expr = exstate->expr; - tle = makeTargetEntry(makeResdom(i, - exprType((Node *) expr), - exprTypmod((Node *) expr), - NULL, - false), - expr); + tle = makeTargetEntry(expr, + i, + NULL, + false); tlestate = makeNode(GenericExprState); tlestate->xprstate.expr = (Expr *) tle; tlestate->xprstate.evalfunc = NULL; @@ -844,12 +842,10 @@ ExecInitSubPlan(SubPlanState *node, EState *estate) /* Process righthand argument */ exstate = (ExprState *) lsecond(fstate->args); expr = exstate->expr; - tle = makeTargetEntry(makeResdom(i, - exprType((Node *) expr), - exprTypmod((Node *) expr), - NULL, - false), - expr); + tle = makeTargetEntry(expr, + i, + NULL, + false); tlestate = makeNode(GenericExprState); tlestate->xprstate.expr = (Expr *) tle; tlestate->xprstate.evalfunc = NULL; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index c2130e370d..e314959e37 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.299 2005/03/29 17:58:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.300 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -539,26 +539,6 @@ _copyLimit(Limit *from) * **************************************************************** */ -/* - * _copyResdom - */ -static Resdom * -_copyResdom(Resdom *from) -{ - Resdom *newnode = makeNode(Resdom); - - COPY_SCALAR_FIELD(resno); - COPY_SCALAR_FIELD(restype); - COPY_SCALAR_FIELD(restypmod); - COPY_STRING_FIELD(resname); - COPY_SCALAR_FIELD(ressortgroupref); - COPY_SCALAR_FIELD(resorigtbl); - COPY_SCALAR_FIELD(resorigcol); - COPY_SCALAR_FIELD(resjunk); - - return newnode; -} - /* * _copyAlias */ @@ -1077,8 +1057,13 @@ _copyTargetEntry(TargetEntry *from) { TargetEntry *newnode = makeNode(TargetEntry); - COPY_NODE_FIELD(resdom); COPY_NODE_FIELD(expr); + COPY_SCALAR_FIELD(resno); + COPY_STRING_FIELD(resname); + COPY_SCALAR_FIELD(ressortgroupref); + COPY_SCALAR_FIELD(resorigtbl); + COPY_SCALAR_FIELD(resorigcol); + COPY_SCALAR_FIELD(resjunk); return newnode; } @@ -2670,9 +2655,6 @@ copyObject(void *from) /* * PRIMITIVE NODES */ - case T_Resdom: - retval = _copyResdom(from); - break; case T_Alias: retval = _copyAlias(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index bcf8c36393..958e320b47 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.238 2005/03/29 17:58:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.239 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,21 +82,6 @@ * Stuff from primnodes.h */ -static bool -_equalResdom(Resdom *a, Resdom *b) -{ - COMPARE_SCALAR_FIELD(resno); - COMPARE_SCALAR_FIELD(restype); - COMPARE_SCALAR_FIELD(restypmod); - COMPARE_STRING_FIELD(resname); - COMPARE_SCALAR_FIELD(ressortgroupref); - COMPARE_SCALAR_FIELD(resorigtbl); - COMPARE_SCALAR_FIELD(resorigcol); - COMPARE_SCALAR_FIELD(resjunk); - - return true; -} - static bool _equalAlias(Alias *a, Alias *b) { @@ -546,8 +531,13 @@ _equalSetToDefault(SetToDefault *a, SetToDefault *b) static bool _equalTargetEntry(TargetEntry *a, TargetEntry *b) { - COMPARE_NODE_FIELD(resdom); COMPARE_NODE_FIELD(expr); + COMPARE_SCALAR_FIELD(resno); + COMPARE_STRING_FIELD(resname); + COMPARE_SCALAR_FIELD(ressortgroupref); + COMPARE_SCALAR_FIELD(resorigtbl); + COMPARE_SCALAR_FIELD(resorigcol); + COMPARE_SCALAR_FIELD(resjunk); return true; } @@ -1814,9 +1804,6 @@ equal(void *a, void *b) /* * PRIMITIVE NODES */ - case T_Resdom: - retval = _equalResdom(a, b); - break; case T_Alias: retval = _equalAlias(a, b); break; diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 026b962bb9..e1e6c3da83 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.46 2004/12/31 21:59:55 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.47 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,48 +87,49 @@ makeVar(Index varno, /* * makeTargetEntry - - * creates a TargetEntry node (contains a Resdom) + * creates a TargetEntry node */ TargetEntry * -makeTargetEntry(Resdom *resdom, Expr *expr) +makeTargetEntry(Expr *expr, + AttrNumber resno, + char *resname, + bool resjunk) { - TargetEntry *rt = makeNode(TargetEntry); + TargetEntry *tle = makeNode(TargetEntry); - rt->resdom = resdom; - rt->expr = expr; - return rt; -} - -/* - * makeResdom - - * creates a Resdom (Result Domain) node - */ -Resdom * -makeResdom(AttrNumber resno, - Oid restype, - int32 restypmod, - char *resname, - bool resjunk) -{ - Resdom *resdom = makeNode(Resdom); - - resdom->resno = resno; - resdom->restype = restype; - resdom->restypmod = restypmod; - resdom->resname = resname; + tle->expr = expr; + tle->resno = resno; + tle->resname = resname; /* * We always set these fields to 0. If the caller wants to change them * he must do so explicitly. Few callers do that, so omitting these * arguments reduces the chance of error. */ - resdom->ressortgroupref = 0; - resdom->resorigtbl = InvalidOid; - resdom->resorigcol = 0; + tle->ressortgroupref = 0; + tle->resorigtbl = InvalidOid; + tle->resorigcol = 0; + + tle->resjunk = resjunk; - resdom->resjunk = resjunk; + return tle; +} + +/* + * flatCopyTargetEntry - + * duplicate a TargetEntry, but don't copy substructure + * + * This is commonly used when we just want to modify the resno or substitute + * a new expression. + */ +TargetEntry * +flatCopyTargetEntry(TargetEntry *src_tle) +{ + TargetEntry *tle = makeNode(TargetEntry); - return resdom; + Assert(IsA(src_tle, TargetEntry)); + memcpy(tle, src_tle, sizeof(TargetEntry)); + return tle; } /* diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index bb2b2c35f9..91a7abf574 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.245 2004/12/31 21:59:55 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.246 2005/04/06 16:34:05 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -520,21 +520,6 @@ _outHash(StringInfo str, Hash *node) * *****************************************************************************/ -static void -_outResdom(StringInfo str, Resdom *node) -{ - WRITE_NODE_TYPE("RESDOM"); - - WRITE_INT_FIELD(resno); - WRITE_OID_FIELD(restype); - WRITE_INT_FIELD(restypmod); - WRITE_STRING_FIELD(resname); - WRITE_UINT_FIELD(ressortgroupref); - WRITE_OID_FIELD(resorigtbl); - WRITE_INT_FIELD(resorigcol); - WRITE_BOOL_FIELD(resjunk); -} - static void _outAlias(StringInfo str, Alias *node) { @@ -900,8 +885,13 @@ _outTargetEntry(StringInfo str, TargetEntry *node) { WRITE_NODE_TYPE("TARGETENTRY"); - WRITE_NODE_FIELD(resdom); WRITE_NODE_FIELD(expr); + WRITE_INT_FIELD(resno); + WRITE_STRING_FIELD(resname); + WRITE_UINT_FIELD(ressortgroupref); + WRITE_OID_FIELD(resorigtbl); + WRITE_INT_FIELD(resorigcol); + WRITE_BOOL_FIELD(resjunk); } static void @@ -1684,9 +1674,6 @@ _outNode(StringInfo str, void *obj) case T_Hash: _outHash(str, obj); break; - case T_Resdom: - _outResdom(str, obj); - break; case T_Alias: _outAlias(str, obj); break; diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index e62d731a6c..35bb99b62f 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.73 2005/03/16 21:38:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.74 2005/04/06 16:34:05 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -449,10 +449,10 @@ print_tl(List *tlist, List *rtable) { TargetEntry *tle = (TargetEntry *) lfirst(tl); - printf("\t%d %s\t", tle->resdom->resno, - tle->resdom->resname ? tle->resdom->resname : ""); - if (tle->resdom->ressortgroupref != 0) - printf("(%u):\t", tle->resdom->ressortgroupref); + printf("\t%d %s\t", tle->resno, + tle->resname ? tle->resname : ""); + if (tle->ressortgroupref != 0) + printf("(%u):\t", tle->ressortgroupref); else printf(" :\t"); print_expr((Node *) tle->expr, rtable); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index f04668b6be..f457d06331 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.175 2004/12/31 21:59:55 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.176 2005/04/06 16:34:05 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -238,26 +238,6 @@ _readSetOperationStmt(void) * Stuff from primnodes.h. */ -/* - * _readResdom - */ -static Resdom * -_readResdom(void) -{ - READ_LOCALS(Resdom); - - READ_INT_FIELD(resno); - READ_OID_FIELD(restype); - READ_INT_FIELD(restypmod); - READ_STRING_FIELD(resname); - READ_UINT_FIELD(ressortgroupref); - READ_OID_FIELD(resorigtbl); - READ_INT_FIELD(resorigcol); - READ_BOOL_FIELD(resjunk); - - READ_DONE(); -} - static Alias * _readAlias(void) { @@ -787,8 +767,13 @@ _readTargetEntry(void) { READ_LOCALS(TargetEntry); - READ_NODE_FIELD(resdom); READ_NODE_FIELD(expr); + READ_INT_FIELD(resno); + READ_STRING_FIELD(resname); + READ_UINT_FIELD(ressortgroupref); + READ_OID_FIELD(resorigtbl); + READ_INT_FIELD(resorigcol); + READ_BOOL_FIELD(resjunk); READ_DONE(); } @@ -952,8 +937,6 @@ parseNodeString(void) return_value = _readGroupClause(); else if (MATCH("SETOPERATIONSTMT", 16)) return_value = _readSetOperationStmt(); - else if (MATCH("RESDOM", 6)) - return_value = _readResdom(); else if (MATCH("ALIAS", 5)) return_value = _readAlias(); else if (MATCH("RANGEVAR", 8)) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 42d8761845..1651310845 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.124 2005/03/10 23:21:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.125 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ #include "optimizer/var.h" #include "parser/parsetree.h" #include "parser/parse_clause.h" +#include "parser/parse_expr.h" #include "rewrite/rewriteManip.h" @@ -656,12 +657,12 @@ compare_tlist_datatypes(List *tlist, List *colTypes, { TargetEntry *tle = (TargetEntry *) lfirst(l); - if (tle->resdom->resjunk) + if (tle->resjunk) continue; /* ignore resjunk columns */ if (colType == NULL) elog(ERROR, "wrong number of tlist entries"); - if (tle->resdom->restype != lfirst_oid(colType)) - differentTypes[tle->resdom->resno] = true; + if (exprType((Node *) tle->expr) != lfirst_oid(colType)) + differentTypes[tle->resno] = true; colType = lnext(colType); } if (colType != NULL) @@ -740,7 +741,7 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual, /* Must find the tlist element referenced by the Var */ tle = get_tle_by_resno(subquery->targetList, var->varattno); Assert(tle != NULL); - Assert(!tle->resdom->resjunk); + Assert(!tle->resjunk); /* If subquery uses DISTINCT or DISTINCT ON, check point 3 */ if (subquery->distinctClause != NIL && diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 0e23045fef..766aa1d116 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.65 2005/03/27 06:29:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.66 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -791,7 +791,7 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery) { TargetEntry *tle = (TargetEntry *) lfirst(k); - if (!tle->resdom->resjunk && + if (!tle->resjunk && equal(tle->expr, sub_key)) { /* Found a representation for this sub_key */ @@ -800,9 +800,9 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery) int score; outer_var = makeVar(rel->relid, - tle->resdom->resno, - tle->resdom->restype, - tle->resdom->restypmod, + tle->resno, + exprType((Node *) tle->expr), + exprTypmod((Node *) tle->expr), 0); outer_item = makePathKeyItem((Node *) outer_var, sub_item->sortop, diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index f4a76a9b3b..41e2edceb2 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.177 2005/03/27 06:29:38 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.178 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -259,7 +259,7 @@ static List * build_relation_tlist(RelOptInfo *rel) { List *tlist = NIL; - int resdomno = 1; + int resno = 1; ListCell *v; foreach(v, rel->reltargetlist) @@ -267,8 +267,11 @@ build_relation_tlist(RelOptInfo *rel) /* Do we really need to copy here? Not sure */ Var *var = (Var *) copyObject(lfirst(v)); - tlist = lappend(tlist, create_tl_element(var, resdomno)); - resdomno++; + tlist = lappend(tlist, makeTargetEntry((Expr *) var, + resno, + NULL, + false)); + resno++; } return tlist; } @@ -557,20 +560,18 @@ create_unique_plan(Query *root, UniquePath *best_path) Node *uniqexpr = lfirst(l); TargetEntry *tle; - tle = tlistentry_member(uniqexpr, newtlist); + tle = tlist_member(uniqexpr, newtlist); if (!tle) { - tle = makeTargetEntry(makeResdom(nextresno, - exprType(uniqexpr), - exprTypmod(uniqexpr), - NULL, - false), - (Expr *) uniqexpr); + tle = makeTargetEntry((Expr *) uniqexpr, + nextresno, + NULL, + false); newtlist = lappend(newtlist, tle); nextresno++; newitems = true; } - groupColIdx[groupColPos++] = tle->resdom->resno; + groupColIdx[groupColPos++] = tle->resno; } if (newitems) @@ -1844,7 +1845,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys) { List *keysublist = (List *) lfirst(i); PathKeyItem *pathkey = NULL; - Resdom *resdom = NULL; + TargetEntry *tle = NULL; ListCell *j; /* @@ -1863,11 +1864,11 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys) { pathkey = (PathKeyItem *) lfirst(j); Assert(IsA(pathkey, PathKeyItem)); - resdom = tlist_member(pathkey->key, tlist); - if (resdom) + tle = tlist_member(pathkey->key, tlist); + if (tle) break; } - if (!resdom) + if (!tle) { /* No matching Var; look for a computable expression */ foreach(j, keysublist) @@ -1901,14 +1902,11 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys) /* * Add resjunk entry to input's tlist */ - resdom = makeResdom(list_length(tlist) + 1, - exprType(pathkey->key), - exprTypmod(pathkey->key), - NULL, - true); - tlist = lappend(tlist, - makeTargetEntry(resdom, - (Expr *) pathkey->key)); + tle = makeTargetEntry((Expr *) pathkey->key, + list_length(tlist) + 1, + NULL, + true); + tlist = lappend(tlist, tle); lefttree->targetlist = tlist; /* just in case NIL before */ } @@ -1918,7 +1916,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys) * scenarios where multiple mergejoinable clauses mention the same * var, for example.) So enter it only once in the sort arrays. */ - numsortkeys = add_sort_column(resdom->resno, pathkey->sortop, + numsortkeys = add_sort_column(tle->resno, pathkey->sortop, numsortkeys, sortColIdx, sortOperators); } @@ -1964,7 +1962,7 @@ make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree) * parser should have removed 'em, but no point in sorting * redundantly. */ - numsortkeys = add_sort_column(tle->resdom->resno, sortcl->sortop, + numsortkeys = add_sort_column(tle->resno, sortcl->sortop, numsortkeys, sortColIdx, sortOperators); } @@ -2020,7 +2018,7 @@ make_sort_from_groupcols(Query *root, * parser should have removed 'em, but no point in sorting * redundantly. */ - numsortkeys = add_sort_column(tle->resdom->resno, grpcl->sortop, + numsortkeys = add_sort_column(tle->resno, grpcl->sortop, numsortkeys, sortColIdx, sortOperators); grpno++; } @@ -2253,7 +2251,7 @@ make_unique(Plan *lefttree, List *distinctList) SortClause *sortcl = (SortClause *) lfirst(slitem); TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist); - uniqColIdx[keyno++] = tle->resdom->resno; + uniqColIdx[keyno++] = tle->resno; } node->numCols = numCols; @@ -2311,7 +2309,7 @@ make_setop(SetOpCmd cmd, Plan *lefttree, SortClause *sortcl = (SortClause *) lfirst(slitem); TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist); - dupColIdx[keyno++] = tle->resdom->resno; + dupColIdx[keyno++] = tle->resno; } node->cmd = cmd; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 5f3c7510cd..9f898997f0 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.181 2005/03/28 00:58:23 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.182 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1349,7 +1349,7 @@ hash_safe_grouping(Query *parse) Operator optup; bool oprcanhash; - optup = equality_oper(tle->resdom->restype, true); + optup = equality_oper(exprType((Node *) tle->expr), true); if (!optup) return false; oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash; @@ -1467,18 +1467,16 @@ make_subplanTargetList(Query *parse, } if (!sl) { - te = makeTargetEntry(makeResdom(list_length(sub_tlist) + 1, - exprType(groupexpr), - exprTypmod(groupexpr), - NULL, - false), - (Expr *) groupexpr); + te = makeTargetEntry((Expr *) groupexpr, + list_length(sub_tlist) + 1, + NULL, + false); sub_tlist = lappend(sub_tlist, te); *need_tlist_eval = true; /* it's not flat anymore */ } /* and save its resno */ - grpColIdx[keyno++] = te->resdom->resno; + grpColIdx[keyno++] = te->resno; } } @@ -1528,7 +1526,7 @@ locate_grouping_columns(Query *parse, if (!sl) elog(ERROR, "failed to locate grouping columns"); - groupColIdx[keyno++] = te->resdom->resno; + groupColIdx[keyno++] = te->resno; } } @@ -1554,17 +1552,16 @@ postprocess_setop_tlist(List *new_tlist, List *orig_tlist) TargetEntry *orig_tle; /* ignore resjunk columns in setop result */ - if (new_tle->resdom->resjunk) + if (new_tle->resjunk) continue; Assert(orig_tlist_item != NULL); orig_tle = (TargetEntry *) lfirst(orig_tlist_item); orig_tlist_item = lnext(orig_tlist_item); - if (orig_tle->resdom->resjunk) /* should not happen */ + if (orig_tle->resjunk) /* should not happen */ elog(ERROR, "resjunk output columns are not implemented"); - Assert(new_tle->resdom->resno == orig_tle->resdom->resno); - Assert(new_tle->resdom->restype == orig_tle->resdom->restype); - new_tle->resdom->ressortgroupref = orig_tle->resdom->ressortgroupref; + Assert(new_tle->resno == orig_tle->resno); + new_tle->ressortgroupref = orig_tle->ressortgroupref; } if (orig_tlist_item != NULL) elog(ERROR, "resjunk output columns are not implemented"); diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index df3fbbe3ae..075c6a339d 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.105 2004/12/31 22:00:09 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.106 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include "optimizer/planmain.h" #include "optimizer/tlist.h" #include "optimizer/var.h" +#include "parser/parse_expr.h" #include "parser/parsetree.h" #include "utils/lsyscache.h" @@ -462,9 +463,9 @@ set_uppernode_references(Plan *plan, Index subvarno) subvarno, subplan_targetlist, tlist_has_non_vars); - output_targetlist = lappend(output_targetlist, - makeTargetEntry(tle->resdom, - (Expr *) newexpr)); + tle = flatCopyTargetEntry(tle); + tle->expr = (Expr *) newexpr; + output_targetlist = lappend(output_targetlist, tle); } plan->targetlist = output_targetlist; @@ -550,25 +551,25 @@ join_references_mutator(Node *node, if (IsA(node, Var)) { Var *var = (Var *) node; - Resdom *resdom; + TargetEntry *tle; /* First look for the var in the input tlists */ - resdom = tlist_member((Node *) var, context->outer_tlist); - if (resdom) + tle = tlist_member((Node *) var, context->outer_tlist); + if (tle) { Var *newvar = (Var *) copyObject(var); newvar->varno = OUTER; - newvar->varattno = resdom->resno; + newvar->varattno = tle->resno; return (Node *) newvar; } - resdom = tlist_member((Node *) var, context->inner_tlist); - if (resdom) + tle = tlist_member((Node *) var, context->inner_tlist); + if (tle) { Var *newvar = (Var *) copyObject(var); newvar->varno = INNER; - newvar->varattno = resdom->resno; + newvar->varattno = tle->resno; return (Node *) newvar; } @@ -582,33 +583,33 @@ join_references_mutator(Node *node, /* Try matching more complex expressions too, if tlists have any */ if (context->tlists_have_non_vars) { - Resdom *resdom; + TargetEntry *tle; - resdom = tlist_member(node, context->outer_tlist); - if (resdom) + tle = tlist_member(node, context->outer_tlist); + if (tle) { /* Found a matching subplan output expression */ Var *newvar; newvar = makeVar(OUTER, - resdom->resno, - resdom->restype, - resdom->restypmod, + tle->resno, + exprType((Node *) tle->expr), + exprTypmod((Node *) tle->expr), 0); newvar->varnoold = 0; /* wasn't ever a plain Var */ newvar->varoattno = 0; return (Node *) newvar; } - resdom = tlist_member(node, context->inner_tlist); - if (resdom) + tle = tlist_member(node, context->inner_tlist); + if (tle) { /* Found a matching subplan output expression */ Var *newvar; newvar = makeVar(INNER, - resdom->resno, - resdom->restype, - resdom->restypmod, + tle->resno, + exprType((Node *) tle->expr), + exprTypmod((Node *) tle->expr), 0); newvar->varnoold = 0; /* wasn't ever a plain Var */ newvar->varoattno = 0; @@ -668,32 +669,32 @@ replace_vars_with_subplan_refs_mutator(Node *node, if (IsA(node, Var)) { Var *var = (Var *) node; - Resdom *resdom; + TargetEntry *tle; Var *newvar; - resdom = tlist_member((Node *) var, context->subplan_targetlist); - if (!resdom) + tle = tlist_member((Node *) var, context->subplan_targetlist); + if (!tle) elog(ERROR, "variable not found in subplan target list"); newvar = (Var *) copyObject(var); newvar->varno = context->subvarno; - newvar->varattno = resdom->resno; + newvar->varattno = tle->resno; return (Node *) newvar; } /* Try matching more complex expressions too, if tlist has any */ if (context->tlist_has_non_vars) { - Resdom *resdom; + TargetEntry *tle; - resdom = tlist_member(node, context->subplan_targetlist); - if (resdom) + tle = tlist_member(node, context->subplan_targetlist); + if (tle) { /* Found a matching subplan output expression */ Var *newvar; newvar = makeVar(context->subvarno, - resdom->resno, - resdom->restype, - resdom->restypmod, + tle->resno, + exprType((Node *) tle->expr), + exprTypmod((Node *) tle->expr), 0); newvar->varnoold = 0; /* wasn't ever a plain Var */ newvar->varoattno = 0; diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index f89f8a8af7..c92fb31531 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.94 2004/12/31 22:00:09 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.95 2005/04/06 16:34:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -350,8 +350,9 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) TargetEntry *te = linitial(plan->targetlist); Param *prm; - Assert(!te->resdom->resjunk); - prm = generate_new_param(te->resdom->restype, te->resdom->restypmod); + Assert(!te->resjunk); + prm = generate_new_param(exprType((Node *) te->expr), + exprTypmod((Node *) te->expr)); node->setParam = list_make1_int(prm->paramid); PlannerInitPlan = lappend(PlannerInitPlan, node); result = (Node *) prm; @@ -362,11 +363,11 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) Oid arraytype; Param *prm; - Assert(!te->resdom->resjunk); - arraytype = get_array_type(te->resdom->restype); + Assert(!te->resjunk); + arraytype = get_array_type(exprType((Node *) te->expr)); if (!OidIsValid(arraytype)) elog(ERROR, "could not find array type for datatype %s", - format_type_be(te->resdom->restype)); + format_type_be(exprType((Node *) te->expr))); prm = generate_new_param(arraytype, -1); node->setParam = list_make1_int(prm->paramid); PlannerInitPlan = lappend(PlannerInitPlan, node); @@ -525,15 +526,15 @@ convert_sublink_opers(List *lefthand, List *operOids, Node *rightop; Operator tup; - Assert(!te->resdom->resjunk); + Assert(!te->resjunk); if (rtindex) { /* Make the Var node representing the subplan's result */ rightop = (Node *) makeVar(rtindex, - te->resdom->resno, - te->resdom->restype, - te->resdom->restypmod, + te->resno, + exprType((Node *) te->expr), + exprTypmod((Node *) te->expr), 0); /* @@ -547,8 +548,8 @@ convert_sublink_opers(List *lefthand, List *operOids, /* Make the Param node representing the subplan's result */ Param *prm; - prm = generate_new_param(te->resdom->restype, - te->resdom->restypmod); + prm = generate_new_param(exprType((Node *) te->expr), + exprTypmod((Node *) te->expr)); /* Record its ID */ *righthandIds = lappend_int(*righthandIds, prm->paramid); rightop = (Node *) prm; @@ -575,7 +576,7 @@ convert_sublink_opers(List *lefthand, List *operOids, leftop, rightop, exprType(leftop), - te->resdom->restype)); + exprType((Node *) te->expr))); ReleaseSysCache(tup); diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index cb5618cfbc..603b8c4358 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -16,7 +16,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.25 2004/12/31 22:00:20 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.26 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -458,7 +458,7 @@ has_nullable_targetlist(Query *subquery) TargetEntry *tle = (TargetEntry *) lfirst(l); /* ignore resjunk columns */ - if (tle->resdom->resjunk) + if (tle->resjunk) continue; /* Must contain a Var of current level */ diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 69dc30c63d..ac8dae65ce 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.73 2005/03/17 23:44:52 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.74 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -79,18 +79,17 @@ preprocess_targetlist(Query *parse, List *tlist) */ if (command_type == CMD_UPDATE || command_type == CMD_DELETE) { - Resdom *resdom; + TargetEntry *tle; Var *var; - resdom = makeResdom(list_length(tlist) + 1, - TIDOID, - -1, - pstrdup("ctid"), - true); - var = makeVar(result_relation, SelfItemPointerAttributeNumber, TIDOID, -1, 0); + tle = makeTargetEntry((Expr *) var, + list_length(tlist) + 1, + pstrdup("ctid"), + true); + /* * For an UPDATE, expand_targetlist already created a fresh tlist. * For DELETE, better do a listCopy so that we don't destructively @@ -99,7 +98,7 @@ preprocess_targetlist(Query *parse, List *tlist) if (command_type == CMD_DELETE) tlist = list_copy(tlist); - tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) var)); + tlist = lappend(tlist, tle); } /* @@ -132,18 +131,9 @@ preprocess_targetlist(Query *parse, List *tlist) foreach(l, parse->rowMarks) { Index rti = lfirst_int(l); - char *resname; - Resdom *resdom; Var *var; - TargetEntry *ctid; - - resname = (char *) palloc(32); - snprintf(resname, 32, "ctid%u", rti); - resdom = makeResdom(list_length(tlist) + 1, - TIDOID, - -1, - resname, - true); + char *resname; + TargetEntry *tle; var = makeVar(rti, SelfItemPointerAttributeNumber, @@ -151,8 +141,15 @@ preprocess_targetlist(Query *parse, List *tlist) -1, 0); - ctid = makeTargetEntry(resdom, (Expr *) var); - tlist = lappend(tlist, ctid); + resname = (char *) palloc(32); + snprintf(resname, 32, "ctid%u", rti); + + tle = makeTargetEntry((Expr *) var, + list_length(tlist) + 1, + resname, + true); + + tlist = lappend(tlist, tle); } } @@ -206,9 +203,8 @@ expand_targetlist(List *tlist, int command_type, if (tlist_item != NULL) { TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item); - Resdom *resdom = old_tle->resdom; - if (!resdom->resjunk && resdom->resno == attrno) + if (!old_tle->resjunk && old_tle->resno == attrno) { new_tle = old_tle; tlist_item = lnext(tlist_item); @@ -268,9 +264,6 @@ expand_targetlist(List *tlist, int command_type, (Datum) 0, true, /* isnull */ true /* byval */ ); - /* label resdom with INT4, too */ - atttype = INT4OID; - atttypmod = -1; } break; case CMD_UPDATE: @@ -290,9 +283,6 @@ expand_targetlist(List *tlist, int command_type, (Datum) 0, true, /* isnull */ true /* byval */ ); - /* label resdom with INT4, too */ - atttype = INT4OID; - atttypmod = -1; } break; default: @@ -302,12 +292,10 @@ expand_targetlist(List *tlist, int command_type, break; } - new_tle = makeTargetEntry(makeResdom(attrno, - atttype, - atttypmod, + new_tle = makeTargetEntry((Expr *) new_expr, + attrno, pstrdup(NameStr(att_tup->attname)), - false), - (Expr *) new_expr); + false); } new_tlist = lappend(new_tlist, new_tle); @@ -324,16 +312,14 @@ expand_targetlist(List *tlist, int command_type, while (tlist_item) { TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item); - Resdom *resdom = old_tle->resdom; - if (!resdom->resjunk) + if (!old_tle->resjunk) elog(ERROR, "targetlist is not sorted correctly"); /* Get the resno right, but don't copy unnecessarily */ - if (resdom->resno != attrno) + if (old_tle->resno != attrno) { - resdom = (Resdom *) copyObject((Node *) resdom); - resdom->resno = attrno; - old_tle = makeTargetEntry(resdom, old_tle->expr); + old_tle = flatCopyTargetEntry(old_tle); + old_tle->resno = attrno; } new_tlist = lappend(new_tlist, old_tle); attrno++; diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index f9e937aaa6..ae3c3a8c18 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.119 2004/12/31 22:00:20 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.120 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,7 @@ #include "optimizer/tlist.h" #include "parser/parse_clause.h" #include "parser/parse_coerce.h" +#include "parser/parse_expr.h" #include "parser/parsetree.h" #include "utils/lsyscache.h" @@ -429,7 +430,7 @@ generate_setop_tlist(List *colTypes, int flag, ListCell *i, *j, *k; - Resdom *resdom; + TargetEntry *tle; Node *expr; j = list_head(input_tlist); @@ -439,12 +440,11 @@ generate_setop_tlist(List *colTypes, int flag, Oid colType = lfirst_oid(i); TargetEntry *inputtle = (TargetEntry *) lfirst(j); TargetEntry *reftle = (TargetEntry *) lfirst(k); - int32 colTypmod; - Assert(inputtle->resdom->resno == resno); - Assert(reftle->resdom->resno == resno); - Assert(!inputtle->resdom->resjunk); - Assert(!reftle->resdom->resjunk); + Assert(inputtle->resno == resno); + Assert(reftle->resno == resno); + Assert(!inputtle->resjunk); + Assert(!reftle->resjunk); /* * Generate columns referencing input columns and having @@ -463,29 +463,23 @@ generate_setop_tlist(List *colTypes, int flag, expr = (Node *) inputtle->expr; else expr = (Node *) makeVar(0, - inputtle->resdom->resno, - inputtle->resdom->restype, - inputtle->resdom->restypmod, + inputtle->resno, + exprType((Node *) inputtle->expr), + exprTypmod((Node *) inputtle->expr), 0); - if (inputtle->resdom->restype == colType) - { - /* no coercion needed, and believe the input typmod */ - colTypmod = inputtle->resdom->restypmod; - } - else + if (exprType(expr) != colType) { expr = coerce_to_common_type(NULL, /* no UNKNOWNs here */ expr, colType, "UNION/INTERSECT/EXCEPT"); - colTypmod = -1; } - resdom = makeResdom((AttrNumber) resno++, - colType, - colTypmod, - pstrdup(reftle->resdom->resname), - false); - tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); + tle = makeTargetEntry((Expr *) expr, + (AttrNumber) resno++, + pstrdup(reftle->resname), + false); + tlist = lappend(tlist, tle); + j = lnext(j); k = lnext(k); } @@ -493,18 +487,17 @@ generate_setop_tlist(List *colTypes, int flag, if (flag >= 0) { /* Add a resjunk flag column */ - resdom = makeResdom((AttrNumber) resno++, - INT4OID, - -1, - pstrdup("flag"), - true); /* flag value is the given constant */ expr = (Node *) makeConst(INT4OID, sizeof(int4), Int32GetDatum(flag), false, true); - tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); + tle = makeTargetEntry((Expr *) expr, + (AttrNumber) resno++, + pstrdup("flag"), + true); + tlist = lappend(tlist, tle); } return tlist; @@ -531,7 +524,7 @@ generate_append_tlist(List *colTypes, bool flag, ListCell *curColType; ListCell *ref_tl_item; int colindex; - Resdom *resdom; + TargetEntry *tle; Node *expr; ListCell *planl; int32 *colTypmods; @@ -555,15 +548,17 @@ generate_append_tlist(List *colTypes, bool flag, { TargetEntry *subtle = (TargetEntry *) lfirst(subtlist); - if (subtle->resdom->resjunk) + if (subtle->resjunk) continue; Assert(curColType != NULL); - if (subtle->resdom->restype == lfirst_oid(curColType)) + if (exprType((Node *) subtle->expr) == lfirst_oid(curColType)) { /* If first subplan, copy the typmod; else compare */ + int32 subtypmod = exprTypmod((Node *) subtle->expr); + if (planl == list_head(input_plans)) - colTypmods[colindex] = subtle->resdom->restypmod; - else if (subtle->resdom->restypmod != colTypmods[colindex]) + colTypmods[colindex] = subtypmod; + else if (subtypmod != colTypmods[colindex]) colTypmods[colindex] = -1; } else @@ -587,36 +582,34 @@ generate_append_tlist(List *colTypes, bool flag, int32 colTypmod = colTypmods[colindex++]; TargetEntry *reftle = (TargetEntry *) lfirst(ref_tl_item); - Assert(reftle->resdom->resno == resno); - Assert(!reftle->resdom->resjunk); + Assert(reftle->resno == resno); + Assert(!reftle->resjunk); expr = (Node *) makeVar(0, resno, colType, colTypmod, 0); - resdom = makeResdom((AttrNumber) resno++, - colType, - colTypmod, - pstrdup(reftle->resdom->resname), - false); - tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); + tle = makeTargetEntry((Expr *) expr, + (AttrNumber) resno++, + pstrdup(reftle->resname), + false); + tlist = lappend(tlist, tle); } if (flag) { /* Add a resjunk flag column */ - resdom = makeResdom((AttrNumber) resno++, - INT4OID, - -1, - pstrdup("flag"), - true); /* flag value is shown as copied up from subplan */ expr = (Node *) makeVar(0, - resdom->resno, + resno, INT4OID, -1, 0); - tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) expr)); + tle = makeTargetEntry((Expr *) expr, + (AttrNumber) resno++, + pstrdup("flag"), + true); + tlist = lappend(tlist, tle); } pfree(colTypmods); @@ -640,7 +633,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK) { TargetEntry *tle = (TargetEntry *) lfirst(l); - if (tle->resdom->resjunk) + if (tle->resjunk) { if (!junkOK) return false; @@ -649,7 +642,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK) { if (curColType == NULL) return false; - if (tle->resdom->restype != lfirst_oid(curColType)) + if (exprType((Node *) tle->expr) != lfirst_oid(curColType)) return false; curColType = lnext(curColType); } @@ -1105,8 +1098,7 @@ adjust_relid_set(Relids relids, Index oldrelid, Index newrelid) * * The given tlist has already been through expression_tree_mutator; * therefore the TargetEntry nodes are fresh copies that it's okay to - * scribble on. But the Resdom nodes have not been copied; make new ones - * if we need to change them! + * scribble on. * * Note that this is not needed for INSERT because INSERT isn't inheritable. */ @@ -1124,18 +1116,15 @@ adjust_inherited_tlist(List *tlist, foreach(tl, tlist) { TargetEntry *tle = (TargetEntry *) lfirst(tl); - Resdom *resdom = tle->resdom; - if (resdom->resjunk) + if (tle->resjunk) continue; /* ignore junk items */ - attrno = translate_inherited_attnum(resdom->resno, context); + attrno = translate_inherited_attnum(tle->resno, context); - if (resdom->resno != attrno) + if (tle->resno != attrno) { - resdom = (Resdom *) copyObject((Node *) resdom); - resdom->resno = attrno; - tle->resdom = resdom; + tle->resno = attrno; changed_it = true; } } @@ -1157,14 +1146,13 @@ adjust_inherited_tlist(List *tlist, foreach(tl, tlist) { TargetEntry *tle = (TargetEntry *) lfirst(tl); - Resdom *resdom = tle->resdom; - if (resdom->resjunk) + if (tle->resjunk) continue; /* ignore junk items */ - if (resdom->resno == attrno) + if (tle->resno == attrno) new_tlist = lappend(new_tlist, tle); - else if (resdom->resno > attrno) + else if (tle->resno > attrno) more = true; } } @@ -1172,17 +1160,11 @@ adjust_inherited_tlist(List *tlist, foreach(tl, tlist) { TargetEntry *tle = (TargetEntry *) lfirst(tl); - Resdom *resdom = tle->resdom; - if (!resdom->resjunk) + if (!tle->resjunk) continue; /* here, ignore non-junk items */ - if (resdom->resno != attrno) - { - resdom = (Resdom *) copyObject((Node *) resdom); - resdom->resno = attrno; - tle->resdom = resdom; - } + tle->resno = attrno; new_tlist = lappend(new_tlist, tle); attrno++; } diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 2cf4fcd663..24d74523c3 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.192 2005/03/31 22:46:09 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.193 2005/04/06 16:34:06 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -966,22 +966,22 @@ has_distinct_on_clause(Query *query) { TargetEntry *tle = (TargetEntry *) lfirst(l); - if (tle->resdom->ressortgroupref == 0) + if (tle->ressortgroupref == 0) { - if (tle->resdom->resjunk) + if (tle->resjunk) continue; /* we can ignore unsorted junk cols */ return true; /* definitely not in DISTINCT list */ } if (targetIsInSortList(tle, query->distinctClause)) { - if (tle->resdom->resjunk) + if (tle->resjunk) return true; /* junk TLE in DISTINCT means DISTINCT ON */ /* else this TLE is okay, keep looking */ } else { /* This TLE is not in DISTINCT list */ - if (!tle->resdom->resjunk) + if (!tle->resjunk) return true; /* non-junk, non-DISTINCT, so DISTINCT ON */ if (targetIsInSortList(tle, query->sortClause)) return true; /* sorted, non-distinct junk */ @@ -3314,10 +3314,6 @@ expression_tree_mutator(Node *node, break; case T_TargetEntry: { - /* - * We mutate the expression, but not the resdom, by - * default. - */ TargetEntry *targetentry = (TargetEntry *) node; TargetEntry *newnode; diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index b6b0cc505f..14b62b80fc 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.114 2005/03/27 06:29:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.115 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -789,7 +789,7 @@ is_distinct_query(Query *query) TargetEntry *tle = get_sortgroupclause_tle(grpcl, query->targetList); - if (tle->resdom->resjunk) + if (tle->resjunk) break; } if (!gl) /* got to the end? */ diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c64f2aad1f..e01a1d76a5 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.103 2005/03/29 00:17:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.104 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -378,6 +378,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel) for (attrno = 1; attrno <= numattrs; attrno++) { Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1]; + Var *var; if (att_tup->attisdropped) { @@ -386,13 +387,17 @@ build_physical_tlist(Query *root, RelOptInfo *rel) break; } + var = makeVar(varno, + attrno, + att_tup->atttypid, + att_tup->atttypmod, + 0); + tlist = lappend(tlist, - create_tl_element(makeVar(varno, - attrno, - att_tup->atttypid, - att_tup->atttypmod, - 0), - attrno)); + makeTargetEntry((Expr *) var, + attrno, + NULL, + false)); } heap_close(relation, AccessShareLock); diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index d5118de296..1672cda77c 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.68 2004/12/31 22:00:23 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/tlist.c,v 1.69 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,12 +25,12 @@ *****************************************************************************/ /* - * tlistentry_member + * tlist_member * Finds the (first) member of the given tlist whose expression is * equal() to the given expression. Result is NULL if no such member. */ TargetEntry * -tlistentry_member(Node *node, List *targetlist) +tlist_member(Node *node, List *targetlist) { ListCell *temp; @@ -44,77 +44,6 @@ tlistentry_member(Node *node, List *targetlist) return NULL; } -#ifdef NOT_USED -/* - * matching_tlist_expr - * Same as tlistentry_member(), except returns the tlist expression - * rather than its parent TargetEntry node. - */ -Node * -matching_tlist_expr(Node *node, List *targetlist) -{ - TargetEntry *tlentry; - - tlentry = tlistentry_member(node, targetlist); - if (tlentry) - return tlentry->expr; - - return NULL; -} -#endif - -/* - * tlist_member - * Same as tlistentry_member(), except returns the Resdom node - * rather than its parent TargetEntry node. - */ -Resdom * -tlist_member(Node *node, List *targetlist) -{ - TargetEntry *tlentry; - - tlentry = tlistentry_member(node, targetlist); - if (tlentry) - return tlentry->resdom; - - return NULL; -} - -/* - * create_tl_element - * Creates a target list entry node and its associated (resdom var) pair - * with its resdom number equal to 'resdomno'. - * - * Note: the argument is almost always a Var, but occasionally not. - */ -TargetEntry * -create_tl_element(Var *var, int resdomno) -{ - Oid vartype; - int32 vartypmod; - - if (IsA(var, Var)) - { - vartype = var->vartype; - vartypmod = var->vartypmod; - } - else - { - vartype = exprType((Node *) var); - vartypmod = exprTypmod((Node *) var); - } - return makeTargetEntry(makeResdom(resdomno, - vartype, - vartypmod, - NULL, - false), - (Expr *) var); -} - -/***************************************************************************** - * ---------- GENERAL target list routines ---------- - *****************************************************************************/ - /* * flatten_tlist * Create a target list that only contains unique variables. @@ -153,24 +82,22 @@ flatten_tlist(List *tlist) List * add_to_flat_tlist(List *tlist, List *vars) { - int next_resdomno = list_length(tlist) + 1; + int next_resno = list_length(tlist) + 1; ListCell *v; foreach(v, vars) { Var *var = (Var *) lfirst(v); - if (!tlistentry_member((Node *) var, tlist)) + if (!tlist_member((Node *) var, tlist)) { - Resdom *r; - - r = makeResdom(next_resdomno++, - var->vartype, - var->vartypmod, - NULL, - false); - tlist = lappend(tlist, - makeTargetEntry(r, copyObject(var))); + TargetEntry *tle; + + tle = makeTargetEntry(copyObject(var), /* copy needed?? */ + next_resno++, + NULL, + false); + tlist = lappend(tlist, tle); } } return tlist; @@ -195,7 +122,7 @@ get_sortgroupclause_tle(SortClause *sortClause, { TargetEntry *tle = (TargetEntry *) lfirst(l); - if (tle->resdom->ressortgroupref == refnumber) + if (tle->ressortgroupref == refnumber) return tle; } diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 6e16086991..191f4446b0 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -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) diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 2885ff51ec..6d13e485b2 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -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 */ diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index ba3dbcad75..058a1566be 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -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 diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 6e391f4eb8..031bfa8fe2 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -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); - - te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++, - exprType(varnode), - exprTypmod(varnode), - label, - false); - te->expr = (Expr *) varnode; + TargetEntry *te; + + 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; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 8675bc2683..d537f570bd 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -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); } diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 1d9458e834..45c44501a6 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.101 2005/01/27 23:24:05 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.102 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "commands/view.h" #include "miscadmin.h" #include "optimizer/clauses.h" +#include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteManip.h" @@ -290,11 +291,11 @@ DefineQueryRewrite(RuleStmt *stmt) foreach(tllist, query->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(tllist); - Resdom *resdom = tle->resdom; + int32 tletypmod; Form_pg_attribute attr; char *attname; - if (resdom->resjunk) + if (tle->resjunk) continue; i++; if (i > event_relation->rd_att->natts) @@ -318,12 +319,12 @@ DefineQueryRewrite(RuleStmt *stmt) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert relation containing dropped columns to view"))); - if (strcmp(resdom->resname, attname) != 0) + if (strcmp(tle->resname, attname) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("SELECT rule's target entry %d has different column name from \"%s\"", i, attname))); - if (attr->atttypid != resdom->restype) + if (attr->atttypid != exprType((Node *) tle->expr)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("SELECT rule's target entry %d has different type from column \"%s\"", i, attname))); @@ -335,8 +336,9 @@ DefineQueryRewrite(RuleStmt *stmt) * length but the select rule's expression will probably have * typmod = -1. */ - if (attr->atttypmod != resdom->restypmod && - attr->atttypmod != -1 && resdom->restypmod != -1) + tletypmod = exprTypmod((Node *) tle->expr); + if (attr->atttypmod != tletypmod && + attr->atttypmod != -1 && tletypmod != -1) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("SELECT rule's target entry %d has different size from column \"%s\"", i, attname))); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 844ab38e83..c190b634b2 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.149 2005/03/26 05:53:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.150 2005/04/06 16:34:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -312,12 +312,11 @@ rewriteTargetList(Query *parsetree, Relation target_relation) foreach(temp, parsetree->targetList) { TargetEntry *old_tle = (TargetEntry *) lfirst(temp); - Resdom *resdom = old_tle->resdom; - if (!resdom->resjunk) + if (!old_tle->resjunk) { /* Normal attr: stash it into new_tles[] */ - attrno = resdom->resno; + attrno = old_tle->resno; if (attrno < 1 || attrno > numattrs) elog(ERROR, "bogus resno %d in targetlist", attrno); att_tup = target_relation->rd_att->attrs[attrno - 1]; @@ -344,11 +343,10 @@ rewriteTargetList(Query *parsetree, Relation target_relation) */ /* Get the resno right, but don't copy unnecessarily */ - if (resdom->resno != next_junk_attrno) + if (old_tle->resno != next_junk_attrno) { - resdom = (Resdom *) copyObject((Node *) resdom); - resdom->resno = next_junk_attrno; - old_tle = makeTargetEntry(resdom, old_tle->expr); + old_tle = flatCopyTargetEntry(old_tle); + old_tle->resno = next_junk_attrno; } junk_tlist = lappend(junk_tlist, old_tle); next_junk_attrno++; @@ -407,12 +405,10 @@ rewriteTargetList(Query *parsetree, Relation target_relation) } if (new_expr) - new_tle = makeTargetEntry(makeResdom(attrno, - att_tup->atttypid, - att_tup->atttypmod, - pstrdup(NameStr(att_tup->attname)), - false), - (Expr *) new_expr); + new_tle = makeTargetEntry((Expr *) new_expr, + attrno, + pstrdup(NameStr(att_tup->attname)), + false); } if (new_tle) @@ -436,7 +432,7 @@ process_matched_tle(TargetEntry *src_tle, TargetEntry *prior_tle, const char *attrName) { - Resdom *resdom = src_tle->resdom; + TargetEntry *result; Node *src_expr; Node *prior_expr; Node *src_input; @@ -547,7 +543,9 @@ process_matched_tle(TargetEntry *src_tle, newexpr = NULL; } - return makeTargetEntry(resdom, (Expr *) newexpr); + result = flatCopyTargetEntry(src_tle); + result->expr = (Expr *) newexpr; + return result; } /* diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 814deff5e3..2f8e86e4b0 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.189 2005/03/29 00:17:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.190 2005/04/06 16:34:06 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -1493,13 +1493,12 @@ deparse_context_for_subplan(const char *name, List *tlist, foreach(tl, tlist) { TargetEntry *tle = lfirst(tl); - Resdom *resdom = tle->resdom; nattrs++; - Assert(resdom->resno == nattrs); - if (resdom->resname) + Assert(tle->resno == nattrs); + if (tle->resname) { - attrs = lappend(attrs, makeString(resdom->resname)); + attrs = lappend(attrs, makeString(tle->resname)); continue; } if (tle->expr && IsA(tle->expr, Var)) @@ -1518,7 +1517,7 @@ deparse_context_for_subplan(const char *name, List *tlist, } } /* Fallback if can't get name */ - snprintf(buf, sizeof(buf), "?column%d?", resdom->resno); + snprintf(buf, sizeof(buf), "?column%d?", tle->resno); attrs = lappend(attrs, makeString(pstrdup(buf))); } @@ -1974,7 +1973,7 @@ get_basic_select_query(Query *query, deparse_context *context, TargetEntry *tle = (TargetEntry *) lfirst(l); char *colname; - if (tle->resdom->resjunk) + if (tle->resjunk) continue; /* ignore junk entries */ appendStringInfo(buf, sep); @@ -1992,7 +1991,7 @@ get_basic_select_query(Query *query, deparse_context *context, if (resultDesc && colno <= resultDesc->natts) colname = NameStr(resultDesc->attrs[colno - 1]->attname); else - colname = tle->resdom->resname; + colname = tle->resname; if (colname) /* resname could be NULL */ { @@ -2166,8 +2165,8 @@ get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno, */ if (force_colno || (expr && IsA(expr, Const))) { - Assert(!tle->resdom->resjunk); - appendStringInfo(buf, "%d", tle->resdom->resno); + Assert(!tle->resjunk); + appendStringInfo(buf, "%d", tle->resno); } else get_rule_expr(expr, context, true); @@ -2227,7 +2226,7 @@ get_insert_query_def(Query *query, deparse_context *context) { TargetEntry *tle = (TargetEntry *) lfirst(l); - if (tle->resdom->resjunk) + if (tle->resjunk) continue; /* ignore junk entries */ appendStringInfo(buf, sep); @@ -2239,7 +2238,7 @@ get_insert_query_def(Query *query, deparse_context *context) */ appendStringInfoString(buf, quote_identifier(get_relid_attribute_name(rte->relid, - tle->resdom->resno))); + tle->resno))); /* * Print any indirection needed (subfields or subscripts), and @@ -2299,7 +2298,7 @@ get_update_query_def(Query *query, deparse_context *context) TargetEntry *tle = (TargetEntry *) lfirst(l); Node *expr; - if (tle->resdom->resjunk) + if (tle->resjunk) continue; /* ignore junk entries */ appendStringInfo(buf, sep); @@ -2311,7 +2310,7 @@ get_update_query_def(Query *query, deparse_context *context) */ appendStringInfoString(buf, quote_identifier(get_relid_attribute_name(rte->relid, - tle->resdom->resno))); + tle->resno))); /* * Print any indirection needed (subfields or subscripts), and diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 45b1695fca..4243ce19b2 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.262 2005/03/29 19:44:23 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.263 2005/04/06 16:34:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200503291 +#define CATALOG_VERSION_NO 200504061 #endif diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 8d50f49971..52444d258b 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.51 2004/12/31 22:03:34 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.52 2005/04/06 16:34:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,13 +29,12 @@ extern Var *makeVar(Index varno, int32 vartypmod, Index varlevelsup); -extern TargetEntry *makeTargetEntry(Resdom *resdom, Expr *expr); +extern TargetEntry *makeTargetEntry(Expr *expr, + AttrNumber resno, + char *resname, + bool resjunk); -extern Resdom *makeResdom(AttrNumber resno, - Oid restype, - int32 restypmod, - char *resname, - bool resjunk); +extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle); extern Const *makeConst(Oid consttype, int constlen, diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 5d70180a0c..4822b5f6cc 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.164 2005/03/14 00:19:37 neilc Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.165 2005/04/06 16:34:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -93,8 +93,7 @@ typedef enum NodeTag /* * TAGS FOR PRIMITIVE NODES (primnodes.h) */ - T_Resdom = 300, - T_Alias, + T_Alias = 300, T_RangeVar, T_Expr, T_Var, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index a6a79e3a4f..85016f3511 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.275 2005/03/29 17:58:51 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.276 2005/04/06 16:34:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -552,11 +552,11 @@ typedef struct RangeTblEntry * SortClause - * representation of ORDER BY clauses * - * tleSortGroupRef must match ressortgroupref of exactly one Resdom of the + * tleSortGroupRef must match ressortgroupref of exactly one entry of the * associated targetlist; that is the expression to be sorted (or grouped) by. * sortop is the OID of the ordering operator. * - * SortClauses are also used to identify Resdoms that we will do a "Unique" + * SortClauses are also used to identify targets that we will do a "Unique" * filter step on (for SELECT DISTINCT and SELECT DISTINCT ON). The * distinctClause list is simply a copy of the relevant members of the * sortClause list. Note that distinctClause can be a subset of sortClause, diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 46de880565..a1d1ef3ebf 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.106 2004/12/31 22:03:34 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.107 2005/04/06 16:34:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,72 +27,6 @@ * ---------------------------------------------------------------- */ -/*-------------------- - * Resdom (Result Domain) - * - * Notes: - * - * In a SELECT's targetlist, resno should always be equal to the item's - * ordinal position (counting from 1). However, in an INSERT or UPDATE - * targetlist, resno represents the attribute number of the destination - * column for the item; so there may be missing or out-of-order resnos. - * It is even legal to have duplicated resnos; consider - * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ... - * The two meanings come together in the executor, because the planner - * transforms INSERT/UPDATE tlists into a normalized form with exactly - * one entry for each column of the destination table. Before that's - * happened, however, it is risky to assume that resno == position. - * Generally get_tle_by_resno() should be used rather than list_nth() - * to fetch tlist entries by resno, and only in SELECT should you assume - * that resno is a unique identifier. - * - * resname is required to represent the correct column name in non-resjunk - * entries of top-level SELECT targetlists, since it will be used as the - * column title sent to the frontend. In most other contexts it is only - * a debugging aid, and may be wrong or even NULL. (In particular, it may - * be wrong in a tlist from a stored rule, if the referenced column has been - * renamed by ALTER TABLE since the rule was made. Also, the planner tends - * to store NULL rather than look up a valid name for tlist entries in - * non-toplevel plan nodes.) In resjunk entries, resname should be either - * a specific system-generated name (such as "ctid") or NULL; anything else - * risks confusing ExecGetJunkAttribute! - * - * ressortgroupref is used in the representation of ORDER BY and - * GROUP BY items. Targetlist entries with ressortgroupref=0 are not - * sort/group items. If ressortgroupref>0, then this item is an ORDER BY or - * GROUP BY value. No two entries in a targetlist may have the same nonzero - * ressortgroupref --- but there is no particular meaning to the nonzero - * values, except as tags. (For example, one must not assume that lower - * ressortgroupref means a more significant sort key.) The order of the - * associated SortClause or GroupClause lists determine the semantics. - * - * resorigtbl/resorigcol identify the source of the column, if it is a - * simple reference to a column of a base table (or view). If it is not - * a simple reference, these fields are zeroes. - * - * If resjunk is true then the column is a working column (such as a sort key) - * that should be removed from the final output of the query. Resjunk columns - * must have resnos that cannot duplicate any regular column's resno. Also - * note that there are places that assume resjunk columns come after non-junk - * columns. - *-------------------- - */ -typedef struct Resdom -{ - NodeTag type; - AttrNumber resno; /* attribute number (see notes above) */ - Oid restype; /* type of the value */ - int32 restypmod; /* type-specific modifier of the value */ - char *resname; /* name of the column (could be NULL) */ - Index ressortgroupref;/* nonzero if referenced by a sort/group - * clause */ - Oid resorigtbl; /* OID of column's source table */ - AttrNumber resorigcol; /* column's number in source table */ - bool resjunk; /* set to true to eliminate the attribute - * from final target list */ -} Resdom; - - /* * Alias - * specifies an alias for a range variable; the alias might also @@ -822,7 +756,7 @@ typedef struct SetToDefault int32 typeMod; /* typemod for substituted value */ } SetToDefault; -/* +/*-------------------- * TargetEntry - * a target entry (used in query target lists) * @@ -831,14 +765,63 @@ typedef struct SetToDefault * very many places it's convenient to process a whole query targetlist as a * single expression tree. * - * The separation between TargetEntry and Resdom is historical. One of these - * days, Resdom should probably get folded into TargetEntry. + * In a SELECT's targetlist, resno should always be equal to the item's + * ordinal position (counting from 1). However, in an INSERT or UPDATE + * targetlist, resno represents the attribute number of the destination + * column for the item; so there may be missing or out-of-order resnos. + * It is even legal to have duplicated resnos; consider + * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ... + * The two meanings come together in the executor, because the planner + * transforms INSERT/UPDATE tlists into a normalized form with exactly + * one entry for each column of the destination table. Before that's + * happened, however, it is risky to assume that resno == position. + * Generally get_tle_by_resno() should be used rather than list_nth() + * to fetch tlist entries by resno, and only in SELECT should you assume + * that resno is a unique identifier. + * + * resname is required to represent the correct column name in non-resjunk + * entries of top-level SELECT targetlists, since it will be used as the + * column title sent to the frontend. In most other contexts it is only + * a debugging aid, and may be wrong or even NULL. (In particular, it may + * be wrong in a tlist from a stored rule, if the referenced column has been + * renamed by ALTER TABLE since the rule was made. Also, the planner tends + * to store NULL rather than look up a valid name for tlist entries in + * non-toplevel plan nodes.) In resjunk entries, resname should be either + * a specific system-generated name (such as "ctid") or NULL; anything else + * risks confusing ExecGetJunkAttribute! + * + * ressortgroupref is used in the representation of ORDER BY and + * GROUP BY items. Targetlist entries with ressortgroupref=0 are not + * sort/group items. If ressortgroupref>0, then this item is an ORDER BY or + * GROUP BY value. No two entries in a targetlist may have the same nonzero + * ressortgroupref --- but there is no particular meaning to the nonzero + * values, except as tags. (For example, one must not assume that lower + * ressortgroupref means a more significant sort key.) The order of the + * associated SortClause or GroupClause lists determine the semantics. + * + * resorigtbl/resorigcol identify the source of the column, if it is a + * simple reference to a column of a base table (or view). If it is not + * a simple reference, these fields are zeroes. + * + * If resjunk is true then the column is a working column (such as a sort key) + * that should be removed from the final output of the query. Resjunk columns + * must have resnos that cannot duplicate any regular column's resno. Also + * note that there are places that assume resjunk columns come after non-junk + * columns. + *-------------------- */ typedef struct TargetEntry { Expr xpr; - Resdom *resdom; /* descriptor for targetlist item */ Expr *expr; /* expression to evaluate */ + AttrNumber resno; /* attribute number (see notes above) */ + char *resname; /* name of the column (could be NULL) */ + Index ressortgroupref;/* nonzero if referenced by a sort/group + * clause */ + Oid resorigtbl; /* OID of column's source table */ + AttrNumber resorigcol; /* column's number in source table */ + bool resjunk; /* set to true to eliminate the attribute + * from final target list */ } TargetEntry; diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h index 33df54cd5d..91418033ae 100644 --- a/src/include/optimizer/tlist.h +++ b/src/include/optimizer/tlist.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.41 2004/12/31 22:03:36 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/tlist.h,v 1.42 2005/04/06 16:34:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,10 +17,7 @@ #include "nodes/relation.h" -extern TargetEntry *tlistentry_member(Node *node, List *targetlist); -extern Resdom *tlist_member(Node *node, List *targetlist); - -extern TargetEntry *create_tl_element(Var *var, int resdomno); +extern TargetEntry *tlist_member(Node *node, List *targetlist); extern List *flatten_tlist(List *tlist); extern List *add_to_flat_tlist(List *tlist, List *vars); diff --git a/src/tools/backend/index.html b/src/tools/backend/index.html index 241c4bb5d5..6d85edfcf8 100644 --- a/src/tools/backend/index.html +++ b/src/tools/backend/index.html @@ -71,9 +71,8 @@ transformFromClause(). Query.rtable holds the query's range table.

Certain queries, like SELECT, return columns of data. Other queries, like INSERT and UPDATE, specify the columns modified by the query. These column references are converted to Resdom entries, which are -placed in target list -entries, and linked together to make up the target list of +HREF="../../include/nodes/primnodes.h">TargetEntry entries, which are +linked together to make up the target list of the query. The target list is stored in Query.targetList, which is generated by transformTargetList().

-- 2.40.0