Commit c06b31dc authored by Tom Lane's avatar Tom Lane

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.
parent c2eef62c
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -29,7 +29,8 @@
#include "utils/typcache.h" #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, static Node *transformAssignmentIndirection(ParseState *pstate,
Node *basenode, Node *basenode,
const char *targetName, const char *targetName,
...@@ -174,7 +175,7 @@ markTargetListOrigins(ParseState *pstate, List *targetlist) ...@@ -174,7 +175,7 @@ markTargetListOrigins(ParseState *pstate, List *targetlist)
{ {
TargetEntry *tle = (TargetEntry *) lfirst(l); 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) ...@@ -182,18 +183,22 @@ markTargetListOrigins(ParseState *pstate, List *targetlist)
* markTargetListOrigin() * 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 '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 * 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. * do not drill down into views, but report the view as the column owner.
*/ */
static void static void
markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var) markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var, int levelsup)
{ {
int netlevelsup;
RangeTblEntry *rte; RangeTblEntry *rte;
AttrNumber attnum; AttrNumber attnum;
if (var == NULL || !IsA(var, Var)) if (var == NULL || !IsA(var, Var))
return; return;
rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup); netlevelsup = var->varlevelsup + levelsup;
rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
attnum = var->varattno; attnum = var->varattno;
switch (rte->rtekind) switch (rte->rtekind)
...@@ -223,7 +228,7 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var) ...@@ -223,7 +228,7 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var)
Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1); aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
markTargetListOrigin(pstate, res, aliasvar); markTargetListOrigin(pstate, res, aliasvar, netlevelsup);
} }
break; break;
case RTE_SPECIAL: case RTE_SPECIAL:
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -182,7 +182,7 @@ static void get_setop_query(Node *setOp, Query *query, ...@@ -182,7 +182,7 @@ static void get_setop_query(Node *setOp, Query *query,
static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist, static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist,
bool force_colno, bool force_colno,
deparse_context *context); 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); char **schemaname, char **refname, char **attname);
static RangeTblEntry *find_rte_by_refname(const char *refname, static RangeTblEntry *find_rte_by_refname(const char *refname,
deparse_context *context); deparse_context *context);
...@@ -1998,7 +1998,7 @@ get_basic_select_query(Query *query, deparse_context *context, ...@@ -1998,7 +1998,7 @@ get_basic_select_query(Query *query, deparse_context *context,
char *refname; char *refname;
char *attname; char *attname;
get_names_for_var(var, context, get_names_for_var(var, 0, context,
&schemaname, &refname, &attname); &schemaname, &refname, &attname);
tell_as = (attname == NULL || tell_as = (attname == NULL ||
strcmp(attname, colname) != 0); strcmp(attname, colname) != 0);
...@@ -2392,6 +2392,10 @@ get_utility_query_def(Query *query, deparse_context *context) ...@@ -2392,6 +2392,10 @@ get_utility_query_def(Query *query, deparse_context *context)
/* /*
* Get the schemaname, refname and attname for a (possibly nonlocal) Var. * 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 * schemaname is usually returned as NULL. It will be non-null only if
* use of the unqualified refname would find the wrong RTE. * use of the unqualified refname would find the wrong RTE.
* *
...@@ -2404,17 +2408,20 @@ get_utility_query_def(Query *query, deparse_context *context) ...@@ -2404,17 +2408,20 @@ get_utility_query_def(Query *query, deparse_context *context)
* distinguish this case.) * distinguish this case.)
*/ */
static void 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) char **schemaname, char **refname, char **attname)
{ {
int netlevelsup;
deparse_namespace *dpns; deparse_namespace *dpns;
RangeTblEntry *rte; RangeTblEntry *rte;
/* Find appropriate nesting depth */ /* Find appropriate nesting depth */
if (var->varlevelsup >= list_length(context->namespaces)) netlevelsup = var->varlevelsup + levelsup;
elog(ERROR, "bogus varlevelsup: %d", var->varlevelsup); if (netlevelsup >= list_length(context->namespaces))
elog(ERROR, "bogus varlevelsup: %d offset %d",
var->varlevelsup, levelsup);
dpns = (deparse_namespace *) list_nth(context->namespaces, dpns = (deparse_namespace *) list_nth(context->namespaces,
var->varlevelsup); netlevelsup);
/* Find the relevant RTE */ /* Find the relevant RTE */
if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
...@@ -2467,7 +2474,7 @@ get_names_for_var(Var *var, deparse_context *context, ...@@ -2467,7 +2474,7 @@ get_names_for_var(Var *var, deparse_context *context,
var->varattno-1); var->varattno-1);
if (IsA(aliasvar, Var)) if (IsA(aliasvar, Var))
{ {
get_names_for_var(aliasvar, context, get_names_for_var(aliasvar, netlevelsup, context,
schemaname, refname, attname); schemaname, refname, attname);
return; return;
} }
...@@ -2867,7 +2874,7 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -2867,7 +2874,7 @@ get_rule_expr(Node *node, deparse_context *context,
char *refname; char *refname;
char *attname; char *attname;
get_names_for_var(var, context, get_names_for_var(var, 0, context,
&schemaname, &refname, &attname); &schemaname, &refname, &attname);
if (refname && (context->varprefix || attname == NULL)) if (refname && (context->varprefix || attname == NULL))
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment