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