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.
This commit is contained in:
parent
c2eef62c66
commit
c06b31dc31
src/backend
@ -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 @@
|
|||||||
#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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
* 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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
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))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user