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,
4949Plan * outer_plan ,
5050int indent ,ExplainState * es );
5151static void show_scan_qual (List * qual ,const char * qlabel ,
52- int scanrelid ,Plan * outer_plan ,
52+ int scanrelid ,Plan * outer_plan ,Plan * inner_plan ,
5353StringInfo str ,int indent ,ExplainState * es );
54- static void show_upper_qual (List * qual ,const char * qlabel ,
55- const char * outer_name ,Plan * outer_plan ,
56- const char * inner_name ,Plan * inner_plan ,
54+ static void show_upper_qual (List * qual ,const char * qlabel ,Plan * plan ,
5755StringInfo str ,int indent ,ExplainState * es );
5856static void show_sort_keys (Plan * sortplan ,int nkeys ,AttrNumber * keycols ,
5957const char * qlabel ,
@@ -725,37 +723,44 @@ explain_outNode(StringInfo str,
725723show_scan_qual (((IndexScan * )plan )-> indexqualorig ,
726724"Index Cond" ,
727725 ((Scan * )plan )-> scanrelid ,
728- outer_plan ,
726+ outer_plan ,NULL ,
729727str ,indent ,es );
730728show_scan_qual (plan -> qual ,
731729"Filter" ,
732730 ((Scan * )plan )-> scanrelid ,
733- outer_plan ,
731+ outer_plan ,NULL ,
734732str ,indent ,es );
735733break ;
736734case T_BitmapIndexScan :
737735show_scan_qual (((BitmapIndexScan * )plan )-> indexqualorig ,
738736"Index Cond" ,
739737 ((Scan * )plan )-> scanrelid ,
740- outer_plan ,
738+ outer_plan ,NULL ,
741739str ,indent ,es );
742740break ;
743741case T_BitmapHeapScan :
744742/* XXX do we want to show this in production? */
745743show_scan_qual (((BitmapHeapScan * )plan )-> bitmapqualorig ,
746744"Recheck Cond" ,
747745 ((Scan * )plan )-> scanrelid ,
748- outer_plan ,
746+ outer_plan ,NULL ,
749747str ,indent ,es );
750748/* FALL THRU */
751749case T_SeqScan :
752- case T_SubqueryScan :
753750case T_FunctionScan :
754751case T_ValuesScan :
752+ show_scan_qual (plan -> qual ,
753+ "Filter" ,
754+ ((Scan * )plan )-> scanrelid ,
755+ outer_plan ,NULL ,
756+ str ,indent ,es );
757+ break ;
758+ case T_SubqueryScan :
755759show_scan_qual (plan -> qual ,
756760"Filter" ,
757761 ((Scan * )plan )-> scanrelid ,
758762outer_plan ,
763+ ((SubqueryScan * )plan )-> subplan ,
759764str ,indent ,es );
760765break ;
761766case T_TidScan :
@@ -771,67 +776,49 @@ explain_outNode(StringInfo str,
771776show_scan_qual (tidquals ,
772777"TID Cond" ,
773778 ((Scan * )plan )-> scanrelid ,
774- outer_plan ,
779+ outer_plan ,NULL ,
775780str ,indent ,es );
776781show_scan_qual (plan -> qual ,
777782"Filter" ,
778783 ((Scan * )plan )-> scanrelid ,
779- outer_plan ,
784+ outer_plan ,NULL ,
780785str ,indent ,es );
781786}
782787break ;
783788case T_NestLoop :
784789show_upper_qual (((NestLoop * )plan )-> join .joinqual ,
785- "Join Filter" ,
786- "outer" ,outerPlan (plan ),
787- "inner" ,innerPlan (plan ),
790+ "Join Filter" ,plan ,
788791str ,indent ,es );
789792show_upper_qual (plan -> qual ,
790- "Filter" ,
791- "outer" ,outerPlan (plan ),
792- "inner" ,innerPlan (plan ),
793+ "Filter" ,plan ,
793794str ,indent ,es );
794795break ;
795796case T_MergeJoin :
796797show_upper_qual (((MergeJoin * )plan )-> mergeclauses ,
797- "Merge Cond" ,
798- "outer" ,outerPlan (plan ),
799- "inner" ,innerPlan (plan ),
798+ "Merge Cond" ,plan ,
800799str ,indent ,es );
801800show_upper_qual (((MergeJoin * )plan )-> join .joinqual ,
802- "Join Filter" ,
803- "outer" ,outerPlan (plan ),
804- "inner" ,innerPlan (plan ),
801+ "Join Filter" ,plan ,
805802str ,indent ,es );
806803show_upper_qual (plan -> qual ,
807- "Filter" ,
808- "outer" ,outerPlan (plan ),
809- "inner" ,innerPlan (plan ),
804+ "Filter" ,plan ,
810805str ,indent ,es );
811806break ;
812807case T_HashJoin :
813808show_upper_qual (((HashJoin * )plan )-> hashclauses ,
814- "Hash Cond" ,
815- "outer" ,outerPlan (plan ),
816- "inner" ,innerPlan (plan ),
809+ "Hash Cond" ,plan ,
817810str ,indent ,es );
818811show_upper_qual (((HashJoin * )plan )-> join .joinqual ,
819- "Join Filter" ,
820- "outer" ,outerPlan (plan ),
821- "inner" ,innerPlan (plan ),
812+ "Join Filter" ,plan ,
822813str ,indent ,es );
823814show_upper_qual (plan -> qual ,
824- "Filter" ,
825- "outer" ,outerPlan (plan ),
826- "inner" ,innerPlan (plan ),
815+ "Filter" ,plan ,
827816str ,indent ,es );
828817break ;
829818case T_Agg :
830819case T_Group :
831820show_upper_qual (plan -> qual ,
832- "Filter" ,
833- "subplan" ,outerPlan (plan ),
834- "" ,NULL ,
821+ "Filter" ,plan ,
835822str ,indent ,es );
836823break ;
837824case T_Sort :
@@ -843,14 +830,10 @@ explain_outNode(StringInfo str,
843830break ;
844831case T_Result :
845832show_upper_qual ((List * ) ((Result * )plan )-> resconstantqual ,
846- "One-Time Filter" ,
847- "subplan" ,outerPlan (plan ),
848- "" ,NULL ,
833+ "One-Time Filter" ,plan ,
849834str ,indent ,es );
850835show_upper_qual (plan -> qual ,
851- "Filter" ,
852- "subplan" ,outerPlan (plan ),
853- "" ,NULL ,
836+ "Filter" ,plan ,
854837str ,indent ,es );
855838break ;
856839default :
@@ -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 */
10361023static void
10371024show_scan_qual (List * qual ,const char * qlabel ,
1038- int scanrelid ,Plan * outer_plan ,
1025+ int scanrelid ,Plan * outer_plan ,Plan * inner_plan ,
10391026StringInfo str ,int indent ,ExplainState * es )
10401027{
1041- Node * outercontext ;
10421028List * context ;
1029+ bool useprefix ;
10431030Node * node ;
10441031char * exprstr ;
10451032int i ;
@@ -1051,31 +1038,14 @@ show_scan_qual(List *qual, const char *qlabel,
10511038/* Convert AND list to explicit AND */
10521039node = (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- Relids varnos = 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 ,
10751044es -> 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 */
10811051for (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 */
10891059static void
1090- show_upper_qual (List * qual ,const char * qlabel ,
1091- const char * outer_name ,Plan * outer_plan ,
1092- const char * inner_name ,Plan * inner_plan ,
1060+ show_upper_qual (List * qual ,const char * qlabel ,Plan * plan ,
10931061StringInfo str ,int indent ,ExplainState * es )
10941062{
10951063List * context ;
1096- Node * outercontext ;
1097- Node * innercontext ;
1098- int outer_varno ;
1099- int inner_varno ;
1064+ bool useprefix ;
11001065Node * node ;
11011066char * exprstr ;
11021067int i ;
@@ -1105,36 +1070,15 @@ show_upper_qual(List *qual, const char *qlabel,
11051070if (qual == NIL )
11061071return ;
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 ),
11331076es -> rtable );
1077+ useprefix = list_length (es -> rtable )> 1 ;
11341078
11351079/* Deparse the expression */
11361080node = (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 */
11401084for (i = 0 ;i < indent ;i ++ )
@@ -1154,7 +1098,6 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
11541098bool useprefix ;
11551099int keyno ;
11561100char * exprstr ;
1157- Relids varnos ;
11581101int i ;
11591102
11601103if (nkeys <=0 )
@@ -1164,33 +1107,11 @@ show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
11641107appendStringInfo (str ," " );
11651108appendStringInfo (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
11951116for (keyno = 0 ;keyno < nkeys ;keyno ++ )
11961117{