|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * 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 $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -3637,6 +3637,49 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
|
3637 | 3637 | return NULL; /* keep compiler quiet */
|
3638 | 3638 | }
|
3639 | 3639 |
|
| 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 | + |
3640 | 3683 | /* Identify names to use */
|
3641 | 3684 | schemaname = NULL; /* default assumptions */
|
3642 | 3685 | refname = rte->eref->aliasname;
|
|
0 commit comments