Fix pg_dump bug in the database-level collation patch. "datcollate" and
[PostgreSQL.git] / src / backend / commands / explain.c
blob7fd39e7f33d7eb2d924e86f18a33e2b589590567
1 /*-------------------------------------------------------------------------
3 * explain.c
4 * Explain query execution plans
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994-5, Regents of the University of California
9 * IDENTIFICATION
10 * $PostgreSQL$
12 *-------------------------------------------------------------------------
14 #include "postgres.h"
16 #include "access/xact.h"
17 #include "catalog/pg_constraint.h"
18 #include "catalog/pg_type.h"
19 #include "commands/explain.h"
20 #include "commands/prepare.h"
21 #include "commands/trigger.h"
22 #include "executor/instrument.h"
23 #include "optimizer/clauses.h"
24 #include "optimizer/planner.h"
25 #include "optimizer/var.h"
26 #include "parser/parsetree.h"
27 #include "rewrite/rewriteHandler.h"
28 #include "tcop/tcopprot.h"
29 #include "utils/builtins.h"
30 #include "utils/guc.h"
31 #include "utils/lsyscache.h"
32 #include "utils/tuplesort.h"
33 #include "utils/snapmgr.h"
36 /* Hook for plugins to get control in ExplainOneQuery() */
37 ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL;
39 /* Hook for plugins to get control in explain_get_index_name() */
40 explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
43 typedef struct ExplainState
45 /* options */
46 bool printTList; /* print plan targetlists */
47 bool printAnalyze; /* print actual times */
48 /* other states */
49 PlannedStmt *pstmt; /* top of plan */
50 List *rtable; /* range table */
51 } ExplainState;
53 static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
54 const char *queryString,
55 ParamListInfo params, TupOutputState *tstate);
56 static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
57 StringInfo buf);
58 static double elapsed_time(instr_time *starttime);
59 static void explain_outNode(StringInfo str,
60 Plan *plan, PlanState *planstate,
61 Plan *outer_plan,
62 int indent, ExplainState *es);
63 static void show_plan_tlist(Plan *plan,
64 StringInfo str, int indent, ExplainState *es);
65 static void show_scan_qual(List *qual, const char *qlabel,
66 int scanrelid, Plan *outer_plan, Plan *inner_plan,
67 StringInfo str, int indent, ExplainState *es);
68 static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
69 StringInfo str, int indent, ExplainState *es);
70 static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
71 const char *qlabel,
72 StringInfo str, int indent, ExplainState *es);
73 static void show_sort_info(SortState *sortstate,
74 StringInfo str, int indent, ExplainState *es);
75 static const char *explain_get_index_name(Oid indexId);
79 * ExplainQuery -
80 * execute an EXPLAIN command
82 void
83 ExplainQuery(ExplainStmt *stmt, const char *queryString,
84 ParamListInfo params, DestReceiver *dest)
86 Oid *param_types;
87 int num_params;
88 TupOutputState *tstate;
89 List *rewritten;
90 ListCell *l;
92 /* Convert parameter type data to the form parser wants */
93 getParamListTypes(params, &param_types, &num_params);
96 * Run parse analysis and rewrite. Note this also acquires sufficient
97 * locks on the source table(s).
99 * Because the parser and planner tend to scribble on their input, we make
100 * a preliminary copy of the source querytree. This prevents problems in
101 * the case that the EXPLAIN is in a portal or plpgsql function and is
102 * executed repeatedly. (See also the same hack in DECLARE CURSOR and
103 * PREPARE.) XXX FIXME someday.
105 rewritten = pg_analyze_and_rewrite((Node *) copyObject(stmt->query),
106 queryString, param_types, num_params);
108 /* prepare for projection of tuples */
109 tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
111 if (rewritten == NIL)
113 /* In the case of an INSTEAD NOTHING, tell at least that */
114 do_text_output_oneline(tstate, "Query rewrites to nothing");
116 else
118 /* Explain every plan */
119 foreach(l, rewritten)
121 ExplainOneQuery((Query *) lfirst(l), stmt,
122 queryString, params, tstate);
123 /* put a blank line between plans */
124 if (lnext(l) != NULL)
125 do_text_output_oneline(tstate, "");
129 end_tup_output(tstate);
133 * ExplainResultDesc -
134 * construct the result tupledesc for an EXPLAIN
136 TupleDesc
137 ExplainResultDesc(ExplainStmt *stmt)
139 TupleDesc tupdesc;
141 /* need a tuple descriptor representing a single TEXT column */
142 tupdesc = CreateTemplateTupleDesc(1, false);
143 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
144 TEXTOID, -1, 0);
145 return tupdesc;
149 * ExplainOneQuery -
150 * print out the execution plan for one Query
152 static void
153 ExplainOneQuery(Query *query, ExplainStmt *stmt, const char *queryString,
154 ParamListInfo params, TupOutputState *tstate)
156 /* planner will not cope with utility statements */
157 if (query->commandType == CMD_UTILITY)
159 ExplainOneUtility(query->utilityStmt, stmt,
160 queryString, params, tstate);
161 return;
164 /* if an advisor plugin is present, let it manage things */
165 if (ExplainOneQuery_hook)
166 (*ExplainOneQuery_hook) (query, stmt, queryString, params, tstate);
167 else
169 PlannedStmt *plan;
171 /* plan the query */
172 plan = pg_plan_query(query, 0, params);
174 /* run it (if needed) and produce output */
175 ExplainOnePlan(plan, params, stmt, tstate);
180 * ExplainOneUtility -
181 * print out the execution plan for one utility statement
182 * (In general, utility statements don't have plans, but there are some
183 * we treat as special cases)
185 * This is exported because it's called back from prepare.c in the
186 * EXPLAIN EXECUTE case
188 void
189 ExplainOneUtility(Node *utilityStmt, ExplainStmt *stmt,
190 const char *queryString, ParamListInfo params,
191 TupOutputState *tstate)
193 if (utilityStmt == NULL)
194 return;
196 if (IsA(utilityStmt, ExecuteStmt))
197 ExplainExecuteQuery((ExecuteStmt *) utilityStmt, stmt,
198 queryString, params, tstate);
199 else if (IsA(utilityStmt, NotifyStmt))
200 do_text_output_oneline(tstate, "NOTIFY");
201 else
202 do_text_output_oneline(tstate,
203 "Utility statements have no plan structure");
207 * ExplainOnePlan -
208 * given a planned query, execute it if needed, and then print
209 * EXPLAIN output
211 * Since we ignore any DeclareCursorStmt that might be attached to the query,
212 * if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll actually run the
213 * query. This is different from pre-8.3 behavior but seems more useful than
214 * not running the query. No cursor will be created, however.
216 * This is exported because it's called back from prepare.c in the
217 * EXPLAIN EXECUTE case, and because an index advisor plugin would need
218 * to call it.
220 void
221 ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
222 ExplainStmt *stmt, TupOutputState *tstate)
224 QueryDesc *queryDesc;
225 instr_time starttime;
226 double totaltime = 0;
227 ExplainState *es;
228 StringInfoData buf;
229 int eflags;
232 * Use a snapshot with an updated command ID to ensure this query sees
233 * results of any previously executed queries.
235 PushUpdatedSnapshot(GetActiveSnapshot());
237 /* Create a QueryDesc requesting no output */
238 queryDesc = CreateQueryDesc(plannedstmt,
239 GetActiveSnapshot(), InvalidSnapshot,
240 None_Receiver, params,
241 stmt->analyze);
243 INSTR_TIME_SET_CURRENT(starttime);
245 /* If analyzing, we need to cope with queued triggers */
246 if (stmt->analyze)
247 AfterTriggerBeginQuery();
249 /* Select execution options */
250 if (stmt->analyze)
251 eflags = 0; /* default run-to-completion flags */
252 else
253 eflags = EXEC_FLAG_EXPLAIN_ONLY;
255 /* call ExecutorStart to prepare the plan for execution */
256 ExecutorStart(queryDesc, eflags);
258 /* Execute the plan for statistics if asked for */
259 if (stmt->analyze)
261 /* run the plan */
262 ExecutorRun(queryDesc, ForwardScanDirection, 0L);
264 /* We can't clean up 'till we're done printing the stats... */
265 totaltime += elapsed_time(&starttime);
268 es = (ExplainState *) palloc0(sizeof(ExplainState));
270 es->printTList = stmt->verbose;
271 es->printAnalyze = stmt->analyze;
272 es->pstmt = queryDesc->plannedstmt;
273 es->rtable = queryDesc->plannedstmt->rtable;
275 initStringInfo(&buf);
276 explain_outNode(&buf,
277 queryDesc->plannedstmt->planTree, queryDesc->planstate,
278 NULL, 0, es);
281 * If we ran the command, run any AFTER triggers it queued. (Note this
282 * will not include DEFERRED triggers; since those don't run until end of
283 * transaction, we can't measure them.) Include into total runtime.
285 if (stmt->analyze)
287 INSTR_TIME_SET_CURRENT(starttime);
288 AfterTriggerEndQuery(queryDesc->estate);
289 totaltime += elapsed_time(&starttime);
292 /* Print info about runtime of triggers */
293 if (es->printAnalyze)
295 ResultRelInfo *rInfo;
296 bool show_relname;
297 int numrels = queryDesc->estate->es_num_result_relations;
298 List *targrels = queryDesc->estate->es_trig_target_relations;
299 int nr;
300 ListCell *l;
302 show_relname = (numrels > 1 || targrels != NIL);
303 rInfo = queryDesc->estate->es_result_relations;
304 for (nr = 0; nr < numrels; rInfo++, nr++)
305 report_triggers(rInfo, show_relname, &buf);
307 foreach(l, targrels)
309 rInfo = (ResultRelInfo *) lfirst(l);
310 report_triggers(rInfo, show_relname, &buf);
315 * Close down the query and free resources. Include time for this in the
316 * total runtime (although it should be pretty minimal).
318 INSTR_TIME_SET_CURRENT(starttime);
320 ExecutorEnd(queryDesc);
322 FreeQueryDesc(queryDesc);
324 PopActiveSnapshot();
326 /* We need a CCI just in case query expanded to multiple plans */
327 if (stmt->analyze)
328 CommandCounterIncrement();
330 totaltime += elapsed_time(&starttime);
332 if (stmt->analyze)
333 appendStringInfo(&buf, "Total runtime: %.3f ms\n",
334 1000.0 * totaltime);
335 do_text_output_multiline(tstate, buf.data);
337 pfree(buf.data);
338 pfree(es);
342 * report_triggers -
343 * report execution stats for a single relation's triggers
345 static void
346 report_triggers(ResultRelInfo *rInfo, bool show_relname, StringInfo buf)
348 int nt;
350 if (!rInfo->ri_TrigDesc || !rInfo->ri_TrigInstrument)
351 return;
352 for (nt = 0; nt < rInfo->ri_TrigDesc->numtriggers; nt++)
354 Trigger *trig = rInfo->ri_TrigDesc->triggers + nt;
355 Instrumentation *instr = rInfo->ri_TrigInstrument + nt;
356 char *conname;
358 /* Must clean up instrumentation state */
359 InstrEndLoop(instr);
362 * We ignore triggers that were never invoked; they likely aren't
363 * relevant to the current query type.
365 if (instr->ntuples == 0)
366 continue;
368 if (OidIsValid(trig->tgconstraint) &&
369 (conname = get_constraint_name(trig->tgconstraint)) != NULL)
371 appendStringInfo(buf, "Trigger for constraint %s", conname);
372 pfree(conname);
374 else
375 appendStringInfo(buf, "Trigger %s", trig->tgname);
377 if (show_relname)
378 appendStringInfo(buf, " on %s",
379 RelationGetRelationName(rInfo->ri_RelationDesc));
381 appendStringInfo(buf, ": time=%.3f calls=%.0f\n",
382 1000.0 * instr->total, instr->ntuples);
386 /* Compute elapsed time in seconds since given timestamp */
387 static double
388 elapsed_time(instr_time *starttime)
390 instr_time endtime;
392 INSTR_TIME_SET_CURRENT(endtime);
393 INSTR_TIME_SUBTRACT(endtime, *starttime);
394 return INSTR_TIME_GET_DOUBLE(endtime);
398 * explain_outNode -
399 * converts a Plan node into ascii string and appends it to 'str'
401 * planstate points to the executor state node corresponding to the plan node.
402 * We need this to get at the instrumentation data (if any) as well as the
403 * list of subplans.
405 * outer_plan, if not null, references another plan node that is the outer
406 * side of a join with the current node. This is only interesting for
407 * deciphering runtime keys of an inner indexscan.
409 static void
410 explain_outNode(StringInfo str,
411 Plan *plan, PlanState *planstate,
412 Plan *outer_plan,
413 int indent, ExplainState *es)
415 const char *pname;
416 int i;
418 if (plan == NULL)
420 appendStringInfoChar(str, '\n');
421 return;
424 switch (nodeTag(plan))
426 case T_Result:
427 pname = "Result";
428 break;
429 case T_Append:
430 pname = "Append";
431 break;
432 case T_BitmapAnd:
433 pname = "BitmapAnd";
434 break;
435 case T_BitmapOr:
436 pname = "BitmapOr";
437 break;
438 case T_NestLoop:
439 switch (((NestLoop *) plan)->join.jointype)
441 case JOIN_INNER:
442 pname = "Nested Loop";
443 break;
444 case JOIN_LEFT:
445 pname = "Nested Loop Left Join";
446 break;
447 case JOIN_FULL:
448 pname = "Nested Loop Full Join";
449 break;
450 case JOIN_RIGHT:
451 pname = "Nested Loop Right Join";
452 break;
453 case JOIN_SEMI:
454 pname = "Nested Loop Semi Join";
455 break;
456 case JOIN_ANTI:
457 pname = "Nested Loop Anti Join";
458 break;
459 default:
460 pname = "Nested Loop ??? Join";
461 break;
463 break;
464 case T_MergeJoin:
465 switch (((MergeJoin *) plan)->join.jointype)
467 case JOIN_INNER:
468 pname = "Merge Join";
469 break;
470 case JOIN_LEFT:
471 pname = "Merge Left Join";
472 break;
473 case JOIN_FULL:
474 pname = "Merge Full Join";
475 break;
476 case JOIN_RIGHT:
477 pname = "Merge Right Join";
478 break;
479 case JOIN_SEMI:
480 pname = "Merge Semi Join";
481 break;
482 case JOIN_ANTI:
483 pname = "Merge Anti Join";
484 break;
485 default:
486 pname = "Merge ??? Join";
487 break;
489 break;
490 case T_HashJoin:
491 switch (((HashJoin *) plan)->join.jointype)
493 case JOIN_INNER:
494 pname = "Hash Join";
495 break;
496 case JOIN_LEFT:
497 pname = "Hash Left Join";
498 break;
499 case JOIN_FULL:
500 pname = "Hash Full Join";
501 break;
502 case JOIN_RIGHT:
503 pname = "Hash Right Join";
504 break;
505 case JOIN_SEMI:
506 pname = "Hash Semi Join";
507 break;
508 case JOIN_ANTI:
509 pname = "Hash Anti Join";
510 break;
511 default:
512 pname = "Hash ??? Join";
513 break;
515 break;
516 case T_SeqScan:
517 pname = "Seq Scan";
518 break;
519 case T_IndexScan:
520 pname = "Index Scan";
521 break;
522 case T_BitmapIndexScan:
523 pname = "Bitmap Index Scan";
524 break;
525 case T_BitmapHeapScan:
526 pname = "Bitmap Heap Scan";
527 break;
528 case T_TidScan:
529 pname = "Tid Scan";
530 break;
531 case T_SubqueryScan:
532 pname = "Subquery Scan";
533 break;
534 case T_FunctionScan:
535 pname = "Function Scan";
536 break;
537 case T_ValuesScan:
538 pname = "Values Scan";
539 break;
540 case T_Material:
541 pname = "Materialize";
542 break;
543 case T_Sort:
544 pname = "Sort";
545 break;
546 case T_Group:
547 pname = "Group";
548 break;
549 case T_Agg:
550 switch (((Agg *) plan)->aggstrategy)
552 case AGG_PLAIN:
553 pname = "Aggregate";
554 break;
555 case AGG_SORTED:
556 pname = "GroupAggregate";
557 break;
558 case AGG_HASHED:
559 pname = "HashAggregate";
560 break;
561 default:
562 pname = "Aggregate ???";
563 break;
565 break;
566 case T_Unique:
567 pname = "Unique";
568 break;
569 case T_SetOp:
570 switch (((SetOp *) plan)->strategy)
572 case SETOP_SORTED:
573 switch (((SetOp *) plan)->cmd)
575 case SETOPCMD_INTERSECT:
576 pname = "SetOp Intersect";
577 break;
578 case SETOPCMD_INTERSECT_ALL:
579 pname = "SetOp Intersect All";
580 break;
581 case SETOPCMD_EXCEPT:
582 pname = "SetOp Except";
583 break;
584 case SETOPCMD_EXCEPT_ALL:
585 pname = "SetOp Except All";
586 break;
587 default:
588 pname = "SetOp ???";
589 break;
591 break;
592 case SETOP_HASHED:
593 switch (((SetOp *) plan)->cmd)
595 case SETOPCMD_INTERSECT:
596 pname = "HashSetOp Intersect";
597 break;
598 case SETOPCMD_INTERSECT_ALL:
599 pname = "HashSetOp Intersect All";
600 break;
601 case SETOPCMD_EXCEPT:
602 pname = "HashSetOp Except";
603 break;
604 case SETOPCMD_EXCEPT_ALL:
605 pname = "HashSetOp Except All";
606 break;
607 default:
608 pname = "HashSetOp ???";
609 break;
611 break;
612 default:
613 pname = "SetOp ???";
614 break;
616 break;
617 case T_Limit:
618 pname = "Limit";
619 break;
620 case T_Hash:
621 pname = "Hash";
622 break;
623 default:
624 pname = "???";
625 break;
628 appendStringInfoString(str, pname);
629 switch (nodeTag(plan))
631 case T_IndexScan:
632 if (ScanDirectionIsBackward(((IndexScan *) plan)->indexorderdir))
633 appendStringInfoString(str, " Backward");
634 appendStringInfo(str, " using %s",
635 explain_get_index_name(((IndexScan *) plan)->indexid));
636 /* FALL THRU */
637 case T_SeqScan:
638 case T_BitmapHeapScan:
639 case T_TidScan:
640 if (((Scan *) plan)->scanrelid > 0)
642 RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
643 es->rtable);
644 char *relname;
646 /* Assume it's on a real relation */
647 Assert(rte->rtekind == RTE_RELATION);
649 /* We only show the rel name, not schema name */
650 relname = get_rel_name(rte->relid);
652 appendStringInfo(str, " on %s",
653 quote_identifier(relname));
654 if (strcmp(rte->eref->aliasname, relname) != 0)
655 appendStringInfo(str, " %s",
656 quote_identifier(rte->eref->aliasname));
658 break;
659 case T_BitmapIndexScan:
660 appendStringInfo(str, " on %s",
661 explain_get_index_name(((BitmapIndexScan *) plan)->indexid));
662 break;
663 case T_SubqueryScan:
664 if (((Scan *) plan)->scanrelid > 0)
666 RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
667 es->rtable);
669 appendStringInfo(str, " %s",
670 quote_identifier(rte->eref->aliasname));
672 break;
673 case T_FunctionScan:
674 if (((Scan *) plan)->scanrelid > 0)
676 RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
677 es->rtable);
678 Node *funcexpr;
679 char *proname;
681 /* Assert it's on a RangeFunction */
682 Assert(rte->rtekind == RTE_FUNCTION);
685 * If the expression is still a function call, we can get the
686 * real name of the function. Otherwise, punt (this can
687 * happen if the optimizer simplified away the function call,
688 * for example).
690 funcexpr = ((FunctionScan *) plan)->funcexpr;
691 if (funcexpr && IsA(funcexpr, FuncExpr))
693 Oid funcid = ((FuncExpr *) funcexpr)->funcid;
695 /* We only show the func name, not schema name */
696 proname = get_func_name(funcid);
698 else
699 proname = rte->eref->aliasname;
701 appendStringInfo(str, " on %s",
702 quote_identifier(proname));
703 if (strcmp(rte->eref->aliasname, proname) != 0)
704 appendStringInfo(str, " %s",
705 quote_identifier(rte->eref->aliasname));
707 break;
708 case T_ValuesScan:
709 if (((Scan *) plan)->scanrelid > 0)
711 RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
712 es->rtable);
713 char *valsname;
715 /* Assert it's on a values rte */
716 Assert(rte->rtekind == RTE_VALUES);
718 valsname = rte->eref->aliasname;
720 appendStringInfo(str, " on %s",
721 quote_identifier(valsname));
723 break;
724 default:
725 break;
728 appendStringInfo(str, " (cost=%.2f..%.2f rows=%.0f width=%d)",
729 plan->startup_cost, plan->total_cost,
730 plan->plan_rows, plan->plan_width);
733 * We have to forcibly clean up the instrumentation state because we
734 * haven't done ExecutorEnd yet. This is pretty grotty ...
736 if (planstate->instrument)
737 InstrEndLoop(planstate->instrument);
739 if (planstate->instrument && planstate->instrument->nloops > 0)
741 double nloops = planstate->instrument->nloops;
743 appendStringInfo(str, " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
744 1000.0 * planstate->instrument->startup / nloops,
745 1000.0 * planstate->instrument->total / nloops,
746 planstate->instrument->ntuples / nloops,
747 planstate->instrument->nloops);
749 else if (es->printAnalyze)
750 appendStringInfo(str, " (never executed)");
751 appendStringInfoChar(str, '\n');
753 /* target list */
754 if (es->printTList)
755 show_plan_tlist(plan, str, indent, es);
757 /* quals, sort keys, etc */
758 switch (nodeTag(plan))
760 case T_IndexScan:
761 show_scan_qual(((IndexScan *) plan)->indexqualorig,
762 "Index Cond",
763 ((Scan *) plan)->scanrelid,
764 outer_plan, NULL,
765 str, indent, es);
766 show_scan_qual(plan->qual,
767 "Filter",
768 ((Scan *) plan)->scanrelid,
769 outer_plan, NULL,
770 str, indent, es);
771 break;
772 case T_BitmapIndexScan:
773 show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
774 "Index Cond",
775 ((Scan *) plan)->scanrelid,
776 outer_plan, NULL,
777 str, indent, es);
778 break;
779 case T_BitmapHeapScan:
780 /* XXX do we want to show this in production? */
781 show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig,
782 "Recheck Cond",
783 ((Scan *) plan)->scanrelid,
784 outer_plan, NULL,
785 str, indent, es);
786 /* FALL THRU */
787 case T_SeqScan:
788 case T_FunctionScan:
789 case T_ValuesScan:
790 show_scan_qual(plan->qual,
791 "Filter",
792 ((Scan *) plan)->scanrelid,
793 outer_plan, NULL,
794 str, indent, es);
795 break;
796 case T_SubqueryScan:
797 show_scan_qual(plan->qual,
798 "Filter",
799 ((Scan *) plan)->scanrelid,
800 outer_plan,
801 ((SubqueryScan *) plan)->subplan,
802 str, indent, es);
803 break;
804 case T_TidScan:
807 * The tidquals list has OR semantics, so be sure to show it
808 * as an OR condition.
810 List *tidquals = ((TidScan *) plan)->tidquals;
812 if (list_length(tidquals) > 1)
813 tidquals = list_make1(make_orclause(tidquals));
814 show_scan_qual(tidquals,
815 "TID Cond",
816 ((Scan *) plan)->scanrelid,
817 outer_plan, NULL,
818 str, indent, es);
819 show_scan_qual(plan->qual,
820 "Filter",
821 ((Scan *) plan)->scanrelid,
822 outer_plan, NULL,
823 str, indent, es);
825 break;
826 case T_NestLoop:
827 show_upper_qual(((NestLoop *) plan)->join.joinqual,
828 "Join Filter", plan,
829 str, indent, es);
830 show_upper_qual(plan->qual,
831 "Filter", plan,
832 str, indent, es);
833 break;
834 case T_MergeJoin:
835 show_upper_qual(((MergeJoin *) plan)->mergeclauses,
836 "Merge Cond", plan,
837 str, indent, es);
838 show_upper_qual(((MergeJoin *) plan)->join.joinqual,
839 "Join Filter", plan,
840 str, indent, es);
841 show_upper_qual(plan->qual,
842 "Filter", plan,
843 str, indent, es);
844 break;
845 case T_HashJoin:
846 show_upper_qual(((HashJoin *) plan)->hashclauses,
847 "Hash Cond", plan,
848 str, indent, es);
849 show_upper_qual(((HashJoin *) plan)->join.joinqual,
850 "Join Filter", plan,
851 str, indent, es);
852 show_upper_qual(plan->qual,
853 "Filter", plan,
854 str, indent, es);
855 break;
856 case T_Agg:
857 case T_Group:
858 show_upper_qual(plan->qual,
859 "Filter", plan,
860 str, indent, es);
861 break;
862 case T_Sort:
863 show_sort_keys(plan,
864 ((Sort *) plan)->numCols,
865 ((Sort *) plan)->sortColIdx,
866 "Sort Key",
867 str, indent, es);
868 show_sort_info((SortState *) planstate,
869 str, indent, es);
870 break;
871 case T_Result:
872 show_upper_qual((List *) ((Result *) plan)->resconstantqual,
873 "One-Time Filter", plan,
874 str, indent, es);
875 show_upper_qual(plan->qual,
876 "Filter", plan,
877 str, indent, es);
878 break;
879 default:
880 break;
883 /* initPlan-s */
884 if (plan->initPlan)
886 ListCell *lst;
888 for (i = 0; i < indent; i++)
889 appendStringInfo(str, " ");
890 appendStringInfo(str, " InitPlan\n");
891 foreach(lst, planstate->initPlan)
893 SubPlanState *sps = (SubPlanState *) lfirst(lst);
894 SubPlan *sp = (SubPlan *) sps->xprstate.expr;
896 for (i = 0; i < indent; i++)
897 appendStringInfo(str, " ");
898 appendStringInfo(str, " -> ");
899 explain_outNode(str,
900 exec_subplan_get_plan(es->pstmt, sp),
901 sps->planstate,
902 NULL,
903 indent + 4, es);
907 /* lefttree */
908 if (outerPlan(plan))
910 for (i = 0; i < indent; i++)
911 appendStringInfo(str, " ");
912 appendStringInfo(str, " -> ");
915 * Ordinarily we don't pass down our own outer_plan value to our child
916 * nodes, but in bitmap scan trees we must, since the bottom
917 * BitmapIndexScan nodes may have outer references.
919 explain_outNode(str, outerPlan(plan),
920 outerPlanState(planstate),
921 IsA(plan, BitmapHeapScan) ? outer_plan : NULL,
922 indent + 3, es);
925 /* righttree */
926 if (innerPlan(plan))
928 for (i = 0; i < indent; i++)
929 appendStringInfo(str, " ");
930 appendStringInfo(str, " -> ");
931 explain_outNode(str, innerPlan(plan),
932 innerPlanState(planstate),
933 outerPlan(plan),
934 indent + 3, es);
937 if (IsA(plan, Append))
939 Append *appendplan = (Append *) plan;
940 AppendState *appendstate = (AppendState *) planstate;
941 ListCell *lst;
942 int j;
944 j = 0;
945 foreach(lst, appendplan->appendplans)
947 Plan *subnode = (Plan *) lfirst(lst);
949 for (i = 0; i < indent; i++)
950 appendStringInfo(str, " ");
951 appendStringInfo(str, " -> ");
954 * Ordinarily we don't pass down our own outer_plan value to our
955 * child nodes, but in an Append we must, since we might be
956 * looking at an appendrel indexscan with outer references from
957 * the member scans.
959 explain_outNode(str, subnode,
960 appendstate->appendplans[j],
961 outer_plan,
962 indent + 3, es);
963 j++;
967 if (IsA(plan, BitmapAnd))
969 BitmapAnd *bitmapandplan = (BitmapAnd *) plan;
970 BitmapAndState *bitmapandstate = (BitmapAndState *) planstate;
971 ListCell *lst;
972 int j;
974 j = 0;
975 foreach(lst, bitmapandplan->bitmapplans)
977 Plan *subnode = (Plan *) lfirst(lst);
979 for (i = 0; i < indent; i++)
980 appendStringInfo(str, " ");
981 appendStringInfo(str, " -> ");
983 explain_outNode(str, subnode,
984 bitmapandstate->bitmapplans[j],
985 outer_plan, /* pass down same outer plan */
986 indent + 3, es);
987 j++;
991 if (IsA(plan, BitmapOr))
993 BitmapOr *bitmaporplan = (BitmapOr *) plan;
994 BitmapOrState *bitmaporstate = (BitmapOrState *) planstate;
995 ListCell *lst;
996 int j;
998 j = 0;
999 foreach(lst, bitmaporplan->bitmapplans)
1001 Plan *subnode = (Plan *) lfirst(lst);
1003 for (i = 0; i < indent; i++)
1004 appendStringInfo(str, " ");
1005 appendStringInfo(str, " -> ");
1007 explain_outNode(str, subnode,
1008 bitmaporstate->bitmapplans[j],
1009 outer_plan, /* pass down same outer plan */
1010 indent + 3, es);
1011 j++;
1015 if (IsA(plan, SubqueryScan))
1017 SubqueryScan *subqueryscan = (SubqueryScan *) plan;
1018 SubqueryScanState *subquerystate = (SubqueryScanState *) planstate;
1019 Plan *subnode = subqueryscan->subplan;
1021 for (i = 0; i < indent; i++)
1022 appendStringInfo(str, " ");
1023 appendStringInfo(str, " -> ");
1025 explain_outNode(str, subnode,
1026 subquerystate->subplan,
1027 NULL,
1028 indent + 3, es);
1031 /* subPlan-s */
1032 if (planstate->subPlan)
1034 ListCell *lst;
1036 for (i = 0; i < indent; i++)
1037 appendStringInfo(str, " ");
1038 appendStringInfo(str, " SubPlan\n");
1039 foreach(lst, planstate->subPlan)
1041 SubPlanState *sps = (SubPlanState *) lfirst(lst);
1042 SubPlan *sp = (SubPlan *) sps->xprstate.expr;
1044 for (i = 0; i < indent; i++)
1045 appendStringInfo(str, " ");
1046 appendStringInfo(str, " -> ");
1047 explain_outNode(str,
1048 exec_subplan_get_plan(es->pstmt, sp),
1049 sps->planstate,
1050 NULL,
1051 indent + 4, es);
1057 * Show the targetlist of a plan node
1059 static void
1060 show_plan_tlist(Plan *plan,
1061 StringInfo str, int indent, ExplainState *es)
1063 List *context;
1064 bool useprefix;
1065 ListCell *lc;
1066 int i;
1068 /* No work if empty tlist (this occurs eg in bitmap indexscans) */
1069 if (plan->targetlist == NIL)
1070 return;
1071 /* The tlist of an Append isn't real helpful, so suppress it */
1072 if (IsA(plan, Append))
1073 return;
1075 /* Set up deparsing context */
1076 context = deparse_context_for_plan((Node *) outerPlan(plan),
1077 (Node *) innerPlan(plan),
1078 es->rtable);
1079 useprefix = list_length(es->rtable) > 1;
1081 /* Emit line prefix */
1082 for (i = 0; i < indent; i++)
1083 appendStringInfo(str, " ");
1084 appendStringInfo(str, " Output: ");
1086 /* Deparse each non-junk result column */
1087 i = 0;
1088 foreach(lc, plan->targetlist)
1090 TargetEntry *tle = (TargetEntry *) lfirst(lc);
1092 if (tle->resjunk)
1093 continue;
1094 if (i++ > 0)
1095 appendStringInfo(str, ", ");
1096 appendStringInfoString(str,
1097 deparse_expression((Node *) tle->expr, context,
1098 useprefix, false));
1101 appendStringInfoChar(str, '\n');
1105 * Show a qualifier expression for a scan plan node
1107 * Note: outer_plan is the referent for any OUTER vars in the scan qual;
1108 * this would be the outer side of a nestloop plan. inner_plan should be
1109 * NULL except for a SubqueryScan plan node, where it should be the subplan.
1111 static void
1112 show_scan_qual(List *qual, const char *qlabel,
1113 int scanrelid, Plan *outer_plan, Plan *inner_plan,
1114 StringInfo str, int indent, ExplainState *es)
1116 List *context;
1117 bool useprefix;
1118 Node *node;
1119 char *exprstr;
1120 int i;
1122 /* No work if empty qual */
1123 if (qual == NIL)
1124 return;
1126 /* Convert AND list to explicit AND */
1127 node = (Node *) make_ands_explicit(qual);
1129 /* Set up deparsing context */
1130 context = deparse_context_for_plan((Node *) outer_plan,
1131 (Node *) inner_plan,
1132 es->rtable);
1133 useprefix = (outer_plan != NULL || inner_plan != NULL);
1135 /* Deparse the expression */
1136 exprstr = deparse_expression(node, context, useprefix, false);
1138 /* And add to str */
1139 for (i = 0; i < indent; i++)
1140 appendStringInfo(str, " ");
1141 appendStringInfo(str, " %s: %s\n", qlabel, exprstr);
1145 * Show a qualifier expression for an upper-level plan node
1147 static void
1148 show_upper_qual(List *qual, const char *qlabel, Plan *plan,
1149 StringInfo str, int indent, ExplainState *es)
1151 List *context;
1152 bool useprefix;
1153 Node *node;
1154 char *exprstr;
1155 int i;
1157 /* No work if empty qual */
1158 if (qual == NIL)
1159 return;
1161 /* Set up deparsing context */
1162 context = deparse_context_for_plan((Node *) outerPlan(plan),
1163 (Node *) innerPlan(plan),
1164 es->rtable);
1165 useprefix = list_length(es->rtable) > 1;
1167 /* Deparse the expression */
1168 node = (Node *) make_ands_explicit(qual);
1169 exprstr = deparse_expression(node, context, useprefix, false);
1171 /* And add to str */
1172 for (i = 0; i < indent; i++)
1173 appendStringInfo(str, " ");
1174 appendStringInfo(str, " %s: %s\n", qlabel, exprstr);
1178 * Show the sort keys for a Sort node.
1180 static void
1181 show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
1182 const char *qlabel,
1183 StringInfo str, int indent, ExplainState *es)
1185 List *context;
1186 bool useprefix;
1187 int keyno;
1188 char *exprstr;
1189 int i;
1191 if (nkeys <= 0)
1192 return;
1194 for (i = 0; i < indent; i++)
1195 appendStringInfo(str, " ");
1196 appendStringInfo(str, " %s: ", qlabel);
1198 /* Set up deparsing context */
1199 context = deparse_context_for_plan((Node *) outerPlan(sortplan),
1200 NULL, /* Sort has no innerPlan */
1201 es->rtable);
1202 useprefix = list_length(es->rtable) > 1;
1204 for (keyno = 0; keyno < nkeys; keyno++)
1206 /* find key expression in tlist */
1207 AttrNumber keyresno = keycols[keyno];
1208 TargetEntry *target = get_tle_by_resno(sortplan->targetlist, keyresno);
1210 if (!target)
1211 elog(ERROR, "no tlist entry for key %d", keyresno);
1212 /* Deparse the expression, showing any top-level cast */
1213 exprstr = deparse_expression((Node *) target->expr, context,
1214 useprefix, true);
1215 /* And add to str */
1216 if (keyno > 0)
1217 appendStringInfo(str, ", ");
1218 appendStringInfoString(str, exprstr);
1221 appendStringInfo(str, "\n");
1225 * If it's EXPLAIN ANALYZE, show tuplesort explain info for a sort node
1227 static void
1228 show_sort_info(SortState *sortstate,
1229 StringInfo str, int indent, ExplainState *es)
1231 Assert(IsA(sortstate, SortState));
1232 if (es->printAnalyze && sortstate->sort_Done &&
1233 sortstate->tuplesortstate != NULL)
1235 char *sortinfo;
1236 int i;
1238 sortinfo = tuplesort_explain((Tuplesortstate *) sortstate->tuplesortstate);
1239 for (i = 0; i < indent; i++)
1240 appendStringInfo(str, " ");
1241 appendStringInfo(str, " %s\n", sortinfo);
1242 pfree(sortinfo);
1247 * Fetch the name of an index in an EXPLAIN
1249 * We allow plugins to get control here so that plans involving hypothetical
1250 * indexes can be explained.
1252 static const char *
1253 explain_get_index_name(Oid indexId)
1255 const char *result;
1257 if (explain_get_index_name_hook)
1258 result = (*explain_get_index_name_hook) (indexId);
1259 else
1260 result = NULL;
1261 if (result == NULL)
1263 /* default behavior: look in the catalogs and quote it */
1264 result = get_rel_name(indexId);
1265 if (result == NULL)
1266 elog(ERROR, "cache lookup failed for index %u", indexId);
1267 result = quote_identifier(result);
1269 return result;