From be95e9296a95eb5e6f19fe4aacd4df4ebc3fe533 Mon Sep 17 00:00:00 2001
From: David Fetter <david@fetter.org>
Date: Sat, 18 May 2019 10:22:33 -0700
Subject: [PATCH v5 1/8] Changed EXPLAIN ANALYZE to EXPLAIN (EXEC)
To: hackers
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.21.0"

This is a multi-part message in MIME format.
--------------2.21.0
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit


diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index a6c6de78f1..8088926174 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -155,8 +155,8 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
 	{
 		DefElem    *opt = (DefElem *) lfirst(lc);
 
-		if (strcmp(opt->defname, "analyze") == 0)
-			es->analyze = defGetBoolean(opt);
+		if (strcmp(opt->defname, "exec") == 0)
+			es->exec = defGetBoolean(opt);
 		else if (strcmp(opt->defname, "verbose") == 0)
 			es->verbose = defGetBoolean(opt);
 		else if (strcmp(opt->defname, "costs") == 0)
@@ -202,22 +202,22 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
 					 parser_errposition(pstate, opt->location)));
 	}
 
-	if (es->buffers && !es->analyze)
+	if (es->buffers && !es->exec)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
+				 errmsg("EXPLAIN option BUFFERS requires EXEC")));
 
 	/* if the timing was not set explicitly, set default value */
-	es->timing = (timing_set) ? es->timing : es->analyze;
+	es->timing = (timing_set) ? es->timing : es->exec;
 
-	/* check that timing is used with EXPLAIN ANALYZE */
-	if (es->timing && !es->analyze)
+	/* check that timing is used with EXPLAIN EXEC */
+	if (es->timing && !es->exec)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("EXPLAIN option TIMING requires ANALYZE")));
+				 errmsg("EXPLAIN option TIMING requires EXEC")));
 
 	/* if the summary was not set explicitly, set default value */
-	es->summary = (summary_set) ? es->summary : es->analyze;
+	es->summary = (summary_set) ? es->summary : es->exec;
 
 	/*
 	 * Parse analysis was done already, but we still have to run the rule
@@ -475,9 +475,9 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
 
 	Assert(plannedstmt->commandType != CMD_UTILITY);
 
-	if (es->analyze && es->timing)
+	if (es->exec && es->timing)
 		instrument_option |= INSTRUMENT_TIMER;
-	else if (es->analyze)
+	else if (es->exec)
 		instrument_option |= INSTRUMENT_ROWS;
 
 	if (es->buffers)
@@ -512,7 +512,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
 								dest, params, queryEnv, instrument_option);
 
 	/* Select execution options */
-	if (es->analyze)
+	if (es->exec)
 		eflags = 0;				/* default run-to-completion flags */
 	else
 		eflags = EXEC_FLAG_EXPLAIN_ONLY;
@@ -523,7 +523,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
 	ExecutorStart(queryDesc, eflags);
 
 	/* Execute the plan for statistics if asked for */
-	if (es->analyze)
+	if (es->exec)
 	{
 		ScanDirection dir;
 
@@ -556,7 +556,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
 	}
 
 	/* Print info about runtime of triggers */
-	if (es->analyze)
+	if (es->exec)
 		ExplainPrintTriggers(es, queryDesc);
 
 	/*
@@ -581,7 +581,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
 	PopActiveSnapshot();
 
 	/* We need a CCI just in case query expanded to multiple plans */
-	if (es->analyze)
+	if (es->exec)
 		CommandCounterIncrement();
 
 	totaltime += elapsed_time(&starttime);
@@ -592,7 +592,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
 	 * user can set SUMMARY OFF to not have the timing information included in
 	 * the output).  By default, ANALYZE sets SUMMARY to true.
 	 */
-	if (es->summary && es->analyze)
+	if (es->summary && es->exec)
 		ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
 							 es);
 
@@ -834,7 +834,7 @@ ExplainPrintJIT(ExplainState *es, int jit_flags,
 						 "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false",
 						 "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false");
 
-		if (es->analyze && es->timing)
+		if (es->exec && es->timing)
 		{
 			appendStringInfoSpaces(es->str, es->indent * 2);
 			appendStringInfo(es->str,
@@ -860,7 +860,7 @@ ExplainPrintJIT(ExplainState *es, int jit_flags,
 		ExplainPropertyBool("Deforming", jit_flags & PGJIT_DEFORM, es);
 		ExplainCloseGroup("Options", "Options", true, es);
 
-		if (es->analyze && es->timing)
+		if (es->exec && es->timing)
 		{
 			ExplainOpenGroup("Timing", "Timing", true, es);
 
@@ -1505,7 +1505,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 	if (planstate->instrument)
 		InstrEndLoop(planstate->instrument);
 
-	if (es->analyze &&
+	if (es->exec &&
 		planstate->instrument && planstate->instrument->nloops > 0)
 	{
 		double		nloops = planstate->instrument->nloops;
@@ -1537,7 +1537,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
 		}
 	}
-	else if (es->analyze)
+	else if (es->exec)
 	{
 		if (es->format == EXPLAIN_FORMAT_TEXT)
 			appendStringInfoString(es->str, " (never executed)");
@@ -1606,7 +1606,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			if (plan->qual)
 				show_instrumentation_count("Rows Removed by Filter", 1,
 										   planstate, es);
-			if (es->analyze)
+			if (es->exec)
 				ExplainPropertyFloat("Heap Fetches", NULL,
 									 planstate->instrument->ntuples2, 0, es);
 			break;
@@ -1624,7 +1624,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			if (plan->qual)
 				show_instrumentation_count("Rows Removed by Filter", 1,
 										   planstate, es);
-			if (es->analyze)
+			if (es->exec)
 				show_tidbitmap_info((BitmapHeapScanState *) planstate, es);
 			break;
 		case T_SampleScan:
@@ -1658,7 +1658,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 				if (gather->initParam)
 					show_eval_params(gather->initParam, es);
 
-				if (es->analyze)
+				if (es->exec)
 				{
 					int			nworkers;
 
@@ -1704,7 +1704,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 				if (gm->initParam)
 					show_eval_params(gm->initParam, es);
 
-				if (es->analyze)
+				if (es->exec)
 				{
 					int			nworkers;
 
@@ -1869,7 +1869,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		show_buffer_usage(es, &planstate->instrument->bufusage);
 
 	/* Show worker detail */
-	if (es->analyze && es->verbose && planstate->worker_instrument)
+	if (es->exec && es->verbose && planstate->worker_instrument)
 	{
 		WorkerInstrumentation *w = planstate->worker_instrument;
 		bool		opened_group = false;
@@ -2531,12 +2531,12 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate,
 }
 
 /*
- * If it's EXPLAIN ANALYZE, show tuplesort stats for a sort node
+ * If it's EXPLAIN (EXEC), show tuplesort stats for a sort node
  */
 static void
 show_sort_info(SortState *sortstate, ExplainState *es)
 {
-	if (!es->analyze)
+	if (!es->exec)
 		return;
 
 	if (sortstate->sort_Done && sortstate->tuplesortstate != NULL)
@@ -2716,7 +2716,7 @@ show_hash_info(HashState *hashstate, ExplainState *es)
 }
 
 /*
- * If it's EXPLAIN ANALYZE, show exact/lossy pages for a BitmapHeapScan node
+ * If it's EXPLAIN (EXEC), show exact/lossy pages for a BitmapHeapScan node
  */
 static void
 show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)
@@ -2744,7 +2744,7 @@ show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)
 }
 
 /*
- * If it's EXPLAIN ANALYZE, show instrumentation information for a plan node
+ * If it's EXPLAIN (EXEC), show instrumentation information for a plan node
  *
  * "which" identifies which instrumentation counter to print
  */
@@ -2755,7 +2755,7 @@ show_instrumentation_count(const char *qlabel, int which,
 	double		nfiltered;
 	double		nloops;
 
-	if (!es->analyze || !planstate->instrument)
+	if (!es->exec || !planstate->instrument)
 		return;
 
 	if (which == 2)
@@ -3283,8 +3283,8 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
 			show_instrumentation_count("Rows Removed by Conflict Filter", 1, &mtstate->ps, es);
 		}
 
-		/* EXPLAIN ANALYZE display of actual outcome for each tuple proposed */
-		if (es->analyze && mtstate->ps.instrument)
+		/* EXPLAIN (EXEC) display of actual outcome for each tuple proposed */
+		if (es->exec && mtstate->ps.instrument)
 		{
 			double		total;
 			double		insert_path;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 3dc0e8a4fb..06f1cceb37 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -10632,8 +10632,9 @@ opt_vacuum_relation_list:
 /*****************************************************************************
  *
  *		QUERY:
- *				EXPLAIN [ANALYZE] [VERBOSE] query
  *				EXPLAIN ( options ) query
+ *      Legacy syntax:
+ *				EXPLAIN [ANALYZE] [VERBOSE] query
  *
  *****************************************************************************/
 
@@ -10645,11 +10646,11 @@ ExplainStmt:
 					n->options = NIL;
 					$$ = (Node *) n;
 				}
-		| EXPLAIN analyze_keyword opt_verbose ExplainableStmt
+		| EXPLAIN exec_keyword opt_verbose ExplainableStmt
 				{
 					ExplainStmt *n = makeNode(ExplainStmt);
 					n->query = $4;
-					n->options = list_make1(makeDefElem("analyze", NULL, @2));
+					n->options = list_make1(makeDefElem("exec", NULL, @2));
 					if ($3)
 						n->options = lappend(n->options,
 											 makeDefElem("verbose", NULL, @3));
@@ -10703,7 +10704,7 @@ explain_option_elem:
 
 explain_option_name:
 			NonReservedWord			{ $$ = $1; }
-			| analyze_keyword		{ $$ = "analyze"; }
+			| exec_keyword			{ $$ = "exec"; }
 		;
 
 explain_option_arg:
@@ -10712,6 +10713,11 @@ explain_option_arg:
 			| /* EMPTY */			{ $$ = NULL; }
 		;
 
+exec_keyword:
+			ANALYZE /* Legacy */					{}
+			| ANALYSE /* British and legacy */		{}
+		;
+
 /*****************************************************************************
  *
  *		QUERY:
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index db48f29501..09cc806d7e 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -30,8 +30,8 @@ typedef struct ExplainState
 	StringInfo	str;			/* output buffer */
 	/* options */
 	bool		verbose;		/* be verbose */
-	bool		analyze;		/* print actual times */
 	bool		costs;			/* print estimated costs */
+	bool		exec;			/* actually execute the query, measure it */
 	bool		buffers;		/* print buffer usage */
 	bool		timing;			/* print detailed node timing */
 	bool		summary;		/* print total planning and execution timing */

--------------2.21.0--


