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