Skip to content

Commit c65bc2e

Browse files
committed
Make it possible for loadable modules to add EXPLAIN options.
Modules can use RegisterExtensionExplainOption to register new EXPLAIN options, and GetExplainExtensionId, GetExplainExtensionState, and SetExplainExtensionState to store related state inside the ExplainState object. Since this substantially increases the amount of code that needs to handle ExplainState-related tasks, move a few bits of existing code to a new file explain_state.c and add the rest of this infrastructure there. See the comments at the top of explain_state.c for further explanation of how this mechanism works. This does not yet provide a way for such such options to do anything useful. The intention is that we'll add hooks for that purpose in a separate commit. Discussion: http://postgr.es/m/CA+TgmoYSzg58hPuBmei46o8D3SKX+SZoO4K_aGQGwiRzvRApLg@mail.gmail.com Reviewed-by: Srinath Reddy <srinath2133@gmail.com> Reviewed-by: Andrei Lepikhov <lepihov@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Sami Imseih <samimseih@gmail.com>
1 parent 9d6db8b commit c65bc2e

File tree

18 files changed

+503
-209
lines changed

18 files changed

+503
-209
lines changed

contrib/auto_explain/auto_explain.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "access/parallel.h"
1818
#include "commands/explain.h"
1919
#include "commands/explain_format.h"
20+
#include "commands/explain_state.h"
2021
#include "common/pg_prng.h"
2122
#include "executor/instrument.h"
2223
#include "utils/guc.h"

contrib/file_fdw/file_fdw.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
#include "commands/copy.h"
2525
#include "commands/copyfrom_internal.h"
2626
#include "commands/defrem.h"
27-
#include "commands/explain.h"
2827
#include "commands/explain_format.h"
28+
#include "commands/explain_state.h"
2929
#include "commands/vacuum.h"
30+
#include "executor/executor.h"
3031
#include "foreign/fdwapi.h"
3132
#include "foreign/foreign.h"
3233
#include "miscadmin.h"

contrib/postgres_fdw/postgres_fdw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include "access/table.h"
2020
#include "catalog/pg_opfamily.h"
2121
#include "commands/defrem.h"
22-
#include "commands/explain.h"
2322
#include "commands/explain_format.h"
23+
#include "commands/explain_state.h"
2424
#include "executor/execAsync.h"
2525
#include "foreign/fdwapi.h"
2626
#include "funcapi.h"

src/backend/commands/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ OBJS = \
3636
explain.o \
3737
explain_dr.o \
3838
explain_format.o \
39+
explain_state.o \
3940
extension.o \
4041
foreigncmds.o \
4142
functioncmds.o \

src/backend/commands/createas.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include "commands/prepare.h"
3636
#include "commands/tablecmds.h"
3737
#include "commands/view.h"
38+
#include "executor/execdesc.h"
39+
#include "executor/executor.h"
3840
#include "nodes/makefuncs.h"
3941
#include "nodes/nodeFuncs.h"
4042
#include "nodes/queryjumble.h"

src/backend/commands/explain.c

Lines changed: 5 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
#include "catalog/pg_type.h"
1818
#include "commands/createas.h"
1919
#include "commands/defrem.h"
20+
#include "commands/explain.h"
2021
#include "commands/explain_dr.h"
2122
#include "commands/explain_format.h"
23+
#include "commands/explain_state.h"
2224
#include "commands/prepare.h"
2325
#include "foreign/fdwapi.h"
2426
#include "jit/jit.h"
@@ -176,130 +178,11 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
176178
JumbleState *jstate = NULL;
177179
Query *query;
178180
List *rewritten;
179-
ListCell *lc;
180-
bool timing_set = false;
181-
bool buffers_set = false;
182-
bool summary_set = false;
183-
184-
/* Parse options list. */
185-
foreach(lc, stmt->options)
186-
{
187-
DefElem *opt = (DefElem *) lfirst(lc);
188181

189-
if (strcmp(opt->defname, "analyze") == 0)
190-
es->analyze = defGetBoolean(opt);
191-
else if (strcmp(opt->defname, "verbose") == 0)
192-
es->verbose = defGetBoolean(opt);
193-
else if (strcmp(opt->defname, "costs") == 0)
194-
es->costs = defGetBoolean(opt);
195-
else if (strcmp(opt->defname, "buffers") == 0)
196-
{
197-
buffers_set = true;
198-
es->buffers = defGetBoolean(opt);
199-
}
200-
else if (strcmp(opt->defname, "wal") == 0)
201-
es->wal = defGetBoolean(opt);
202-
else if (strcmp(opt->defname, "settings") == 0)
203-
es->settings = defGetBoolean(opt);
204-
else if (strcmp(opt->defname, "generic_plan") == 0)
205-
es->generic = defGetBoolean(opt);
206-
else if (strcmp(opt->defname, "timing") == 0)
207-
{
208-
timing_set = true;
209-
es->timing = defGetBoolean(opt);
210-
}
211-
else if (strcmp(opt->defname, "summary") == 0)
212-
{
213-
summary_set = true;
214-
es->summary = defGetBoolean(opt);
215-
}
216-
else if (strcmp(opt->defname, "memory") == 0)
217-
es->memory = defGetBoolean(opt);
218-
else if (strcmp(opt->defname, "serialize") == 0)
219-
{
220-
if (opt->arg)
221-
{
222-
char *p = defGetString(opt);
223-
224-
if (strcmp(p, "off") == 0 || strcmp(p, "none") == 0)
225-
es->serialize = EXPLAIN_SERIALIZE_NONE;
226-
else if (strcmp(p, "text") == 0)
227-
es->serialize = EXPLAIN_SERIALIZE_TEXT;
228-
else if (strcmp(p, "binary") == 0)
229-
es->serialize = EXPLAIN_SERIALIZE_BINARY;
230-
else
231-
ereport(ERROR,
232-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
233-
errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
234-
opt->defname, p),
235-
parser_errposition(pstate, opt->location)));
236-
}
237-
else
238-
{
239-
/* SERIALIZE without an argument is taken as 'text' */
240-
es->serialize = EXPLAIN_SERIALIZE_TEXT;
241-
}
242-
}
243-
else if (strcmp(opt->defname, "format") == 0)
244-
{
245-
char *p = defGetString(opt);
246-
247-
if (strcmp(p, "text") == 0)
248-
es->format = EXPLAIN_FORMAT_TEXT;
249-
else if (strcmp(p, "xml") == 0)
250-
es->format = EXPLAIN_FORMAT_XML;
251-
else if (strcmp(p, "json") == 0)
252-
es->format = EXPLAIN_FORMAT_JSON;
253-
else if (strcmp(p, "yaml") == 0)
254-
es->format = EXPLAIN_FORMAT_YAML;
255-
else
256-
ereport(ERROR,
257-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
258-
errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"",
259-
opt->defname, p),
260-
parser_errposition(pstate, opt->location)));
261-
}
262-
else
263-
ereport(ERROR,
264-
(errcode(ERRCODE_SYNTAX_ERROR),
265-
errmsg("unrecognized EXPLAIN option \"%s\"",
266-
opt->defname),
267-
parser_errposition(pstate, opt->location)));
268-
}
269-
270-
/* check that WAL is used with EXPLAIN ANALYZE */
271-
if (es->wal && !es->analyze)
272-
ereport(ERROR,
273-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
274-
errmsg("EXPLAIN option %s requires ANALYZE", "WAL")));
275-
276-
/* if the timing was not set explicitly, set default value */
277-
es->timing = (timing_set) ? es->timing : es->analyze;
278-
279-
/* if the buffers was not set explicitly, set default value */
280-
es->buffers = (buffers_set) ? es->buffers : es->analyze;
281-
282-
/* check that timing is used with EXPLAIN ANALYZE */
283-
if (es->timing && !es->analyze)
284-
ereport(ERROR,
285-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
286-
errmsg("EXPLAIN option %s requires ANALYZE", "TIMING")));
287-
288-
/* check that serialize is used with EXPLAIN ANALYZE */
289-
if (es->serialize != EXPLAIN_SERIALIZE_NONE && !es->analyze)
290-
ereport(ERROR,
291-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
292-
errmsg("EXPLAIN option %s requires ANALYZE", "SERIALIZE")));
293-
294-
/* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */
295-
if (es->generic && es->analyze)
296-
ereport(ERROR,
297-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
298-
errmsg("EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together")));
299-
300-
/* if the summary was not set explicitly, set default value */
301-
es->summary = (summary_set) ? es->summary : es->analyze;
182+
/* Configure the ExplainState based on the provided options */
183+
ParseExplainOptionList(es, stmt->options, pstate);
302184

185+
/* Extract the query and, if enabled, jumble it */
303186
query = castNode(Query, stmt->query);
304187
if (IsQueryIdEnabled())
305188
jstate = JumbleQuery(query);
@@ -360,22 +243,6 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
360243
pfree(es->str->data);
361244
}
362245

363-
/*
364-
* Create a new ExplainState struct initialized with default options.
365-
*/
366-
ExplainState *
367-
NewExplainState(void)
368-
{
369-
ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
370-
371-
/* Set default options (most fields can be left as zeroes). */
372-
es->costs = true;
373-
/* Prepare output buffer. */
374-
es->str = makeStringInfo();
375-
376-
return es;
377-
}
378-
379246
/*
380247
* ExplainResultDesc -
381248
* construct the result tupledesc for an EXPLAIN

src/backend/commands/explain_dr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "commands/explain.h"
1717
#include "commands/explain_dr.h"
18+
#include "commands/explain_state.h"
1819
#include "libpq/pqformat.h"
1920
#include "libpq/protocol.h"
2021
#include "utils/lsyscache.h"

src/backend/commands/explain_format.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "commands/explain.h"
1717
#include "commands/explain_format.h"
18+
#include "commands/explain_state.h"
1819
#include "utils/json.h"
1920
#include "utils/xml.h"
2021

0 commit comments

Comments
 (0)