Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit655aa5b

Browse files
committed
Now that plans have flat rangetable lists, it's a lot easier to get EXPLAIN to
drill down into subplan targetlists to print the referent expression for anOUTER or INNER var in an upper plan node. Hence, make it do that always, andbanish the old hack of showing "?columnN?" when things got too complicated.Along the way, fix an EXPLAIN bug I introduced by suppressing subqueries fromexecution-time range tables: get_name_for_var_field() assumed it could look atrte->subquery to find out the real type of a RECORD var. That doesn't workanymore, but instead we can look at the input plan of the SubqueryScan plannode.
1 parent9cc2a71 commit655aa5b

File tree

4 files changed

+444
-457
lines changed

4 files changed

+444
-457
lines changed

‎src/backend/commands/explain.c

Lines changed: 51 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.158 2007/02/22 23:44:24 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.159 2007/02/23 21:59:44 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -49,11 +49,9 @@ static void explain_outNode(StringInfo str,
4949
Plan*outer_plan,
5050
intindent,ExplainState*es);
5151
staticvoidshow_scan_qual(List*qual,constchar*qlabel,
52-
intscanrelid,Plan*outer_plan,
52+
intscanrelid,Plan*outer_plan,Plan*inner_plan,
5353
StringInfostr,intindent,ExplainState*es);
54-
staticvoidshow_upper_qual(List*qual,constchar*qlabel,
55-
constchar*outer_name,Plan*outer_plan,
56-
constchar*inner_name,Plan*inner_plan,
54+
staticvoidshow_upper_qual(List*qual,constchar*qlabel,Plan*plan,
5755
StringInfostr,intindent,ExplainState*es);
5856
staticvoidshow_sort_keys(Plan*sortplan,intnkeys,AttrNumber*keycols,
5957
constchar*qlabel,
@@ -725,37 +723,44 @@ explain_outNode(StringInfo str,
725723
show_scan_qual(((IndexScan*)plan)->indexqualorig,
726724
"Index Cond",
727725
((Scan*)plan)->scanrelid,
728-
outer_plan,
726+
outer_plan,NULL,
729727
str,indent,es);
730728
show_scan_qual(plan->qual,
731729
"Filter",
732730
((Scan*)plan)->scanrelid,
733-
outer_plan,
731+
outer_plan,NULL,
734732
str,indent,es);
735733
break;
736734
caseT_BitmapIndexScan:
737735
show_scan_qual(((BitmapIndexScan*)plan)->indexqualorig,
738736
"Index Cond",
739737
((Scan*)plan)->scanrelid,
740-
outer_plan,
738+
outer_plan,NULL,
741739
str,indent,es);
742740
break;
743741
caseT_BitmapHeapScan:
744742
/* XXX do we want to show this in production? */
745743
show_scan_qual(((BitmapHeapScan*)plan)->bitmapqualorig,
746744
"Recheck Cond",
747745
((Scan*)plan)->scanrelid,
748-
outer_plan,
746+
outer_plan,NULL,
749747
str,indent,es);
750748
/* FALL THRU */
751749
caseT_SeqScan:
752-
caseT_SubqueryScan:
753750
caseT_FunctionScan:
754751
caseT_ValuesScan:
752+
show_scan_qual(plan->qual,
753+
"Filter",
754+
((Scan*)plan)->scanrelid,
755+
outer_plan,NULL,
756+
str,indent,es);
757+
break;
758+
caseT_SubqueryScan:
755759
show_scan_qual(plan->qual,
756760
"Filter",
757761
((Scan*)plan)->scanrelid,
758762
outer_plan,
763+
((SubqueryScan*)plan)->subplan,
759764
str,indent,es);
760765
break;
761766
caseT_TidScan:
@@ -771,67 +776,49 @@ explain_outNode(StringInfo str,
771776
show_scan_qual(tidquals,
772777
"TID Cond",
773778
((Scan*)plan)->scanrelid,
774-
outer_plan,
779+
outer_plan,NULL,
775780
str,indent,es);
776781
show_scan_qual(plan->qual,
777782
"Filter",
778783
((Scan*)plan)->scanrelid,
779-
outer_plan,
784+
outer_plan,NULL,
780785
str,indent,es);
781786
}
782787
break;
783788
caseT_NestLoop:
784789
show_upper_qual(((NestLoop*)plan)->join.joinqual,
785-
"Join Filter",
786-
"outer",outerPlan(plan),
787-
"inner",innerPlan(plan),
790+
"Join Filter",plan,
788791
str,indent,es);
789792
show_upper_qual(plan->qual,
790-
"Filter",
791-
"outer",outerPlan(plan),
792-
"inner",innerPlan(plan),
793+
"Filter",plan,
793794
str,indent,es);
794795
break;
795796
caseT_MergeJoin:
796797
show_upper_qual(((MergeJoin*)plan)->mergeclauses,
797-
"Merge Cond",
798-
"outer",outerPlan(plan),
799-
"inner",innerPlan(plan),
798+
"Merge Cond",plan,
800799
str,indent,es);
801800
show_upper_qual(((MergeJoin*)plan)->join.joinqual,
802-
"Join Filter",
803-
"outer",outerPlan(plan),
804-
"inner",innerPlan(plan),
801+
"Join Filter",plan,
805802
str,indent,es);
806803
show_upper_qual(plan->qual,
807-
"Filter",
808-
"outer",outerPlan(plan),
809-
"inner",innerPlan(plan),
804+
"Filter",plan,
810805
str,indent,es);
811806
break;
812807
caseT_HashJoin:
813808
show_upper_qual(((HashJoin*)plan)->hashclauses,
814-
"Hash Cond",
815-
"outer",outerPlan(plan),
816-
"inner",innerPlan(plan),
809+
"Hash Cond",plan,
817810
str,indent,es);
818811
show_upper_qual(((HashJoin*)plan)->join.joinqual,
819-
"Join Filter",
820-
"outer",outerPlan(plan),
821-
"inner",innerPlan(plan),
812+
"Join Filter",plan,
822813
str,indent,es);
823814
show_upper_qual(plan->qual,
824-
"Filter",
825-
"outer",outerPlan(plan),
826-
"inner",innerPlan(plan),
815+
"Filter",plan,
827816
str,indent,es);
828817
break;
829818
caseT_Agg:
830819
caseT_Group:
831820
show_upper_qual(plan->qual,
832-
"Filter",
833-
"subplan",outerPlan(plan),
834-
"",NULL,
821+
"Filter",plan,
835822
str,indent,es);
836823
break;
837824
caseT_Sort:
@@ -843,14 +830,10 @@ explain_outNode(StringInfo str,
843830
break;
844831
caseT_Result:
845832
show_upper_qual((List*) ((Result*)plan)->resconstantqual,
846-
"One-Time Filter",
847-
"subplan",outerPlan(plan),
848-
"",NULL,
833+
"One-Time Filter",plan,
849834
str,indent,es);
850835
show_upper_qual(plan->qual,
851-
"Filter",
852-
"subplan",outerPlan(plan),
853-
"",NULL,
836+
"Filter",plan,
854837
str,indent,es);
855838
break;
856839
default:
@@ -1032,14 +1015,18 @@ explain_outNode(StringInfo str,
10321015

10331016
/*
10341017
* Show a qualifier expression for a scan plan node
1018+
*
1019+
* Note: outer_plan is the referent for any OUTER vars in the scan qual;
1020+
* this would be the outer side of a nestloop plan. inner_plan should be
1021+
* NULL except for a SubqueryScan plan node, where it should be the subplan.
10351022
*/
10361023
staticvoid
10371024
show_scan_qual(List*qual,constchar*qlabel,
1038-
intscanrelid,Plan*outer_plan,
1025+
intscanrelid,Plan*outer_plan,Plan*inner_plan,
10391026
StringInfostr,intindent,ExplainState*es)
10401027
{
1041-
Node*outercontext;
10421028
List*context;
1029+
booluseprefix;
10431030
Node*node;
10441031
char*exprstr;
10451032
inti;
@@ -1051,31 +1038,14 @@ show_scan_qual(List *qual, const char *qlabel,
10511038
/* Convert AND list to explicit AND */
10521039
node= (Node*)make_ands_explicit(qual);
10531040

1054-
/*
1055-
* If we have an outer plan that is referenced by the qual, add it to the
1056-
* deparse context. If not, don't (so that we don't force prefixes
1057-
* unnecessarily).
1058-
*/
1059-
if (outer_plan)
1060-
{
1061-
Relidsvarnos=pull_varnos(node);
1062-
1063-
if (bms_is_member(OUTER,varnos))
1064-
outercontext=deparse_context_for_subplan("outer",
1065-
(Node*)outer_plan);
1066-
else
1067-
outercontext=NULL;
1068-
bms_free(varnos);
1069-
}
1070-
else
1071-
outercontext=NULL;
1072-
1073-
context=deparse_context_for_plan(OUTER,outercontext,
1074-
0,NULL,
1041+
/* Set up deparsing context */
1042+
context=deparse_context_for_plan((Node*)outer_plan,
1043+
(Node*)inner_plan,
10751044
es->rtable);
1045+
useprefix= (outer_plan!=NULL||inner_plan!=NULL);
10761046

10771047
/* Deparse the expression */
1078-
exprstr=deparse_expression(node,context,(outercontext!=NULL), false);
1048+
exprstr=deparse_expression(node,context,useprefix, false);
10791049

10801050
/* And add to str */
10811051
for (i=0;i<indent;i++)
@@ -1087,16 +1057,11 @@ show_scan_qual(List *qual, const char *qlabel,
10871057
* Show a qualifier expression for an upper-level plan node
10881058
*/
10891059
staticvoid
1090-
show_upper_qual(List*qual,constchar*qlabel,
1091-
constchar*outer_name,Plan*outer_plan,
1092-
constchar*inner_name,Plan*inner_plan,
1060+
show_upper_qual(List*qual,constchar*qlabel,Plan*plan,
10931061
StringInfostr,intindent,ExplainState*es)
10941062
{
10951063
List*context;
1096-
Node*outercontext;
1097-
Node*innercontext;
1098-
intouter_varno;
1099-
intinner_varno;
1064+
booluseprefix;
11001065
Node*node;
11011066
char*exprstr;
11021067
inti;
@@ -1105,36 +1070,15 @@ show_upper_qual(List *qual, const char *qlabel,
11051070
if (qual==NIL)
11061071
return;
11071072

1108-
/* Generate deparse context */
1109-
if (outer_plan)
1110-
{
1111-
outercontext=deparse_context_for_subplan(outer_name,
1112-
(Node*)outer_plan);
1113-
outer_varno=OUTER;
1114-
}
1115-
else
1116-
{
1117-
outercontext=NULL;
1118-
outer_varno=0;
1119-
}
1120-
if (inner_plan)
1121-
{
1122-
innercontext=deparse_context_for_subplan(inner_name,
1123-
(Node*)inner_plan);
1124-
inner_varno=INNER;
1125-
}
1126-
else
1127-
{
1128-
innercontext=NULL;
1129-
inner_varno=0;
1130-
}
1131-
context=deparse_context_for_plan(outer_varno,outercontext,
1132-
inner_varno,innercontext,
1073+
/* Set up deparsing context */
1074+
context=deparse_context_for_plan((Node*)outerPlan(plan),
1075+
(Node*)innerPlan(plan),
11331076
es->rtable);
1077+
useprefix=list_length(es->rtable)>1;
11341078

11351079
/* Deparse the expression */
11361080
node= (Node*)make_ands_explicit(qual);
1137-
exprstr=deparse_expression(node,context,(inner_plan!=NULL), false);
1081+
exprstr=deparse_expression(node,context,useprefix, false);
11381082

11391083
/* And add to str */
11401084
for (i=0;i<indent;i++)
@@ -1154,7 +1098,6 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
11541098
booluseprefix;
11551099
intkeyno;
11561100
char*exprstr;
1157-
Relidsvarnos;
11581101
inti;
11591102

11601103
if (nkeys <=0)
@@ -1164,33 +1107,11 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
11641107
appendStringInfo(str," ");
11651108
appendStringInfo(str," %s: ",qlabel);
11661109

1167-
/*
1168-
* In this routine we expect that the plan node's tlist has not been
1169-
* processed by set_plan_references().Normally, any Vars will contain
1170-
* valid varnos referencing the actual rtable.But we might instead be
1171-
* looking at a dummy tlist generated by prepunion.c; if there are Vars
1172-
* with zero varno, use the tlist itself to determine their names.
1173-
*/
1174-
varnos=pull_varnos((Node*)sortplan->targetlist);
1175-
if (bms_is_member(0,varnos))
1176-
{
1177-
Node*outercontext;
1178-
1179-
outercontext=deparse_context_for_subplan("sort",
1180-
(Node*)sortplan);
1181-
context=deparse_context_for_plan(0,outercontext,
1182-
0,NULL,
1183-
es->rtable);
1184-
useprefix= false;
1185-
}
1186-
else
1187-
{
1188-
context=deparse_context_for_plan(0,NULL,
1189-
0,NULL,
1190-
es->rtable);
1191-
useprefix=list_length(es->rtable)>1;
1192-
}
1193-
bms_free(varnos);
1110+
/* Set up deparsing context */
1111+
context=deparse_context_for_plan((Node*)outerPlan(sortplan),
1112+
NULL,/* Sort has no innerPlan */
1113+
es->rtable);
1114+
useprefix=list_length(es->rtable)>1;
11941115

11951116
for (keyno=0;keyno<nkeys;keyno++)
11961117
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp