PostgreSQL Source Code git master
Loading...
Searching...
No Matches
explain_state.c File Reference
#include "postgres.h"
#include "commands/defrem.h"
#include "commands/explain.h"
#include "commands/explain_state.h"
#include "utils/builtins.h"
#include "utils/guc.h"
Include dependency graph for explain_state.c:

Go to the source code of this file.

Data Structures

struct  ExplainExtensionOption
 

Functions

ExplainStateNewExplainState (void)
 
void ParseExplainOptionList (ExplainState *es, List *options, ParseState *pstate)
 
int GetExplainExtensionId (const char *extension_name)
 
voidGetExplainExtensionState (ExplainState *es, int extension_id)
 
void SetExplainExtensionState (ExplainState *es, int extension_id, void *opaque)
 
void RegisterExtensionExplainOption (const char *option_name, ExplainOptionHandler handler, ExplainOptionGUCCheckHandler guc_check_handler)
 
bool ApplyExtensionExplainOption (ExplainState *es, DefElem *opt, ParseState *pstate)
 
bool GUCCheckExplainExtensionOption (const char *option_name, const char *option_value, NodeTag option_type)
 
bool GUCCheckBooleanExplainOption (const char *option_name, const char *option_value, NodeTag option_type)
 

Variables

explain_validate_options_hook_type explain_validate_options_hook = NULL
 
static const char ** ExplainExtensionNameArray = NULL
 
static int ExplainExtensionNamesAssigned = 0
 
static int ExplainExtensionNamesAllocated = 0
 
static ExplainExtensionOptionExplainExtensionOptionArray = NULL
 
static int ExplainExtensionOptionsAssigned = 0
 
static int ExplainExtensionOptionsAllocated = 0
 

Function Documentation

◆ ApplyExtensionExplainOption()

bool ApplyExtensionExplainOption ( ExplainState es,
DefElem opt,
ParseState pstate 
)

Definition at line 389 of file explain_state.c.

390{
391 for (int i = 0; i < ExplainExtensionOptionsAssigned; ++i)
392 {
393 if (strcmp(ExplainExtensionOptionArray[i].option_name,
394 opt->defname) == 0)
395 {
397 return true;
398 }
399 }
400
401 return false;
402}
static ExplainExtensionOption * ExplainExtensionOptionArray
static int ExplainExtensionOptionsAssigned
int i
Definition isn.c:77
static int fb(int x)
char * defname
Definition parsenodes.h:860
ExplainOptionHandler option_handler

References DefElem::defname, ExplainExtensionOptionArray, ExplainExtensionOptionsAssigned, fb(), i, and ExplainExtensionOption::option_handler.

Referenced by apply_extension_options(), and ParseExplainOptionList().

◆ GetExplainExtensionId()

int GetExplainExtensionId ( const char extension_name)

Definition at line 232 of file explain_state.c.

233{
234 /* Search for an existing extension by this name; if found, return ID. */
235 for (int i = 0; i < ExplainExtensionNamesAssigned; ++i)
237 return i;
238
239 /* If there is no array yet, create one. */
241 {
243 ExplainExtensionNameArray = (const char **)
246 * sizeof(char *));
247 }
248
249 /* If there's an array but it's currently full, expand it. */
251 {
253
254 ExplainExtensionNameArray = (const char **)
255 repalloc(ExplainExtensionNameArray, i * sizeof(char *));
257 }
258
259 /* Assign and return new ID. */
262}
static const char ** ExplainExtensionNameArray
static int ExplainExtensionNamesAssigned
static int ExplainExtensionNamesAllocated
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
MemoryContext TopMemoryContext
Definition mcxt.c:166
static uint32 pg_nextpower2_32(uint32 num)

References ExplainExtensionNameArray, ExplainExtensionNamesAllocated, ExplainExtensionNamesAssigned, fb(), i, MemoryContextAlloc(), pg_nextpower2_32(), repalloc(), and TopMemoryContext.

Referenced by _PG_init().

◆ GetExplainExtensionState()

void * GetExplainExtensionState ( ExplainState es,
int  extension_id 
)

◆ GUCCheckBooleanExplainOption()

bool GUCCheckBooleanExplainOption ( const char option_name,
const char option_value,
NodeTag  option_type 
)

Definition at line 454 of file explain_state.c.

457{
458 bool valid = false;
459
460 if (option_value == NULL)
461 {
462 /* defGetBoolean treats no argument as valid */
463 valid = true;
464 }
465 else if (option_type == T_String)
466 {
467 /* defGetBoolean accepts exactly these string values */
468 if (pg_strcasecmp(option_value, "true") == 0 ||
469 pg_strcasecmp(option_value, "false") == 0 ||
470 pg_strcasecmp(option_value, "on") == 0 ||
471 pg_strcasecmp(option_value, "off") == 0)
472 valid = true;
473 }
474 else if (option_type == T_Integer)
475 {
476 long value;
477 char *end;
478
479 /*
480 * defGetBoolean accepts only 0 and 1, but those can be spelled in
481 * various ways (e.g. 01, 0x01).
482 */
483 errno = 0;
484 value = strtol(option_value, &end, 0);
485 if (errno == 0 && *end == '\0' && end != option_value &&
486 value == (int) value && (value == 0 || value == 1))
487 valid = true;
488 }
489
490 if (!valid)
491 {
492 GUC_check_errmsg("EXPLAIN option \"%s\" requires a Boolean value",
493 option_name);
494 return false;
495 }
496
497 return true;
498}
#define GUC_check_errmsg
Definition guc.h:503
static struct @177 value
int pg_strcasecmp(const char *s1, const char *s2)
static enum slash_option_type option_type

References fb(), GUC_check_errmsg, option_type, pg_strcasecmp(), and value.

Referenced by _PG_init().

◆ GUCCheckExplainExtensionOption()

bool GUCCheckExplainExtensionOption ( const char option_name,
const char option_value,
NodeTag  option_type 
)

Definition at line 413 of file explain_state.c.

416{
417 for (int i = 0; i < ExplainExtensionOptionsAssigned; i++)
418 {
420
421 if (strcmp(exopt->option_name, option_name) == 0)
422 return exopt->guc_check_handler(option_name, option_value,
424 }
425
426 /* Unrecognized option name. */
427 GUC_check_errmsg("unrecognized EXPLAIN option \"%s\"", option_name);
428 return false;
429}
ExplainOptionGUCCheckHandler guc_check_handler

References ExplainExtensionOptionArray, ExplainExtensionOptionsAssigned, fb(), GUC_check_errmsg, ExplainExtensionOption::guc_check_handler, i, and option_type.

Referenced by check_log_extension_options().

◆ NewExplainState()

ExplainState * NewExplainState ( void  )

Definition at line 64 of file explain_state.c.

65{
67
68 /* Set default options (most fields can be left as zeroes). */
69 es->costs = true;
70 /* Prepare output buffer. */
71 es->str = makeStringInfo();
72
73 return es;
74}
#define palloc0_object(type)
Definition fe_memutils.h:75
StringInfo makeStringInfo(void)
Definition stringinfo.c:72
StringInfo str

References ExplainState::costs, makeStringInfo(), palloc0_object, and ExplainState::str.

Referenced by explain_ExecutorEnd(), and ExplainQuery().

◆ ParseExplainOptionList()

void ParseExplainOptionList ( ExplainState es,
List options,
ParseState pstate 
)

Definition at line 80 of file explain_state.c.

81{
82 ListCell *lc;
83 bool timing_set = false;
84 bool buffers_set = false;
85 bool summary_set = false;
86
87 /* Parse options list. */
88 foreach(lc, options)
89 {
90 DefElem *opt = (DefElem *) lfirst(lc);
91
92 if (strcmp(opt->defname, "analyze") == 0)
93 es->analyze = defGetBoolean(opt);
94 else if (strcmp(opt->defname, "verbose") == 0)
95 es->verbose = defGetBoolean(opt);
96 else if (strcmp(opt->defname, "costs") == 0)
97 es->costs = defGetBoolean(opt);
98 else if (strcmp(opt->defname, "buffers") == 0)
99 {
100 buffers_set = true;
101 es->buffers = defGetBoolean(opt);
102 }
103 else if (strcmp(opt->defname, "wal") == 0)
104 es->wal = defGetBoolean(opt);
105 else if (strcmp(opt->defname, "settings") == 0)
106 es->settings = defGetBoolean(opt);
107 else if (strcmp(opt->defname, "generic_plan") == 0)
108 es->generic = defGetBoolean(opt);
109 else if (strcmp(opt->defname, "timing") == 0)
110 {
111 timing_set = true;
112 es->timing = defGetBoolean(opt);
113 }
114 else if (strcmp(opt->defname, "summary") == 0)
115 {
116 summary_set = true;
117 es->summary = defGetBoolean(opt);
118 }
119 else if (strcmp(opt->defname, "memory") == 0)
120 es->memory = defGetBoolean(opt);
121 else if (strcmp(opt->defname, "serialize") == 0)
122 {
123 if (opt->arg)
124 {
125 char *p = defGetString(opt);
126
127 if (strcmp(p, "off") == 0 || strcmp(p, "none") == 0)
129 else if (strcmp(p, "text") == 0)
131 else if (strcmp(p, "binary") == 0)
133 else
136 errmsg("unrecognized value for %s option \"%s\": \"%s\"",
137 "EXPLAIN", opt->defname, p),
138 parser_errposition(pstate, opt->location)));
139 }
140 else
141 {
142 /* SERIALIZE without an argument is taken as 'text' */
144 }
145 }
146 else if (strcmp(opt->defname, "format") == 0)
147 {
148 char *p = defGetString(opt);
149
150 if (strcmp(p, "text") == 0)
152 else if (strcmp(p, "xml") == 0)
154 else if (strcmp(p, "json") == 0)
156 else if (strcmp(p, "yaml") == 0)
158 else
161 errmsg("unrecognized value for %s option \"%s\": \"%s\"",
162 "EXPLAIN", opt->defname, p),
163 parser_errposition(pstate, opt->location)));
164 }
165 else if (strcmp(opt->defname, "io") == 0)
166 es->io = defGetBoolean(opt);
167 else if (!ApplyExtensionExplainOption(es, opt, pstate))
170 errmsg("unrecognized %s option \"%s\"",
171 "EXPLAIN", opt->defname),
172 parser_errposition(pstate, opt->location)));
173 }
174
175 /* check that WAL is used with EXPLAIN ANALYZE */
176 if (es->wal && !es->analyze)
179 errmsg("EXPLAIN option %s requires ANALYZE", "WAL")));
180
181 /* if the timing was not set explicitly, set default value */
182 es->timing = (timing_set) ? es->timing : es->analyze;
183
184 /* if the buffers was not set explicitly, set default value */
185 es->buffers = (buffers_set) ? es->buffers : es->analyze;
186
187 /* check that timing is used with EXPLAIN ANALYZE */
188 if (es->timing && !es->analyze)
191 errmsg("EXPLAIN option %s requires ANALYZE", "TIMING")));
192
193 /* check that IO is used with EXPLAIN ANALYZE */
194 if (es->io && !es->analyze)
197 errmsg("EXPLAIN option %s requires ANALYZE", "IO")));
198
199 /* check that serialize is used with EXPLAIN ANALYZE */
200 if (es->serialize != EXPLAIN_SERIALIZE_NONE && !es->analyze)
203 errmsg("EXPLAIN option %s requires ANALYZE", "SERIALIZE")));
204
205 /* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */
206 if (es->generic && es->analyze)
209 errmsg("%s options %s and %s cannot be used together",
210 "EXPLAIN", "ANALYZE", "GENERIC_PLAN")));
211
212 /* if the summary was not set explicitly, set default value */
213 es->summary = (summary_set) ? es->summary : es->analyze;
214
215 /* plugin specific option validation */
217 (*explain_validate_options_hook) (es, options, pstate);
218}
char * defGetString(DefElem *def)
Definition define.c:34
bool defGetBoolean(DefElem *def)
Definition define.c:93
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
explain_validate_options_hook_type explain_validate_options_hook
bool ApplyExtensionExplainOption(ExplainState *es, DefElem *opt, ParseState *pstate)
@ EXPLAIN_SERIALIZE_TEXT
@ EXPLAIN_SERIALIZE_NONE
@ EXPLAIN_SERIALIZE_BINARY
@ EXPLAIN_FORMAT_XML
@ EXPLAIN_FORMAT_YAML
@ EXPLAIN_FORMAT_TEXT
@ EXPLAIN_FORMAT_JSON
static char * errmsg
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
#define lfirst(lc)
Definition pg_list.h:172
static long analyze(struct nfa *nfa)
Definition regc_nfa.c:3051
ParseLoc location
Definition parsenodes.h:864
Node * arg
Definition parsenodes.h:861
ExplainFormat format
ExplainSerializeOption serialize

References ExplainState::analyze, ApplyExtensionExplainOption(), DefElem::arg, ExplainState::buffers, ExplainState::costs, defGetBoolean(), defGetString(), DefElem::defname, ereport, errcode(), errmsg, ERROR, EXPLAIN_FORMAT_JSON, EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, EXPLAIN_FORMAT_YAML, EXPLAIN_SERIALIZE_BINARY, EXPLAIN_SERIALIZE_NONE, EXPLAIN_SERIALIZE_TEXT, explain_validate_options_hook, fb(), ExplainState::format, ExplainState::generic, ExplainState::io, lfirst, DefElem::location, ExplainState::memory, parser_errposition(), ExplainState::serialize, ExplainState::settings, ExplainState::summary, ExplainState::timing, ExplainState::verbose, and ExplainState::wal.

Referenced by ExplainQuery().

◆ RegisterExtensionExplainOption()

void RegisterExtensionExplainOption ( const char option_name,
ExplainOptionHandler  handler,
ExplainOptionGUCCheckHandler  guc_check_handler 
)

Definition at line 332 of file explain_state.c.

335{
337
338 Assert(handler != NULL);
339 Assert(guc_check_handler != NULL);
340
341 /* Search for an existing option by this name; if found, update handler. */
342 for (int i = 0; i < ExplainExtensionOptionsAssigned; ++i)
343 {
344 if (strcmp(ExplainExtensionOptionArray[i].option_name,
345 option_name) == 0)
346 {
348
349 exopt->option_handler = handler;
350 exopt->guc_check_handler = guc_check_handler;
351 return;
352 }
353 }
354
355 /* If there is no array yet, create one. */
357 {
362 * sizeof(ExplainExtensionOption));
363 }
364
365 /* If there's an array but it's currently full, expand it. */
367 {
369
373 }
374
375 /* Assign and return new ID. */
377 exopt->option_name = option_name;
378 exopt->option_handler = handler;
379 exopt->guc_check_handler = guc_check_handler;
380}
static int ExplainExtensionOptionsAllocated

References Assert, ExplainExtensionOptionArray, ExplainExtensionOptionsAllocated, ExplainExtensionOptionsAssigned, fb(), i, MemoryContextAlloc(), ExplainExtensionOption::option_handler, ExplainExtensionOption::option_name, pg_nextpower2_32(), repalloc(), and TopMemoryContext.

Referenced by _PG_init().

◆ SetExplainExtensionState()

void SetExplainExtensionState ( ExplainState es,
int  extension_id,
void opaque 
)

Definition at line 289 of file explain_state.c.

290{
291 Assert(extension_id >= 0);
292
293 /* If there is no array yet, create one. */
294 if (es->extension_state == NULL)
295 {
298 es->extension_state =
299 palloc0(es->extension_state_allocated * sizeof(void *));
300 }
301
302 /* If there's an array but it's currently full, expand it. */
304 {
305 int i;
306
310 }
311
312 es->extension_state[extension_id] = opaque;
313}
#define Max(x, y)
Definition c.h:1085
void * palloc0(Size size)
Definition mcxt.c:1417
#define repalloc0_array(pointer, type, oldcount, count)
Definition palloc.h:109

References Assert, ExplainState::extension_state, ExplainState::extension_state_allocated, fb(), i, Max, palloc0(), pg_nextpower2_32(), and repalloc0_array.

Referenced by overexplain_ensure_options(), and pg_plan_advice_explain_option_handler().

Variable Documentation

◆ explain_validate_options_hook

explain_validate_options_hook_type explain_validate_options_hook = NULL

Definition at line 43 of file explain_state.c.

Referenced by ParseExplainOptionList().

◆ ExplainExtensionNameArray

const char** ExplainExtensionNameArray = NULL
static

Definition at line 52 of file explain_state.c.

Referenced by GetExplainExtensionId().

◆ ExplainExtensionNamesAllocated

int ExplainExtensionNamesAllocated = 0
static

Definition at line 54 of file explain_state.c.

Referenced by GetExplainExtensionId().

◆ ExplainExtensionNamesAssigned

int ExplainExtensionNamesAssigned = 0
static

Definition at line 53 of file explain_state.c.

Referenced by GetExplainExtensionId().

◆ ExplainExtensionOptionArray

ExplainExtensionOption* ExplainExtensionOptionArray = NULL
static

◆ ExplainExtensionOptionsAllocated

int ExplainExtensionOptionsAllocated = 0
static

Definition at line 58 of file explain_state.c.

Referenced by RegisterExtensionExplainOption().

◆ ExplainExtensionOptionsAssigned

int ExplainExtensionOptionsAssigned = 0
static