Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2b8a624

Browse files
committed
Fix ruleutils' get_variable() to print something useful for Vars referencing
resjunk outputs of subquery tlists, instead of throwing an error. Per bug #5548 from Daniel Grace. We might at some point find we ought to back-patch this further than 9.0, but I think that such Vars can only occur as resjunk members of upper-level tlists, in which case the problem can't arise because prior versions didn't print resjunk tlist items in EXPLAIN VERBOSE.
1 parent a0d7c5f commit 2b8a624

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

src/backend/utils/adt/ruleutils.c

+44-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.326 2010/05/30 18:10:41 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.327 2010/07/09 21:11:47 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -3637,6 +3637,49 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
36373637
return NULL; /* keep compiler quiet */
36383638
}
36393639

3640+
/*
3641+
* The planner will sometimes emit Vars referencing resjunk elements of a
3642+
* subquery's target list (this is currently only possible if it chooses
3643+
* to generate a "physical tlist" for a SubqueryScan or CteScan node).
3644+
* Although we prefer to print subquery-referencing Vars using the
3645+
* subquery's alias, that's not possible for resjunk items since they have
3646+
* no alias. So in that case, drill down to the subplan and print the
3647+
* contents of the referenced tlist item. This works because in a plan
3648+
* tree, such Vars can only occur in a SubqueryScan or CteScan node,
3649+
* and we'll have set dpns->inner_plan to reference the child plan node.
3650+
*/
3651+
if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
3652+
attnum > list_length(rte->eref->colnames) &&
3653+
dpns->inner_plan)
3654+
{
3655+
TargetEntry *tle;
3656+
Plan *save_outer;
3657+
Plan *save_inner;
3658+
3659+
tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3660+
if (!tle)
3661+
elog(ERROR, "bogus varattno for subquery var: %d", var->varattno);
3662+
3663+
Assert(netlevelsup == 0);
3664+
save_outer = dpns->outer_plan;
3665+
save_inner = dpns->inner_plan;
3666+
push_plan(dpns, dpns->inner_plan);
3667+
3668+
/*
3669+
* Force parentheses because our caller probably assumed a Var is a
3670+
* simple expression.
3671+
*/
3672+
if (!IsA(tle->expr, Var))
3673+
appendStringInfoChar(buf, '(');
3674+
get_rule_expr((Node *) tle->expr, context, true);
3675+
if (!IsA(tle->expr, Var))
3676+
appendStringInfoChar(buf, ')');
3677+
3678+
dpns->outer_plan = save_outer;
3679+
dpns->inner_plan = save_inner;
3680+
return NULL;
3681+
}
3682+
36403683
/* Identify names to use */
36413684
schemaname = NULL; /* default assumptions */
36423685
refname = rte->eref->aliasname;

0 commit comments

Comments
 (0)