PostgreSQL Source Code git master
Loading...
Searching...
No Matches
auto_explain.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * auto_explain.c
4 *
5 *
6 * Copyright (c) 2008-2026, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * contrib/auto_explain/auto_explain.c
10 *
11 *-------------------------------------------------------------------------
12 */
13#include "postgres.h"
14
15#include <limits.h>
16
17#include "access/parallel.h"
18#include "commands/defrem.h"
19#include "commands/explain.h"
22#include "common/pg_prng.h"
23#include "executor/instrument.h"
24#include "nodes/makefuncs.h"
25#include "nodes/value.h"
26#include "parser/scansup.h"
27#include "utils/guc.h"
28#include "utils/varlena.h"
29
31 .name = "auto_explain",
32 .version = PG_VERSION
33);
34
35/* GUC variables */
36static int auto_explain_log_min_duration = -1; /* msec or -1 */
37static int auto_explain_log_parameter_max_length = -1; /* bytes or -1 */
38static bool auto_explain_log_analyze = false;
39static bool auto_explain_log_verbose = false;
40static bool auto_explain_log_buffers = false;
41static bool auto_explain_log_io = false;
42static bool auto_explain_log_wal = false;
43static bool auto_explain_log_triggers = false;
44static bool auto_explain_log_timing = true;
45static bool auto_explain_log_settings = false;
49static double auto_explain_sample_rate = 1;
51
52/*
53 * Parsed form of one option from auto_explain.log_extension_options.
54 */
61
62/*
63 * Parsed form of the entirety of auto_explain.log_extension_options, stored
64 * as GUC extra. The options[] array will have pointers into the string
65 * following the array.
66 */
68{
71 /* a null-terminated copy of the GUC string follows the array */
73
75
76static const struct config_enum_entry format_options[] = {
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};
83
84static const struct config_enum_entry loglevel_options[] = {
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};
97
98/* Current nesting depth of ExecutorRun calls */
99static int nesting_level = 0;
100
101/* Is the current top-level query to be sampled? */
102static bool current_query_sampled = false;
103
104#define auto_explain_enabled() \
105 (auto_explain_log_min_duration >= 0 && \
106 (nesting_level == 0 || auto_explain_log_nested_statements) && \
107 current_query_sampled)
108
109/* Saved hook values */
114
115static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags);
116static void explain_ExecutorRun(QueryDesc *queryDesc,
117 ScanDirection direction,
118 uint64 count);
119static void explain_ExecutorFinish(QueryDesc *queryDesc);
120static void explain_ExecutorEnd(QueryDesc *queryDesc);
121
122static bool check_log_extension_options(char **newval, void **extra,
124static void assign_log_extension_options(const char *newval, void *extra);
127static char *auto_explain_scan_literal(char **endp, char **nextp);
128static int auto_explain_split_options(char *rawstring,
130 int maxoptions, char **errmsg);
131
132/*
133 * Module load callback
134 */
135void
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}
322
323/*
324 * ExecutorStart hook: start up logging if needed
325 */
326static void
327explain_ExecutorStart(QueryDesc *queryDesc, int eflags)
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}
373
374/*
375 * ExecutorRun hook: all we need do is track nesting depth
376 */
377static void
379 uint64 count)
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}
395
396/*
397 * ExecutorFinish hook: all we need do is track nesting depth
398 */
399static void
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}
416
417/*
418 * ExecutorEnd hook: log results if needed
419 */
420static void
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}
501
502/*
503 * GUC check hook for auto_explain.log_extension_options.
504 */
505static bool
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}
576
577/*
578 * GUC assign hook for auto_explain.log_extension_options.
579 */
580static void
581assign_log_extension_options(const char *newval, void *extra)
582{
584}
585
586/*
587 * Apply parsed extension options to an ExplainState.
588 */
589static void
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}
614
615/*
616 * auto_explain_scan_literal - In-place scanner for single-quoted string
617 * literals.
618 *
619 * This is the single-quote analog of scan_quoted_identifier from varlena.c.
620 */
621static char *
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}
642
643/*
644 * auto_explain_split_options - Parse an option string into an array of
645 * auto_explain_option structs.
646 *
647 * Much of this logic is similar to SplitIdentifierString and friends, but our
648 * needs are different enough that we roll our own parsing logic. The goal here
649 * is to accept the same syntax that the main parser would accept inside of
650 * an EXPLAIN option list. While we can't do that perfectly without adding a
651 * lot more code, the goal of this implementation is to be close enough that
652 * users don't really notice the differences.
653 *
654 * The input string is modified in place (null-terminated, downcased, quotes
655 * collapsed). All name and value pointers in the output array refer into
656 * this string, so the caller must ensure the string outlives the array.
657 *
658 * Returns the full number of options in the input string, but stores no
659 * more than maxoptions into the caller-provided array. If a syntax error
660 * occurs, returns -1 and sets *errmsg.
661 */
662static int
664 int maxoptions, char **errmsg)
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}
static ExecutorRun_hook_type prev_ExecutorRun
static int auto_explain_log_min_duration
static bool auto_explain_log_analyze
static void explain_ExecutorEnd(QueryDesc *queryDesc)
void _PG_init(void)
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 bool auto_explain_log_nested_statements
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 int nesting_level
static bool current_query_sampled
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
#define FLEXIBLE_ARRAY_MEMBER
Definition c.h:558
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 DEBUG3
Definition elog.h:29
#define PG_TRY(...)
Definition elog.h:374
#define WARNING
Definition elog.h:37
#define DEBUG2
Definition elog.h:30
#define PG_END_TRY(...)
Definition elog.h:399
#define DEBUG1
Definition elog.h:31
#define NOTICE
Definition elog.h:36
#define PG_FINALLY(...)
Definition elog.h:391
#define INFO
Definition elog.h:35
#define ereport(elevel,...)
Definition elog.h:152
#define DEBUG5
Definition elog.h:27
#define DEBUG4
Definition elog.h:28
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
void(* ExecutorFinish_hook_type)(QueryDesc *queryDesc)
Definition executor.h:87
void(* ExecutorRun_hook_type)(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition executor.h:81
void(* ExecutorStart_hook_type)(QueryDesc *queryDesc, int eflags)
Definition executor.h:77
void(* ExecutorEnd_hook_type)(QueryDesc *queryDesc)
Definition executor.h:91
#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_XML
@ EXPLAIN_FORMAT_YAML
@ EXPLAIN_FORMAT_TEXT
@ EXPLAIN_FORMAT_JSON
#define PG_MODULE_MAGIC_EXT(...)
Definition fmgr.h:540
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
StringInfo str
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]
Definition guc.h:174
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