summaryrefslogtreecommitdiffstats
path: root/src/backend/utils/misc/README
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/misc/README')
-rw-r--r--src/backend/utils/misc/README295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/backend/utils/misc/README b/src/backend/utils/misc/README
new file mode 100644
index 0000000..6e29438
--- /dev/null
+++ b/src/backend/utils/misc/README
@@ -0,0 +1,295 @@
+src/backend/utils/misc/README
+
+GUC Implementation Notes
+========================
+
+The GUC (Grand Unified Configuration) module implements configuration
+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.
+
+
+Per-Variable Hooks
+------------------
+
+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
+ 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 (and other SQL features for showing GUC variable values).
+The return value can point to a static buffer, since show functions are
+not used reentrantly.
+
+
+Saving/Restoring GUC Variable Values
+------------------------------------
+
+Prior values of configuration variables must be remembered in order to deal
+with several special cases: RESET (a/k/a SET TO DEFAULT), rollback of SET
+on transaction abort, rollback of SET LOCAL at transaction end (either
+commit or abort), and save/restore around a function that has a SET option.
+RESET is defined as selecting the value that would be effective had there
+never been any SET commands in the current session.
+
+To handle these cases we must keep track of many distinct values for each
+variable. The primary values are:
+
+* actual variable contents always the current effective value
+
+* reset_val the value to use for RESET
+
+(Each GUC entry also has a boot_val which is the wired-in default value.
+This is assigned to the reset_val and the actual variable during
+InitializeGUCOptions(). The boot_val is also consulted to restore the
+correct reset_val if SIGHUP processing discovers that a variable formerly
+specified in postgresql.conf is no longer set there.)
+
+In addition to the primary values, there is a stack of former effective
+values that might need to be restored in future. Stacking and unstacking
+is controlled by the GUC "nest level", which is zero when outside any
+transaction, one at top transaction level, and incremented for each
+open subtransaction or function call with a SET option. A stack entry
+is made whenever a GUC variable is first modified at a given nesting level.
+(Note: the reset_val need not be stacked because it is only changed by
+non-transactional operations.)
+
+A stack entry has a state, a prior value of the GUC variable, a remembered
+source of that prior value, and depending on the state may also have a
+"masked" value. The masked value is needed when SET followed by SET LOCAL
+occur at the same nest level: the SET's value is masked but must be
+remembered to restore after transaction commit.
+
+During initialization we set the actual value and reset_val based on
+whichever non-interactive source has the highest priority. They will
+have the same value.
+
+The possible transactional operations on a GUC value are:
+
+Entry to a function with a SET option:
+
+ Push a stack entry with the prior variable value and state SAVE,
+ then set the variable.
+
+Plain SET command:
+
+ If no stack entry of current level:
+ Push new stack entry w/prior value and state SET
+ else if stack entry's state is SAVE, SET, or LOCAL:
+ change stack state to SET, don't change saved value
+ (here we are forgetting effects of prior set action)
+ else (entry must have state SET+LOCAL):
+ discard its masked value, change state to SET
+ (here we are forgetting effects of prior SET and SET LOCAL)
+ Now set new value.
+
+SET LOCAL command:
+
+ If no stack entry of current level:
+ Push new stack entry w/prior value and state LOCAL
+ else if stack entry's state is SAVE or LOCAL or SET+LOCAL:
+ no change to stack entry
+ (in SAVE case, SET LOCAL will be forgotten at func exit)
+ else (entry must have state SET):
+ put current active into its masked slot, set state SET+LOCAL
+ Now set new value.
+
+Transaction or subtransaction abort:
+
+ Pop stack entries, restoring prior value, until top < subxact depth
+
+Transaction or subtransaction commit (incl. successful function exit):
+
+ While stack entry level >= subxact depth
+
+ if entry's state is SAVE:
+ pop, restoring prior value
+ else if level is 1 and entry's state is SET+LOCAL:
+ pop, restoring *masked* value
+ else if level is 1 and entry's state is SET:
+ pop, discarding old value
+ else if level is 1 and entry's state is LOCAL:
+ pop, restoring prior value
+ else if there is no entry of exactly level N-1:
+ decrement entry's level, no other state change
+ else
+ merge entries of level N-1 and N as specified below
+
+The merged entry will have level N-1 and prior = older prior, so easiest
+to keep older entry and free newer. There are 12 possibilities since
+we already handled level N state = SAVE:
+
+N-1 N
+
+SAVE SET discard top prior, set state SET
+SAVE LOCAL discard top prior, no change to stack entry
+SAVE SET+LOCAL discard top prior, copy masked, state S+L
+
+SET SET discard top prior, no change to stack entry
+SET LOCAL copy top prior to masked, state S+L
+SET SET+LOCAL discard top prior, copy masked, state S+L
+
+LOCAL SET discard top prior, set state SET
+LOCAL LOCAL discard top prior, no change to stack entry
+LOCAL SET+LOCAL discard top prior, copy masked, state S+L
+
+SET+LOCAL SET discard top prior and second masked, state SET
+SET+LOCAL LOCAL discard top prior, no change to stack entry
+SET+LOCAL SET+LOCAL discard top prior, copy masked, state S+L
+
+
+RESET is executed like a SET, but using the reset_val as the desired new
+value. (We do not provide a RESET LOCAL command, but SET LOCAL TO DEFAULT
+has the same behavior that RESET LOCAL would.) The source associated with
+the reset_val also becomes associated with the actual value.
+
+If SIGHUP is received, the GUC code rereads the postgresql.conf
+configuration file (this does not happen in the signal handler, but at
+next return to main loop; note that it can be executed while within a
+transaction). New values from postgresql.conf are assigned to actual
+variable, reset_val, and stacked actual values, but only if each of
+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 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.
+
+
+GUC Memory Handling
+-------------------
+
+String variable values are allocated with malloc/strdup, not with the
+palloc/pstrdup 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 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.