Skip to content

Commit cd35e9d

Browse files
committed
Some infrastructure changes for the upcoming auto-explain contrib module:
* Refactor explain.c slightly to export a convenient-to-use subroutine for printing EXPLAIN results. * Provide hooks for plugins to get control at ExecutorStart and ExecutorEnd as well as ExecutorRun. * Add some minimal support for tracking the total runtime of ExecutorRun. This code won't actually do anything unless a plugin prods it to. * Change the API of the DefineCustomXXXVariable functions to allow nonzero "flags" to be specified for a custom GUC variable. While at it, also make the "bootstrap" default value for custom GUCs be explicitly specified as a parameter to these functions. This is to eliminate confusion over where the default comes from, as has been expressed in the past by some users of the custom-variable facility. * Refactor GUC code a bit to ensure that a custom variable gets initialized to something valid (like its default value) even if the placeholder value was invalid.
1 parent 667685c commit cd35e9d

File tree

10 files changed

+293
-170
lines changed

10 files changed

+293
-170
lines changed

src/backend/commands/explain.c

Lines changed: 32 additions & 14 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.180 2008/10/06 20:29:38 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.181 2008/11/19 01:10:23 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -224,7 +224,6 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
224224
QueryDesc *queryDesc;
225225
instr_time starttime;
226226
double totaltime = 0;
227-
ExplainState *es;
228227
StringInfoData buf;
229228
int eflags;
230229

@@ -265,17 +264,9 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
265264
totaltime += elapsed_time(&starttime);
266265
}
267266

268-
es = (ExplainState *) palloc0(sizeof(ExplainState));
269-
270-
es->printTList = stmt->verbose;
271-
es->printAnalyze = stmt->analyze;
272-
es->pstmt = queryDesc->plannedstmt;
273-
es->rtable = queryDesc->plannedstmt->rtable;
274-
267+
/* Create textual dump of plan tree */
275268
initStringInfo(&buf);
276-
explain_outNode(&buf,
277-
queryDesc->plannedstmt->planTree, queryDesc->planstate,
278-
NULL, 0, es);
269+
ExplainPrintPlan(&buf, queryDesc, stmt->analyze, stmt->verbose);
279270

280271
/*
281272
* If we ran the command, run any AFTER triggers it queued. (Note this
@@ -290,7 +281,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
290281
}
291282

292283
/* Print info about runtime of triggers */
293-
if (es->printAnalyze)
284+
if (stmt->analyze)
294285
{
295286
ResultRelInfo *rInfo;
296287
bool show_relname;
@@ -335,7 +326,34 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
335326
do_text_output_multiline(tstate, buf.data);
336327

337328
pfree(buf.data);
338-
pfree(es);
329+
}
330+
331+
/*
332+
* ExplainPrintPlan -
333+
* convert a QueryDesc's plan tree to text and append it to 'str'
334+
*
335+
* 'analyze' means to include runtime instrumentation results
336+
* 'verbose' means a verbose printout (currently, it shows targetlists)
337+
*
338+
* NB: will not work on utility statements
339+
*/
340+
void
341+
ExplainPrintPlan(StringInfo str, QueryDesc *queryDesc,
342+
bool analyze, bool verbose)
343+
{
344+
ExplainState es;
345+
346+
Assert(queryDesc->plannedstmt != NULL);
347+
348+
memset(&es, 0, sizeof(es));
349+
es.printTList = verbose;
350+
es.printAnalyze = analyze;
351+
es.pstmt = queryDesc->plannedstmt;
352+
es.rtable = queryDesc->plannedstmt->rtable;
353+
354+
explain_outNode(str,
355+
queryDesc->plannedstmt->planTree, queryDesc->planstate,
356+
NULL, 0, &es);
339357
}
340358

341359
/*

src/backend/executor/execMain.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.317 2008/11/16 17:34:28 tgl Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.318 2008/11/19 01:10:23 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -60,8 +60,10 @@
6060
#include "utils/tqual.h"
6161

6262

63-
/* Hook for plugins to get control in ExecutorRun() */
64-
ExecutorRun_hook_type ExecutorRun_hook = NULL;
63+
/* Hooks for plugins to get control in ExecutorStart/Run/End() */
64+
ExecutorStart_hook_type ExecutorStart_hook = NULL;
65+
ExecutorRun_hook_type ExecutorRun_hook = NULL;
66+
ExecutorEnd_hook_type ExecutorEnd_hook = NULL;
6567

6668
typedef struct evalPlanQual
6769
{
@@ -129,10 +131,24 @@ static void intorel_destroy(DestReceiver *self);
129131
*
130132
* NB: the CurrentMemoryContext when this is called will become the parent
131133
* of the per-query context used for this Executor invocation.
134+
*
135+
* We provide a function hook variable that lets loadable plugins
136+
* get control when ExecutorStart is called. Such a plugin would
137+
* normally call standard_ExecutorStart().
138+
*
132139
* ----------------------------------------------------------------
133140
*/
134141
void
135142
ExecutorStart(QueryDesc *queryDesc, int eflags)
143+
{
144+
if (ExecutorStart_hook)
145+
(*ExecutorStart_hook) (queryDesc, eflags);
146+
else
147+
standard_ExecutorStart(queryDesc, eflags);
148+
}
149+
150+
void
151+
standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
136152
{
137153
EState *estate;
138154
MemoryContext oldcontext;
@@ -263,6 +279,10 @@ standard_ExecutorRun(QueryDesc *queryDesc,
263279
*/
264280
oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
265281

282+
/* Allow instrumentation of ExecutorRun overall runtime */
283+
if (queryDesc->totaltime)
284+
InstrStartNode(queryDesc->totaltime);
285+
266286
/*
267287
* extract information from the query descriptor and the query feature.
268288
*/
@@ -298,6 +318,9 @@ standard_ExecutorRun(QueryDesc *queryDesc,
298318
if (sendTuples)
299319
(*dest->rShutdown) (dest);
300320

321+
if (queryDesc->totaltime)
322+
InstrStopNode(queryDesc->totaltime, estate->es_processed);
323+
301324
MemoryContextSwitchTo(oldcontext);
302325
}
303326

@@ -306,10 +329,24 @@ standard_ExecutorRun(QueryDesc *queryDesc,
306329
*
307330
* This routine must be called at the end of execution of any
308331
* query plan
332+
*
333+
* We provide a function hook variable that lets loadable plugins
334+
* get control when ExecutorEnd is called. Such a plugin would
335+
* normally call standard_ExecutorEnd().
336+
*
309337
* ----------------------------------------------------------------
310338
*/
311339
void
312340
ExecutorEnd(QueryDesc *queryDesc)
341+
{
342+
if (ExecutorEnd_hook)
343+
(*ExecutorEnd_hook) (queryDesc);
344+
else
345+
standard_ExecutorEnd(queryDesc);
346+
}
347+
348+
void
349+
standard_ExecutorEnd(QueryDesc *queryDesc)
313350
{
314351
EState *estate;
315352
MemoryContext oldcontext;
@@ -353,6 +390,7 @@ ExecutorEnd(QueryDesc *queryDesc)
353390
queryDesc->tupDesc = NULL;
354391
queryDesc->estate = NULL;
355392
queryDesc->planstate = NULL;
393+
queryDesc->totaltime = NULL;
356394
}
357395

358396
/* ----------------------------------------------------------------

src/backend/tcop/pquery.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.124 2008/08/01 13:16:09 alvherre Exp $
11+
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.125 2008/11/19 01:10:23 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -82,6 +82,7 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
8282
qd->tupDesc = NULL;
8383
qd->estate = NULL;
8484
qd->planstate = NULL;
85+
qd->totaltime = NULL;
8586

8687
return qd;
8788
}
@@ -110,6 +111,7 @@ CreateUtilityQueryDesc(Node *utilitystmt,
110111
qd->tupDesc = NULL;
111112
qd->estate = NULL;
112113
qd->planstate = NULL;
114+
qd->totaltime = NULL;
113115

114116
return qd;
115117
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy