@ -1,10 +1,10 @@
src/backend/utils/misc/README
Guc Implementation Notes
GUC Implementation Notes
========================
The GUC (Grand Unified Configuration) module implements configuration
variables of multiple types (currently boolean, enum, int, float , and string).
variables of multiple types (currently boolean, enum, int, real , and string).
Variable settings can come from various places, with a priority ordering
determining which setting is used.
@ -12,65 +12,112 @@ determining which setting is used.
Per-Variable Hooks
------------------
Each variable known to GUC can optionally have an assign_hook and/or
a show_hook to provide customized behavior. Assign hooks are used to
perform validity checking on variable values (above and beyond what
GUC can do). They are also used to update any derived state that needs
to change when a GUC variable is set. Show hooks are used to modify
the default SHOW display for a variable.
Each variable known to GUC can optionally have a check_hook, an
assign_hook, and/or a show_hook to provide customized behavior.
Check hooks are used to perform validity checking on variable values
(above and beyond what GUC can do), to compute derived settings when
nontrivial work is needed to do that, and optionally to "canonicalize"
user-supplied values. Assign hooks are used to update any derived state
that needs to change when a GUC variable is set. Show hooks are used to
modify the default SHOW display for a variable.
If a check_hook is provided, it points to a function of the signature
bool check_hook(datatype *newvalue, void **extra, GucSource source)
The "newvalue" argument is of type bool *, int *, double *, or char **
for bool, int/enum, real, or string variables respectively. The check
function should validate the proposed new value, and return true if it is
OK or false if not. The function can optionally do a few other things:
* When rejecting a bad proposed value, it may be useful to append some
additional information to the generic "invalid value for parameter FOO"
complaint that guc.c will emit. To do that, call
void GUC_check_errdetail(const char *format, ...)
where the format string and additional arguments follow the rules for
errdetail() arguments. The resulting string will be emitted as the
DETAIL line of guc.c's error report, so it should follow the message style
guidelines for DETAIL messages. There is also
void GUC_check_errhint(const char *format, ...)
which can be used in the same way to append a HINT message.
Occasionally it may even be appropriate to override guc.c's generic primary
message or error code, which can be done with
void GUC_check_errcode(int sqlerrcode)
void GUC_check_errmsg(const char *format, ...)
In general, check_hooks should avoid throwing errors directly if possible,
though this may be impractical to avoid for some corner cases such as
out-of-memory.
* Since the newvalue is pass-by-reference, the function can modify it.
This might be used for example to canonicalize the spelling of a string
value, round off a buffer size to the nearest supported value, or replace
a special value such as "-1" with a computed default value. If the
function wishes to replace a string value, it must malloc (not palloc)
the replacement value, and be sure to free() the previous value.
* Derived information, such as the role OID represented by a user name,
can be stored for use by the assign hook. To do this, malloc (not palloc)
storage space for the information, and return its address at *extra.
guc.c will automatically free() this space when the associated GUC setting
is no longer of interest. *extra is initialized to NULL before call, so
it can be ignored if not needed.
The "source" argument indicates the source of the proposed new value,
If it is >= PGC_S_INTERACTIVE, then we are performing an interactive
assignment (e.g., a SET command). But when source < PGC_S_INTERACTIVE,
we are reading a non-interactive option source, such as postgresql.conf.
This is sometimes needed to determine whether a setting should be
allowed. The check_hook might also look at the current actual value of
the variable to determine what is allowed.
Note that check hooks are sometimes called just to validate a value,
without any intention of actually changing the setting. Therefore the
check hook must *not* take any action based on the assumption that an
assignment will occur.
If an assign_hook is provided, it points to a function of the signature
bool assign_hook(newvalue, bool doit, GucSource source)
where the type of "newvalue" matches the kind of variable. This function
is called immediately before actually setting the variable's value (so it
can look at the actual variable to determine the old value). If the
function returns "true" then the assignment is completed; if it returns
"false" then newvalue is considered invalid and the assignment is not
performed. If "doit" is false then the function should simply check
validity of newvalue and not change any derived state. The "source" parameter
indicates where the new value came from. If it is >= PGC_S_INTERACTIVE,
then we are performing an interactive assignment (e.g., a SET command), and
ereport(ERROR) is safe to do. But when source < PGC_S_INTERACTIVE, we are
reading a non-interactive option source, such as postgresql.conf. In this
case the assign_hook should *not* ereport but should just return false if it
doesn't like the newvalue.
If an assign_hook returns false then guc.c will report a generic "invalid
value for option FOO" error message. If you feel the need to provide a more
specific error message, ereport() it using "GUC_complaint_elevel(source)"
as the error level. Note that this might return either ERROR or a lower level
such as LOG, so the ereport call might or might not return. If it does
return, return false out of the assign_hook.
For string variables, the signature for assign hooks is a bit different:
const char *assign_hook(const char *newvalue,
bool doit,
GucSource source)
The meanings of the parameters are the same as for the other types of GUC
variables, but the return value is handled differently:
NULL --- assignment fails (like returning false for other datatypes)
newvalue --- assignment succeeds, assign the newvalue as-is
malloc'd (not palloc'd!!!) string --- assign that value instead
The third choice is allowed in case the assign_hook wants to return a
"canonical" version of the new value. For example, the assign_hook for
datestyle always returns a string that includes both output and input
datestyle options, although the input might have specified only one.
Note that a string variable's assign_hook will NEVER be called with a NULL
value for newvalue, since there would be no way to distinguish success
and failure returns. If the boot_val or reset_val for a string variable
is NULL, it will just be assigned without calling the assign_hook.
Therefore, a NULL boot_val should never be used in combination with an
assign_hook that has side-effects, as the side-effects wouldn't happen
during a RESET that re-institutes the boot-time setting.
void assign_hook(datatype newvalue, void *extra)
where the type of "newvalue" matches the kind of variable, and "extra"
is the derived-information pointer returned by the check_hook (always
NULL if there is no check_hook). This function is called immediately
before actually setting the variable's value (so it can look at the actual
variable to determine the old value, for example to avoid doing work when
the value isn't really changing).
Note that there is no provision for a failure result code. assign_hooks
should never fail except under the most dire circumstances, since a failure
may for example result in GUC settings not being rolled back properly during
transaction abort. In general, try to do anything that could conceivably
fail in a check_hook instead, and pass along the results in an "extra"
struct, so that the assign hook has little to do beyond copying the data to
someplace. This applies particularly to catalog lookups: any required
lookups must be done in the check_hook, since the assign_hook may be
executed during transaction rollback when lookups will be unsafe.
Note that check_hooks are sometimes called outside any transaction, too.
This happens when processing the wired-in "bootstrap" value, values coming
from the postmaster command line or environment, or values coming from
postgresql.conf. Therefore, any catalog lookups done in a check_hook
should be guarded with an IsTransactionState() test, and there must be a
fallback path to allow derived values to be computed during the first
subsequent use of the GUC setting within a transaction. A typical
arrangement is for the catalog values computed by the check_hook and
installed by the assign_hook to be used only for the remainder of the
transaction in which the new setting is made. Each subsequent transaction
looks up the values afresh on first use. This arrangement is useful to
prevent use of stale catalog values, independently of the problem of
needing to check GUC values outside a transaction.
If a show_hook is provided, it points to a function of the signature
const char *show_hook(void)
This hook allows variable-specific computation of the value displayed
by SHOW.
by SHOW (and other SQL features for showing GUC variable values).
The return value can point to a static buffer, since show functions are
not used re-entrantly.
Saving/Restoring Guc Variable Values
Saving/Restoring GUC Variable Values
------------------------------------
Prior values of configuration variables must be remembered in order to deal
@ -200,27 +247,49 @@ these has a current source priority <= PGC_S_FILE. (It is thus possible
for reset_val to track the config-file setting even if there is
currently a different interactive value of the actual variable.)
The assign_hook and show_hook routines work only with the actual variable,
and are not directly aware of the additional values maintained by GUC.
This is not a problem for normal usage, since we can assign first to the
actual variable and then (if that succeeds) to the additional values as
needed. However, for SIGHUP rereads we may not want to assign to the
actual variable. Our procedure in that case is to call the assign_hook
with doit = false so that the value is validated, but no derived state is
changed.
The check_hook, assign_hook and show_hook routines work only with the
actual variable, and are not directly aware of the additional values
maintained by GUC.
String Memory Handling
----------------------
GUC Memory Handling
-------------------
String option values are allocated with strdup, not with the
pstrdup/palloc mechanisms. We would need to keep them in a permanent
context anyway, and strdup gives us more control over handling
String variable values are allocated with malloc/ strdup, not with the
palloc/p strdup mechanisms. We would need to keep them in a permanent
context anyway, and malloc gives us more control over handling
out-of-memory failures.
We allow a string variable's actual value, reset_val, boot_val, and stacked
values to point at the same storage. This makes it slightly harder to free
space (we must test whether a value to be freed isn't equal to any of the
other pointers in the GUC entry or associated stack items). The main
advantage is that we never need to strdup during transaction commit/abort,
advantage is that we never need to malloc during transaction commit/abort,
so cannot cause an out-of-memory failure there.
"Extra" structs returned by check_hook routines are managed in the same
way as string values. Note that we support "extra" structs for all types
of GUC variables, although they are mainly useful with strings.
GUC and Null String Variables
-----------------------------
A GUC string variable can have a boot_val of NULL. guc.c handles this
unsurprisingly, assigning the NULL to the underlying C variable. Any code
using such a variable, as well as any hook functions for it, must then be
prepared to deal with a NULL value.
However, it is not possible to assign a NULL value to a GUC string
variable in any other way: values coming from SET, postgresql.conf, etc,
might be empty strings, but they'll never be NULL. And SHOW displays
a NULL the same as an empty string. It is therefore not appropriate to
treat a NULL value as a distinct user-visible setting. A typical use
for a NULL boot_val is to denote that a value hasn't yet been set for
a variable that will receive a real value later in startup.
If it's undesirable for code using the underlying C variable to have to
worry about NULL values ever, the variable can be given a non-null static
initializer as well as a non-null boot_val. guc.c will overwrite the
static initializer pointer with a copy of the boot_val during
InitializeGUCOptions, but the variable will never contain a NULL.