1/*--------------------------------------------------------------------
5 * SQL commands and SQL-accessible functions related to GUC variables.
8 * Copyright (c) 2000-2025, PostgreSQL Global Development Group
9 * Written by Peter Eisentraut <peter_e@gmx.net>.
12 * src/backend/utils/misc/guc_funcs.c
14 *--------------------------------------------------------------------
48 * Workers synchronize these parameters at the start of the parallel
49 * operation; then, we block SET during the operation.
53 (
errcode(ERRCODE_INVALID_TRANSACTION_STATE),
54 errmsg(
"cannot set parameters during a parallel operation")));
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.
77 if (strcmp(
stmt->name,
"TRANSACTION") == 0)
83 foreach(head,
stmt->args)
87 if (strcmp(item->
defname,
"transaction_isolation") == 0)
90 else if (strcmp(item->
defname,
"transaction_read_only") == 0)
93 else if (strcmp(item->
defname,
"transaction_deferrable") == 0)
97 elog(
ERROR,
"unexpected SET TRANSACTION element: %s",
101 else if (strcmp(
stmt->name,
"SESSION CHARACTERISTICS") == 0)
105 foreach(head,
stmt->args)
109 if (strcmp(item->
defname,
"transaction_isolation") == 0)
112 else if (strcmp(item->
defname,
"transaction_read_only") == 0)
115 else if (strcmp(item->
defname,
"transaction_deferrable") == 0)
119 elog(
ERROR,
"unexpected SET SESSION element: %s",
123 else if (strcmp(
stmt->name,
"TRANSACTION SNAPSHOT") == 0)
129 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
130 errmsg(
"SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
136 elog(
ERROR,
"unexpected SET MULTI element: %s",
155 /* Invoke the post-alter hook for setting this GUC variable, by name. */
161 * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
162 * The result is palloc'd.
164 * This is exported for use by actions such as ALTER ROLE SET.
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.
185 * We need to be told the name of the variable the args are for, because
186 * the flattening rules vary (ugh).
188 * The result is NULL if args is NIL (i.e., SET ... TO DEFAULT), otherwise
199 /* Fast path if just DEFAULT */
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.)
213 /* Complain if list input and non-list variable */
217 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
218 errmsg(
"SET %s takes only one argument",
name)));
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).
255 /* represented as a string, so just copy it */
260 if (typeName != NULL)
263 * Must be a ConstInterval argument for TIME ZONE. Coerce
264 * to interval and back to normalize the value and account
273 Assert(typoid == INTERVALOID);
289 * Plain string literal or identifier. For quote mode,
290 * quote it if it's not a vanilla identifier.
299 elog(
ERROR,
"unrecognized node type: %d",
309 * SetPGVariable - SET command exported as an easily-C-callable function.
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.
319 /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
329 * SET command wrapped as a SQL callable function.
341 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
342 errmsg(
"SET requires parameter name")));
344 /* Get the GUC variable name */
347 /* Get the desired value or set to NULL for a reset request */
354 * Get the desired state of is_local. Default to false if provided value
362 /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
370 /* get the new current value */
373 /* Convert return string to text */
391 * Get a tuple descriptor for SHOW's result
400 /* need a tuple descriptor representing three TEXT columns */
413 /* Get the canonical spelling of name */
416 /* need a tuple descriptor representing a single TEXT column */
435 /* Get the value and canonical spelling of name */
438 /* need a tuple descriptor representing a single TEXT column */
443 /* prepare for projection of tuples */
463 bool isnull[3] = {
false,
false,
false};
465 /* collect the variables, in sorted order */
468 /* need a tuple descriptor representing three TEXT columns */
477 /* prepare for projection of tuples */
480 for (
int i = 0;
i < num_vars;
i++)
485 /* skip if marked NO_SHOW_ALL */
489 /* return only options visible to the current user */
493 /* assign to the values array */
519 /* send it to dest */
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.
544#define MAX_GUC_FLAGS 6
553 /* return NULL if no such variable */
572 /* Returns the record as Datum */
578 * Return whether or not the GUC variable is visible to the current user.
591 * Extract fields to show in pg_settings for given variable.
598 /* first get the generic attributes */
603 /* setting: use ShowGUCOption in order to avoid duplicating the logic */
606 /* unit, if any (NULL is fine) */
627 /* now get the type specific attributes */
656 snprintf(buffer,
sizeof(buffer),
"%d", lconf->
min);
660 snprintf(buffer,
sizeof(buffer),
"%d", lconf->
max);
681 snprintf(buffer,
sizeof(buffer),
"%g", lconf->
min);
685 snprintf(buffer,
sizeof(buffer),
"%g", lconf->
max);
741 * NOTE! enumvals with double quotes in them are not
745 "{\"",
"\"}",
"\",\"");
760 * should never get here, but in case we do, set 'em to NULL
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.
803 * show_config_by_name - equiv to SHOW X command but implemented as
815 /* Convert to text */
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.
834 /* return NULL if no such variable */
838 /* Convert to text */
843 * show_all_settings - equiv to SHOW ALL command but implemented as
846 #define NUM_PG_SETTINGS_ATTS 17
860 /* stuff done only on the first call of the function */
863 /* create a function context for cross-call persistence */
867 * switch to memory context appropriate for multiple function calls
872 * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
873 * of the appropriate types
899 TEXTARRAYOID, -1, 0);
912 * Generate attribute metadata needed later to produce tuples from raw
918 /* collect the variables, in sorted order */
921 /* use user_fctx to remember the array location */
924 /* total number of tuples to be returned */
930 /* stuff done on every call of the function */
938 while (call_cntr < max_calls)
/* do when there is more left to send */
945 /* skip if marked NO_SHOW_ALL or if not visible to current user */
953 /* extract values for the current variable */
959 /* make the tuple into a datum */
965 /* do when there is no more left */
970 * show_all_file_settings
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.)
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.
986#define NUM_PG_FILE_SETTINGS_ATTS 7
991 /* Scan the config files using current context as workspace */
994 /* Build a tuplestore to return our results in */
997 /* Process the results and create a tuplestore */
998 for (seqno = 1; conf != NULL; conf = conf->next, seqno++)
1004 memset(nulls, 0,
sizeof(nulls));
1012 /* sourceline (not meaningful if no sourcefile) */
1042 /* shove row into tuplestore */
bool has_privs_of_role(Oid member, Oid role)
#define PG_RETURN_ARRAYTYPE_P(x)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Datum interval_out(PG_FUNCTION_ARGS)
Datum interval_in(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
const TupleTableSlotOps TTSOpsVirtual
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)
#define DirectFunctionCall1(func, arg1)
#define PG_GETARG_DATUM(n)
#define PG_RETURN_TEXT_P(x)
#define PG_GETARG_BOOL(n)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
const char * get_config_unit_name(int flags)
char * GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
struct config_generic ** get_guc_variables(int *num_vars)
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
char * config_enum_get_options(struct config_enum *record, const char *prefix, const char *suffix, const char *separator)
void ResetAllOptions(void)
const char * config_enum_lookup_by_value(struct config_enum *record, int val)
char * ShowGUCOption(struct config_generic *record, bool use_units)
ConfigVariable * ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
int guc_name_compare(const char *namea, const char *nameb)
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
#define GUC_SUPERUSER_ONLY
#define GUC_RUNTIME_COMPUTED
#define GUC_NOT_IN_SAMPLE
void GetPGVariable(const char *name, DestReceiver *dest)
static void ShowGUCConfigOption(const char *name, DestReceiver *dest)
Datum set_config_by_name(PG_FUNCTION_ARGS)
static char * flatten_set_variable_args(const char *name, List *args)
Datum show_config_by_name(PG_FUNCTION_ARGS)
#define NUM_PG_SETTINGS_ATTS
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
TupleDesc GetPGVariableResultDesc(const char *name)
#define NUM_PG_FILE_SETTINGS_ATTS
void SetPGVariable(const char *name, List *args, bool is_local)
bool ConfigOptionIsVisible(struct config_generic *conf)
Datum show_all_file_settings(PG_FUNCTION_ARGS)
void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
Datum show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
Datum pg_settings_get_flags(PG_FUNCTION_ARGS)
static void GetConfigOptionValues(struct config_generic *conf, const char **values)
Datum show_all_settings(PG_FUNCTION_ARGS)
static void ShowAllGUCConfig(DestReceiver *dest)
const char *const GucContext_Names[]
const char *const GucSource_Names[]
const char *const config_type_names[]
const char *const config_group_names[]
#define GUC_PENDING_RESTART
Assert(PointerIsAligned(start, uint64))
char * pstrdup(const char *in)
void pfree(void *pointer)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
#define InvokeObjectPostAlterHookArgStr(classId, objectName, subId, auxiliaryId, is_internal)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
static int list_length(const List *l)
#define linitial_node(type, l)
static ListCell * list_head(const List *l)
static Datum PointerGetDatum(const void *X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Pointer DatumGetPointer(Datum X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
const char * quote_identifier(const char *ident)
void ImportSnapshot(const char *idstr)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoString(StringInfo str, const char *s)
void initStringInfo(StringInfo str)
AttInMetadata * attinmeta
MemoryContext multi_call_memory_ctx
Tuplestorestate * setResult
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitBuiltinEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
text * cstring_to_text(const char *s)
void WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
bool IsInParallelMode(void)