mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Fix EXPLAIN so that it can drill down through multiple levels of subplan
when trying to locate the referent of a RECORD variable. This fixes the 'record type has not been registered' failure reported by Stefan Kaltenbrunner about a month ago. A side effect of the way I chose to fix it is that most variable references in join conditions will now be properly labeled with the variable's source table name, instead of the not-too-helpful 'outer' or 'inner' we used to use.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.146 2006/03/05 15:58:24 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.147 2006/04/08 18:49:52 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -58,7 +58,7 @@ static void show_upper_qual(List *qual, const char *qlabel,
|
||||
const char *outer_name, int outer_varno, Plan *outer_plan,
|
||||
const char *inner_name, int inner_varno, Plan *inner_plan,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static void show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
||||
static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
|
||||
const char *qlabel,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
|
||||
@ -815,7 +815,7 @@ explain_outNode(StringInfo str,
|
||||
str, indent, es);
|
||||
break;
|
||||
case T_Sort:
|
||||
show_sort_keys(plan->targetlist,
|
||||
show_sort_keys(plan,
|
||||
((Sort *) plan)->numCols,
|
||||
((Sort *) plan)->sortColIdx,
|
||||
"Sort Key",
|
||||
@ -1030,8 +1030,6 @@ show_scan_qual(List *qual, const char *qlabel,
|
||||
int scanrelid, Plan *outer_plan,
|
||||
StringInfo str, int indent, ExplainState *es)
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
Node *scancontext;
|
||||
Node *outercontext;
|
||||
List *context;
|
||||
Node *node;
|
||||
@ -1045,11 +1043,6 @@ show_scan_qual(List *qual, const char *qlabel,
|
||||
/* Convert AND list to explicit AND */
|
||||
node = (Node *) make_ands_explicit(qual);
|
||||
|
||||
/* Generate deparse context */
|
||||
Assert(scanrelid > 0 && scanrelid <= list_length(es->rtable));
|
||||
rte = rt_fetch(scanrelid, es->rtable);
|
||||
scancontext = deparse_context_for_rte(rte);
|
||||
|
||||
/*
|
||||
* If we have an outer plan that is referenced by the qual, add it to the
|
||||
* deparse context. If not, don't (so that we don't force prefixes
|
||||
@ -1061,8 +1054,7 @@ show_scan_qual(List *qual, const char *qlabel,
|
||||
|
||||
if (bms_is_member(OUTER, varnos))
|
||||
outercontext = deparse_context_for_subplan("outer",
|
||||
outer_plan->targetlist,
|
||||
es->rtable);
|
||||
(Node *) outer_plan);
|
||||
else
|
||||
outercontext = NULL;
|
||||
bms_free(varnos);
|
||||
@ -1070,9 +1062,9 @@ show_scan_qual(List *qual, const char *qlabel,
|
||||
else
|
||||
outercontext = NULL;
|
||||
|
||||
context = deparse_context_for_plan(scanrelid, scancontext,
|
||||
OUTER, outercontext,
|
||||
NIL);
|
||||
context = deparse_context_for_plan(OUTER, outercontext,
|
||||
0, NULL,
|
||||
es->rtable);
|
||||
|
||||
/* Deparse the expression */
|
||||
exprstr = deparse_expression(node, context, (outercontext != NULL), false);
|
||||
@ -1106,19 +1098,17 @@ show_upper_qual(List *qual, const char *qlabel,
|
||||
/* Generate deparse context */
|
||||
if (outer_plan)
|
||||
outercontext = deparse_context_for_subplan(outer_name,
|
||||
outer_plan->targetlist,
|
||||
es->rtable);
|
||||
(Node *) outer_plan);
|
||||
else
|
||||
outercontext = NULL;
|
||||
if (inner_plan)
|
||||
innercontext = deparse_context_for_subplan(inner_name,
|
||||
inner_plan->targetlist,
|
||||
es->rtable);
|
||||
(Node *) inner_plan);
|
||||
else
|
||||
innercontext = NULL;
|
||||
context = deparse_context_for_plan(outer_varno, outercontext,
|
||||
inner_varno, innercontext,
|
||||
NIL);
|
||||
es->rtable);
|
||||
|
||||
/* Deparse the expression */
|
||||
node = (Node *) make_ands_explicit(qual);
|
||||
@ -1134,7 +1124,7 @@ show_upper_qual(List *qual, const char *qlabel,
|
||||
* Show the sort keys for a Sort node.
|
||||
*/
|
||||
static void
|
||||
show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
||||
show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
|
||||
const char *qlabel,
|
||||
StringInfo str, int indent, ExplainState *es)
|
||||
{
|
||||
@ -1159,17 +1149,16 @@ show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
||||
* looking at a dummy tlist generated by prepunion.c; if there are Vars
|
||||
* with zero varno, use the tlist itself to determine their names.
|
||||
*/
|
||||
varnos = pull_varnos((Node *) tlist);
|
||||
varnos = pull_varnos((Node *) sortplan->targetlist);
|
||||
if (bms_is_member(0, varnos))
|
||||
{
|
||||
Node *outercontext;
|
||||
|
||||
outercontext = deparse_context_for_subplan("sort",
|
||||
tlist,
|
||||
es->rtable);
|
||||
(Node *) sortplan);
|
||||
context = deparse_context_for_plan(0, outercontext,
|
||||
0, NULL,
|
||||
NIL);
|
||||
es->rtable);
|
||||
useprefix = false;
|
||||
}
|
||||
else
|
||||
@ -1185,7 +1174,7 @@ show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
||||
{
|
||||
/* find key expression in tlist */
|
||||
AttrNumber keyresno = keycols[keyno];
|
||||
TargetEntry *target = get_tle_by_resno(tlist, keyresno);
|
||||
TargetEntry *target = get_tle_by_resno(sortplan->targetlist, keyresno);
|
||||
|
||||
if (!target)
|
||||
elog(ERROR, "no tlist entry for key %d", keyresno);
|
||||
|
Reference in New Issue
Block a user