mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Merge the last few variable.c configuration variables into the generic
GUC support. It's now possible to set datestyle, timezone, and client_encoding from postgresql.conf and per-database or per-user settings. Also, implement rollback of SET commands that occur in a transaction that later fails. Create a SET LOCAL var = value syntax that sets the variable only for the duration of the current transaction. All per previous discussions in pghackers.
This commit is contained in:
136
src/backend/utils/misc/README
Normal file
136
src/backend/utils/misc/README
Normal file
@@ -0,0 +1,136 @@
|
||||
$Header: /cvsroot/pgsql/src/backend/utils/misc/README,v 1.1 2002/05/17 01:19:18 tgl Exp $
|
||||
|
||||
|
||||
GUC IMPLEMENTATION NOTES
|
||||
|
||||
The GUC (Grand Unified Configuration) module implements configuration
|
||||
variables of multiple types (currently boolean, int, float, 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 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.
|
||||
|
||||
If an assign_hook is provided, it points to a function of the signature
|
||||
bool assign_hook(newvalue, bool doit, bool interactive)
|
||||
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. "interactive" is
|
||||
true when we are performing a SET command; in this case it is okay for the
|
||||
assign_hook to raise an error via elog(). If the function returns false
|
||||
for an interactive assignment then guc.c will report a generic "invalid
|
||||
value" error message. (An internal elog() in an assign_hook is only
|
||||
needed if you want to generate a specialized error message.) But when
|
||||
"interactive" is false we are reading a non-interactive option source,
|
||||
such as postgresql.conf. In this case the assign_hook should *not* elog
|
||||
but should just return false if it doesn't like the newvalue. (An
|
||||
elog(LOG) call would be acceptable if you feel a need for a custom
|
||||
complaint in this situation.)
|
||||
|
||||
For string variables, the signature for assign hooks is a bit different:
|
||||
const char *assign_hook(const char *newvalue,
|
||||
bool doit,
|
||||
bool interactive)
|
||||
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 basic datestyle and
|
||||
us/euro option, although the input might have specified only one.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
SAVING/RESTORING GUC VARIABLE VALUES
|
||||
|
||||
Prior values of configuration variables must be remembered in order to
|
||||
deal with three special cases: RESET (a/k/a SET TO DEFAULT), rollback of
|
||||
SET on transaction abort, and rollback of SET LOCAL at transaction end
|
||||
(either commit or abort). 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 as many as four distinct
|
||||
values for each variable. They are:
|
||||
|
||||
* actual variable contents always the current effective value
|
||||
|
||||
* reset_value the value to use for RESET
|
||||
|
||||
* session_value the "committed" setting for the session
|
||||
|
||||
* tentative_value the uncommitted result of SET
|
||||
|
||||
During initialization we set the first three of these (actual, reset_value,
|
||||
and session_value) based on whichever non-interactive source has the
|
||||
highest priority. All three will have the same value.
|
||||
|
||||
A SET LOCAL command sets the actual variable (and nothing else). At
|
||||
transaction end, the session_value is used to restore the actual variable
|
||||
to its pre-transaction value.
|
||||
|
||||
A SET (or SET SESSION) command sets the actual variable, and if no error,
|
||||
then sets the tentative_value. If the transaction commits, the
|
||||
tentative_value is assigned to the session_value and the actual variable
|
||||
(which could by now be different, if the SET was followed by SET LOCAL).
|
||||
If the transaction aborts, the tentative_value is discarded and the
|
||||
actual variable is restored from the session_value.
|
||||
|
||||
RESET is executed like a SET, but using the reset_value 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_value also becomes associated with the actual and session values.
|
||||
|
||||
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_value, and session_value, but only if each of these has a
|
||||
current source priority <= PGC_S_FILE. (It is thus possible for
|
||||
reset_value to track the config-file setting even if there is currently
|
||||
a different interactive value of the actual variable.)
|
||||
|
||||
Note that tentative_value is unused and undefined except between a SET
|
||||
command and the end of the transaction. Also notice that we must track
|
||||
the source associated with each of the four values.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
STRING 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
|
||||
out-of-memory failures.
|
||||
|
||||
We allow a variable's actual value, reset_val, session_val, and
|
||||
tentative_val to point at the same storage. This makes it slightly harder
|
||||
to free space (must test that the value to be freed isn't equal to any of
|
||||
the other three pointers). The main advantage is that we never need to
|
||||
strdup during transaction commit/abort, so cannot cause an out-of-memory
|
||||
failure there.
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright 2000 by PostgreSQL Global Development Group
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc-file.l,v 1.11 2002/03/02 21:39:33 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc-file.l,v 1.12 2002/05/17 01:19:18 tgl Exp $
|
||||
*/
|
||||
|
||||
%{
|
||||
@@ -168,7 +168,7 @@ ProcessConfigFile(GucContext context)
|
||||
head = tail = NULL;
|
||||
opt_name = opt_value = NULL;
|
||||
|
||||
while((token = yylex()))
|
||||
while ((token = yylex()))
|
||||
switch(parse_state)
|
||||
{
|
||||
case 0: /* no previous input */
|
||||
@@ -188,23 +188,22 @@ ProcessConfigFile(GucContext context)
|
||||
token = yylex();
|
||||
|
||||
if (token != GUC_ID && token != GUC_STRING &&
|
||||
token != GUC_INTEGER && token != GUC_REAL &&
|
||||
token != GUC_UNQUOTED_STRING)
|
||||
token != GUC_INTEGER && token != GUC_REAL &&
|
||||
token != GUC_UNQUOTED_STRING)
|
||||
goto parse_error;
|
||||
opt_value = strdup(yytext);
|
||||
if (opt_value == NULL)
|
||||
goto out_of_memory;
|
||||
if (token == GUC_STRING)
|
||||
{
|
||||
/* remove the beginning and ending quote/apostrophe */
|
||||
/* first: shift the whole shooting match down one
|
||||
character */
|
||||
memmove(opt_value,opt_value+1,strlen(opt_value)-1);
|
||||
/* second: null out the 2 characters we shifted */
|
||||
opt_value[strlen(opt_value)-2]='\0';
|
||||
/* do the escape thing. free()'s the strdup above */
|
||||
opt_value=GUC_scanstr(opt_value);
|
||||
}
|
||||
if (token == GUC_STRING)
|
||||
{
|
||||
/* remove the beginning and ending quote/apostrophe */
|
||||
/* first: shift the whole thing down one character */
|
||||
memmove(opt_value,opt_value+1,strlen(opt_value)-1);
|
||||
/* second: null out the 2 characters we shifted */
|
||||
opt_value[strlen(opt_value)-2]='\0';
|
||||
/* do the escape thing. free()'s the strdup above */
|
||||
opt_value=GUC_scanstr(opt_value);
|
||||
}
|
||||
parse_state = 2;
|
||||
break;
|
||||
|
||||
@@ -241,14 +240,14 @@ ProcessConfigFile(GucContext context)
|
||||
for(item = head; item; item=item->next)
|
||||
{
|
||||
if (!set_config_option(item->name, item->value, context,
|
||||
false, PGC_S_INFINITY))
|
||||
PGC_S_FILE, false, false))
|
||||
goto cleanup_exit;
|
||||
}
|
||||
|
||||
/* If we got here all the options parsed okay. */
|
||||
for(item = head; item; item=item->next)
|
||||
set_config_option(item->name, item->value, context,
|
||||
true, PGC_S_FILE);
|
||||
PGC_S_FILE, false, true);
|
||||
|
||||
cleanup_exit:
|
||||
free_name_value_list(head);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -192,7 +192,10 @@
|
||||
#
|
||||
#dynamic_library_path = '$libdir'
|
||||
#search_path = '$user,public'
|
||||
#datestyle = 'iso, us'
|
||||
#timezone = unknown # actually, defaults to TZ environment setting
|
||||
#australian_timezones = false
|
||||
#client_encoding = sql_ascii # actually, defaults to database encoding
|
||||
#authentication_timeout = 60 # min 1, max 600
|
||||
#deadlock_timeout = 1000
|
||||
#default_transaction_isolation = 'read committed'
|
||||
|
||||
Reference in New Issue
Block a user