PostgreSQL Source Code git master
Loading...
Searching...
No Matches
guc_funcs.c
Go to the documentation of this file.
1/*--------------------------------------------------------------------
2 *
3 * guc_funcs.c
4 *
5 * SQL commands and SQL-accessible functions related to GUC variables.
6 *
7 *
8 * Copyright (c) 2000-2026, PostgreSQL Global Development Group
9 * Written by Peter Eisentraut <peter_e@gmx.net>.
10 *
11 * IDENTIFICATION
12 * src/backend/utils/misc/guc_funcs.c
13 *
14 *--------------------------------------------------------------------
15 */
16#include "postgres.h"
17
18#include <sys/stat.h>
19#include <unistd.h>
20
21#include "access/xact.h"
23#include "catalog/pg_authid.h"
25#include "catalog/pg_type_d.h"
26#include "funcapi.h"
27#include "guc_internal.h"
28#include "miscadmin.h"
29#include "parser/parse_type.h"
30#include "utils/acl.h"
31#include "utils/builtins.h"
32#include "utils/guc_tables.h"
33#include "utils/snapmgr.h"
34#include "utils/tuplestore.h"
35
36static char *flatten_set_variable_args(const char *name, List *args);
37static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
38static void ShowAllGUCConfig(DestReceiver *dest);
39
40
41/*
42 * SET command
43 */
44void
46{
47 GucAction action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
48
49 /*
50 * Workers synchronize these parameters at the start of the parallel
51 * operation; then, we block SET during the operation.
52 */
53 if (IsInParallelMode())
56 errmsg("cannot set parameters during a parallel operation")));
57
58 switch (stmt->kind)
59 {
60 case VAR_SET_VALUE:
61 case VAR_SET_CURRENT:
62 if (stmt->is_local)
68 action, true, 0, false);
69 break;
70 case VAR_SET_MULTI:
71
72 /*
73 * Special-case SQL syntaxes. The TRANSACTION and SESSION
74 * CHARACTERISTICS cases effectively set more than one variable
75 * per statement. TRANSACTION SNAPSHOT only takes one argument,
76 * but we put it here anyway since it's a special case and not
77 * related to any GUC variable.
78 */
79 if (strcmp(stmt->name, "TRANSACTION") == 0)
80 {
81 ListCell *head;
82
83 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
84
85 foreach(head, stmt->args)
86 {
87 DefElem *item = (DefElem *) lfirst(head);
88
89 if (strcmp(item->defname, "transaction_isolation") == 0)
90 SetPGVariable("transaction_isolation",
91 list_make1(item->arg), stmt->is_local);
92 else if (strcmp(item->defname, "transaction_read_only") == 0)
93 SetPGVariable("transaction_read_only",
94 list_make1(item->arg), stmt->is_local);
95 else if (strcmp(item->defname, "transaction_deferrable") == 0)
96 SetPGVariable("transaction_deferrable",
97 list_make1(item->arg), stmt->is_local);
98 else
99 elog(ERROR, "unexpected SET TRANSACTION element: %s",
100 item->defname);
101 }
102 }
103 else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
104 {
105 ListCell *head;
106
107 foreach(head, stmt->args)
108 {
109 DefElem *item = (DefElem *) lfirst(head);
110
111 if (strcmp(item->defname, "transaction_isolation") == 0)
112 SetPGVariable("default_transaction_isolation",
113 list_make1(item->arg), stmt->is_local);
114 else if (strcmp(item->defname, "transaction_read_only") == 0)
115 SetPGVariable("default_transaction_read_only",
116 list_make1(item->arg), stmt->is_local);
117 else if (strcmp(item->defname, "transaction_deferrable") == 0)
118 SetPGVariable("default_transaction_deferrable",
119 list_make1(item->arg), stmt->is_local);
120 else
121 elog(ERROR, "unexpected SET SESSION element: %s",
122 item->defname);
123 }
124 }
125 else if (strcmp(stmt->name, "TRANSACTION SNAPSHOT") == 0)
126 {
127 A_Const *con = linitial_node(A_Const, stmt->args);
128
129 if (stmt->is_local)
132 errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
133
134 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
135 ImportSnapshot(strVal(&con->val));
136 }
137 else
138 elog(ERROR, "unexpected SET MULTI element: %s",
139 stmt->name);
140 break;
141 case VAR_SET_DEFAULT:
142 if (stmt->is_local)
145 case VAR_RESET:
147 NULL,
150 action, true, 0, false);
151 break;
152 case VAR_RESET_ALL:
154 break;
155 }
156
157 /* Invoke the post-alter hook for setting this GUC variable, by name. */
159 ACL_SET, stmt->kind, false);
160}
161
162/*
163 * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
164 * The result is palloc'd.
165 *
166 * This is exported for use by actions such as ALTER ROLE SET.
167 */
168char *
170{
171 switch (stmt->kind)
172 {
173 case VAR_SET_VALUE:
174 return flatten_set_variable_args(stmt->name, stmt->args);
175 case VAR_SET_CURRENT:
176 return GetConfigOptionByName(stmt->name, NULL, false);
177 default:
178 return NULL;
179 }
180}
181
182/*
183 * flatten_set_variable_args
184 * Given a parsenode List as emitted by the grammar for SET,
185 * convert to the flat string representation used by GUC.
186 *
187 * We need to be told the name of the variable the args are for, because
188 * the flattening rules vary (ugh).
189 *
190 * The result is NULL if args is NIL (i.e., SET ... TO DEFAULT), otherwise
191 * a palloc'd string.
192 */
193static char *
195{
196 struct config_generic *record;
197 int flags;
199 ListCell *l;
200
201 /* Fast path if just DEFAULT */
202 if (args == NIL)
203 return NULL;
204
205 /*
206 * Get flags for the variable; if it's not known, use default flags.
207 * (Caller might throw error later, but not our business to do so here.)
208 */
209 record = find_option(name, false, true, WARNING);
210 if (record)
211 flags = record->flags;
212 else
213 flags = 0;
214
215 /*
216 * Handle special cases for list input.
217 */
218 if (flags & GUC_LIST_INPUT)
219 {
220 /* NULL represents an empty list. */
221 if (list_length(args) == 1)
222 {
223 Node *arg = (Node *) linitial(args);
224
225 if (IsA(arg, A_Const) &&
226 ((A_Const *) arg)->isnull)
227 return pstrdup("");
228 }
229 }
230 else
231 {
232 /* Complain if list input and non-list variable. */
233 if (list_length(args) != 1)
236 errmsg("SET %s takes only one argument", name)));
237 }
238
240
241 /*
242 * Each list member may be a plain A_Const node, or an A_Const within a
243 * TypeCast; the latter case is supported only for ConstInterval arguments
244 * (for SET TIME ZONE).
245 */
246 foreach(l, args)
247 {
248 Node *arg = (Node *) lfirst(l);
249 char *val;
250 TypeName *typeName = NULL;
251 A_Const *con;
252
253 if (l != list_head(args))
255
256 if (IsA(arg, TypeCast))
257 {
258 TypeCast *tc = (TypeCast *) arg;
259
260 arg = tc->arg;
261 typeName = tc->typeName;
262 }
263
264 if (!IsA(arg, A_Const))
265 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
266 con = (A_Const *) arg;
267
268 /* Complain if NULL is used with a non-list variable. */
269 if (con->isnull)
272 errmsg("NULL is an invalid value for %s", name)));
273
274 switch (nodeTag(&con->val))
275 {
276 case T_Integer:
277 appendStringInfo(&buf, "%d", intVal(&con->val));
278 break;
279 case T_Float:
280 /* represented as a string, so just copy it */
282 break;
283 case T_String:
284 val = strVal(&con->val);
285 if (typeName != NULL)
286 {
287 /*
288 * Must be a ConstInterval argument for TIME ZONE. Coerce
289 * to interval and back to normalize the value and account
290 * for any typmod.
291 */
292 Oid typoid;
293 int32 typmod;
295 char *intervalout;
296
297 /* gram.y ensures this is only reachable for TIME ZONE */
299
300 typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod);
301 Assert(typoid == INTERVALOID);
302
303 interval =
307 Int32GetDatum(typmod));
308
311 interval));
312 appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
313 }
314 else
315 {
316 /*
317 * Plain string literal or identifier. For quote mode,
318 * quote it if it's not a vanilla identifier.
319 */
320 if (flags & GUC_LIST_QUOTE)
322 else
324 }
325 break;
326 default:
327 elog(ERROR, "unrecognized node type: %d",
328 (int) nodeTag(&con->val));
329 break;
330 }
331 }
332
333 return buf.data;
334}
335
336/*
337 * SetPGVariable - SET command exported as an easily-C-callable function.
338 *
339 * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
340 * by passing args == NIL), but not SET FROM CURRENT functionality.
341 */
342void
343SetPGVariable(const char *name, List *args, bool is_local)
344{
346
347 /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
349 argstring,
352 is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
353 true, 0, false);
354}
355
356/*
357 * SET command wrapped as a SQL callable function.
358 */
359Datum
361{
362 char *name;
363 char *value;
364 char *new_value;
365 bool is_local;
366
367 if (PG_ARGISNULL(0))
370 errmsg("SET requires parameter name")));
371
372 /* Get the GUC variable name */
374
375 /* Get the desired value or set to NULL for a reset request */
376 if (PG_ARGISNULL(1))
377 value = NULL;
378 else
380
381 /*
382 * Get the desired state of is_local. Default to false if provided value
383 * is NULL
384 */
385 if (PG_ARGISNULL(2))
386 is_local = false;
387 else
388 is_local = PG_GETARG_BOOL(2);
389
390 /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
392 value,
395 is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
396 true, 0, false);
397
398 /* get the new current value */
400
401 /* Convert return string to text */
403}
404
405
406/*
407 * SHOW command
408 */
409void
410GetPGVariable(const char *name, DestReceiver *dest)
411{
412 if (guc_name_compare(name, "all") == 0)
413 ShowAllGUCConfig(dest);
414 else
416}
417
418/*
419 * Get a tuple descriptor for SHOW's result
420 */
423{
424 TupleDesc tupdesc;
425
426 if (guc_name_compare(name, "all") == 0)
427 {
428 /* need a tuple descriptor representing three TEXT columns */
429 tupdesc = CreateTemplateTupleDesc(3);
430 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
431 TEXTOID, -1, 0);
432 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
433 TEXTOID, -1, 0);
434 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
435 TEXTOID, -1, 0);
436 }
437 else
438 {
439 const char *varname;
440
441 /* Get the canonical spelling of name */
442 (void) GetConfigOptionByName(name, &varname, false);
443
444 /* need a tuple descriptor representing a single TEXT column */
445 tupdesc = CreateTemplateTupleDesc(1);
446 TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
447 TEXTOID, -1, 0);
448 }
449 TupleDescFinalize(tupdesc);
450 return tupdesc;
451}
452
453/*
454 * SHOW one variable
455 */
456static void
458{
460 TupleDesc tupdesc;
461 const char *varname;
462 char *value;
463
464 /* Get the value and canonical spelling of name */
465 value = GetConfigOptionByName(name, &varname, false);
466
467 /* need a tuple descriptor representing a single TEXT column */
468 tupdesc = CreateTemplateTupleDesc(1);
469 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname,
470 TEXTOID, -1, 0);
471 TupleDescFinalize(tupdesc);
472
473 /* prepare for projection of tuples */
475
476 /* Send it */
478
480}
481
482/*
483 * SHOW ALL command
484 */
485static void
487{
488 struct config_generic **guc_vars;
489 int num_vars;
491 TupleDesc tupdesc;
492 Datum values[3];
493 bool isnull[3] = {false, false, false};
494
495 /* collect the variables, in sorted order */
496 guc_vars = get_guc_variables(&num_vars);
497
498 /* need a tuple descriptor representing three TEXT columns */
499 tupdesc = CreateTemplateTupleDesc(3);
500 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "name",
501 TEXTOID, -1, 0);
502 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "setting",
503 TEXTOID, -1, 0);
504 TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "description",
505 TEXTOID, -1, 0);
506 TupleDescFinalize(tupdesc);
507
508 /* prepare for projection of tuples */
510
511 for (int i = 0; i < num_vars; i++)
512 {
513 struct config_generic *conf = guc_vars[i];
514 char *setting;
515
516 /* skip if marked NO_SHOW_ALL */
517 if (conf->flags & GUC_NO_SHOW_ALL)
518 continue;
519
520 /* return only options visible to the current user */
522 continue;
523
524 /* assign to the values array */
526
527 setting = ShowGUCOption(conf, true);
528 if (setting)
529 {
531 isnull[1] = false;
532 }
533 else
534 {
536 isnull[1] = true;
537 }
538
539 if (conf->short_desc)
540 {
541 values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
542 isnull[2] = false;
543 }
544 else
545 {
547 isnull[2] = true;
548 }
549
550 /* send it to dest */
551 do_tup_output(tstate, values, isnull);
552
553 /* clean up */
555 if (setting)
556 {
557 pfree(setting);
559 }
560 if (conf->short_desc)
562 }
563
565}
566
567/*
568 * Return some of the flags associated to the specified GUC in the shape of
569 * a text array, and NULL if it does not exist. An empty array is returned
570 * if the GUC exists without any meaningful flags to show.
571 */
572Datum
574{
575#define MAX_GUC_FLAGS 6
576 char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
577 struct config_generic *record;
578 int cnt = 0;
580 ArrayType *a;
581
582 record = find_option(varname, false, true, ERROR);
583
584 /* return NULL if no such variable */
585 if (record == NULL)
587
588 if (record->flags & GUC_EXPLAIN)
589 flags[cnt++] = CStringGetTextDatum("EXPLAIN");
590 if (record->flags & GUC_NO_RESET)
591 flags[cnt++] = CStringGetTextDatum("NO_RESET");
592 if (record->flags & GUC_NO_RESET_ALL)
593 flags[cnt++] = CStringGetTextDatum("NO_RESET_ALL");
594 if (record->flags & GUC_NO_SHOW_ALL)
595 flags[cnt++] = CStringGetTextDatum("NO_SHOW_ALL");
596 if (record->flags & GUC_NOT_IN_SAMPLE)
597 flags[cnt++] = CStringGetTextDatum("NOT_IN_SAMPLE");
598 if (record->flags & GUC_RUNTIME_COMPUTED)
599 flags[cnt++] = CStringGetTextDatum("RUNTIME_COMPUTED");
600
601 Assert(cnt <= MAX_GUC_FLAGS);
602
603 /* Returns the record as Datum */
606}
607
608/*
609 * Return whether or not the GUC variable is visible to the current user.
610 */
611bool
613{
614 if ((conf->flags & GUC_SUPERUSER_ONLY) &&
616 return false;
617 else
618 return true;
619}
620
621/*
622 * Extract fields to show in pg_settings for given variable.
623 */
624static void
626{
627 char buffer[256];
628
629 /* first get the generic attributes */
630
631 /* name */
632 values[0] = conf->name;
633
634 /* setting: use ShowGUCOption in order to avoid duplicating the logic */
635 values[1] = ShowGUCOption(conf, false);
636
637 /* unit, if any (NULL is fine) */
638 values[2] = get_config_unit_name(conf->flags);
639
640 /* group */
641 values[3] = _(config_group_names[conf->group]);
642
643 /* short_desc */
644 values[4] = conf->short_desc != NULL ? _(conf->short_desc) : NULL;
645
646 /* extra_desc */
647 values[5] = conf->long_desc != NULL ? _(conf->long_desc) : NULL;
648
649 /* context */
650 values[6] = GucContext_Names[conf->context];
651
652 /* vartype */
653 values[7] = config_type_names[conf->vartype];
654
655 /* source */
656 values[8] = GucSource_Names[conf->source];
657
658 /* now get the type specific attributes */
659 switch (conf->vartype)
660 {
661 case PGC_BOOL:
662 {
663 const struct config_bool *lconf = &conf->_bool;
664
665 /* min_val */
666 values[9] = NULL;
667
668 /* max_val */
669 values[10] = NULL;
670
671 /* enumvals */
672 values[11] = NULL;
673
674 /* boot_val */
675 values[12] = pstrdup(lconf->boot_val ? "on" : "off");
676
677 /* reset_val */
678 values[13] = pstrdup(lconf->reset_val ? "on" : "off");
679 }
680 break;
681
682 case PGC_INT:
683 {
684 const struct config_int *lconf = &conf->_int;
685
686 /* min_val */
687 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
688 values[9] = pstrdup(buffer);
689
690 /* max_val */
691 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
692 values[10] = pstrdup(buffer);
693
694 /* enumvals */
695 values[11] = NULL;
696
697 /* boot_val */
698 snprintf(buffer, sizeof(buffer), "%d", lconf->boot_val);
699 values[12] = pstrdup(buffer);
700
701 /* reset_val */
702 snprintf(buffer, sizeof(buffer), "%d", lconf->reset_val);
703 values[13] = pstrdup(buffer);
704 }
705 break;
706
707 case PGC_REAL:
708 {
709 const struct config_real *lconf = &conf->_real;
710
711 /* min_val */
712 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
713 values[9] = pstrdup(buffer);
714
715 /* max_val */
716 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
717 values[10] = pstrdup(buffer);
718
719 /* enumvals */
720 values[11] = NULL;
721
722 /* boot_val */
723 snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val);
724 values[12] = pstrdup(buffer);
725
726 /* reset_val */
727 snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val);
728 values[13] = pstrdup(buffer);
729 }
730 break;
731
732 case PGC_STRING:
733 {
734 const struct config_string *lconf = &conf->_string;
735
736 /* min_val */
737 values[9] = NULL;
738
739 /* max_val */
740 values[10] = NULL;
741
742 /* enumvals */
743 values[11] = NULL;
744
745 /* boot_val */
746 if (lconf->boot_val == NULL)
747 values[12] = NULL;
748 else
749 values[12] = pstrdup(lconf->boot_val);
750
751 /* reset_val */
752 if (lconf->reset_val == NULL)
753 values[13] = NULL;
754 else
755 values[13] = pstrdup(lconf->reset_val);
756 }
757 break;
758
759 case PGC_ENUM:
760 {
761 const struct config_enum *lconf = &conf->_enum;
762
763 /* min_val */
764 values[9] = NULL;
765
766 /* max_val */
767 values[10] = NULL;
768
769 /* enumvals */
770
771 /*
772 * NOTE! enumvals with double quotes in them are not
773 * supported!
774 */
776 "{\"", "\"}", "\",\"");
777
778 /* boot_val */
780 lconf->boot_val));
781
782 /* reset_val */
784 lconf->reset_val));
785 }
786 break;
787
788 default:
789 {
790 /*
791 * should never get here, but in case we do, set 'em to NULL
792 */
793
794 /* min_val */
795 values[9] = NULL;
796
797 /* max_val */
798 values[10] = NULL;
799
800 /* enumvals */
801 values[11] = NULL;
802
803 /* boot_val */
804 values[12] = NULL;
805
806 /* reset_val */
807 values[13] = NULL;
808 }
809 break;
810 }
811
812 /*
813 * If the setting came from a config file, set the source location. For
814 * security reasons, we don't show source file/line number for
815 * insufficiently-privileged users.
816 */
817 if (conf->source == PGC_S_FILE &&
819 {
820 values[14] = conf->sourcefile;
821 snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);
822 values[15] = pstrdup(buffer);
823 }
824 else
825 {
826 values[14] = NULL;
827 values[15] = NULL;
828 }
829
830 values[16] = (conf->status & GUC_PENDING_RESTART) ? "t" : "f";
831}
832
833/*
834 * show_config_by_name - equiv to SHOW X command but implemented as
835 * a function.
836 */
837Datum
839{
840 char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
841 char *varval;
842
843 /* Get the value */
844 varval = GetConfigOptionByName(varname, NULL, false);
845
846 /* Convert to text */
848}
849
850/*
851 * show_config_by_name_missing_ok - equiv to SHOW X command but implemented as
852 * a function. If X does not exist, suppress the error and just return NULL
853 * if missing_ok is true.
854 */
855Datum
857{
858 char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
859 bool missing_ok = PG_GETARG_BOOL(1);
860 char *varval;
861
862 /* Get the value */
863 varval = GetConfigOptionByName(varname, NULL, missing_ok);
864
865 /* return NULL if no such variable */
866 if (varval == NULL)
868
869 /* Convert to text */
871}
872
873/*
874 * show_all_settings - equiv to SHOW ALL command but implemented as
875 * a Table Function.
876 */
877#define NUM_PG_SETTINGS_ATTS 17
878
879Datum
881{
883 struct config_generic **guc_vars;
884 int num_vars;
885 TupleDesc tupdesc;
886 int call_cntr;
887 int max_calls;
888 AttInMetadata *attinmeta;
889 MemoryContext oldcontext;
890
891 /* stuff done only on the first call of the function */
892 if (SRF_IS_FIRSTCALL())
893 {
894 /* create a function context for cross-call persistence */
896
897 /*
898 * switch to memory context appropriate for multiple function calls
899 */
900 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
901
902 /*
903 * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
904 * of the appropriate types
905 */
907 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
908 TEXTOID, -1, 0);
909 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
910 TEXTOID, -1, 0);
911 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
912 TEXTOID, -1, 0);
913 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
914 TEXTOID, -1, 0);
915 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
916 TEXTOID, -1, 0);
917 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
918 TEXTOID, -1, 0);
919 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
920 TEXTOID, -1, 0);
921 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
922 TEXTOID, -1, 0);
923 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
924 TEXTOID, -1, 0);
925 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
926 TEXTOID, -1, 0);
927 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
928 TEXTOID, -1, 0);
929 TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
930 TEXTARRAYOID, -1, 0);
931 TupleDescInitEntry(tupdesc, (AttrNumber) 13, "boot_val",
932 TEXTOID, -1, 0);
933 TupleDescInitEntry(tupdesc, (AttrNumber) 14, "reset_val",
934 TEXTOID, -1, 0);
935 TupleDescInitEntry(tupdesc, (AttrNumber) 15, "sourcefile",
936 TEXTOID, -1, 0);
937 TupleDescInitEntry(tupdesc, (AttrNumber) 16, "sourceline",
938 INT4OID, -1, 0);
939 TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
940 BOOLOID, -1, 0);
941
942 TupleDescFinalize(tupdesc);
943
944 /*
945 * Generate attribute metadata needed later to produce tuples from raw
946 * C strings
947 */
948 attinmeta = TupleDescGetAttInMetadata(tupdesc);
949 funcctx->attinmeta = attinmeta;
950
951 /* collect the variables, in sorted order */
952 guc_vars = get_guc_variables(&num_vars);
953
954 /* use user_fctx to remember the array location */
955 funcctx->user_fctx = guc_vars;
956
957 /* total number of tuples to be returned */
958 funcctx->max_calls = num_vars;
959
960 MemoryContextSwitchTo(oldcontext);
961 }
962
963 /* stuff done on every call of the function */
965
966 guc_vars = (struct config_generic **) funcctx->user_fctx;
967 call_cntr = funcctx->call_cntr;
968 max_calls = funcctx->max_calls;
969 attinmeta = funcctx->attinmeta;
970
971 while (call_cntr < max_calls) /* do when there is more left to send */
972 {
973 struct config_generic *conf = guc_vars[call_cntr];
975 HeapTuple tuple;
976 Datum result;
977
978 /* skip if marked NO_SHOW_ALL or if not visible to current user */
979 if ((conf->flags & GUC_NO_SHOW_ALL) ||
981 {
982 call_cntr = ++funcctx->call_cntr;
983 continue;
984 }
985
986 /* extract values for the current variable */
987 GetConfigOptionValues(conf, (const char **) values);
988
989 /* build a tuple */
990 tuple = BuildTupleFromCStrings(attinmeta, values);
991
992 /* make the tuple into a datum */
993 result = HeapTupleGetDatum(tuple);
994
995 SRF_RETURN_NEXT(funcctx, result);
996 }
997
998 /* do when there is no more left */
1000}
1001
1002/*
1003 * show_all_file_settings
1004 *
1005 * Returns a table of all parameter settings in all configuration files
1006 * which includes the config file pathname, the line number, a sequence number
1007 * indicating the order in which the settings were encountered, the parameter
1008 * name and value, a bool showing if the value could be applied, and possibly
1009 * an associated error message. (For problems such as syntax errors, the
1010 * parameter name/value might be NULL.)
1011 *
1012 * Note: no filtering is done here, instead we depend on the GRANT system
1013 * to prevent unprivileged users from accessing this function or the view
1014 * built on top of it.
1015 */
1016Datum
1018{
1019#define NUM_PG_FILE_SETTINGS_ATTS 7
1020 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1022
1023 /* Scan the config files using current context as workspace */
1025
1026 /* Build a tuplestore to return our results in */
1027 InitMaterializedSRF(fcinfo, 0);
1028
1029 /* Process the results and create a tuplestore */
1030 for (int seqno = 1; conf != NULL; conf = conf->next, seqno++)
1031 {
1033 bool nulls[NUM_PG_FILE_SETTINGS_ATTS];
1034
1035 memset(values, 0, sizeof(values));
1036 memset(nulls, 0, sizeof(nulls));
1037
1038 /* sourcefile */
1039 if (conf->filename)
1040 values[0] = PointerGetDatum(cstring_to_text(conf->filename));
1041 else
1042 nulls[0] = true;
1043
1044 /* sourceline (not meaningful if no sourcefile) */
1045 if (conf->filename)
1046 values[1] = Int32GetDatum(conf->sourceline);
1047 else
1048 nulls[1] = true;
1049
1050 /* seqno */
1052
1053 /* name */
1054 if (conf->name)
1056 else
1057 nulls[3] = true;
1058
1059 /* setting */
1060 if (conf->value)
1062 else
1063 nulls[4] = true;
1064
1065 /* applied */
1066 values[5] = BoolGetDatum(conf->applied);
1067
1068 /* error */
1069 if (conf->errmsg)
1071 else
1072 nulls[6] = true;
1073
1074 /* shove row into tuplestore */
1075 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
1076 }
1077
1078 return (Datum) 0;
1079}
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5314
#define PG_RETURN_ARRAYTYPE_P(x)
Definition array.h:265
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
int16 AttrNumber
Definition attnum.h:21
Datum interval_out(PG_FUNCTION_ARGS)
Definition timestamp.c:966
Datum interval_in(PG_FUNCTION_ARGS)
Definition timestamp.c:884
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define TextDatumGetCString(d)
Definition builtins.h:99
#define Assert(condition)
Definition c.h:945
int32_t int32
Definition c.h:614
#define pg_fallthrough
Definition c.h:152
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
#define _(x)
Definition elog.c:95
#define DEBUG3
Definition elog.h:28
#define WARNING
Definition elog.h:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
const TupleTableSlotOps TTSOpsVirtual
Definition execTuples.c:84
void end_tup_output(TupOutputState *tstate)
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
#define do_text_output_oneline(tstate, str_to_emit)
Definition executor.h:632
#define PG_ARGISNULL(n)
Definition fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_RETURN_TEXT_P(x)
Definition fmgr.h:374
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:688
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition funcapi.c:76
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
const char * config_enum_lookup_by_value(const struct config_generic *record, int val)
Definition guc.c:2927
char * config_enum_get_options(const struct config_enum *record, const char *prefix, const char *suffix, const char *separator)
Definition guc.c:2972
const char * get_config_unit_name(int flags)
Definition guc.c:2718
char * GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
Definition guc.c:5333
struct config_generic ** get_guc_variables(int *num_vars)
Definition guc.c:840
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
Definition guc.c:1114
void ResetAllOptions(void)
Definition guc.c:1910
ConfigVariable * ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
Definition guc.c:285
int guc_name_compare(const char *namea, const char *nameb)
Definition guc.c:1178
char * ShowGUCOption(const struct config_generic *record, bool use_units)
Definition guc.c:5366
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition guc.c:3248
GucAction
Definition guc.h:201
@ GUC_ACTION_SET
Definition guc.h:203
@ GUC_ACTION_LOCAL
Definition guc.h:204
#define GUC_EXPLAIN
Definition guc.h:219
#define GUC_SUPERUSER_ONLY
Definition guc.h:224
#define GUC_NO_RESET_ALL
Definition guc.h:218
#define GUC_NO_RESET
Definition guc.h:217
#define GUC_LIST_QUOTE
Definition guc.h:215
#define GUC_LIST_INPUT
Definition guc.h:214
#define GUC_RUNTIME_COMPUTED
Definition guc.h:229
@ PGC_S_FILE
Definition guc.h:116
@ PGC_S_SESSION
Definition guc.h:126
#define GUC_NO_SHOW_ALL
Definition guc.h:216
@ PGC_SUSET
Definition guc.h:78
@ PGC_USERSET
Definition guc.h:79
@ PGC_SIGHUP
Definition guc.h:75
#define GUC_NOT_IN_SAMPLE
Definition guc.h:221
void GetPGVariable(const char *name, DestReceiver *dest)
Definition guc_funcs.c:410
static void ShowGUCConfigOption(const char *name, DestReceiver *dest)
Definition guc_funcs.c:457
static void GetConfigOptionValues(const struct config_generic *conf, const char **values)
Definition guc_funcs.c:625
Datum set_config_by_name(PG_FUNCTION_ARGS)
Definition guc_funcs.c:360
static char * flatten_set_variable_args(const char *name, List *args)
Definition guc_funcs.c:194
Datum show_config_by_name(PG_FUNCTION_ARGS)
Definition guc_funcs.c:838
#define NUM_PG_SETTINGS_ATTS
Definition guc_funcs.c:877
bool ConfigOptionIsVisible(const struct config_generic *conf)
Definition guc_funcs.c:612
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition guc_funcs.c:169
#define MAX_GUC_FLAGS
TupleDesc GetPGVariableResultDesc(const char *name)
Definition guc_funcs.c:422
#define NUM_PG_FILE_SETTINGS_ATTS
void SetPGVariable(const char *name, List *args, bool is_local)
Definition guc_funcs.c:343
Datum show_all_file_settings(PG_FUNCTION_ARGS)
Definition guc_funcs.c:1017
void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
Definition guc_funcs.c:45
Datum show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
Definition guc_funcs.c:856
Datum pg_settings_get_flags(PG_FUNCTION_ARGS)
Definition guc_funcs.c:573
Datum show_all_settings(PG_FUNCTION_ARGS)
Definition guc_funcs.c:880
static void ShowAllGUCConfig(DestReceiver *dest)
Definition guc_funcs.c:486
const char *const GucContext_Names[]
Definition guc_tables.c:676
const char *const GucSource_Names[]
Definition guc_tables.c:695
const char *const config_type_names[]
Definition guc_tables.c:779
const char *const config_group_names[]
Definition guc_tables.c:719
@ PGC_BOOL
Definition guc_tables.h:25
@ PGC_STRING
Definition guc_tables.h:28
@ PGC_ENUM
Definition guc_tables.h:29
@ PGC_REAL
Definition guc_tables.h:27
@ PGC_INT
Definition guc_tables.h:26
#define GUC_PENDING_RESTART
Definition guc_tables.h:299
#define stmt
long val
Definition informix.c:689
static struct @175 value
int a
Definition isn.c:73
int i
Definition isn.c:77
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
Oid GetUserId(void)
Definition miscinit.c:470
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
#define castNode(_type_, nodeptr)
Definition nodes.h:182
static char * errmsg
#define InvokeObjectPostAlterHookArgStr(classId, objectName, subId, auxiliaryId, is_internal)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition parse_type.c:310
#define ACL_SET
Definition parsenodes.h:88
@ VAR_SET_DEFAULT
@ VAR_RESET
@ VAR_SET_MULTI
@ VAR_SET_VALUE
@ VAR_SET_CURRENT
@ VAR_RESET_ALL
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial_node(type, l)
Definition pg_list.h:181
#define NIL
Definition pg_list.h:68
#define list_make1(x1)
Definition pg_list.h:244
#define linitial(l)
Definition pg_list.h:178
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static char * DatumGetCString(Datum X)
Definition postgres.h:355
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
unsigned int Oid
static int fb(int x)
const char * quote_identifier(const char *ident)
void ImportSnapshot(const char *idstr)
Definition snapmgr.c:1387
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
bool isnull
Definition parsenodes.h:388
union ValUnion val
Definition parsenodes.h:387
char * defname
Definition parsenodes.h:857
Node * arg
Definition parsenodes.h:858
Definition value.h:48
Definition pg_list.h:54
Definition nodes.h:135
Node * arg
Definition parsenodes.h:398
bool superuser(void)
Definition superuser.c:47
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitBuiltinEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:976
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:900
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
#define intVal(v)
Definition value.h:79
#define strVal(v)
Definition value.h:82
text * cstring_to_text(const char *s)
Definition varlena.c:184
const char * name
void WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
Definition xact.c:3733
bool IsInParallelMode(void)
Definition xact.c:1091