mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
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.
This commit is contained in:
parent
a0d7c5f689
commit
2b8a624596
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.326 2010/05/30 18:10:41 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.327 2010/07/09 21:11:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -3637,6 +3637,49 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
|
|||||||
return NULL; /* keep compiler quiet */
|
return NULL; /* keep compiler quiet */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The planner will sometimes emit Vars referencing resjunk elements of a
|
||||||
|
* subquery's target list (this is currently only possible if it chooses
|
||||||
|
* to generate a "physical tlist" for a SubqueryScan or CteScan node).
|
||||||
|
* Although we prefer to print subquery-referencing Vars using the
|
||||||
|
* subquery's alias, that's not possible for resjunk items since they have
|
||||||
|
* no alias. So in that case, drill down to the subplan and print the
|
||||||
|
* contents of the referenced tlist item. This works because in a plan
|
||||||
|
* tree, such Vars can only occur in a SubqueryScan or CteScan node,
|
||||||
|
* and we'll have set dpns->inner_plan to reference the child plan node.
|
||||||
|
*/
|
||||||
|
if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
|
||||||
|
attnum > list_length(rte->eref->colnames) &&
|
||||||
|
dpns->inner_plan)
|
||||||
|
{
|
||||||
|
TargetEntry *tle;
|
||||||
|
Plan *save_outer;
|
||||||
|
Plan *save_inner;
|
||||||
|
|
||||||
|
tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
|
||||||
|
if (!tle)
|
||||||
|
elog(ERROR, "bogus varattno for subquery var: %d", var->varattno);
|
||||||
|
|
||||||
|
Assert(netlevelsup == 0);
|
||||||
|
save_outer = dpns->outer_plan;
|
||||||
|
save_inner = dpns->inner_plan;
|
||||||
|
push_plan(dpns, dpns->inner_plan);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force parentheses because our caller probably assumed a Var is a
|
||||||
|
* simple expression.
|
||||||
|
*/
|
||||||
|
if (!IsA(tle->expr, Var))
|
||||||
|
appendStringInfoChar(buf, '(');
|
||||||
|
get_rule_expr((Node *) tle->expr, context, true);
|
||||||
|
if (!IsA(tle->expr, Var))
|
||||||
|
appendStringInfoChar(buf, ')');
|
||||||
|
|
||||||
|
dpns->outer_plan = save_outer;
|
||||||
|
dpns->inner_plan = save_inner;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Identify names to use */
|
/* Identify names to use */
|
||||||
schemaname = NULL; /* default assumptions */
|
schemaname = NULL; /* default assumptions */
|
||||||
refname = rte->eref->aliasname;
|
refname = rte->eref->aliasname;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user