diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2003-05-06 00:20:33 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2003-05-06 00:20:33 +0000 |
commit | 2cf57c8f8d060711c1ad7e1dd6cc1115a2839b47 (patch) | |
tree | b3b2a9616d425072d26cfc57efcbe676c56b399e /src/backend/parser/parse_target.c | |
parent | 94a3c60324465f98850b60f548c1ea481ab4e52f (diff) | |
download | postgresql-2cf57c8f8d060711c1ad7e1dd6cc1115a2839b47.tar.gz postgresql-2cf57c8f8d060711c1ad7e1dd6cc1115a2839b47.zip |
Implement feature of new FE/BE protocol whereby RowDescription identifies
the column by table OID and column number, if it's a simple column
reference. Along the way, get rid of reskey/reskeyop fields in Resdoms.
Turns out that representation was not convenient for either the planner
or the executor; we can make the planner deliver exactly what the
executor wants with no more effort.
initdb forced due to change in stored rule representation.
Diffstat (limited to 'src/backend/parser/parse_target.c')
-rw-r--r-- | src/backend/parser/parse_target.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index dc8f241d45e..10892bc292d 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.100 2003/04/29 22:13:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.101 2003/05/06 00:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ #include "utils/builtins.h" +static void markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var); static List *ExpandAllTables(ParseState *pstate); static char *FigureColname(Node *node); static int FigureColnameInternal(Node *node, char **name); @@ -205,6 +206,94 @@ transformTargetList(ParseState *pstate, List *targetlist) /* + * markTargetListOrigins() + * Mark targetlist columns that are simple Vars with the source + * table's OID and column number. + * + * Currently, this is done only for SELECT targetlists, since we only + * need the info if we are going to send it to the frontend. + */ +void +markTargetListOrigins(ParseState *pstate, List *targetlist) +{ + List *l; + + foreach(l, targetlist) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + + markTargetListOrigin(pstate, tle->resdom, (Var *) tle->expr); + } +} + +/* + * markTargetListOrigin() + * If 'var' is a Var of a plain relation, mark 'res' with its origin + * + * This is split out so it can recurse for join references. Note that we + * do not drill down into views, but report the view as the column owner. + */ +static void +markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var) +{ + RangeTblEntry *rte; + AttrNumber attnum; + + if (var == NULL || !IsA(var, Var)) + return; + Assert(var->varno > 0 && + (int) var->varno <= length(pstate->p_rtable)); + rte = rt_fetch(var->varno, pstate->p_rtable); + attnum = var->varattno; + + switch (rte->rtekind) + { + case RTE_RELATION: + /* It's a table or view, report it */ + res->resorigtbl = rte->relid; + res->resorigcol = attnum; + break; + case RTE_SUBQUERY: + { + /* Subselect-in-FROM: copy up from the subselect */ + List *subtl; + + foreach(subtl, rte->subquery->targetList) + { + TargetEntry *subte = (TargetEntry *) lfirst(subtl); + + if (subte->resdom->resjunk || + subte->resdom->resno != attnum) + continue; + res->resorigtbl = subte->resdom->resorigtbl; + res->resorigcol = subte->resdom->resorigcol; + break; + } + /* falling off end of list shouldn't happen... */ + if (subtl == NIL) + elog(ERROR, "Subquery %s does not have attribute %d", + rte->eref->aliasname, attnum); + } + break; + case RTE_JOIN: + { + /* Join RTE --- recursively inspect the alias variable */ + Var *aliasvar; + + Assert(attnum > 0 && attnum <= length(rte->joinaliasvars)); + aliasvar = (Var *) nth(attnum - 1, rte->joinaliasvars); + markTargetListOrigin(pstate, res, aliasvar); + } + break; + case RTE_SPECIAL: + case RTE_FUNCTION: + /* not a simple relation, leave it unmarked */ + break; + } +} + + +/* * updateTargetListEntry() * This is used in INSERT and UPDATE statements only. It prepares a * TargetEntry for assignment to a column of the target table. |