Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
f0584518
Commit
f0584518
authored
Aug 14, 2006
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert (again) GUC patch to return commented fields to their default
values, due to concern about the patch.
parent
36481474
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
291 additions
and
562 deletions
+291
-562
src/backend/utils/misc/guc-file.l
src/backend/utils/misc/guc-file.l
+17
-107
src/backend/utils/misc/guc.c
src/backend/utils/misc/guc.c
+268
-442
src/include/utils/guc.h
src/include/utils/guc.h
+1
-4
src/include/utils/guc_tables.h
src/include/utils/guc_tables.h
+5
-9
No files found.
src/backend/utils/misc/guc-file.l
View file @
f0584518
...
...
@@ -4,7 +4,7 @@
*
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.4
4 2006/08/13 02:22:24
momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.4
5 2006/08/14 02:27:26
momjian Exp $
*/
%{
...
...
@@ -50,8 +50,7 @@ int GUC_yylex(void);
static bool ParseConfigFile(const char *config_file, const char *calling_file,
int depth, GucContext context, int elevel,
struct name_value_pair **head_p,
struct name_value_pair **tail_p,
int *varcount);
struct name_value_pair **tail_p);
static void free_name_value_list(struct name_value_pair * list);
static char *GUC_scanstr(const char *s);
...
...
@@ -115,11 +114,8 @@ STRING \'([^'\\\n]|\\.|\'\')*\'
void
ProcessConfigFile(GucContext context)
{
int elevel
, i
;
int elevel;
struct name_value_pair *item, *head, *tail;
char *env;
bool *apply_list = NULL;
int varcount = 0;
Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
...
...
@@ -138,109 +134,25 @@ ProcessConfigFile(GucContext context)
if (!ParseConfigFile(ConfigFileName, NULL,
0, context, elevel,
&head, &tail
, &varcount
))
&head, &tail))
goto cleanup_list;
/* Can we allocate memory here, what about leaving here prematurely? */
apply_list = (bool *) palloc(sizeof(bool) * varcount);
/* Check if all options are valid */
for (item = head
, i = 0; item; item = item->next, i++
)
for (item = head
; item; item = item->next
)
{
bool isEqual, isContextOk;
if (!verify_config_option(item->name, item->value, context,
PGC_S_FILE, &isEqual, &isContextOk))
{
ereport(elevel,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("configuration file is invalid")));
if (!set_config_option(item->name, item->value, context,
PGC_S_FILE, false, false))
goto cleanup_list;
}
if (isContextOk == false)
{
apply_list[i] = false;
if (context == PGC_SIGHUP)
{
if (isEqual == false)
ereport(elevel,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("parameter \"%s\" cannot be changed after server start; configuration file change ignored",
item->name)));
}
else
/* if it is boot phase, context must be valid for all
* configuration item. */
goto cleanup_list;
}
else
apply_list[i] = true;
}
/* If we got here all the options checked out okay, so apply them. */
for (item = head, i = 0; item; item = item->next, i++)
if (apply_list[i])
set_config_option(item->name, item->value, context,
PGC_S_FILE, false, true);
if (context == PGC_SIGHUP)
for (item = head; item; item = item->next)
{
/*
* Revert all "untouched" options with reset source PGC_S_FILE to
* default/boot value.
*/
for (i = 0; i < num_guc_variables; i++)
{
struct config_generic *gconf = guc_variables[i];
if (gconf->reset_source == PGC_S_FILE &&
!(gconf->status & GUC_IN_CONFFILE))
{
if (gconf->context == PGC_BACKEND && IsUnderPostmaster)
; /* Be silent. Does any body want message from each session? */
else if (gconf->context == PGC_POSTMASTER)
ereport(elevel,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("parameter \"%s\" cannot be changed (commented) after server start; configuration file change ignored",
gconf->name)));
else if (set_config_option(gconf->name, NULL, context,
PGC_S_FILE, false, true))
{
GucStack *stack;
gconf->reset_source = PGC_S_DEFAULT;
for (stack = gconf->stack; stack; stack = stack->prev)
if (stack->source == PGC_S_FILE)
stack->source = PGC_S_DEFAULT;
ereport(elevel,
(errcode(ERRCODE_SUCCESSFUL_COMPLETION),
errmsg("configuration option %s returned to default value", gconf->name)));
}
}
gconf->status &= ~GUC_IN_CONFFILE;
}
/*
* Revert to environment variable. PGPORT is ignored, because it cannot be
* set in running state.
*/
env = getenv("PGDATESTYLE");
if (env != NULL)
set_config_option("datestyle", env, context,
PGC_S_ENV_VAR, false, true);
env = getenv("PGCLIENTENCODING");
if (env != NULL)
set_config_option("client_encoding", env, context,
PGC_S_ENV_VAR, false, true);
set_config_option(item->name, item->value, context,
PGC_S_FILE, false, true);
}
cleanup_list:
if (apply_list)
pfree(apply_list);
cleanup_list:
free_name_value_list(head);
}
...
...
@@ -277,14 +189,13 @@ static bool
ParseConfigFile(const char *config_file, const char *calling_file,
int depth, GucContext context, int elevel,
struct name_value_pair **head_p,
struct name_value_pair **tail_p,
int *varcount)
struct name_value_pair **tail_p)
{
bool
OK = true;
char
abs_path[MAXPGPATH];
FILE
*fp;
bool OK = true;
char abs_path[MAXPGPATH];
FILE *fp;
YY_BUFFER_STATE lex_buffer;
int
token;
int token;
/*
* Reject too-deep include nesting depth. This is just a safety check
...
...
@@ -378,7 +289,7 @@ ParseConfigFile(const char *config_file, const char *calling_file,
if (!ParseConfigFile(opt_value, config_file,
depth + 1, context, elevel,
head_p, tail_p
, varcount
))
head_p, tail_p))
{
pfree(opt_name);
pfree(opt_value);
...
...
@@ -422,7 +333,6 @@ ParseConfigFile(const char *config_file, const char *calling_file,
else
(*tail_p)->next = item;
*tail_p = item;
(*varcount)++;
}
/* break out of loop if read EOF, else loop for next line */
...
...
src/backend/utils/misc/guc.c
View file @
f0584518
...
...
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.34
0 2006/08/13 15:37:02
momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.34
1 2006/08/14 02:27:26
momjian Exp $
*
*--------------------------------------------------------------------
*/
...
...
@@ -2313,7 +2313,7 @@ guc_strdup(int elevel, const char *src)
* states).
*/
static
void
set_string_field
(
struct
config_string
*
conf
,
char
**
field
,
char
*
newval
)
set_string_field
(
struct
config_string
*
conf
,
char
**
field
,
char
*
newval
)
{
char
*
oldval
=
*
field
;
GucStack
*
stack
;
...
...
@@ -2535,7 +2535,8 @@ add_placeholder_variable(const char *name, int elevel)
gen
=
&
var
->
gen
;
memset
(
var
,
0
,
sz
);
if
((
gen
->
name
=
guc_strdup
(
elevel
,
name
))
==
NULL
)
gen
->
name
=
guc_strdup
(
elevel
,
name
);
if
(
gen
->
name
==
NULL
)
{
free
(
var
);
return
NULL
;
...
...
@@ -2692,40 +2693,40 @@ InitializeGUCOptions(void)
{
struct
config_bool
*
conf
=
(
struct
config_bool
*
)
gconf
;
if
(
conf
->
assign_hook
&&
!
(
*
conf
->
assign_hook
)
(
conf
->
boo
t_val
,
true
,
PGC_S_DEFAULT
))
elog
(
FATAL
,
"failed to initialize %s to %d"
,
conf
->
gen
.
name
,
(
int
)
conf
->
boo
t_val
);
*
conf
->
variable
=
conf
->
reset_val
=
conf
->
boot_val
;
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
conf
->
rese
t_val
,
true
,
PGC_S_DEFAULT
))
elog
(
FATAL
,
"failed to initialize %s to %d"
,
conf
->
gen
.
name
,
(
int
)
conf
->
rese
t_val
);
*
conf
->
variable
=
conf
->
reset_val
;
break
;
}
case
PGC_INT
:
{
struct
config_int
*
conf
=
(
struct
config_int
*
)
gconf
;
Assert
(
conf
->
boo
t_val
>=
conf
->
min
);
Assert
(
conf
->
boo
t_val
<=
conf
->
max
);
if
(
conf
->
assign_hook
&&
!
(
*
conf
->
assign_hook
)
(
conf
->
boo
t_val
,
true
,
PGC_S_DEFAULT
))
elog
(
FATAL
,
"failed to initialize %s to %d"
,
conf
->
gen
.
name
,
conf
->
boo
t_val
);
*
conf
->
variable
=
conf
->
reset_val
=
conf
->
boot_val
;
Assert
(
conf
->
rese
t_val
>=
conf
->
min
);
Assert
(
conf
->
rese
t_val
<=
conf
->
max
);
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
conf
->
rese
t_val
,
true
,
PGC_S_DEFAULT
))
elog
(
FATAL
,
"failed to initialize %s to %d"
,
conf
->
gen
.
name
,
conf
->
rese
t_val
);
*
conf
->
variable
=
conf
->
reset_val
;
break
;
}
case
PGC_REAL
:
{
struct
config_real
*
conf
=
(
struct
config_real
*
)
gconf
;
Assert
(
conf
->
boo
t_val
>=
conf
->
min
);
Assert
(
conf
->
boo
t_val
<=
conf
->
max
);
if
(
conf
->
assign_hook
&&
!
(
*
conf
->
assign_hook
)
(
conf
->
boo
t_val
,
true
,
PGC_S_DEFAULT
))
elog
(
FATAL
,
"failed to initialize %s to %g"
,
conf
->
gen
.
name
,
conf
->
boo
t_val
);
*
conf
->
variable
=
conf
->
reset_val
=
conf
->
boot_val
;
Assert
(
conf
->
rese
t_val
>=
conf
->
min
);
Assert
(
conf
->
rese
t_val
<=
conf
->
max
);
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
conf
->
rese
t_val
,
true
,
PGC_S_DEFAULT
))
elog
(
FATAL
,
"failed to initialize %s to %g"
,
conf
->
gen
.
name
,
conf
->
rese
t_val
);
*
conf
->
variable
=
conf
->
reset_val
;
break
;
}
case
PGC_STRING
:
...
...
@@ -2738,8 +2739,10 @@ InitializeGUCOptions(void)
conf
->
tentative_val
=
NULL
;
if
(
conf
->
boot_val
==
NULL
)
{
/* Cannot set value yet */
break
;
}
str
=
guc_strdup
(
FATAL
,
conf
->
boot_val
);
conf
->
reset_val
=
str
;
...
...
@@ -2751,8 +2754,10 @@ InitializeGUCOptions(void)
newstr
=
(
*
conf
->
assign_hook
)
(
str
,
true
,
PGC_S_DEFAULT
);
if
(
newstr
==
NULL
)
{
elog
(
FATAL
,
"failed to initialize %s to
\"
%s
\"
"
,
conf
->
gen
.
name
,
str
);
}
else
if
(
newstr
!=
str
)
{
free
(
str
);
...
...
@@ -2792,10 +2797,12 @@ InitializeGUCOptions(void)
if
(
env
!=
NULL
)
SetConfigOption
(
"port"
,
env
,
PGC_POSTMASTER
,
PGC_S_ENV_VAR
);
if
((
env
=
getenv
(
"PGDATESTYLE"
))
!=
NULL
)
env
=
getenv
(
"PGDATESTYLE"
);
if
(
env
!=
NULL
)
SetConfigOption
(
"datestyle"
,
env
,
PGC_POSTMASTER
,
PGC_S_ENV_VAR
);
if
((
env
=
getenv
(
"PGCLIENTENCODING"
))
!=
NULL
)
env
=
getenv
(
"PGCLIENTENCODING"
);
if
(
env
!=
NULL
)
SetConfigOption
(
"client_encoding"
,
env
,
PGC_POSTMASTER
,
PGC_S_ENV_VAR
);
}
...
...
@@ -3172,7 +3179,7 @@ AtEOXact_GUC(bool isCommit, bool isSubXact)
for
(
i
=
0
;
i
<
num_guc_variables
;
i
++
)
{
struct
config_generic
*
gconf
=
guc_variables
[
i
];
int
my_status
=
gconf
->
status
&
(
~
GUC_IN_CONFFILE
)
;
int
my_status
=
gconf
->
status
;
GucStack
*
stack
=
gconf
->
stack
;
bool
useTentative
;
bool
changed
;
...
...
@@ -3683,294 +3690,96 @@ call_string_assign_hook(GucStringAssignHook assign_hook,
return
result
;
}
/*
* Try to parse value. Determine what is type and call related
* parsing function or if newval is equal to NULL, reset value
* to default or bootval. If the value parsed okay return true,
* else false.
* Sets option `name' to given value. The value should be a string
* which is going to be parsed and converted to the appropriate data
* type. The context and source parameters indicate in which context this
* function is being called so it can apply the access restrictions
* properly.
*
* If value is NULL, set the option to its default value. If the
* parameter changeVal is false then don't really set the option but do all
* the checks to see if it would work.
*
* If there is an error (non-existing option, invalid value) then an
* ereport(ERROR) is thrown *unless* this is called in a context where we
* don't want to ereport (currently, startup or SIGHUP config file reread).
* In that case we write a suitable error message via ereport(DEBUG) and
* return false. This is working around the deficiencies in the ereport
* mechanism, so don't blame me. In all other cases, the function
* returns true, including cases where the input is valid but we chose
* not to apply it because of context or source-priority considerations.
*
* See also SetConfigOption for an external interface.
*/
static
bool
parse_value
(
int
elevel
,
const
struct
config_generic
*
record
,
const
char
*
value
,
GucSource
*
source
,
bool
changeVal
,
union
config_var_value
*
retv
al
)
bool
set_config_option
(
const
char
*
name
,
const
char
*
value
,
GucContext
context
,
GucSource
source
,
bool
isLocal
,
bool
changeV
al
)
{
/*
* Evaluate value and set variable.
*/
switch
(
record
->
vartype
)
{
case
PGC_BOOL
:
{
struct
config_bool
*
conf
=
(
struct
config_bool
*
)
record
;
bool
newval
;
if
(
value
)
{
if
(
!
parse_bool
(
value
,
&
newval
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"parameter
\"
%s
\"
requires a Boolean value"
,
record
->
name
)));
return
false
;
}
}
else
{
/*
* Revert value to default if source is configuration file. It is used when
* configuration parameter is removed/commented out in the config file. Else
* RESET or SET TO DEFAULT command is called and reset_val is used.
*/
if
(
*
source
==
PGC_S_FILE
)
newval
=
conf
->
boot_val
;
else
{
newval
=
conf
->
reset_val
;
*
source
=
conf
->
gen
.
reset_source
;
}
}
if
(
conf
->
assign_hook
&&
!
(
*
conf
->
assign_hook
)
(
newval
,
changeVal
,
*
source
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
: %d"
,
record
->
name
,
(
int
)
newval
)));
return
false
;
}
if
(
retval
)
retval
->
boolval
=
newval
;
break
;
}
case
PGC_INT
:
{
struct
config_int
*
conf
=
(
struct
config_int
*
)
record
;
int
newval
;
if
(
value
)
{
if
(
!
parse_int
(
value
,
&
newval
,
conf
->
gen
.
flags
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"parameter
\"
%s
\"
requires an integer value"
,
record
->
name
)));
return
false
;
}
if
(
newval
<
conf
->
min
||
newval
>
conf
->
max
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"%d is outside the valid range for parameter
\"
%s
\"
(%d .. %d)"
,
newval
,
record
->
name
,
conf
->
min
,
conf
->
max
)));
return
false
;
}
}
else
{
/*
* Revert value to default if source is configuration file. It is used when
* configuration parameter is removed/commented out in the config file. Else
* RESET or SET TO DEFAULT command is called and reset_val is used.
*/
if
(
*
source
==
PGC_S_FILE
)
newval
=
conf
->
boot_val
;
else
{
newval
=
conf
->
reset_val
;
*
source
=
conf
->
gen
.
reset_source
;
}
}
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
newval
,
changeVal
,
*
source
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
: %d"
,
record
->
name
,
newval
)));
return
false
;
}
if
(
retval
)
retval
->
intval
=
newval
;
break
;
}
case
PGC_REAL
:
{
struct
config_real
*
conf
=
(
struct
config_real
*
)
record
;
double
newval
;
if
(
value
)
{
if
(
!
parse_real
(
value
,
&
newval
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"parameter
\"
%s
\"
requires a numeric value"
,
record
->
name
)));
return
false
;
}
if
(
newval
<
conf
->
min
||
newval
>
conf
->
max
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"%g is outside the valid range for parameter
\"
%s
\"
(%g .. %g)"
,
newval
,
record
->
name
,
conf
->
min
,
conf
->
max
)));
return
false
;
}
}
else
{
/*
* Revert value to default if source is configuration file. It is used when
* configuration parameter is removed/commented out in the config file. Else
* RESET or SET TO DEFAULT command is called and reset_val is used.
*/
if
(
*
source
==
PGC_S_FILE
)
newval
=
conf
->
boot_val
;
else
{
newval
=
conf
->
reset_val
;
*
source
=
conf
->
gen
.
reset_source
;
}
}
if
(
conf
->
assign_hook
&&
!
(
*
conf
->
assign_hook
)
(
newval
,
changeVal
,
*
source
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
: %g"
,
record
->
name
,
newval
)));
return
false
;
}
if
(
retval
)
retval
->
realval
=
newval
;
break
;
}
case
PGC_STRING
:
{
struct
config_string
*
conf
=
(
struct
config_string
*
)
record
;
char
*
newval
;
if
(
value
)
{
if
((
newval
=
guc_strdup
(
elevel
,
value
))
==
NULL
)
return
false
;
/*
* The only sort of "parsing" check we need to do is
* apply truncation if GUC_IS_NAME.
*/
if
(
conf
->
gen
.
flags
&
GUC_IS_NAME
)
truncate_identifier
(
newval
,
strlen
(
newval
),
true
);
}
else
if
(
*
source
==
PGC_S_FILE
)
{
/* Revert value to default when item is removed from config file. */
if
(
conf
->
boot_val
!=
NULL
)
{
newval
=
guc_strdup
(
elevel
,
conf
->
boot_val
);
if
(
newval
==
NULL
)
return
false
;
}
else
return
false
;
}
else
if
(
conf
->
reset_val
)
{
/*
* We could possibly avoid strdup here, but easier to make
* this case work the same as the normal assignment case.
*/
if
((
newval
=
guc_strdup
(
elevel
,
conf
->
reset_val
))
==
NULL
)
return
false
;
*
source
=
conf
->
gen
.
reset_source
;
}
else
/* Nothing to reset to, as yet; so do nothing */
break
;
if
(
conf
->
assign_hook
)
{
const
char
*
hookresult
;
/*
* If the hook ereports, we have to make sure we free
* newval, else it will be a permanent memory leak.
*/
hookresult
=
call_string_assign_hook
(
conf
->
assign_hook
,
newval
,
changeVal
,
*
source
);
if
(
hookresult
==
NULL
)
{
free
(
newval
);
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
:
\"
%s
\"
"
,
record
->
name
,
value
?
value
:
""
)));
return
false
;
}
else
if
(
hookresult
!=
newval
)
{
free
(
newval
);
struct
config_generic
*
record
;
int
elevel
;
bool
makeDefault
;
/*
* Having to cast away const here is annoying, but the
* alternative is to declare assign_hooks as returning
* char*, which would mean they'd have to cast away
* const, or as both taking and returning char*, which
* doesn't seem attractive either --- we don't want
* them to scribble on the passed str.
*/
newval
=
(
char
*
)
hookresult
;
}
}
if
(
context
==
PGC_SIGHUP
||
source
==
PGC_S_DEFAULT
)
{
/*
* To avoid cluttering the log, only the postmaster bleats loudly
* about problems with the config file.
*/
elevel
=
IsUnderPostmaster
?
DEBUG2
:
LOG
;
}
else
if
(
source
==
PGC_S_DATABASE
||
source
==
PGC_S_USER
)
elevel
=
INFO
;
else
elevel
=
ERROR
;
if
(
retval
)
retval
->
stringval
=
newval
;
else
free
(
newval
);
break
;
}
record
=
find_option
(
name
,
elevel
);
if
(
record
==
NULL
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"unrecognized configuration parameter
\"
%s
\"
"
,
name
)));
return
false
;
}
return
true
;
}
/*
* Check if the option can be set at this time. See guc.h for the precise
* rules.
*/
static
bool
checkContext
(
int
elevel
,
struct
config_generic
*
record
,
GucContext
context
)
{
/*
* Check if the option can be set at this time. See guc.h for the precise
* rules. Note that we don't want to throw errors if we're in the SIGHUP
* context. In that case we just ignore the attempt and return true.
*/
switch
(
record
->
context
)
{
case
PGC_INTERNAL
:
if
(
context
==
PGC_SIGHUP
)
return
true
;
if
(
context
!=
PGC_INTERNAL
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed"
,
record
->
name
)));
name
)));
return
false
;
}
break
;
case
PGC_POSTMASTER
:
if
(
context
==
PGC_SIGHUP
)
return
false
;
{
if
(
changeVal
&&
!
is_newvalue_equal
(
record
,
value
))
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed after server start; configuration file change ignored"
,
name
)));
return
true
;
}
if
(
context
!=
PGC_POSTMASTER
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed after server start"
,
record
->
name
)));
name
)));
return
false
;
}
break
;
...
...
@@ -3980,7 +3789,7 @@ checkContext(int elevel, struct config_generic *record, GucContext context)
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed now"
,
record
->
name
)));
name
)));
return
false
;
}
...
...
@@ -4003,16 +3812,14 @@ checkContext(int elevel, struct config_generic *record, GucContext context)
* backend start.
*/
if
(
IsUnderPostmaster
)
{
return
false
;
}
return
true
;
}
else
if
(
context
!=
PGC_BACKEND
&&
context
!=
PGC_POSTMASTER
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be set after connection start"
,
record
->
name
)));
name
)));
return
false
;
}
break
;
...
...
@@ -4022,7 +3829,7 @@ checkContext(int elevel, struct config_generic *record, GucContext context)
ereport
(
elevel
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
errmsg
(
"permission denied to set parameter
\"
%s
\"
"
,
record
->
name
)));
name
)));
return
false
;
}
break
;
...
...
@@ -4030,128 +3837,12 @@ checkContext(int elevel, struct config_generic *record, GucContext context)
/* always okay */
break
;
}
return
true
;
}
/*
* Get error level for different sources and context.
*/
static
int
get_elevel
(
GucContext
context
,
GucSource
source
)
{
int
elevel
;
if
(
context
==
PGC_SIGHUP
||
source
==
PGC_S_DEFAULT
)
{
/*
* To avoid cluttering the log, only the postmaster bleats loudly
* about problems with the config file.
*/
elevel
=
IsUnderPostmaster
?
DEBUG2
:
LOG
;
}
else
if
(
source
==
PGC_S_DATABASE
||
source
==
PGC_S_USER
)
elevel
=
INFO
;
else
elevel
=
ERROR
;
return
elevel
;
}
/*
* Verify if option exists and value is valid.
* It is primary used for validation of items in configuration file.
*/
bool
verify_config_option
(
const
char
*
name
,
const
char
*
value
,
GucContext
context
,
GucSource
source
,
bool
*
isNewEqual
,
bool
*
isContextOK
)
{
int
elevel
;
struct
config_generic
*
record
;
elevel
=
get_elevel
(
context
,
source
);
record
=
find_option
(
name
,
elevel
);
if
(
record
==
NULL
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"unrecognized configuration parameter
\"
%s
\"
"
,
name
)));
return
false
;
}
if
(
parse_value
(
elevel
,
record
,
value
,
&
source
,
false
,
NULL
))
{
/*
* Mark record as present in the config file. Be carefull if
* you use this function for another purpose than config file
* verification. It causes confusion in the config file parser.
*/
record
->
status
|=
GUC_IN_CONFFILE
;
if
(
isNewEqual
!=
NULL
)
*
isNewEqual
=
is_newvalue_equal
(
record
,
value
);
if
(
isContextOK
!=
NULL
)
*
isContextOK
=
checkContext
(
elevel
,
record
,
context
);
}
else
return
false
;
return
true
;
}
/*
* Sets option `name' to given value. The value should be a string
* which is going to be parsed and converted to the appropriate data
* type. The context and source parameters indicate in which context this
* function is being called so it can apply the access restrictions
* properly.
*
* If value is NULL, set the option to its default value. If the
* parameter changeVal is false then don't really set the option but do all
* the checks to see if it would work.
*
* If there is an error (non-existing option, invalid value) then an
* ereport(ERROR) is thrown *unless* this is called in a context where we
* don't want to ereport (currently, startup or SIGHUP config file reread).
* In that case we write a suitable error message via ereport(DEBUG) and
* return false. This is working around the deficiencies in the ereport
* mechanism, so don't blame me. In all other cases, the function
* returns true, including cases where the input is valid but we chose
* not to apply it because of context or source-priority considerations.
*
* See also SetConfigOption for an external interface.
*/
bool
set_config_option
(
const
char
*
name
,
const
char
*
value
,
GucContext
context
,
GucSource
source
,
bool
isLocal
,
bool
changeVal
)
{
struct
config_generic
*
record
;
int
elevel
;
bool
makeDefault
;
elevel
=
get_elevel
(
context
,
source
);
record
=
find_option
(
name
,
elevel
);
if
(
record
==
NULL
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"unrecognized configuration parameter
\"
%s
\"
"
,
name
)));
return
false
;
}
/* Check if change is allowed in the running context. */
if
(
!
checkContext
(
elevel
,
record
,
context
))
return
false
;
/*
* Should we set reset/stacked values? (If so, the behavior is not
* transactional.)
*/
makeDefault
=
changeVal
&&
(
source
<=
PGC_S_OVERRIDE
)
&&
(
value
!=
NULL
||
source
==
PGC_S_FILE
);
makeDefault
=
changeVal
&&
(
source
<=
PGC_S_OVERRIDE
)
&&
(
value
!=
NULL
);
/*
* Ignore attempted set if overridden by previously processed setting.
...
...
@@ -4180,23 +3871,44 @@ set_config_option(const char *name, const char *value,
{
struct
config_bool
*
conf
=
(
struct
config_bool
*
)
record
;
bool
newval
;
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
(
union
config_var_value
*
)
&
newval
))
return
false
;
if
(
value
)
{
if
(
!
parse_bool
(
value
,
&
newval
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"parameter
\"
%s
\"
requires a Boolean value"
,
name
)));
return
false
;
}
}
else
{
newval
=
conf
->
reset_val
;
source
=
conf
->
gen
.
reset_source
;
}
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
newval
,
changeVal
,
source
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
: %d"
,
name
,
(
int
)
newval
)));
return
false
;
}
if
(
changeVal
||
makeDefault
)
{
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
{
*
conf
->
variable
=
newval
;
conf
->
gen
.
source
=
source
;
}
if
(
makeDefault
)
{
GucStack
*
stack
;
...
...
@@ -4236,22 +3948,51 @@ set_config_option(const char *name, const char *value,
struct
config_int
*
conf
=
(
struct
config_int
*
)
record
;
int
newval
;
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
(
union
config_var_value
*
)
&
newval
))
return
false
;
if
(
value
)
{
if
(
!
parse_int
(
value
,
&
newval
,
conf
->
gen
.
flags
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"parameter
\"
%s
\"
requires an integer value"
,
name
)));
return
false
;
}
if
(
newval
<
conf
->
min
||
newval
>
conf
->
max
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"%d is outside the valid range for parameter
\"
%s
\"
(%d .. %d)"
,
newval
,
name
,
conf
->
min
,
conf
->
max
)));
return
false
;
}
}
else
{
newval
=
conf
->
reset_val
;
source
=
conf
->
gen
.
reset_source
;
}
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
newval
,
changeVal
,
source
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
: %d"
,
name
,
newval
)));
return
false
;
}
if
(
changeVal
||
makeDefault
)
{
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
{
*
conf
->
variable
=
newval
;
conf
->
gen
.
source
=
source
;
}
if
(
makeDefault
)
{
GucStack
*
stack
;
...
...
@@ -4291,22 +4032,51 @@ set_config_option(const char *name, const char *value,
struct
config_real
*
conf
=
(
struct
config_real
*
)
record
;
double
newval
;
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
(
union
config_var_value
*
)
&
newval
))
return
false
;
if
(
value
)
{
if
(
!
parse_real
(
value
,
&
newval
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"parameter
\"
%s
\"
requires a numeric value"
,
name
)));
return
false
;
}
if
(
newval
<
conf
->
min
||
newval
>
conf
->
max
)
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"%g is outside the valid range for parameter
\"
%s
\"
(%g .. %g)"
,
newval
,
name
,
conf
->
min
,
conf
->
max
)));
return
false
;
}
}
else
{
newval
=
conf
->
reset_val
;
source
=
conf
->
gen
.
reset_source
;
}
if
(
conf
->
assign_hook
)
if
(
!
(
*
conf
->
assign_hook
)
(
newval
,
changeVal
,
source
))
{
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
: %g"
,
name
,
newval
)));
return
false
;
}
if
(
changeVal
||
makeDefault
)
{
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
{
*
conf
->
variable
=
newval
;
conf
->
gen
.
source
=
source
;
}
if
(
makeDefault
)
{
GucStack
*
stack
;
...
...
@@ -4346,22 +4116,82 @@ set_config_option(const char *name, const char *value,
struct
config_string
*
conf
=
(
struct
config_string
*
)
record
;
char
*
newval
;
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
(
union
config_var_value
*
)
&
newval
))
return
false
;
if
(
value
)
{
newval
=
guc_strdup
(
elevel
,
value
);
if
(
newval
==
NULL
)
return
false
;
/*
* The only sort of "parsing" check we need to do is
* apply truncation if GUC_IS_NAME.
*/
if
(
conf
->
gen
.
flags
&
GUC_IS_NAME
)
truncate_identifier
(
newval
,
strlen
(
newval
),
true
);
}
else
if
(
conf
->
reset_val
)
{
/*
* We could possibly avoid strdup here, but easier to make
* this case work the same as the normal assignment case.
*/
newval
=
guc_strdup
(
elevel
,
conf
->
reset_val
);
if
(
newval
==
NULL
)
return
false
;
source
=
conf
->
gen
.
reset_source
;
}
else
{
/* Nothing to reset to, as yet; so do nothing */
break
;
}
if
(
conf
->
assign_hook
)
{
const
char
*
hookresult
;
/*
* If the hook ereports, we have to make sure we free
* newval, else it will be a permanent memory leak.
*/
hookresult
=
call_string_assign_hook
(
conf
->
assign_hook
,
newval
,
changeVal
,
source
);
if
(
hookresult
==
NULL
)
{
free
(
newval
);
ereport
(
elevel
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"invalid value for parameter
\"
%s
\"
:
\"
%s
\"
"
,
name
,
value
?
value
:
""
)));
return
false
;
}
else
if
(
hookresult
!=
newval
)
{
free
(
newval
);
/*
* Having to cast away const here is annoying, but the
* alternative is to declare assign_hooks as returning
* char*, which would mean they'd have to cast away
* const, or as both taking and returning char*, which
* doesn't seem attractive either --- we don't want
* them to scribble on the passed str.
*/
newval
=
(
char
*
)
hookresult
;
}
}
if
(
changeVal
||
makeDefault
)
{
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
{
set_string_field
(
conf
,
conf
->
variable
,
newval
);
conf
->
gen
.
source
=
source
;
}
if
(
makeDefault
)
{
GucStack
*
stack
;
...
...
@@ -4937,7 +4767,8 @@ GetPGVariableResultDesc(const char *name)
/* need a tuple descriptor representing a single TEXT column */
tupdesc
=
CreateTemplateTupleDesc
(
1
,
false
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
1
,
varname
,
TEXTOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
1
,
varname
,
TEXTOID
,
-
1
,
0
);
}
return
tupdesc
;
}
...
...
@@ -5029,6 +4860,7 @@ ShowAllGUCConfig(DestReceiver *dest)
/* send it to dest */
do_tup_output
(
tstate
,
values
);
/* clean up */
if
(
values
[
1
]
!=
NULL
)
pfree
(
values
[
1
]);
}
...
...
@@ -5482,9 +5314,6 @@ _ShowOption(struct config_generic * record, bool use_units)
static
bool
is_newvalue_equal
(
struct
config_generic
*
record
,
const
char
*
newvalue
)
{
if
(
!
newvalue
)
return
false
;
switch
(
record
->
vartype
)
{
case
PGC_BOOL
:
...
...
@@ -5512,10 +5341,7 @@ is_newvalue_equal(struct config_generic *record, const char *newvalue)
{
struct
config_string
*
conf
=
(
struct
config_string
*
)
record
;
if
(
!*
conf
->
variable
)
/* custom variable with no value yet */
return
false
;
else
return
strcmp
(
*
conf
->
variable
,
newvalue
)
==
0
;
return
strcmp
(
*
conf
->
variable
,
newvalue
)
==
0
;
}
}
...
...
src/include/utils/guc.h
View file @
f0584518
...
...
@@ -7,7 +7,7 @@
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.7
4 2006/08/13 01:30:1
7 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.7
5 2006/08/14 02:27:2
7 momjian Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
...
...
@@ -193,9 +193,6 @@ extern void ParseLongOption(const char *string, char **name, char **value);
extern
bool
set_config_option
(
const
char
*
name
,
const
char
*
value
,
GucContext
context
,
GucSource
source
,
bool
isLocal
,
bool
changeVal
);
extern
bool
verify_config_option
(
const
char
*
name
,
const
char
*
value
,
GucContext
context
,
GucSource
source
,
bool
*
isNewEqual
,
bool
*
isContextOK
);
extern
char
*
GetConfigOptionByName
(
const
char
*
name
,
const
char
**
varname
);
extern
void
GetConfigOptionByNum
(
int
varnum
,
const
char
**
values
,
bool
*
noshow
);
extern
int
GetNumConfigOptions
(
void
);
...
...
src/include/utils/guc_tables.h
View file @
f0584518
...
...
@@ -7,7 +7,7 @@
*
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.2
7 2006/08/13 02:22:24
momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.2
8 2006/08/14 02:27:27
momjian Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -143,8 +143,7 @@ struct config_generic
#define GUC_HAVE_TENTATIVE 0x0001
/* tentative value is defined */
#define GUC_HAVE_LOCAL 0x0002
/* a SET LOCAL has been executed */
#define GUC_HAVE_STACK 0x0004
/* we have stacked prior value(s) */
#define GUC_IN_CONFFILE 0x0008
/* value shows up in the configuration
file (is not commented) */
/* GUC records for specific variable types */
...
...
@@ -154,12 +153,11 @@ struct config_bool
/* these fields must be set correctly in initial value: */
/* (all but reset_val are constants) */
bool
*
variable
;
bool
boo
t_val
;
bool
rese
t_val
;
GucBoolAssignHook
assign_hook
;
GucShowHook
show_hook
;
/* variable fields, initialized at runtime: */
bool
tentative_val
;
bool
reset_val
;
};
struct
config_int
...
...
@@ -168,14 +166,13 @@ struct config_int
/* these fields must be set correctly in initial value: */
/* (all but reset_val are constants) */
int
*
variable
;
int
boo
t_val
;
int
rese
t_val
;
int
min
;
int
max
;
GucIntAssignHook
assign_hook
;
GucShowHook
show_hook
;
/* variable fields, initialized at runtime: */
int
tentative_val
;
int
reset_val
;
};
struct
config_real
...
...
@@ -184,14 +181,13 @@ struct config_real
/* these fields must be set correctly in initial value: */
/* (all but reset_val are constants) */
double
*
variable
;
double
boo
t_val
;
double
rese
t_val
;
double
min
;
double
max
;
GucRealAssignHook
assign_hook
;
GucShowHook
show_hook
;
/* variable fields, initialized at runtime: */
double
tentative_val
;
double
reset_val
;
};
struct
config_string
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment