aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_target.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-05-06 00:20:33 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-05-06 00:20:33 +0000
commit2cf57c8f8d060711c1ad7e1dd6cc1115a2839b47 (patch)
treeb3b2a9616d425072d26cfc57efcbe676c56b399e /src/backend/parser/parse_target.c
parent94a3c60324465f98850b60f548c1ea481ab4e52f (diff)
downloadpostgresql-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.c91
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.