PostgreSQL Source Code git master
Loading...
Searching...
No Matches
auto_explain.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/parallel.h"
#include "commands/defrem.h"
#include "commands/explain.h"
#include "commands/explain_format.h"
#include "commands/explain_state.h"
#include "common/pg_prng.h"
#include "executor/instrument.h"
#include "nodes/makefuncs.h"
#include "nodes/value.h"
#include "parser/scansup.h"
#include "utils/guc.h"
#include "utils/varlena.h"
Include dependency graph for auto_explain.c:

Go to the source code of this file.

Data Structures

struct  auto_explain_option
 
struct  auto_explain_extension_options
 

Macros

#define auto_explain_enabled()
 

Typedefs

typedef struct auto_explain_option auto_explain_option
 
typedef struct auto_explain_extension_options auto_explain_extension_options
 

Functions

 PG_MODULE_MAGIC_EXT (.name="auto_explain",.version=PG_VERSION)
 
static void explain_ExecutorStart (QueryDesc *queryDesc, int eflags)
 
static void explain_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, uint64 count)
 
static void explain_ExecutorFinish (QueryDesc *queryDesc)
 
static void explain_ExecutorEnd (QueryDesc *queryDesc)
 
static bool check_log_extension_options (char **newval, void **extra, GucSource source)
 
static void assign_log_extension_options (const char *newval, void *extra)
 
static void apply_extension_options (ExplainState *es, auto_explain_extension_options *ext)
 
static charauto_explain_scan_literal (char **endp, char **nextp)
 
static int auto_explain_split_options (char *rawstring, auto_explain_option *options, int maxoptions, char **errmsg)
 
void _PG_init (void)
 

Variables

static int auto_explain_log_min_duration = -1
 
static int auto_explain_log_parameter_max_length = -1
 
static bool auto_explain_log_analyze = false
 
static bool auto_explain_log_verbose = false
 
static bool auto_explain_log_buffers = false
 
static bool auto_explain_log_io = false
 
static bool auto_explain_log_wal = false
 
static bool auto_explain_log_triggers = false
 
static bool auto_explain_log_timing = true
 
static bool auto_explain_log_settings = false
 
static int auto_explain_log_format = EXPLAIN_FORMAT_TEXT
 
static int auto_explain_log_level = LOG
 
static bool auto_explain_log_nested_statements = false
 
static double auto_explain_sample_rate = 1
 
static charauto_explain_log_extension_options = NULL
 
static auto_explain_extension_optionsextension_options = NULL
 
static const struct config_enum_entry format_options []
 
static const struct config_enum_entry loglevel_options []
 
static int nesting_level = 0
 
static bool current_query_sampled = false
 
static ExecutorStart_hook_type prev_ExecutorStart = NULL
 
static ExecutorRun_hook_type prev_ExecutorRun = NULL
 
static ExecutorFinish_hook_type prev_ExecutorFinish = NULL
 
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL
 

Macro Definition Documentation

◆ auto_explain_enabled

#define auto_explain_enabled ( )
Value:
static int auto_explain_log_min_duration
static bool auto_explain_log_nested_statements
static int nesting_level
static bool current_query_sampled

Definition at line 104 of file auto_explain.c.

136{
137 /* Define custom GUC variables. */
138 DefineCustomIntVariable("auto_explain.log_min_duration",
139 "Sets the minimum execution time above which plans will be logged.",
140 "-1 disables logging plans. 0 means log all plans.",
142 -1,
143 -1, INT_MAX,
144 PGC_SUSET,
146 NULL,
147 NULL,
148 NULL);
149
150 DefineCustomIntVariable("auto_explain.log_parameter_max_length",
151 "Sets the maximum length of query parameter values to log.",
152 "-1 means log values in full.",
154 -1,
155 -1, INT_MAX,
156 PGC_SUSET,
158 NULL,
159 NULL,
160 NULL);
161
162 DefineCustomBoolVariable("auto_explain.log_analyze",
163 "Use EXPLAIN ANALYZE for plan logging.",
164 NULL,
166 false,
167 PGC_SUSET,
168 0,
169 NULL,
170 NULL,
171 NULL);
172
173 DefineCustomBoolVariable("auto_explain.log_settings",
174 "Log modified configuration parameters affecting query planning.",
175 NULL,
177 false,
178 PGC_SUSET,
179 0,
180 NULL,
181 NULL,
182 NULL);
183
184 DefineCustomBoolVariable("auto_explain.log_verbose",
185 "Use EXPLAIN VERBOSE for plan logging.",
186 NULL,
188 false,
189 PGC_SUSET,
190 0,
191 NULL,
192 NULL,
193 NULL);
194
195 DefineCustomBoolVariable("auto_explain.log_buffers",
196 "Log buffers usage.",
197 NULL,
199 false,
200 PGC_SUSET,
201 0,
202 NULL,
203 NULL,
204 NULL);
205
206 DefineCustomBoolVariable("auto_explain.log_io",
207 "Log I/O statistics.",
208 NULL,
210 false,
211 PGC_SUSET,
212 0,
213 NULL,
214 NULL,
215 NULL);
216
217 DefineCustomBoolVariable("auto_explain.log_wal",
218 "Log WAL usage.",
219 NULL,
221 false,
222 PGC_SUSET,
223 0,
224 NULL,
225 NULL,
226 NULL);
227
228 DefineCustomBoolVariable("auto_explain.log_triggers",
229 "Include trigger statistics in plans.",
230 "This has no effect unless log_analyze is also set.",
232 false,
233 PGC_SUSET,
234 0,
235 NULL,
236 NULL,
237 NULL);
238
239 DefineCustomEnumVariable("auto_explain.log_format",
240 "EXPLAIN format to be used for plan logging.",
241 NULL,
245 PGC_SUSET,
246 0,
247 NULL,
248 NULL,
249 NULL);
250
251 DefineCustomEnumVariable("auto_explain.log_level",
252 "Log level for the plan.",
253 NULL,
255 LOG,
257 PGC_SUSET,
258 0,
259 NULL,
260 NULL,
261 NULL);
262
263 DefineCustomBoolVariable("auto_explain.log_nested_statements",
264 "Log nested statements.",
265 NULL,
267 false,
268 PGC_SUSET,
269 0,
270 NULL,
271 NULL,
272 NULL);
273
274 DefineCustomBoolVariable("auto_explain.log_timing",
275 "Collect timing data, not just row counts.",
276 NULL,
278 true,
279 PGC_SUSET,
280 0,
281 NULL,
282 NULL,
283 NULL);
284
285 DefineCustomStringVariable("auto_explain.log_extension_options",
286 "Extension EXPLAIN options to be added.",
287 NULL,
289 NULL,
290 PGC_SUSET,
291 0,
294 NULL);
295
296 DefineCustomRealVariable("auto_explain.sample_rate",
297 "Fraction of queries to process.",
298 NULL,
300 1.0,
301 0.0,
302 1.0,
303 PGC_SUSET,
304 0,
305 NULL,
306 NULL,
307 NULL);
308
309 MarkGUCPrefixReserved("auto_explain");
310
311 /* Install hooks. */
320}
321
322/*
323 * ExecutorStart hook: start up logging if needed
324 */
325static void
326explain_ExecutorStart(QueryDesc *queryDesc, int eflags)
327{
328 /*
329 * At the beginning of each top-level statement, decide whether we'll
330 * sample this statement. If nested-statement explaining is enabled,
331 * either all nested statements will be explained or none will.
332 *
333 * When in a parallel worker, we should do nothing, which we can implement
334 * cheaply by pretending we decided not to sample the current statement.
335 * If EXPLAIN is active in the parent session, data will be collected and
336 * reported back to the parent, and it's no business of ours to interfere.
337 */
338 if (nesting_level == 0)
339 {
342 else
343 current_query_sampled = false;
344 }
345
347 {
348 /* We're always interested in runtime */
350
351 /* Enable per-node instrumentation iff log_analyze is required. */
353 {
356 else
361 queryDesc->instrument_options |= INSTRUMENT_IO;
364 }
365 }
366
368 prev_ExecutorStart(queryDesc, eflags);
369 else
370 standard_ExecutorStart(queryDesc, eflags);
371}
372
373/*
374 * ExecutorRun hook: all we need do is track nesting depth
375 */
376static void
377explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction,
378 uint64 count)
379{
381 PG_TRY();
382 {
384 prev_ExecutorRun(queryDesc, direction, count);
385 else
386 standard_ExecutorRun(queryDesc, direction, count);
387 }
388 PG_FINALLY();
389 {
391 }
392 PG_END_TRY();
393}
394
395/*
396 * ExecutorFinish hook: all we need do is track nesting depth
397 */
398static void
400{
402 PG_TRY();
403 {
405 prev_ExecutorFinish(queryDesc);
406 else
407 standard_ExecutorFinish(queryDesc);
408 }
409 PG_FINALLY();
410 {
412 }
413 PG_END_TRY();
414}
415
416/*
417 * ExecutorEnd hook: log results if needed
418 */
419static void
421{
422 if (queryDesc->query_instr && auto_explain_enabled())
423 {
425 double msec;
426
427 /*
428 * Make sure we operate in the per-query context, so any cruft will be
429 * discarded later during ExecutorEnd.
430 */
432
433 /* Log plan if duration is exceeded. */
436 {
438
442 es->io = (es->analyze && auto_explain_log_io);
443 es->wal = (es->analyze && auto_explain_log_wal);
445 es->summary = es->analyze;
446 /* No support for MEMORY */
447 /* es->memory = false; */
450
452
454 ExplainQueryText(es, queryDesc);
456 ExplainPrintPlan(es, queryDesc);
458 ExplainPrintTriggers(es, queryDesc);
459 if (es->costs)
460 ExplainPrintJITSummary(es, queryDesc);
462 (*explain_per_plan_hook) (queryDesc->plannedstmt,
463 NULL, es,
464 queryDesc->sourceText,
465 queryDesc->params,
466 queryDesc->estate->es_queryEnv);
468
469 /* Remove last line break */
470 if (es->str->len > 0 && es->str->data[es->str->len - 1] == '\n')
471 es->str->data[--es->str->len] = '\0';
472
473 /* Fix JSON to output an object */
475 {
476 es->str->data[0] = '{';
477 es->str->data[es->str->len - 1] = '}';
478 }
479
480 /*
481 * Note: we rely on the existing logging of context or
482 * debug_query_string to identify just which statement is being
483 * reported. This isn't ideal but trying to do it here would
484 * often result in duplication.
485 */
487 (errmsg("duration: %.3f ms plan:\n%s",
488 msec, es->str->data),
489 errhidestmt(true)));
490 }
491
493 }
494
496 prev_ExecutorEnd(queryDesc);
497 else
498 standard_ExecutorEnd(queryDesc);
499}
500
501/*
502 * GUC check hook for auto_explain.log_extension_options.
503 */
504static bool
506{
507 char *rawstring;
510 int maxoptions = 8;
512 Size allocsize;
513 char *errmsg;
514
515 /* NULL or empty string means no options. */
516 if (*newval == NULL || (*newval)[0] == '\0')
517 {
518 *extra = NULL;
519 return true;
520 }
521
523
524retry:
525 /* Try to allocate an auto_explain_extension_options object. */
530 if (result == NULL)
531 return false;
532
533 /* Copy the string after the options array. */
534 rawstring = (char *) &result->options[maxoptions];
536
537 /* Parse. */
538 options = result->options;
541 if (result->noptions < 0)
542 {
545 return false;
546 }
547
548 /*
549 * Retry with a larger array if needed.
550 *
551 * It should be impossible for this to loop more than once, because
552 * auto_explain_split_options tells us how many entries are needed.
553 */
554 if (result->noptions > maxoptions)
555 {
556 maxoptions = result->noptions;
558 goto retry;
559 }
560
561 /* Validate each option against its registered check handler. */
562 for (int i = 0; i < result->noptions; i++)
563 {
565 options[i].type))
566 {
568 return false;
569 }
570 }
571
572 *extra = result;
573 return true;
574}
575
576/*
577 * GUC assign hook for auto_explain.log_extension_options.
578 */
579static void
580assign_log_extension_options(const char *newval, void *extra)
581{
583}
584
585/*
586 * Apply parsed extension options to an ExplainState.
587 */
588static void
590{
591 if (ext == NULL)
592 return;
593
594 for (int i = 0; i < ext->noptions; i++)
595 {
596 auto_explain_option *opt = &ext->options[i];
597 DefElem *def;
598 Node *arg;
599
600 if (opt->value == NULL)
601 arg = NULL;
602 else if (opt->type == T_Integer)
603 arg = (Node *) makeInteger(strtol(opt->value, NULL, 0));
604 else if (opt->type == T_Float)
605 arg = (Node *) makeFloat(opt->value);
606 else
607 arg = (Node *) makeString(opt->value);
608
609 def = makeDefElem(opt->name, arg, -1);
611 }
612}
613
614/*
615 * auto_explain_scan_literal - In-place scanner for single-quoted string
616 * literals.
617 *
618 * This is the single-quote analog of scan_quoted_identifier from varlena.c.
619 */
620static char *
622{
623 char *token = *nextp + 1;
624
625 for (;;)
626 {
627 *endp = strchr(*nextp + 1, '\'');
628 if (*endp == NULL)
629 return NULL; /* mismatched quotes */
630 if ((*endp)[1] != '\'')
631 break; /* found end of literal */
632 /* Collapse adjacent quotes into one quote, and look again */
633 memmove(*endp, *endp + 1, strlen(*endp));
634 *nextp = *endp;
635 }
636 /* *endp now points at the terminating quote */
637 *nextp = *endp + 1;
638
639 return token;
640}
641
642/*
643 * auto_explain_split_options - Parse an option string into an array of
644 * auto_explain_option structs.
645 *
646 * Much of this logic is similar to SplitIdentifierString and friends, but our
647 * needs are different enough that we roll our own parsing logic. The goal here
648 * is to accept the same syntax that the main parser would accept inside of
649 * an EXPLAIN option list. While we can't do that perfectly without adding a
650 * lot more code, the goal of this implementation is to be close enough that
651 * users don't really notice the differences.
652 *
653 * The input string is modified in place (null-terminated, downcased, quotes
654 * collapsed). All name and value pointers in the output array refer into
655 * this string, so the caller must ensure the string outlives the array.
656 *
657 * Returns the full number of options in the input string, but stores no
658 * more than maxoptions into the caller-provided array. If a syntax error
659 * occurs, returns -1 and sets *errmsg.
660 */
661static int
663 int maxoptions, char **errmsg)
664{
665 char *nextp = rawstring;
666 int noptions = 0;
667 bool done = false;
668
669 *errmsg = NULL;
670
671 while (scanner_isspace(*nextp))
672 nextp++; /* skip leading whitespace */
673
674 if (*nextp == '\0')
675 return 0; /* empty string is fine */
676
677 while (!done)
678 {
679 char *name;
680 char *name_endp;
681 char *value = NULL;
682 char *value_endp = NULL;
684
685 /* Parse the option name. */
686 name = scan_identifier(&name_endp, &nextp, ',', true);
687 if (name == NULL || name_endp == name)
688 {
689 *errmsg = "option name missing or empty";
690 return -1;
691 }
692
693 /* Skip whitespace after the option name. */
694 while (scanner_isspace(*nextp))
695 nextp++;
696
697 /*
698 * Determine whether we have an option value. A comma or end of
699 * string means no value; otherwise we have one.
700 */
701 if (*nextp != '\0' && *nextp != ',')
702 {
703 if (*nextp == '\'')
704 {
705 /* Single-quoted string literal. */
706 type = T_String;
708 if (value == NULL)
709 {
710 *errmsg = "unterminated single-quoted string";
711 return -1;
712 }
713 }
714 else if (isdigit((unsigned char) *nextp) ||
715 ((*nextp == '+' || *nextp == '-') &&
716 isdigit((unsigned char) nextp[1])))
717 {
718 char *endptr;
719 long intval;
720 char saved;
721
722 /* Remember the start of the next token, and find the end. */
723 value = nextp;
724 while (*nextp && *nextp != ',' && !scanner_isspace(*nextp))
725 nextp++;
727
728 /* Temporarily '\0'-terminate so we can use strtol/strtod. */
729 saved = *value_endp;
730 *value_endp = '\0';
731
732 /*
733 * Integer, float, or neither?
734 *
735 * NB: Since we use strtol and strtod here rather than
736 * pg_strtoint64_safe, some syntax that would be accepted by
737 * the main parser is not accepted here, e.g. 100_000. On the
738 * plus side, strtol and strtod won't allocate, and
739 * pg_strtoint64_safe might. For now, it seems better to keep
740 * things simple here.
741 */
742 errno = 0;
743 intval = strtol(value, &endptr, 0);
744 if (errno == 0 && *endptr == '\0' && endptr != value &&
745 intval == (int) intval)
746 type = T_Integer;
747 else
748 {
749 type = T_Float;
750 (void) strtod(value, &endptr);
751 if (*endptr != '\0')
752 {
753 *value_endp = saved;
754 *errmsg = "invalid numeric value";
755 return -1;
756 }
757 }
758
759 /* Remove temporary terminator. */
760 *value_endp = saved;
761 }
762 else
763 {
764 /* Identifier, possibly double-quoted. */
765 type = T_String;
766 value = scan_identifier(&value_endp, &nextp, ',', true);
767 if (value == NULL)
768 {
769 /*
770 * scan_identifier will return NULL if it finds an
771 * unterminated double-quoted identifier or it finds no
772 * identifier at all because the next character is
773 * whitespace or the separator character, here a comma.
774 * But the latter case is impossible here because the code
775 * above has skipped whitespace and checked for commas.
776 */
777 *errmsg = "unterminated double-quoted string";
778 return -1;
779 }
780 }
781 }
782
783 /* Skip trailing whitespace. */
784 while (scanner_isspace(*nextp))
785 nextp++;
786
787 /* Expect comma or end of string. */
788 if (*nextp == ',')
789 {
790 nextp++;
791 while (scanner_isspace(*nextp))
792 nextp++;
793 if (*nextp == '\0')
794 {
795 *errmsg = "trailing comma in option list";
796 return -1;
797 }
798 }
799 else if (*nextp == '\0')
800 done = true;
801 else
802 {
803 *errmsg = "expected comma or end of option list";
804 return -1;
805 }
806
807 /*
808 * Now safe to null-terminate the name and value. We couldn't do this
809 * earlier because in the unquoted case, the null terminator position
810 * may coincide with a character that the scanning logic above still
811 * needed to read.
812 */
813 *name_endp = '\0';
814 if (value_endp != NULL)
815 *value_endp = '\0';
816
817 /* Always count this option, and store the details if there is room. */
818 if (noptions < maxoptions)
819 {
820 options[noptions].name = name;
821 options[noptions].type = type;
822 options[noptions].value = value;
823 }
824 noptions++;
825 }
826
827 return noptions;
828}
static ExecutorRun_hook_type prev_ExecutorRun
static bool auto_explain_log_analyze
static void explain_ExecutorEnd(QueryDesc *queryDesc)
static bool check_log_extension_options(char **newval, void **extra, GucSource source)
static auto_explain_extension_options * extension_options
static bool auto_explain_log_wal
#define auto_explain_enabled()
static int auto_explain_split_options(char *rawstring, auto_explain_option *options, int maxoptions, char **errmsg)
static double auto_explain_sample_rate
static int auto_explain_log_parameter_max_length
static void assign_log_extension_options(const char *newval, void *extra)
static bool auto_explain_log_io
static bool auto_explain_log_verbose
static void apply_extension_options(ExplainState *es, auto_explain_extension_options *ext)
static void explain_ExecutorFinish(QueryDesc *queryDesc)
static void explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags)
static char * auto_explain_scan_literal(char **endp, char **nextp)
static ExecutorStart_hook_type prev_ExecutorStart
static const struct config_enum_entry loglevel_options[]
static bool auto_explain_log_timing
static int auto_explain_log_format
static bool auto_explain_log_buffers
static bool auto_explain_log_triggers
static const struct config_enum_entry format_options[]
static char * auto_explain_log_extension_options
static ExecutorEnd_hook_type prev_ExecutorEnd
static int auto_explain_log_level
static ExecutorFinish_hook_type prev_ExecutorFinish
static bool auto_explain_log_settings
uint64_t uint64
Definition c.h:625
size_t Size
Definition c.h:689
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
Datum arg
Definition elog.c:1322
int int errhidestmt(bool hide_stmt)
#define LOG
Definition elog.h:32
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define PG_FINALLY(...)
Definition elog.h:391
#define ereport(elevel,...)
Definition elog.h:152
ExecutorEnd_hook_type ExecutorEnd_hook
Definition execMain.c:73
ExecutorFinish_hook_type ExecutorFinish_hook
Definition execMain.c:72
ExecutorStart_hook_type ExecutorStart_hook
Definition execMain.c:70
void standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition execMain.c:143
ExecutorRun_hook_type ExecutorRun_hook
Definition execMain.c:71
void standard_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition execMain.c:318
void standard_ExecutorEnd(QueryDesc *queryDesc)
Definition execMain.c:486
void standard_ExecutorFinish(QueryDesc *queryDesc)
Definition execMain.c:426
#define EXEC_FLAG_EXPLAIN_ONLY
Definition executor.h:67
void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:883
void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:1067
explain_per_plan_hook_type explain_per_plan_hook
Definition explain.c:58
void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:767
void ExplainQueryParameters(ExplainState *es, ParamListInfo params, int maxlen)
Definition explain.c:1082
void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
Definition explain.c:840
void ExplainEndOutput(ExplainState *es)
void ExplainBeginOutput(ExplainState *es)
ExplainState * NewExplainState(void)
bool GUCCheckExplainExtensionOption(const char *option_name, const char *option_value, NodeTag option_type)
bool ApplyExtensionExplainOption(ExplainState *es, DefElem *opt, ParseState *pstate)
@ EXPLAIN_FORMAT_TEXT
@ EXPLAIN_FORMAT_JSON
void guc_free(void *ptr)
Definition guc.c:688
void DefineCustomRealVariable(const char *name, const char *short_desc, const char *long_desc, double *valueAddr, double bootValue, double minValue, double maxValue, GucContext context, int flags, GucRealCheckHook check_hook, GucRealAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5101
void DefineCustomEnumVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, const struct config_enum_entry *options, GucContext context, int flags, GucEnumCheckHook check_hook, GucEnumAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5152
void DefineCustomStringVariable(const char *name, const char *short_desc, const char *long_desc, char **valueAddr, const char *bootValue, GucContext context, int flags, GucStringCheckHook check_hook, GucStringAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5129
void * guc_malloc(int elevel, size_t size)
Definition guc.c:637
void DefineCustomBoolVariable(const char *name, const char *short_desc, const char *long_desc, bool *valueAddr, bool bootValue, GucContext context, int flags, GucBoolCheckHook check_hook, GucBoolAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5049
#define newval
void MarkGUCPrefixReserved(const char *className)
Definition guc.c:5186
void DefineCustomIntVariable(const char *name, const char *short_desc, const char *long_desc, int *valueAddr, int bootValue, int minValue, int maxValue, GucContext context, int flags, GucIntCheckHook check_hook, GucIntAssignHook assign_hook, GucShowHook show_hook)
Definition guc.c:5073
#define GUC_UNIT_MS
Definition guc.h:239
#define GUC_check_errdetail
Definition guc.h:507
GucSource
Definition guc.h:112
@ PGC_SUSET
Definition guc.h:78
#define GUC_UNIT_BYTE
Definition guc.h:236
#define IsParallelWorker()
Definition parallel.h:62
#define token
static struct @177 value
#define INSTR_TIME_GET_MILLISEC(t)
Definition instr_time.h:451
@ INSTRUMENT_TIMER
Definition instrument.h:63
@ INSTRUMENT_IO
Definition instrument.h:67
@ INSTRUMENT_BUFFERS
Definition instrument.h:64
@ INSTRUMENT_WAL
Definition instrument.h:66
@ INSTRUMENT_ROWS
Definition instrument.h:65
int i
Definition isn.c:77
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition makefuncs.c:637
NodeTag
Definition nodes.h:27
@ T_Invalid
Definition nodes.h:28
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
double pg_prng_double(pg_prng_state *state)
Definition pg_prng.c:268
pg_prng_state pg_global_prng_state
Definition pg_prng.c:34
static size_t noptions
static rewind_source * source
Definition pg_rewind.c:89
static int fb(int x)
bool scanner_isspace(char ch)
Definition scansup.c:105
ScanDirection
Definition sdir.h:25
QueryEnvironment * es_queryEnv
Definition execnodes.h:743
MemoryContext es_query_cxt
Definition execnodes.h:746
ExplainFormat format
instr_time total
Definition instrument.h:88
Definition nodes.h:135
const char * sourceText
Definition execdesc.h:38
ParamListInfo params
Definition execdesc.h:42
int instrument_options
Definition execdesc.h:44
EState * estate
Definition execdesc.h:50
PlannedStmt * plannedstmt
Definition execdesc.h:37
int query_instr_options
Definition execdesc.h:45
struct Instrumentation * query_instr
Definition execdesc.h:57
auto_explain_option options[FLEXIBLE_ARRAY_MEMBER]
Integer * makeInteger(int i)
Definition value.c:23
String * makeString(char *str)
Definition value.c:63
Float * makeFloat(char *numericStr)
Definition value.c:37
char * scan_identifier(char **endp, char **nextp, char separator, bool downcase_unquoted)
Definition varlena.c:2802
const char * type
const char * name

Typedef Documentation

◆ auto_explain_extension_options

◆ auto_explain_option

Function Documentation

◆ _PG_init()

void _PG_init ( void  )

Definition at line 136 of file auto_explain.c.

137{
138 /* Define custom GUC variables. */
139 DefineCustomIntVariable("auto_explain.log_min_duration",
140 "Sets the minimum execution time above which plans will be logged.",
141 "-1 disables logging plans. 0 means log all plans.",
143 -1,
144 -1, INT_MAX,
145 PGC_SUSET,
147 NULL,
148 NULL,
149 NULL);
150
151 DefineCustomIntVariable("auto_explain.log_parameter_max_length",
152 "Sets the maximum length of query parameter values to log.",
153 "-1 means log values in full.",
155 -1,
156 -1, INT_MAX,
157 PGC_SUSET,
159 NULL,
160 NULL,
161 NULL);
162
163 DefineCustomBoolVariable("auto_explain.log_analyze",
164 "Use EXPLAIN ANALYZE for plan logging.",
165 NULL,
167 false,
168 PGC_SUSET,
169 0,
170 NULL,
171 NULL,
172 NULL);
173
174 DefineCustomBoolVariable("auto_explain.log_settings",
175 "Log modified configuration parameters affecting query planning.",
176 NULL,
178 false,
179 PGC_SUSET,
180 0,
181 NULL,
182 NULL,
183 NULL);
184
185 DefineCustomBoolVariable("auto_explain.log_verbose",
186 "Use EXPLAIN VERBOSE for plan logging.",
187 NULL,
189 false,
190 PGC_SUSET,
191 0,
192 NULL,
193 NULL,
194 NULL);
195
196 DefineCustomBoolVariable("auto_explain.log_buffers",
197 "Log buffers usage.",
198 NULL,
200 false,
201 PGC_SUSET,
202 0,
203 NULL,
204 NULL,
205 NULL);
206
207 DefineCustomBoolVariable("auto_explain.log_io",
208 "Log I/O statistics.",
209 NULL,
211 false,
212 PGC_SUSET,
213 0,
214 NULL,
215 NULL,
216 NULL);
217
218 DefineCustomBoolVariable("auto_explain.log_wal",
219 "Log WAL usage.",
220 NULL,
222 false,
223 PGC_SUSET,
224 0,
225 NULL,
226 NULL,
227 NULL);
228
229 DefineCustomBoolVariable("auto_explain.log_triggers",
230 "Include trigger statistics in plans.",
231 "This has no effect unless log_analyze is also set.",
233 false,
234 PGC_SUSET,
235 0,
236 NULL,
237 NULL,
238 NULL);
239
240 DefineCustomEnumVariable("auto_explain.log_format",
241 "EXPLAIN format to be used for plan logging.",
242 NULL,
246 PGC_SUSET,
247 0,
248 NULL,
249 NULL,
250 NULL);
251
252 DefineCustomEnumVariable("auto_explain.log_level",
253 "Log level for the plan.",
254 NULL,
256 LOG,
258 PGC_SUSET,
259 0,
260 NULL,
261 NULL,
262 NULL);
263
264 DefineCustomBoolVariable("auto_explain.log_nested_statements",
265 "Log nested statements.",
266 NULL,
268 false,
269 PGC_SUSET,
270 0,
271 NULL,
272 NULL,
273 NULL);
274
275 DefineCustomBoolVariable("auto_explain.log_timing",
276 "Collect timing data, not just row counts.",
277 NULL,
279 true,
280 PGC_SUSET,
281 0,
282 NULL,
283 NULL,
284 NULL);
285
286 DefineCustomStringVariable("auto_explain.log_extension_options",
287 "Extension EXPLAIN options to be added.",
288 NULL,
290 NULL,
291 PGC_SUSET,
292 0,
295 NULL);
296
297 DefineCustomRealVariable("auto_explain.sample_rate",
298 "Fraction of queries to process.",
299 NULL,
301 1.0,
302 0.0,
303 1.0,
304 PGC_SUSET,
305 0,
306 NULL,
307 NULL,
308 NULL);
309
310 MarkGUCPrefixReserved("auto_explain");
311
312 /* Install hooks. */
321}

References assign_log_extension_options(), auto_explain_log_analyze, auto_explain_log_buffers, auto_explain_log_extension_options, auto_explain_log_format, auto_explain_log_io, auto_explain_log_level, auto_explain_log_min_duration, auto_explain_log_nested_statements, auto_explain_log_parameter_max_length, auto_explain_log_settings, auto_explain_log_timing, auto_explain_log_triggers, auto_explain_log_verbose, auto_explain_log_wal, auto_explain_sample_rate, check_log_extension_options(), DefineCustomBoolVariable(), DefineCustomEnumVariable(), DefineCustomIntVariable(), DefineCustomRealVariable(), DefineCustomStringVariable(), ExecutorEnd_hook, ExecutorFinish_hook, ExecutorRun_hook, ExecutorStart_hook, explain_ExecutorEnd(), explain_ExecutorFinish(), explain_ExecutorRun(), explain_ExecutorStart(), EXPLAIN_FORMAT_TEXT, format_options, GUC_UNIT_BYTE, GUC_UNIT_MS, LOG, loglevel_options, MarkGUCPrefixReserved(), PGC_SUSET, prev_ExecutorEnd, prev_ExecutorFinish, prev_ExecutorRun, and prev_ExecutorStart.

◆ apply_extension_options()

static void apply_extension_options ( ExplainState es,
auto_explain_extension_options ext 
)
static

Definition at line 590 of file auto_explain.c.

591{
592 if (ext == NULL)
593 return;
594
595 for (int i = 0; i < ext->noptions; i++)
596 {
597 auto_explain_option *opt = &ext->options[i];
598 DefElem *def;
599 Node *arg;
600
601 if (opt->value == NULL)
602 arg = NULL;
603 else if (opt->type == T_Integer)
604 arg = (Node *) makeInteger(strtol(opt->value, NULL, 0));
605 else if (opt->type == T_Float)
606 arg = (Node *) makeFloat(opt->value);
607 else
608 arg = (Node *) makeString(opt->value);
609
610 def = makeDefElem(opt->name, arg, -1);
612 }
613}

References ApplyExtensionExplainOption(), arg, fb(), i, makeDefElem(), makeFloat(), makeInteger(), makeString(), auto_explain_option::name, auto_explain_extension_options::noptions, auto_explain_extension_options::options, auto_explain_option::type, and auto_explain_option::value.

Referenced by explain_ExecutorEnd().

◆ assign_log_extension_options()

static void assign_log_extension_options ( const char newval,
void extra 
)
static

Definition at line 581 of file auto_explain.c.

References extension_options.

Referenced by _PG_init().

◆ auto_explain_scan_literal()

static char * auto_explain_scan_literal ( char **  endp,
char **  nextp 
)
static

Definition at line 622 of file auto_explain.c.

623{
624 char *token = *nextp + 1;
625
626 for (;;)
627 {
628 *endp = strchr(*nextp + 1, '\'');
629 if (*endp == NULL)
630 return NULL; /* mismatched quotes */
631 if ((*endp)[1] != '\'')
632 break; /* found end of literal */
633 /* Collapse adjacent quotes into one quote, and look again */
634 memmove(*endp, *endp + 1, strlen(*endp));
635 *nextp = *endp;
636 }
637 /* *endp now points at the terminating quote */
638 *nextp = *endp + 1;
639
640 return token;
641}

References fb(), and token.

Referenced by auto_explain_split_options().

◆ auto_explain_split_options()

static int auto_explain_split_options ( char rawstring,
auto_explain_option options,
int  maxoptions,
char **  errmsg 
)
static

Definition at line 663 of file auto_explain.c.

665{
666 char *nextp = rawstring;
667 int noptions = 0;
668 bool done = false;
669
670 *errmsg = NULL;
671
672 while (scanner_isspace(*nextp))
673 nextp++; /* skip leading whitespace */
674
675 if (*nextp == '\0')
676 return 0; /* empty string is fine */
677
678 while (!done)
679 {
680 char *name;
681 char *name_endp;
682 char *value = NULL;
683 char *value_endp = NULL;
685
686 /* Parse the option name. */
687 name = scan_identifier(&name_endp, &nextp, ',', true);
688 if (name == NULL || name_endp == name)
689 {
690 *errmsg = "option name missing or empty";
691 return -1;
692 }
693
694 /* Skip whitespace after the option name. */
695 while (scanner_isspace(*nextp))
696 nextp++;
697
698 /*
699 * Determine whether we have an option value. A comma or end of
700 * string means no value; otherwise we have one.
701 */
702 if (*nextp != '\0' && *nextp != ',')
703 {
704 if (*nextp == '\'')
705 {
706 /* Single-quoted string literal. */
707 type = T_String;
709 if (value == NULL)
710 {
711 *errmsg = "unterminated single-quoted string";
712 return -1;
713 }
714 }
715 else if (isdigit((unsigned char) *nextp) ||
716 ((*nextp == '+' || *nextp == '-') &&
717 isdigit((unsigned char) nextp[1])))
718 {
719 char *endptr;
720 long intval;
721 char saved;
722
723 /* Remember the start of the next token, and find the end. */
724 value = nextp;
725 while (*nextp && *nextp != ',' && !scanner_isspace(*nextp))
726 nextp++;
728
729 /* Temporarily '\0'-terminate so we can use strtol/strtod. */
730 saved = *value_endp;
731 *value_endp = '\0';
732
733 /*
734 * Integer, float, or neither?
735 *
736 * NB: Since we use strtol and strtod here rather than
737 * pg_strtoint64_safe, some syntax that would be accepted by
738 * the main parser is not accepted here, e.g. 100_000. On the
739 * plus side, strtol and strtod won't allocate, and
740 * pg_strtoint64_safe might. For now, it seems better to keep
741 * things simple here.
742 */
743 errno = 0;
744 intval = strtol(value, &endptr, 0);
745 if (errno == 0 && *endptr == '\0' && endptr != value &&
746 intval == (int) intval)
747 type = T_Integer;
748 else
749 {
750 type = T_Float;
751 (void) strtod(value, &endptr);
752 if (*endptr != '\0')
753 {
754 *value_endp = saved;
755 *errmsg = "invalid numeric value";
756 return -1;
757 }
758 }
759
760 /* Remove temporary terminator. */
761 *value_endp = saved;
762 }
763 else
764 {
765 /* Identifier, possibly double-quoted. */
766 type = T_String;
767 value = scan_identifier(&value_endp, &nextp, ',', true);
768 if (value == NULL)
769 {
770 /*
771 * scan_identifier will return NULL if it finds an
772 * unterminated double-quoted identifier or it finds no
773 * identifier at all because the next character is
774 * whitespace or the separator character, here a comma.
775 * But the latter case is impossible here because the code
776 * above has skipped whitespace and checked for commas.
777 */
778 *errmsg = "unterminated double-quoted string";
779 return -1;
780 }
781 }
782 }
783
784 /* Skip trailing whitespace. */
785 while (scanner_isspace(*nextp))
786 nextp++;
787
788 /* Expect comma or end of string. */
789 if (*nextp == ',')
790 {
791 nextp++;
792 while (scanner_isspace(*nextp))
793 nextp++;
794 if (*nextp == '\0')
795 {
796 *errmsg = "trailing comma in option list";
797 return -1;
798 }
799 }
800 else if (*nextp == '\0')
801 done = true;
802 else
803 {
804 *errmsg = "expected comma or end of option list";
805 return -1;
806 }
807
808 /*
809 * Now safe to null-terminate the name and value. We couldn't do this
810 * earlier because in the unquoted case, the null terminator position
811 * may coincide with a character that the scanning logic above still
812 * needed to read.
813 */
814 *name_endp = '\0';
815 if (value_endp != NULL)
816 *value_endp = '\0';
817
818 /* Always count this option, and store the details if there is room. */
819 if (noptions < maxoptions)
820 {
821 options[noptions].name = name;
822 options[noptions].type = type;
823 options[noptions].value = value;
824 }
825 noptions++;
826 }
827
828 return noptions;
829}

References auto_explain_scan_literal(), errmsg, fb(), name, noptions, scan_identifier(), scanner_isspace(), T_Invalid, type, and value.

Referenced by check_log_extension_options().

◆ check_log_extension_options()

static bool check_log_extension_options ( char **  newval,
void **  extra,
GucSource  source 
)
static

Definition at line 506 of file auto_explain.c.

507{
508 char *rawstring;
511 int maxoptions = 8;
513 Size allocsize;
514 char *errmsg;
515
516 /* NULL or empty string means no options. */
517 if (*newval == NULL || (*newval)[0] == '\0')
518 {
519 *extra = NULL;
520 return true;
521 }
522
524
525retry:
526 /* Try to allocate an auto_explain_extension_options object. */
531 if (result == NULL)
532 return false;
533
534 /* Copy the string after the options array. */
535 rawstring = (char *) &result->options[maxoptions];
537
538 /* Parse. */
539 options = result->options;
542 if (result->noptions < 0)
543 {
546 return false;
547 }
548
549 /*
550 * Retry with a larger array if needed.
551 *
552 * It should be impossible for this to loop more than once, because
553 * auto_explain_split_options tells us how many entries are needed.
554 */
555 if (result->noptions > maxoptions)
556 {
557 maxoptions = result->noptions;
559 goto retry;
560 }
561
562 /* Validate each option against its registered check handler. */
563 for (int i = 0; i < result->noptions; i++)
564 {
566 options[i].type))
567 {
569 return false;
570 }
571 }
572
573 *extra = result;
574 return true;
575}

References auto_explain_split_options(), errmsg, fb(), GUC_check_errdetail, guc_free(), guc_malloc(), GUCCheckExplainExtensionOption(), i, LOG, memcpy(), name, newval, result, type, and value.

Referenced by _PG_init().

◆ explain_ExecutorEnd()

static void explain_ExecutorEnd ( QueryDesc queryDesc)
static

Definition at line 421 of file auto_explain.c.

422{
423 if (queryDesc->query_instr && auto_explain_enabled())
424 {
426 double msec;
427
428 /*
429 * Make sure we operate in the per-query context, so any cruft will be
430 * discarded later during ExecutorEnd.
431 */
433
434 /* Log plan if duration is exceeded. */
437 {
439
443 es->io = (es->analyze && auto_explain_log_io);
444 es->wal = (es->analyze && auto_explain_log_wal);
446 es->summary = es->analyze;
447 /* No support for MEMORY */
448 /* es->memory = false; */
451
453
455 ExplainQueryText(es, queryDesc);
457 ExplainPrintPlan(es, queryDesc);
459 ExplainPrintTriggers(es, queryDesc);
460 if (es->costs)
461 ExplainPrintJITSummary(es, queryDesc);
463 (*explain_per_plan_hook) (queryDesc->plannedstmt,
464 NULL, es,
465 queryDesc->sourceText,
466 queryDesc->params,
467 queryDesc->estate->es_queryEnv);
469
470 /* Remove last line break */
471 if (es->str->len > 0 && es->str->data[es->str->len - 1] == '\n')
472 es->str->data[--es->str->len] = '\0';
473
474 /* Fix JSON to output an object */
476 {
477 es->str->data[0] = '{';
478 es->str->data[es->str->len - 1] = '}';
479 }
480
481 /*
482 * Note: we rely on the existing logging of context or
483 * debug_query_string to identify just which statement is being
484 * reported. This isn't ideal but trying to do it here would
485 * often result in duplication.
486 */
488 (errmsg("duration: %.3f ms plan:\n%s",
489 msec, es->str->data),
490 errhidestmt(true)));
491 }
492
494 }
495
497 prev_ExecutorEnd(queryDesc);
498 else
499 standard_ExecutorEnd(queryDesc);
500}

References ExplainState::analyze, apply_extension_options(), auto_explain_enabled, auto_explain_log_analyze, auto_explain_log_buffers, auto_explain_log_format, auto_explain_log_io, auto_explain_log_level, auto_explain_log_min_duration, auto_explain_log_parameter_max_length, auto_explain_log_settings, auto_explain_log_timing, auto_explain_log_triggers, auto_explain_log_verbose, auto_explain_log_wal, ExplainState::buffers, ExplainState::costs, StringInfoData::data, ereport, errhidestmt(), errmsg, EState::es_query_cxt, EState::es_queryEnv, QueryDesc::estate, EXPLAIN_FORMAT_JSON, explain_per_plan_hook, ExplainBeginOutput(), ExplainEndOutput(), ExplainPrintJITSummary(), ExplainPrintPlan(), ExplainPrintTriggers(), ExplainQueryParameters(), ExplainQueryText(), extension_options, fb(), ExplainState::format, INSTR_TIME_GET_MILLISEC, QueryDesc::instrument_options, ExplainState::io, StringInfoData::len, MemoryContextSwitchTo(), NewExplainState(), QueryDesc::params, QueryDesc::plannedstmt, prev_ExecutorEnd, QueryDesc::query_instr, ExplainState::settings, QueryDesc::sourceText, standard_ExecutorEnd(), ExplainState::str, ExplainState::summary, ExplainState::timing, Instrumentation::total, ExplainState::verbose, and ExplainState::wal.

Referenced by _PG_init().

◆ explain_ExecutorFinish()

static void explain_ExecutorFinish ( QueryDesc queryDesc)
static

Definition at line 400 of file auto_explain.c.

401{
403 PG_TRY();
404 {
406 prev_ExecutorFinish(queryDesc);
407 else
408 standard_ExecutorFinish(queryDesc);
409 }
410 PG_FINALLY();
411 {
413 }
414 PG_END_TRY();
415}

References nesting_level, PG_END_TRY, PG_FINALLY, PG_TRY, prev_ExecutorFinish, and standard_ExecutorFinish().

Referenced by _PG_init().

◆ explain_ExecutorRun()

static void explain_ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
uint64  count 
)
static

Definition at line 378 of file auto_explain.c.

380{
382 PG_TRY();
383 {
385 prev_ExecutorRun(queryDesc, direction, count);
386 else
387 standard_ExecutorRun(queryDesc, direction, count);
388 }
389 PG_FINALLY();
390 {
392 }
393 PG_END_TRY();
394}

References nesting_level, PG_END_TRY, PG_FINALLY, PG_TRY, prev_ExecutorRun, and standard_ExecutorRun().

Referenced by _PG_init().

◆ explain_ExecutorStart()

static void explain_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)
static

Definition at line 327 of file auto_explain.c.

328{
329 /*
330 * At the beginning of each top-level statement, decide whether we'll
331 * sample this statement. If nested-statement explaining is enabled,
332 * either all nested statements will be explained or none will.
333 *
334 * When in a parallel worker, we should do nothing, which we can implement
335 * cheaply by pretending we decided not to sample the current statement.
336 * If EXPLAIN is active in the parent session, data will be collected and
337 * reported back to the parent, and it's no business of ours to interfere.
338 */
339 if (nesting_level == 0)
340 {
343 else
344 current_query_sampled = false;
345 }
346
348 {
349 /* We're always interested in runtime */
351
352 /* Enable per-node instrumentation iff log_analyze is required. */
354 {
357 else
362 queryDesc->instrument_options |= INSTRUMENT_IO;
365 }
366 }
367
369 prev_ExecutorStart(queryDesc, eflags);
370 else
371 standard_ExecutorStart(queryDesc, eflags);
372}

References auto_explain_enabled, auto_explain_log_analyze, auto_explain_log_buffers, auto_explain_log_io, auto_explain_log_min_duration, auto_explain_log_timing, auto_explain_log_wal, auto_explain_sample_rate, current_query_sampled, EXEC_FLAG_EXPLAIN_ONLY, INSTRUMENT_BUFFERS, INSTRUMENT_IO, QueryDesc::instrument_options, INSTRUMENT_ROWS, INSTRUMENT_TIMER, INSTRUMENT_WAL, IsParallelWorker, nesting_level, pg_global_prng_state, pg_prng_double(), prev_ExecutorStart, QueryDesc::query_instr_options, and standard_ExecutorStart().

Referenced by _PG_init().

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "auto_explain",
version = PG_VERSION 
)

Variable Documentation

◆ auto_explain_log_analyze

bool auto_explain_log_analyze = false
static

Definition at line 38 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

◆ auto_explain_log_buffers

bool auto_explain_log_buffers = false
static

Definition at line 40 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

◆ auto_explain_log_extension_options

char* auto_explain_log_extension_options = NULL
static

Definition at line 50 of file auto_explain.c.

Referenced by _PG_init().

◆ auto_explain_log_format

int auto_explain_log_format = EXPLAIN_FORMAT_TEXT
static

Definition at line 46 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ auto_explain_log_io

bool auto_explain_log_io = false
static

Definition at line 41 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

◆ auto_explain_log_level

int auto_explain_log_level = LOG
static

Definition at line 47 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ auto_explain_log_min_duration

int auto_explain_log_min_duration = -1
static

Definition at line 36 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

◆ auto_explain_log_nested_statements

bool auto_explain_log_nested_statements = false
static

Definition at line 48 of file auto_explain.c.

Referenced by _PG_init().

◆ auto_explain_log_parameter_max_length

int auto_explain_log_parameter_max_length = -1
static

Definition at line 37 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ auto_explain_log_settings

bool auto_explain_log_settings = false
static

Definition at line 45 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ auto_explain_log_timing

bool auto_explain_log_timing = true
static

Definition at line 44 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

◆ auto_explain_log_triggers

bool auto_explain_log_triggers = false
static

Definition at line 43 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ auto_explain_log_verbose

bool auto_explain_log_verbose = false
static

Definition at line 39 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ auto_explain_log_wal

bool auto_explain_log_wal = false
static

Definition at line 42 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

◆ auto_explain_sample_rate

double auto_explain_sample_rate = 1
static

Definition at line 49 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorStart().

◆ current_query_sampled

bool current_query_sampled = false
static

Definition at line 102 of file auto_explain.c.

Referenced by explain_ExecutorStart().

◆ extension_options

auto_explain_extension_options* extension_options = NULL
static

Definition at line 74 of file auto_explain.c.

Referenced by assign_log_extension_options(), and explain_ExecutorEnd().

◆ format_options

const struct config_enum_entry format_options[]
static
Initial value:
= {
{"text", EXPLAIN_FORMAT_TEXT, false},
{"xml", EXPLAIN_FORMAT_XML, false},
{"json", EXPLAIN_FORMAT_JSON, false},
{"yaml", EXPLAIN_FORMAT_YAML, false},
{NULL, 0, false}
}
@ EXPLAIN_FORMAT_XML
@ EXPLAIN_FORMAT_YAML

Definition at line 76 of file auto_explain.c.

76 {
77 {"text", EXPLAIN_FORMAT_TEXT, false},
78 {"xml", EXPLAIN_FORMAT_XML, false},
79 {"json", EXPLAIN_FORMAT_JSON, false},
80 {"yaml", EXPLAIN_FORMAT_YAML, false},
81 {NULL, 0, false}
82};

Referenced by _PG_init().

◆ loglevel_options

const struct config_enum_entry loglevel_options[]
static
Initial value:
= {
{"debug5", DEBUG5, false},
{"debug4", DEBUG4, false},
{"debug3", DEBUG3, false},
{"debug2", DEBUG2, false},
{"debug1", DEBUG1, false},
{"debug", DEBUG2, true},
{"info", INFO, false},
{"notice", NOTICE, false},
{"warning", WARNING, false},
{"log", LOG, false},
{NULL, 0, false}
}
#define DEBUG3
Definition elog.h:29
#define WARNING
Definition elog.h:37
#define DEBUG2
Definition elog.h:30
#define DEBUG1
Definition elog.h:31
#define NOTICE
Definition elog.h:36
#define INFO
Definition elog.h:35
#define DEBUG5
Definition elog.h:27
#define DEBUG4
Definition elog.h:28

Definition at line 84 of file auto_explain.c.

84 {
85 {"debug5", DEBUG5, false},
86 {"debug4", DEBUG4, false},
87 {"debug3", DEBUG3, false},
88 {"debug2", DEBUG2, false},
89 {"debug1", DEBUG1, false},
90 {"debug", DEBUG2, true},
91 {"info", INFO, false},
92 {"notice", NOTICE, false},
93 {"warning", WARNING, false},
94 {"log", LOG, false},
95 {NULL, 0, false}
96};

Referenced by _PG_init().

◆ nesting_level

int nesting_level = 0
static

◆ prev_ExecutorEnd

ExecutorEnd_hook_type prev_ExecutorEnd = NULL
static

Definition at line 113 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

◆ prev_ExecutorFinish

ExecutorFinish_hook_type prev_ExecutorFinish = NULL
static

Definition at line 112 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorFinish().

◆ prev_ExecutorRun

ExecutorRun_hook_type prev_ExecutorRun = NULL
static

Definition at line 111 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorRun().

◆ prev_ExecutorStart

ExecutorStart_hook_type prev_ExecutorStart = NULL
static

Definition at line 110 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorStart().