explain.c 30.8 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * explain.c
4
 *	  Explain query execution plans
5
 *
6
 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994-5, Regents of the University of California
8
 *
9
 * IDENTIFICATION
10
 *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.175 2008/05/14 19:10:29 tgl Exp $
11
 *
12
 *-------------------------------------------------------------------------
13
 */
14
#include "postgres.h"
M
Marc G. Fournier 已提交
15

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"
B
Bruce Momjian 已提交
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"
34

35

36 37
/* Hook for plugins to get control in ExplainOneQuery() */
ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL;
B
Bruce Momjian 已提交
38

39 40 41 42
/* Hook for plugins to get control in explain_get_index_name() */
explain_get_index_name_hook_type explain_get_index_name_hook = NULL;


43 44 45
typedef struct ExplainState
{
	/* 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;
52

53
static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
B
Bruce Momjian 已提交
54 55
				const char *queryString,
				ParamListInfo params, TupOutputState *tstate);
56
static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
B
Bruce Momjian 已提交
57
				StringInfo buf);
58
static double elapsed_time(instr_time *starttime);
59
static void explain_outNode(StringInfo str,
60
				Plan *plan, PlanState *planstate,
B
Bruce Momjian 已提交
61 62
				Plan *outer_plan,
				int indent, ExplainState *es);
63 64
static void show_plan_tlist(Plan *plan,
							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,
B
Bruce Momjian 已提交
67
			   StringInfo str, int indent, ExplainState *es);
68
static void show_upper_qual(List *qual, const char *qlabel, Plan *plan,
B
Bruce Momjian 已提交
69
				StringInfo str, int indent, ExplainState *es);
70
static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
B
Bruce Momjian 已提交
71 72
			   const char *qlabel,
			   StringInfo str, int indent, ExplainState *es);
73 74
static void show_sort_info(SortState *sortstate,
			   StringInfo str, int indent, ExplainState *es);
75 76
static const char *explain_get_index_name(Oid indexId);

77 78 79

/*
 * ExplainQuery -
80
 *	  execute an EXPLAIN command
81 82
 */
void
83 84
ExplainQuery(ExplainStmt *stmt, const char *queryString,
			 ParamListInfo params, DestReceiver *dest)
85
{
86 87
	Oid		   *param_types;
	int			num_params;
88
	TupOutputState *tstate;
B
Bruce Momjian 已提交
89
	List	   *rewritten;
90
	ListCell   *l;
91

92 93 94
	/* Convert parameter type data to the form parser wants */
	getParamListTypes(params, &param_types, &num_params);

95
	/*
B
Bruce Momjian 已提交
96
	 * Run parse analysis and rewrite.	Note this also acquires sufficient
97 98
	 * locks on the source table(s).
	 *
B
Bruce Momjian 已提交
99 100 101 102 103
	 * Because the parser and planner tend to scribble on their input, we make
	 * a preliminary copy of the source querytree.	This prevents problems in
	 * the case that the EXPLAIN is in a portal or plpgsql function and is
	 * executed repeatedly.  (See also the same hack in DECLARE CURSOR and
	 * PREPARE.)  XXX FIXME someday.
104
	 */
105 106
	rewritten = pg_analyze_and_rewrite((Node *) copyObject(stmt->query),
									   queryString, param_types, num_params);
107

108
	/* prepare for projection of tuples */
109
	tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
110

111
	if (rewritten == NIL)
112
	{
113 114
		/* In the case of an INSTEAD NOTHING, tell at least that */
		do_text_output_oneline(tstate, "Query rewrites to nothing");
115
	}
116
	else
B
Bruce Momjian 已提交
117
	{
118 119
		/* Explain every plan */
		foreach(l, rewritten)
120
		{
121 122
			ExplainOneQuery((Query *) lfirst(l), stmt,
							queryString, params, tstate);
123 124 125
			/* put a blank line between plans */
			if (lnext(l) != NULL)
				do_text_output_oneline(tstate, "");
126
		}
B
Bruce Momjian 已提交
127 128
	}

129
	end_tup_output(tstate);
B
Bruce Momjian 已提交
130 131
}

132 133 134 135 136 137 138 139 140 141 142 143
/*
 * ExplainResultDesc -
 *	  construct the result tupledesc for an EXPLAIN
 */
TupleDesc
ExplainResultDesc(ExplainStmt *stmt)
{
	TupleDesc	tupdesc;

	/* need a tuple descriptor representing a single TEXT column */
	tupdesc = CreateTemplateTupleDesc(1, false);
	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
144
					   TEXTOID, -1, 0);
145 146 147
	return tupdesc;
}

B
Bruce Momjian 已提交
148 149
/*
 * ExplainOneQuery -
150
 *	  print out the execution plan for one Query
B
Bruce Momjian 已提交
151 152
 */
static void
153
ExplainOneQuery(Query *query, ExplainStmt *stmt, const char *queryString,
154
				ParamListInfo params, TupOutputState *tstate)
B
Bruce Momjian 已提交
155
{
156 157 158
	/* planner will not cope with utility statements */
	if (query->commandType == CMD_UTILITY)
	{
159 160 161
		ExplainOneUtility(query->utilityStmt, stmt,
						  queryString, params, tstate);
		return;
162 163
	}

164 165 166 167 168 169
	/* if an advisor plugin is present, let it manage things */
	if (ExplainOneQuery_hook)
		(*ExplainOneQuery_hook) (query, stmt, queryString, params, tstate);
	else
	{
		PlannedStmt *plan;
170

171 172
		/* plan the query */
		plan = planner(query, 0, params);
173

174 175 176
		/* run it (if needed) and produce output */
		ExplainOnePlan(plan, params, stmt, tstate);
	}
177 178
}

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
/*
 * ExplainOneUtility -
 *	  print out the execution plan for one utility statement
 *	  (In general, utility statements don't have plans, but there are some
 *	  we treat as special cases)
 *
 * This is exported because it's called back from prepare.c in the
 * EXPLAIN EXECUTE case
 */
void
ExplainOneUtility(Node *utilityStmt, ExplainStmt *stmt,
				  const char *queryString, ParamListInfo params,
				  TupOutputState *tstate)
{
	if (utilityStmt == NULL)
		return;

196
	if (IsA(utilityStmt, ExecuteStmt))
197 198 199 200 201 202 203 204 205
		ExplainExecuteQuery((ExecuteStmt *) utilityStmt, stmt,
							queryString, params, tstate);
	else if (IsA(utilityStmt, NotifyStmt))
		do_text_output_oneline(tstate, "NOTIFY");
	else
		do_text_output_oneline(tstate,
							   "Utility statements have no plan structure");
}

206 207 208 209 210
/*
 * ExplainOnePlan -
 *		given a planned query, execute it if needed, and then print
 *		EXPLAIN output
 *
211 212 213 214 215
 * Since we ignore any DeclareCursorStmt that might be attached to the query,
 * if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll actually run the
 * query.  This is different from pre-8.3 behavior but seems more useful than
 * 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 218
 * EXPLAIN EXECUTE case, and because an index advisor plugin would need
 * to call it.
219 220
 */
void
221
ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
222
			   ExplainStmt *stmt, TupOutputState *tstate)
223
{
224
	QueryDesc  *queryDesc;
B
Bruce Momjian 已提交
225
	instr_time	starttime;
226 227
	double		totaltime = 0;
	ExplainState *es;
228
	StringInfoData buf;
229
	int			eflags;
230

231
	/*
232 233
	 * Use a snapshot with an updated command ID to ensure this query sees
	 * results of any previously executed queries.
234
	 */
235
	PushUpdatedSnapshot(GetActiveSnapshot());
236 237 238

	/* Create a QueryDesc requesting no output */
	queryDesc = CreateQueryDesc(plannedstmt,
239
								GetActiveSnapshot(), InvalidSnapshot,
240 241 242
								None_Receiver, params,
								stmt->analyze);

243
	INSTR_TIME_SET_CURRENT(starttime);
244

245 246 247 248
	/* If analyzing, we need to cope with queued triggers */
	if (stmt->analyze)
		AfterTriggerBeginQuery();

249 250 251 252 253 254
	/* Select execution options */
	if (stmt->analyze)
		eflags = 0;				/* default run-to-completion flags */
	else
		eflags = EXEC_FLAG_EXPLAIN_ONLY;

255
	/* call ExecutorStart to prepare the plan for execution */
256
	ExecutorStart(queryDesc, eflags);
257

258
	/* Execute the plan for statistics if asked for */
259
	if (stmt->analyze)
260
	{
261 262
		/* run the plan */
		ExecutorRun(queryDesc, ForwardScanDirection, 0L);
263

264 265
		/* We can't clean up 'till we're done printing the stats... */
		totaltime += elapsed_time(&starttime);
266 267
	}

268
	es = (ExplainState *) palloc0(sizeof(ExplainState));
B
Bruce Momjian 已提交
269

270
	es->printTList = stmt->verbose;
271
	es->printAnalyze = stmt->analyze;
272
	es->pstmt = queryDesc->plannedstmt;
273
	es->rtable = queryDesc->plannedstmt->rtable;
274

275
	initStringInfo(&buf);
276 277
	explain_outNode(&buf,
					queryDesc->plannedstmt->planTree, queryDesc->planstate,
278
					NULL, 0, es);
279 280

	/*
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
	 * If we ran the command, run any AFTER triggers it queued.  (Note this
	 * will not include DEFERRED triggers; since those don't run until end of
	 * transaction, we can't measure them.)  Include into total runtime.
	 */
	if (stmt->analyze)
	{
		INSTR_TIME_SET_CURRENT(starttime);
		AfterTriggerEndQuery(queryDesc->estate);
		totaltime += elapsed_time(&starttime);
	}

	/* Print info about runtime of triggers */
	if (es->printAnalyze)
	{
		ResultRelInfo *rInfo;
296
		bool		show_relname;
B
Bruce Momjian 已提交
297
		int			numrels = queryDesc->estate->es_num_result_relations;
298
		List	   *targrels = queryDesc->estate->es_trig_target_relations;
B
Bruce Momjian 已提交
299
		int			nr;
300
		ListCell   *l;
301

302
		show_relname = (numrels > 1 || targrels != NIL);
303 304
		rInfo = queryDesc->estate->es_result_relations;
		for (nr = 0; nr < numrels; rInfo++, nr++)
305 306 307
			report_triggers(rInfo, show_relname, &buf);

		foreach(l, targrels)
308
		{
309 310
			rInfo = (ResultRelInfo *) lfirst(l);
			report_triggers(rInfo, show_relname, &buf);
311 312 313 314
		}
	}

	/*
B
Bruce Momjian 已提交
315 316
	 * Close down the query and free resources.  Include time for this in the
	 * total runtime (although it should be pretty minimal).
317
	 */
318
	INSTR_TIME_SET_CURRENT(starttime);
319

320
	ExecutorEnd(queryDesc);
321

322 323
	FreeQueryDesc(queryDesc);

324 325
	PopActiveSnapshot();

326 327 328
	/* We need a CCI just in case query expanded to multiple plans */
	if (stmt->analyze)
		CommandCounterIncrement();
329 330 331

	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);
336

337
	pfree(buf.data);
B
Bruce Momjian 已提交
338
	pfree(es);
339 340
}

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
/*
 * report_triggers -
 *		report execution stats for a single relation's triggers
 */
static void
report_triggers(ResultRelInfo *rInfo, bool show_relname, StringInfo buf)
{
	int			nt;

	if (!rInfo->ri_TrigDesc || !rInfo->ri_TrigInstrument)
		return;
	for (nt = 0; nt < rInfo->ri_TrigDesc->numtriggers; nt++)
	{
		Trigger    *trig = rInfo->ri_TrigDesc->triggers + nt;
		Instrumentation *instr = rInfo->ri_TrigInstrument + nt;
		char	   *conname;

		/* Must clean up instrumentation state */
		InstrEndLoop(instr);

		/*
B
Bruce Momjian 已提交
362 363
		 * We ignore triggers that were never invoked; they likely aren't
		 * relevant to the current query type.
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
		 */
		if (instr->ntuples == 0)
			continue;

		if (OidIsValid(trig->tgconstraint) &&
			(conname = get_constraint_name(trig->tgconstraint)) != NULL)
		{
			appendStringInfo(buf, "Trigger for constraint %s", conname);
			pfree(conname);
		}
		else
			appendStringInfo(buf, "Trigger %s", trig->tgname);

		if (show_relname)
			appendStringInfo(buf, " on %s",
							 RelationGetRelationName(rInfo->ri_RelationDesc));

		appendStringInfo(buf, ": time=%.3f calls=%.0f\n",
						 1000.0 * instr->total, instr->ntuples);
	}
}

386
/* Compute elapsed time in seconds since given timestamp */
387
static double
388
elapsed_time(instr_time *starttime)
389
{
B
Bruce Momjian 已提交
390
	instr_time	endtime;
391

392
	INSTR_TIME_SET_CURRENT(endtime);
393
	INSTR_TIME_SUBTRACT(endtime, *starttime);
394
	return INSTR_TIME_GET_DOUBLE(endtime);
395
}
396 397 398

/*
 * explain_outNode -
399 400
 *	  converts a Plan node into ascii string and appends it to 'str'
 *
401 402 403 404
 * planstate points to the executor state node corresponding to the plan node.
 * We need this to get at the instrumentation data (if any) as well as the
 * list of subplans.
 *
405 406 407
 * outer_plan, if not null, references another plan node that is the outer
 * side of a join with the current node.  This is only interesting for
 * deciphering runtime keys of an inner indexscan.
408 409
 */
static void
410
explain_outNode(StringInfo str,
411
				Plan *plan, PlanState *planstate,
412
				Plan *outer_plan,
413
				int indent, ExplainState *es)
414
{
415
	const char *pname;
B
Bruce Momjian 已提交
416
	int			i;
417 418 419

	if (plan == NULL)
	{
420
		appendStringInfoChar(str, '\n');
421 422 423 424 425
		return;
	}

	switch (nodeTag(plan))
	{
426 427 428 429 430 431
		case T_Result:
			pname = "Result";
			break;
		case T_Append:
			pname = "Append";
			break;
432 433 434 435 436 437
		case T_BitmapAnd:
			pname = "BitmapAnd";
			break;
		case T_BitmapOr:
			pname = "BitmapOr";
			break;
438
		case T_NestLoop:
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
			switch (((NestLoop *) plan)->join.jointype)
			{
				case JOIN_INNER:
					pname = "Nested Loop";
					break;
				case JOIN_LEFT:
					pname = "Nested Loop Left Join";
					break;
				case JOIN_FULL:
					pname = "Nested Loop Full Join";
					break;
				case JOIN_RIGHT:
					pname = "Nested Loop Right Join";
					break;
				case JOIN_IN:
					pname = "Nested Loop IN Join";
					break;
				default:
					pname = "Nested Loop ??? Join";
					break;
			}
460 461
			break;
		case T_MergeJoin:
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
			switch (((MergeJoin *) plan)->join.jointype)
			{
				case JOIN_INNER:
					pname = "Merge Join";
					break;
				case JOIN_LEFT:
					pname = "Merge Left Join";
					break;
				case JOIN_FULL:
					pname = "Merge Full Join";
					break;
				case JOIN_RIGHT:
					pname = "Merge Right Join";
					break;
				case JOIN_IN:
					pname = "Merge IN Join";
					break;
				default:
					pname = "Merge ??? Join";
					break;
			}
483 484
			break;
		case T_HashJoin:
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
			switch (((HashJoin *) plan)->join.jointype)
			{
				case JOIN_INNER:
					pname = "Hash Join";
					break;
				case JOIN_LEFT:
					pname = "Hash Left Join";
					break;
				case JOIN_FULL:
					pname = "Hash Full Join";
					break;
				case JOIN_RIGHT:
					pname = "Hash Right Join";
					break;
				case JOIN_IN:
					pname = "Hash IN Join";
					break;
				default:
					pname = "Hash ??? Join";
					break;
			}
506 507 508 509 510 511 512
			break;
		case T_SeqScan:
			pname = "Seq Scan";
			break;
		case T_IndexScan:
			pname = "Index Scan";
			break;
513 514 515 516 517 518
		case T_BitmapIndexScan:
			pname = "Bitmap Index Scan";
			break;
		case T_BitmapHeapScan:
			pname = "Bitmap Heap Scan";
			break;
519 520 521 522 523 524
		case T_TidScan:
			pname = "Tid Scan";
			break;
		case T_SubqueryScan:
			pname = "Subquery Scan";
			break;
525 526 527
		case T_FunctionScan:
			pname = "Function Scan";
			break;
528 529 530
		case T_ValuesScan:
			pname = "Values Scan";
			break;
531 532 533
		case T_Material:
			pname = "Materialize";
			break;
534 535 536 537 538 539 540
		case T_Sort:
			pname = "Sort";
			break;
		case T_Group:
			pname = "Group";
			break;
		case T_Agg:
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
			switch (((Agg *) plan)->aggstrategy)
			{
				case AGG_PLAIN:
					pname = "Aggregate";
					break;
				case AGG_SORTED:
					pname = "GroupAggregate";
					break;
				case AGG_HASHED:
					pname = "HashAggregate";
					break;
				default:
					pname = "Aggregate ???";
					break;
			}
556 557 558 559
			break;
		case T_Unique:
			pname = "Unique";
			break;
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
		case T_SetOp:
			switch (((SetOp *) plan)->cmd)
			{
				case SETOPCMD_INTERSECT:
					pname = "SetOp Intersect";
					break;
				case SETOPCMD_INTERSECT_ALL:
					pname = "SetOp Intersect All";
					break;
				case SETOPCMD_EXCEPT:
					pname = "SetOp Except";
					break;
				case SETOPCMD_EXCEPT_ALL:
					pname = "SetOp Except All";
					break;
				default:
					pname = "SetOp ???";
					break;
			}
			break;
580 581 582
		case T_Limit:
			pname = "Limit";
			break;
583 584 585 586
		case T_Hash:
			pname = "Hash";
			break;
		default:
587
			pname = "???";
588
			break;
589 590
	}

591
	appendStringInfoString(str, pname);
592 593
	switch (nodeTag(plan))
	{
594
		case T_IndexScan:
595
			if (ScanDirectionIsBackward(((IndexScan *) plan)->indexorderdir))
596
				appendStringInfoString(str, " Backward");
597
			appendStringInfo(str, " using %s",
B
Bruce Momjian 已提交
598
					  explain_get_index_name(((IndexScan *) plan)->indexid));
599
			/* FALL THRU */
600
		case T_SeqScan:
601
		case T_BitmapHeapScan:
602
		case T_TidScan:
603 604
			if (((Scan *) plan)->scanrelid > 0)
			{
605 606
				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
											  es->rtable);
B
Bruce Momjian 已提交
607
				char	   *relname;
608 609

				/* Assume it's on a real relation */
610
				Assert(rte->rtekind == RTE_RELATION);
611 612 613

				/* We only show the rel name, not schema name */
				relname = get_rel_name(rte->relid);
614

615
				appendStringInfo(str, " on %s",
616
								 quote_identifier(relname));
617
				if (strcmp(rte->eref->aliasname, relname) != 0)
618
					appendStringInfo(str, " %s",
B
Bruce Momjian 已提交
619
									 quote_identifier(rte->eref->aliasname));
620 621
			}
			break;
622 623
		case T_BitmapIndexScan:
			appendStringInfo(str, " on %s",
624
				explain_get_index_name(((BitmapIndexScan *) plan)->indexid));
625
			break;
626 627 628 629 630 631 632
		case T_SubqueryScan:
			if (((Scan *) plan)->scanrelid > 0)
			{
				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
											  es->rtable);

				appendStringInfo(str, " %s",
633
								 quote_identifier(rte->eref->aliasname));
634 635
			}
			break;
636 637 638 639 640
		case T_FunctionScan:
			if (((Scan *) plan)->scanrelid > 0)
			{
				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
											  es->rtable);
641
				Node	   *funcexpr;
B
Bruce Momjian 已提交
642
				char	   *proname;
643 644 645 646

				/* Assert it's on a RangeFunction */
				Assert(rte->rtekind == RTE_FUNCTION);

647
				/*
B
Bruce Momjian 已提交
648 649 650 651
				 * If the expression is still a function call, we can get the
				 * real name of the function.  Otherwise, punt (this can
				 * happen if the optimizer simplified away the function call,
				 * for example).
652
				 */
653 654
				funcexpr = ((FunctionScan *) plan)->funcexpr;
				if (funcexpr && IsA(funcexpr, FuncExpr))
655
				{
656
					Oid			funcid = ((FuncExpr *) funcexpr)->funcid;
657 658 659 660 661 662

					/* We only show the func name, not schema name */
					proname = get_func_name(funcid);
				}
				else
					proname = rte->eref->aliasname;
663 664 665 666 667

				appendStringInfo(str, " on %s",
								 quote_identifier(proname));
				if (strcmp(rte->eref->aliasname, proname) != 0)
					appendStringInfo(str, " %s",
B
Bruce Momjian 已提交
668
									 quote_identifier(rte->eref->aliasname));
669 670
			}
			break;
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
		case T_ValuesScan:
			if (((Scan *) plan)->scanrelid > 0)
			{
				RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
											  es->rtable);
				char	   *valsname;

				/* Assert it's on a values rte */
				Assert(rte->rtekind == RTE_VALUES);

				valsname = rte->eref->aliasname;

				appendStringInfo(str, " on %s",
								 quote_identifier(valsname));
			}
			break;
687 688
		default:
			break;
689
	}
B
Bruce Momjian 已提交
690

691 692 693
	appendStringInfo(str, "  (cost=%.2f..%.2f rows=%.0f width=%d)",
					 plan->startup_cost, plan->total_cost,
					 plan->plan_rows, plan->plan_width);
694

695
	/*
B
Bruce Momjian 已提交
696 697
	 * We have to forcibly clean up the instrumentation state because we
	 * haven't done ExecutorEnd yet.  This is pretty grotty ...
698 699 700
	 */
	if (planstate->instrument)
		InstrEndLoop(planstate->instrument);
701

702 703 704
	if (planstate->instrument && planstate->instrument->nloops > 0)
	{
		double		nloops = planstate->instrument->nloops;
705

706
		appendStringInfo(str, " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
B
Bruce Momjian 已提交
707 708
						 1000.0 * planstate->instrument->startup / nloops,
						 1000.0 * planstate->instrument->total / nloops,
709 710
						 planstate->instrument->ntuples / nloops,
						 planstate->instrument->nloops);
711
	}
712 713
	else if (es->printAnalyze)
		appendStringInfo(str, " (never executed)");
714
	appendStringInfoChar(str, '\n');
715

716
	/* target list */
717 718
	if (es->printTList)
		show_plan_tlist(plan, str, indent, es);
719

720
	/* quals, sort keys, etc */
721 722 723
	switch (nodeTag(plan))
	{
		case T_IndexScan:
724
			show_scan_qual(((IndexScan *) plan)->indexqualorig,
725
						   "Index Cond",
726
						   ((Scan *) plan)->scanrelid,
727
						   outer_plan, NULL,
728
						   str, indent, es);
729
			show_scan_qual(plan->qual,
730
						   "Filter",
731
						   ((Scan *) plan)->scanrelid,
732
						   outer_plan, NULL,
733 734
						   str, indent, es);
			break;
735
		case T_BitmapIndexScan:
736
			show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
737 738
						   "Index Cond",
						   ((Scan *) plan)->scanrelid,
739
						   outer_plan, NULL,
740 741 742 743
						   str, indent, es);
			break;
		case T_BitmapHeapScan:
			/* XXX do we want to show this in production? */
744
			show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig,
745 746
						   "Recheck Cond",
						   ((Scan *) plan)->scanrelid,
747
						   outer_plan, NULL,
748 749
						   str, indent, es);
			/* FALL THRU */
750
		case T_SeqScan:
751
		case T_FunctionScan:
752
		case T_ValuesScan:
753 754 755 756 757 758 759
			show_scan_qual(plan->qual,
						   "Filter",
						   ((Scan *) plan)->scanrelid,
						   outer_plan, NULL,
						   str, indent, es);
			break;
		case T_SubqueryScan:
760
			show_scan_qual(plan->qual,
761
						   "Filter",
762
						   ((Scan *) plan)->scanrelid,
763
						   outer_plan,
764
						   ((SubqueryScan *) plan)->subplan,
765 766
						   str, indent, es);
			break;
767 768 769 770 771 772
		case T_TidScan:
			{
				/*
				 * The tidquals list has OR semantics, so be sure to show it
				 * as an OR condition.
				 */
B
Bruce Momjian 已提交
773
				List	   *tidquals = ((TidScan *) plan)->tidquals;
774 775 776 777 778 779

				if (list_length(tidquals) > 1)
					tidquals = list_make1(make_orclause(tidquals));
				show_scan_qual(tidquals,
							   "TID Cond",
							   ((Scan *) plan)->scanrelid,
780
							   outer_plan, NULL,
781 782 783 784
							   str, indent, es);
				show_scan_qual(plan->qual,
							   "Filter",
							   ((Scan *) plan)->scanrelid,
785
							   outer_plan, NULL,
786 787 788
							   str, indent, es);
			}
			break;
789
		case T_NestLoop:
790
			show_upper_qual(((NestLoop *) plan)->join.joinqual,
791
							"Join Filter", plan,
792
							str, indent, es);
793
			show_upper_qual(plan->qual,
794
							"Filter", plan,
795 796 797
							str, indent, es);
			break;
		case T_MergeJoin:
798
			show_upper_qual(((MergeJoin *) plan)->mergeclauses,
799
							"Merge Cond", plan,
800
							str, indent, es);
801
			show_upper_qual(((MergeJoin *) plan)->join.joinqual,
802
							"Join Filter", plan,
803
							str, indent, es);
804
			show_upper_qual(plan->qual,
805
							"Filter", plan,
806 807 808
							str, indent, es);
			break;
		case T_HashJoin:
809
			show_upper_qual(((HashJoin *) plan)->hashclauses,
810
							"Hash Cond", plan,
811
							str, indent, es);
812
			show_upper_qual(((HashJoin *) plan)->join.joinqual,
813
							"Join Filter", plan,
814
							str, indent, es);
815
			show_upper_qual(plan->qual,
816
							"Filter", plan,
817 818 819 820
							str, indent, es);
			break;
		case T_Agg:
		case T_Group:
821
			show_upper_qual(plan->qual,
822
							"Filter", plan,
823 824
							str, indent, es);
			break;
825
		case T_Sort:
826
			show_sort_keys(plan,
827 828
						   ((Sort *) plan)->numCols,
						   ((Sort *) plan)->sortColIdx,
829 830
						   "Sort Key",
						   str, indent, es);
831 832
			show_sort_info((SortState *) planstate,
						   str, indent, es);
833
			break;
834 835
		case T_Result:
			show_upper_qual((List *) ((Result *) plan)->resconstantqual,
836
							"One-Time Filter", plan,
837
							str, indent, es);
838
			show_upper_qual(plan->qual,
839
							"Filter", plan,
840 841 842 843 844 845
							str, indent, es);
			break;
		default:
			break;
	}

V
Vadim B. Mikheev 已提交
846 847 848
	/* initPlan-s */
	if (plan->initPlan)
	{
849
		ListCell   *lst;
850

B
Bruce Momjian 已提交
851
		for (i = 0; i < indent; i++)
V
Vadim B. Mikheev 已提交
852 853
			appendStringInfo(str, "  ");
		appendStringInfo(str, "  InitPlan\n");
854
		foreach(lst, planstate->initPlan)
V
Vadim B. Mikheev 已提交
855
		{
856
			SubPlanState *sps = (SubPlanState *) lfirst(lst);
B
Bruce Momjian 已提交
857
			SubPlan    *sp = (SubPlan *) sps->xprstate.expr;
858

V
Vadim B. Mikheev 已提交
859 860 861
			for (i = 0; i < indent; i++)
				appendStringInfo(str, "  ");
			appendStringInfo(str, "    ->  ");
862 863
			explain_outNode(str,
							exec_subplan_get_plan(es->pstmt, sp),
864
							sps->planstate,
865
							NULL,
866
							indent + 4, es);
V
Vadim B. Mikheev 已提交
867 868
		}
	}
869 870 871 872 873 874

	/* lefttree */
	if (outerPlan(plan))
	{
		for (i = 0; i < indent; i++)
			appendStringInfo(str, "  ");
V
Vadim B. Mikheev 已提交
875
		appendStringInfo(str, "  ->  ");
B
Bruce Momjian 已提交
876

877
		/*
B
Bruce Momjian 已提交
878 879
		 * Ordinarily we don't pass down our own outer_plan value to our child
		 * nodes, but in bitmap scan trees we must, since the bottom
880 881
		 * BitmapIndexScan nodes may have outer references.
		 */
882 883
		explain_outNode(str, outerPlan(plan),
						outerPlanState(planstate),
884
						IsA(plan, BitmapHeapScan) ? outer_plan : NULL,
885
						indent + 3, es);
886
	}
887 888 889 890 891 892

	/* righttree */
	if (innerPlan(plan))
	{
		for (i = 0; i < indent; i++)
			appendStringInfo(str, "  ");
V
Vadim B. Mikheev 已提交
893
		appendStringInfo(str, "  ->  ");
894 895 896
		explain_outNode(str, innerPlan(plan),
						innerPlanState(planstate),
						outerPlan(plan),
897
						indent + 3, es);
V
Vadim B. Mikheev 已提交
898
	}
899

900
	if (IsA(plan, Append))
901
	{
902
		Append	   *appendplan = (Append *) plan;
903
		AppendState *appendstate = (AppendState *) planstate;
904
		ListCell   *lst;
905
		int			j;
906

907
		j = 0;
908 909
		foreach(lst, appendplan->appendplans)
		{
910
			Plan	   *subnode = (Plan *) lfirst(lst);
911 912 913

			for (i = 0; i < indent; i++)
				appendStringInfo(str, "  ");
914
			appendStringInfo(str, "  ->  ");
915

916 917 918
			/*
			 * Ordinarily we don't pass down our own outer_plan value to our
			 * child nodes, but in an Append we must, since we might be
B
Bruce Momjian 已提交
919 920
			 * looking at an appendrel indexscan with outer references from
			 * the member scans.
921
			 */
922 923
			explain_outNode(str, subnode,
							appendstate->appendplans[j],
924
							outer_plan,
925 926
							indent + 3, es);
			j++;
927 928
		}
	}
929

930 931
	if (IsA(plan, BitmapAnd))
	{
B
Bruce Momjian 已提交
932
		BitmapAnd  *bitmapandplan = (BitmapAnd *) plan;
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
		BitmapAndState *bitmapandstate = (BitmapAndState *) planstate;
		ListCell   *lst;
		int			j;

		j = 0;
		foreach(lst, bitmapandplan->bitmapplans)
		{
			Plan	   *subnode = (Plan *) lfirst(lst);

			for (i = 0; i < indent; i++)
				appendStringInfo(str, "  ");
			appendStringInfo(str, "  ->  ");

			explain_outNode(str, subnode,
							bitmapandstate->bitmapplans[j],
B
Bruce Momjian 已提交
948
							outer_plan, /* pass down same outer plan */
949 950 951 952 953 954 955
							indent + 3, es);
			j++;
		}
	}

	if (IsA(plan, BitmapOr))
	{
B
Bruce Momjian 已提交
956
		BitmapOr   *bitmaporplan = (BitmapOr *) plan;
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
		BitmapOrState *bitmaporstate = (BitmapOrState *) planstate;
		ListCell   *lst;
		int			j;

		j = 0;
		foreach(lst, bitmaporplan->bitmapplans)
		{
			Plan	   *subnode = (Plan *) lfirst(lst);

			for (i = 0; i < indent; i++)
				appendStringInfo(str, "  ");
			appendStringInfo(str, "  ->  ");

			explain_outNode(str, subnode,
							bitmaporstate->bitmapplans[j],
B
Bruce Momjian 已提交
972
							outer_plan, /* pass down same outer plan */
973 974 975 976 977
							indent + 3, es);
			j++;
		}
	}

978 979 980
	if (IsA(plan, SubqueryScan))
	{
		SubqueryScan *subqueryscan = (SubqueryScan *) plan;
981
		SubqueryScanState *subquerystate = (SubqueryScanState *) planstate;
982 983 984 985 986 987
		Plan	   *subnode = subqueryscan->subplan;

		for (i = 0; i < indent; i++)
			appendStringInfo(str, "  ");
		appendStringInfo(str, "  ->  ");

988 989 990 991
		explain_outNode(str, subnode,
						subquerystate->subplan,
						NULL,
						indent + 3, es);
992 993 994
	}

	/* subPlan-s */
995
	if (planstate->subPlan)
996
	{
997
		ListCell   *lst;
998 999 1000 1001

		for (i = 0; i < indent; i++)
			appendStringInfo(str, "  ");
		appendStringInfo(str, "  SubPlan\n");
1002
		foreach(lst, planstate->subPlan)
1003
		{
1004
			SubPlanState *sps = (SubPlanState *) lfirst(lst);
B
Bruce Momjian 已提交
1005
			SubPlan    *sp = (SubPlan *) sps->xprstate.expr;
1006

1007 1008 1009
			for (i = 0; i < indent; i++)
				appendStringInfo(str, "  ");
			appendStringInfo(str, "    ->  ");
1010 1011
			explain_outNode(str,
							exec_subplan_get_plan(es->pstmt, sp),
1012 1013
							sps->planstate,
							NULL,
1014 1015 1016
							indent + 4, es);
		}
	}
1017 1018
}

1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
/*
 * Show the targetlist of a plan node
 */
static void
show_plan_tlist(Plan *plan,
				StringInfo str, int indent, ExplainState *es)
{
	List	   *context;
	bool		useprefix;
	ListCell   *lc;
	int			i;

	/* No work if empty tlist (this occurs eg in bitmap indexscans) */
	if (plan->targetlist == NIL)
		return;
	/* The tlist of an Append isn't real helpful, so suppress it */
	if (IsA(plan, Append))
		return;

	/* Set up deparsing context */
	context = deparse_context_for_plan((Node *) outerPlan(plan),
									   (Node *) innerPlan(plan),
									   es->rtable);
	useprefix = list_length(es->rtable) > 1;

	/* Emit line prefix */
	for (i = 0; i < indent; i++)
		appendStringInfo(str, "  ");
	appendStringInfo(str, "  Output: ");

	/* Deparse each non-junk result column */
	i = 0;
	foreach(lc, plan->targetlist)
	{
		TargetEntry *tle = (TargetEntry *) lfirst(lc);

		if (tle->resjunk)
			continue;
		if (i++ > 0)
			appendStringInfo(str, ", ");
		appendStringInfoString(str,
							   deparse_expression((Node *) tle->expr, context,
												  useprefix, false));
	}

	appendStringInfoChar(str, '\n');
}

1067 1068
/*
 * Show a qualifier expression for a scan plan node
1069 1070 1071 1072
 *
 * Note: outer_plan is the referent for any OUTER vars in the scan qual;
 * this would be the outer side of a nestloop plan.  inner_plan should be
 * NULL except for a SubqueryScan plan node, where it should be the subplan.
1073 1074
 */
static void
1075
show_scan_qual(List *qual, const char *qlabel,
1076
			   int scanrelid, Plan *outer_plan, Plan *inner_plan,
1077 1078 1079
			   StringInfo str, int indent, ExplainState *es)
{
	List	   *context;
1080
	bool		useprefix;
1081 1082 1083 1084 1085 1086 1087 1088
	Node	   *node;
	char	   *exprstr;
	int			i;

	/* No work if empty qual */
	if (qual == NIL)
		return;

1089 1090
	/* Convert AND list to explicit AND */
	node = (Node *) make_ands_explicit(qual);
1091

1092 1093 1094
	/* Set up deparsing context */
	context = deparse_context_for_plan((Node *) outer_plan,
									   (Node *) inner_plan,
1095
									   es->rtable);
1096
	useprefix = (outer_plan != NULL || inner_plan != NULL);
1097 1098

	/* Deparse the expression */
1099
	exprstr = deparse_expression(node, context, useprefix, false);
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110

	/* And add to str */
	for (i = 0; i < indent; i++)
		appendStringInfo(str, "  ");
	appendStringInfo(str, "  %s: %s\n", qlabel, exprstr);
}

/*
 * Show a qualifier expression for an upper-level plan node
 */
static void
1111
show_upper_qual(List *qual, const char *qlabel, Plan *plan,
1112 1113 1114
				StringInfo str, int indent, ExplainState *es)
{
	List	   *context;
1115
	bool		useprefix;
1116 1117 1118 1119 1120 1121 1122 1123
	Node	   *node;
	char	   *exprstr;
	int			i;

	/* No work if empty qual */
	if (qual == NIL)
		return;

1124 1125 1126
	/* Set up deparsing context */
	context = deparse_context_for_plan((Node *) outerPlan(plan),
									   (Node *) innerPlan(plan),
1127
									   es->rtable);
1128
	useprefix = list_length(es->rtable) > 1;
1129 1130 1131

	/* Deparse the expression */
	node = (Node *) make_ands_explicit(qual);
1132
	exprstr = deparse_expression(node, context, useprefix, false);
1133 1134 1135 1136 1137 1138 1139

	/* And add to str */
	for (i = 0; i < indent; i++)
		appendStringInfo(str, "  ");
	appendStringInfo(str, "  %s: %s\n", qlabel, exprstr);
}

1140 1141 1142 1143
/*
 * Show the sort keys for a Sort node.
 */
static void
1144
show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
1145
			   const char *qlabel,
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
			   StringInfo str, int indent, ExplainState *es)
{
	List	   *context;
	bool		useprefix;
	int			keyno;
	char	   *exprstr;
	int			i;

	if (nkeys <= 0)
		return;

	for (i = 0; i < indent; i++)
		appendStringInfo(str, "  ");
	appendStringInfo(str, "  %s: ", qlabel);

1161 1162
	/* Set up deparsing context */
	context = deparse_context_for_plan((Node *) outerPlan(sortplan),
B
Bruce Momjian 已提交
1163
									   NULL,	/* Sort has no innerPlan */
1164 1165
									   es->rtable);
	useprefix = list_length(es->rtable) > 1;
1166

1167
	for (keyno = 0; keyno < nkeys; keyno++)
1168 1169
	{
		/* find key expression in tlist */
1170
		AttrNumber	keyresno = keycols[keyno];
1171
		TargetEntry *target = get_tle_by_resno(sortplan->targetlist, keyresno);
1172

1173
		if (!target)
1174
			elog(ERROR, "no tlist entry for key %d", keyresno);
1175 1176 1177 1178 1179 1180
		/* Deparse the expression, showing any top-level cast */
		exprstr = deparse_expression((Node *) target->expr, context,
									 useprefix, true);
		/* And add to str */
		if (keyno > 0)
			appendStringInfo(str, ", ");
N
Neil Conway 已提交
1181
		appendStringInfoString(str, exprstr);
1182 1183 1184 1185
	}

	appendStringInfo(str, "\n");
}
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207

/*
 * If it's EXPLAIN ANALYZE, show tuplesort explain info for a sort node
 */
static void
show_sort_info(SortState *sortstate,
			   StringInfo str, int indent, ExplainState *es)
{
	Assert(IsA(sortstate, SortState));
	if (es->printAnalyze && sortstate->sort_Done &&
		sortstate->tuplesortstate != NULL)
	{
		char	   *sortinfo;
		int			i;

		sortinfo = tuplesort_explain((Tuplesortstate *) sortstate->tuplesortstate);
		for (i = 0; i < indent; i++)
			appendStringInfo(str, "  ");
		appendStringInfo(str, "  %s\n", sortinfo);
		pfree(sortinfo);
	}
}
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217

/*
 * Fetch the name of an index in an EXPLAIN
 *
 * We allow plugins to get control here so that plans involving hypothetical
 * indexes can be explained.
 */
static const char *
explain_get_index_name(Oid indexId)
{
B
Bruce Momjian 已提交
1218
	const char *result;
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233

	if (explain_get_index_name_hook)
		result = (*explain_get_index_name_hook) (indexId);
	else
		result = NULL;
	if (result == NULL)
	{
		/* default behavior: look in the catalogs and quote it */
		result = get_rel_name(indexId);
		if (result == NULL)
			elog(ERROR, "cache lookup failed for index %u", indexId);
		result = quote_identifier(result);
	}
	return result;
}