From c06b31dc31e5f6a8ee669449157b39be9987e375 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 13 Jan 2005 17:19:10 +0000 Subject: [PATCH] get_names_for_var didn't do recursion for unnamed JOIN vars quite right; got it wrong when the JOIN was in an outer query level. Per example from Laurie Burrow. Also fix same issue in markTargetListOrigin. I think the latter is only a latent bug since we currently don't apply markTargetListOrigin except at the outer level ... but should do it right anyway. --- src/backend/parser/parse_target.c | 17 +++++++++++------ src/backend/utils/adt/ruleutils.c | 25 ++++++++++++++++--------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index b931b3bb0c..ebba3e868f 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.128 2004/12/31 22:00:27 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.129 2005/01/13 17:19:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,8 @@ #include "utils/typcache.h" -static void markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var); +static void markTargetListOrigin(ParseState *pstate, Resdom *res, + Var *var, int levelsup); static Node *transformAssignmentIndirection(ParseState *pstate, Node *basenode, const char *targetName, @@ -174,7 +175,7 @@ markTargetListOrigins(ParseState *pstate, List *targetlist) { TargetEntry *tle = (TargetEntry *) lfirst(l); - markTargetListOrigin(pstate, tle->resdom, (Var *) tle->expr); + markTargetListOrigin(pstate, tle->resdom, (Var *) tle->expr, 0); } } @@ -182,18 +183,22 @@ markTargetListOrigins(ParseState *pstate, List *targetlist) * markTargetListOrigin() * If 'var' is a Var of a plain relation, mark 'res' with its origin * + * levelsup is an extra offset to interpret the Var's varlevelsup correctly. + * * 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) +markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup) { + int netlevelsup; RangeTblEntry *rte; AttrNumber attnum; if (var == NULL || !IsA(var, Var)) return; - rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup); + netlevelsup = var->varlevelsup + levelsup; + rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup); attnum = var->varattno; switch (rte->rtekind) @@ -223,7 +228,7 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var) Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1); - markTargetListOrigin(pstate, res, aliasvar); + markTargetListOrigin(pstate, res, aliasvar, netlevelsup); } break; case RTE_SPECIAL: diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 4cd5cd6972..f3458a5abe 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.187 2004/12/13 00:33:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.188 2005/01/13 17:19:10 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -182,7 +182,7 @@ static void get_setop_query(Node *setOp, Query *query, static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno, deparse_context *context); -static void get_names_for_var(Var *var, deparse_context *context, +static void get_names_for_var(Var *var, int levelsup, deparse_context *context, char **schemaname, char **refname, char **attname); static RangeTblEntry *find_rte_by_refname(const char *refname, deparse_context *context); @@ -1998,7 +1998,7 @@ get_basic_select_query(Query *query, deparse_context *context, char *refname; char *attname; - get_names_for_var(var, context, + get_names_for_var(var, 0, context, &schemaname, &refname, &attname); tell_as = (attname == NULL || strcmp(attname, colname) != 0); @@ -2392,6 +2392,10 @@ get_utility_query_def(Query *query, deparse_context *context) /* * Get the schemaname, refname and attname for a (possibly nonlocal) Var. * + * In some cases (currently only when recursing into an unnamed join) + * the Var's varlevelsup has to be interpreted with respect to a context + * above the current one; levelsup indicates the offset. + * * schemaname is usually returned as NULL. It will be non-null only if * use of the unqualified refname would find the wrong RTE. * @@ -2404,17 +2408,20 @@ get_utility_query_def(Query *query, deparse_context *context) * distinguish this case.) */ static void -get_names_for_var(Var *var, deparse_context *context, +get_names_for_var(Var *var, int levelsup, deparse_context *context, char **schemaname, char **refname, char **attname) { + int netlevelsup; deparse_namespace *dpns; RangeTblEntry *rte; /* Find appropriate nesting depth */ - if (var->varlevelsup >= list_length(context->namespaces)) - elog(ERROR, "bogus varlevelsup: %d", var->varlevelsup); + netlevelsup = var->varlevelsup + levelsup; + if (netlevelsup >= list_length(context->namespaces)) + elog(ERROR, "bogus varlevelsup: %d offset %d", + var->varlevelsup, levelsup); dpns = (deparse_namespace *) list_nth(context->namespaces, - var->varlevelsup); + netlevelsup); /* Find the relevant RTE */ if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) @@ -2467,7 +2474,7 @@ get_names_for_var(Var *var, deparse_context *context, var->varattno-1); if (IsA(aliasvar, Var)) { - get_names_for_var(aliasvar, context, + get_names_for_var(aliasvar, netlevelsup, context, schemaname, refname, attname); return; } @@ -2867,7 +2874,7 @@ get_rule_expr(Node *node, deparse_context *context, char *refname; char *attname; - get_names_for_var(var, context, + get_names_for_var(var, 0, context, &schemaname, &refname, &attname); if (refname && (context->varprefix || attname == NULL)) { -- 2.11.0