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
e7da38bf
Commit
e7da38bf
authored
Aug 13, 2006
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Re-apply guc cleanup patch, with memory allocation bugs fixed.
parent
3f8db37c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
423 additions
and
255 deletions
+423
-255
src/backend/utils/misc/guc-file.l
src/backend/utils/misc/guc-file.l
+55
-19
src/backend/utils/misc/guc.c
src/backend/utils/misc/guc.c
+364
-235
src/include/utils/guc.h
src/include/utils/guc.h
+4
-1
No files found.
src/backend/utils/misc/guc-file.l
View file @
e7da38bf
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
*
*
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
*
*
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.4
2 2006/08/12 04:12:41
momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.4
3 2006/08/13 01:30:17
momjian Exp $
*/
*/
%{
%{
...
@@ -50,7 +50,8 @@ int GUC_yylex(void);
...
@@ -50,7 +50,8 @@ int GUC_yylex(void);
static bool ParseConfigFile(const char *config_file, const char *calling_file,
static bool ParseConfigFile(const char *config_file, const char *calling_file,
int depth, GucContext context, int elevel,
int depth, GucContext context, int elevel,
struct name_value_pair **head_p,
struct name_value_pair **head_p,
struct name_value_pair **tail_p);
struct name_value_pair **tail_p,
int *varcount);
static void free_name_value_list(struct name_value_pair * list);
static void free_name_value_list(struct name_value_pair * list);
static char *GUC_scanstr(const char *s);
static char *GUC_scanstr(const char *s);
...
@@ -114,8 +115,10 @@ STRING \'([^'\\\n]|\\.|\'\')*\'
...
@@ -114,8 +115,10 @@ STRING \'([^'\\\n]|\\.|\'\')*\'
void
void
ProcessConfigFile(GucContext context)
ProcessConfigFile(GucContext context)
{
{
int elevel;
int elevel
, i
;
struct name_value_pair *item, *head, *tail;
struct name_value_pair *item, *head, *tail;
bool *apply_list = NULL;
int varcount = 0;
Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
...
@@ -134,25 +137,56 @@ ProcessConfigFile(GucContext context)
...
@@ -134,25 +137,56 @@ ProcessConfigFile(GucContext context)
if (!ParseConfigFile(ConfigFileName, NULL,
if (!ParseConfigFile(ConfigFileName, NULL,
0, context, elevel,
0, context, elevel,
&head, &tail))
&head, &tail
, &varcount
))
goto cleanup_list;
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 */
/* Check if all options are valid */
for (item = head; item; item = item->next)
for (item = head, i = 0; item; item = item->next, i++)
{
bool isEqual, isContextOk;
if (!verify_config_option(item->name, item->value, context,
PGC_S_FILE, &isEqual, &isContextOk))
{
{
if (!set_config_option(item->name, item->value, context,
ereport(elevel,
PGC_S_FILE, false, false))
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("configuration file is invalid")));
goto cleanup_list;
goto cleanup_list;
}
}
/* If we got here all the options checked out okay, so apply them. */
if (isContextOk == false)
for (item = head; item; item = item->next)
{
{
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,
set_config_option(item->name, item->value, context,
PGC_S_FILE, false, true);
PGC_S_FILE, false, true);
}
cleanup_list:
cleanup_list:
if (apply_list)
pfree(apply_list);
free_name_value_list(head);
free_name_value_list(head);
}
}
...
@@ -189,7 +223,8 @@ static bool
...
@@ -189,7 +223,8 @@ static bool
ParseConfigFile(const char *config_file, const char *calling_file,
ParseConfigFile(const char *config_file, const char *calling_file,
int depth, GucContext context, int elevel,
int depth, GucContext context, int elevel,
struct name_value_pair **head_p,
struct name_value_pair **head_p,
struct name_value_pair **tail_p)
struct name_value_pair **tail_p,
int *varcount)
{
{
bool OK = true;
bool OK = true;
char abs_path[MAXPGPATH];
char abs_path[MAXPGPATH];
...
@@ -289,7 +324,7 @@ ParseConfigFile(const char *config_file, const char *calling_file,
...
@@ -289,7 +324,7 @@ ParseConfigFile(const char *config_file, const char *calling_file,
if (!ParseConfigFile(opt_value, config_file,
if (!ParseConfigFile(opt_value, config_file,
depth + 1, context, elevel,
depth + 1, context, elevel,
head_p, tail_p))
head_p, tail_p
, varcount
))
{
{
pfree(opt_name);
pfree(opt_name);
pfree(opt_value);
pfree(opt_value);
...
@@ -333,6 +368,7 @@ ParseConfigFile(const char *config_file, const char *calling_file,
...
@@ -333,6 +368,7 @@ ParseConfigFile(const char *config_file, const char *calling_file,
else
else
(*tail_p)->next = item;
(*tail_p)->next = item;
*tail_p = item;
*tail_p = item;
(*varcount)++;
}
}
/* break out of loop if read EOF, else loop for next line */
/* break out of loop if read EOF, else loop for next line */
...
...
src/backend/utils/misc/guc.c
View file @
e7da38bf
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.33
7 2006/08/12 04:12:41
momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.33
8 2006/08/13 01:30:17
momjian Exp $
*
*
*--------------------------------------------------------------------
*--------------------------------------------------------------------
*/
*/
...
@@ -2313,7 +2313,7 @@ guc_strdup(int elevel, const char *src)
...
@@ -2313,7 +2313,7 @@ guc_strdup(int elevel, const char *src)
* states).
* states).
*/
*/
static
void
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
;
char
*
oldval
=
*
field
;
GucStack
*
stack
;
GucStack
*
stack
;
...
@@ -2535,8 +2535,7 @@ add_placeholder_variable(const char *name, int elevel)
...
@@ -2535,8 +2535,7 @@ add_placeholder_variable(const char *name, int elevel)
gen
=
&
var
->
gen
;
gen
=
&
var
->
gen
;
memset
(
var
,
0
,
sz
);
memset
(
var
,
0
,
sz
);
gen
->
name
=
guc_strdup
(
elevel
,
name
);
if
((
gen
->
name
=
guc_strdup
(
elevel
,
name
))
==
NULL
)
if
(
gen
->
name
==
NULL
)
{
{
free
(
var
);
free
(
var
);
return
NULL
;
return
NULL
;
...
@@ -3690,96 +3689,254 @@ call_string_assign_hook(GucStringAssignHook assign_hook,
...
@@ -3690,96 +3689,254 @@ call_string_assign_hook(GucStringAssignHook assign_hook,
return
result
;
return
result
;
}
}
/*
/*
* Sets option `name' to given value. The value should be a string
* Try to parse value. Determine what is type and call related
* which is going to be parsed and converted to the appropriate data
* parsing function or if newval is equal to NULL, reset value
* type. The context and source parameters indicate in which context this
* to default or bootval. If the value parsed okay return true,
* function is being called so it can apply the access restrictions
* else false.
* 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
static
bool
set_config_option
(
const
char
*
name
,
const
char
*
value
,
parse_value
(
int
elevel
,
const
struct
config_generic
*
record
,
GucContext
context
,
GucSource
source
,
const
char
*
value
,
GucSource
*
source
,
bool
changeVal
,
bool
isLocal
,
bool
changeV
al
)
union
config_var_value
*
retv
al
)
{
{
struct
config_generic
*
record
;
/*
int
elevel
;
* Evaluate value and set variable.
bool
makeDefault
;
*/
switch
(
record
->
vartype
)
{
case
PGC_BOOL
:
{
struct
config_bool
*
conf
=
(
struct
config_bool
*
)
record
;
bool
newval
;
if
(
context
==
PGC_SIGHUP
||
source
==
PGC_S_DEFAULT
)
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
{
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
,
(
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
{
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
{
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"
,
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
;
/*
/*
* To avoid cluttering the log, only the postmaster bleats loudly
* The only sort of "parsing" check we need to do is
* about problems with the config file
.
* apply truncation if GUC_IS_NAME
.
*/
*/
elevel
=
IsUnderPostmaster
?
DEBUG2
:
LOG
;
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.
*/
if
((
newval
=
guc_strdup
(
elevel
,
conf
->
reset_val
))
==
NULL
)
return
false
;
*
source
=
conf
->
gen
.
reset_source
;
}
}
else
if
(
source
==
PGC_S_DATABASE
||
source
==
PGC_S_USER
)
elevel
=
INFO
;
else
else
elevel
=
ERROR
;
{
/* Nothing to reset to, as yet; so do nothing */
break
;
}
record
=
find_option
(
name
,
elevel
);
if
(
conf
->
assign_hook
)
if
(
record
==
NULL
)
{
{
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
,
ereport
(
elevel
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
errmsg
(
"unrecognized configuration parameter
\"
%s
\"
"
,
name
)));
errmsg
(
"invalid value for parameter
\"
%s
\"
:
\"
%s
\"
"
,
record
->
name
,
value
?
value
:
""
)));
return
false
;
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
(
retval
)
retval
->
stringval
=
newval
;
else
free
(
newval
);
break
;
}
}
return
true
;
}
/*
* Check if the option can be set at this time. See guc.h for the precise
* 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
* rules.
* context. In that case we just ignore the attempt and return true.
*/
*/
static
bool
checkContext
(
int
elevel
,
struct
config_generic
*
record
,
GucContext
context
)
{
switch
(
record
->
context
)
switch
(
record
->
context
)
{
{
case
PGC_INTERNAL
:
case
PGC_INTERNAL
:
if
(
context
==
PGC_SIGHUP
)
return
true
;
if
(
context
!=
PGC_INTERNAL
)
if
(
context
!=
PGC_INTERNAL
)
{
{
ereport
(
elevel
,
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed"
,
errmsg
(
"parameter
\"
%s
\"
cannot be changed"
,
name
)));
record
->
name
)));
return
false
;
return
false
;
}
}
break
;
break
;
case
PGC_POSTMASTER
:
case
PGC_POSTMASTER
:
if
(
context
==
PGC_SIGHUP
)
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
)
if
(
context
!=
PGC_POSTMASTER
)
{
{
ereport
(
elevel
,
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed after server start"
,
errmsg
(
"parameter
\"
%s
\"
cannot be changed after server start"
,
name
)));
record
->
name
)));
return
false
;
return
false
;
}
}
break
;
break
;
...
@@ -3789,7 +3946,7 @@ set_config_option(const char *name, const char *value,
...
@@ -3789,7 +3946,7 @@ set_config_option(const char *name, const char *value,
ereport
(
elevel
,
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be changed now"
,
errmsg
(
"parameter
\"
%s
\"
cannot be changed now"
,
name
)));
record
->
name
)));
return
false
;
return
false
;
}
}
...
@@ -3812,14 +3969,16 @@ set_config_option(const char *name, const char *value,
...
@@ -3812,14 +3969,16 @@ set_config_option(const char *name, const char *value,
* backend start.
* backend start.
*/
*/
if
(
IsUnderPostmaster
)
if
(
IsUnderPostmaster
)
return
true
;
{
return
false
;
}
}
}
else
if
(
context
!=
PGC_BACKEND
&&
context
!=
PGC_POSTMASTER
)
else
if
(
context
!=
PGC_BACKEND
&&
context
!=
PGC_POSTMASTER
)
{
{
ereport
(
elevel
,
ereport
(
elevel
,
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
(
errcode
(
ERRCODE_CANT_CHANGE_RUNTIME_PARAM
),
errmsg
(
"parameter
\"
%s
\"
cannot be set after connection start"
,
errmsg
(
"parameter
\"
%s
\"
cannot be set after connection start"
,
name
)));
record
->
name
)));
return
false
;
return
false
;
}
}
break
;
break
;
...
@@ -3829,7 +3988,7 @@ set_config_option(const char *name, const char *value,
...
@@ -3829,7 +3988,7 @@ set_config_option(const char *name, const char *value,
ereport
(
elevel
,
ereport
(
elevel
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
errmsg
(
"permission denied to set parameter
\"
%s
\"
"
,
errmsg
(
"permission denied to set parameter
\"
%s
\"
"
,
name
)));
record
->
name
)));
return
false
;
return
false
;
}
}
break
;
break
;
...
@@ -3837,6 +3996,114 @@ set_config_option(const char *name, const char *value,
...
@@ -3837,6 +3996,114 @@ set_config_option(const char *name, const char *value,
/* always okay */
/* always okay */
break
;
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
))
{
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
* Should we set reset/stacked values? (If so, the behavior is not
...
@@ -3872,43 +4139,22 @@ set_config_option(const char *name, const char *value,
...
@@ -3872,43 +4139,22 @@ set_config_option(const char *name, const char *value,
struct
config_bool
*
conf
=
(
struct
config_bool
*
)
record
;
struct
config_bool
*
conf
=
(
struct
config_bool
*
)
record
;
bool
newval
;
bool
newval
;
if
(
value
)
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
{
(
union
config_var_value
*
)
&
newval
))
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
;
return
false
;
}
if
(
changeVal
||
makeDefault
)
if
(
changeVal
||
makeDefault
)
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
if
(
changeVal
)
{
{
*
conf
->
variable
=
newval
;
*
conf
->
variable
=
newval
;
conf
->
gen
.
source
=
source
;
conf
->
gen
.
source
=
source
;
}
}
if
(
makeDefault
)
if
(
makeDefault
)
{
{
GucStack
*
stack
;
GucStack
*
stack
;
...
@@ -3948,51 +4194,22 @@ set_config_option(const char *name, const char *value,
...
@@ -3948,51 +4194,22 @@ set_config_option(const char *name, const char *value,
struct
config_int
*
conf
=
(
struct
config_int
*
)
record
;
struct
config_int
*
conf
=
(
struct
config_int
*
)
record
;
int
newval
;
int
newval
;
if
(
value
)
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
{
(
union
config_var_value
*
)
&
newval
))
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
;
return
false
;
}
if
(
changeVal
||
makeDefault
)
if
(
changeVal
||
makeDefault
)
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
if
(
changeVal
)
{
{
*
conf
->
variable
=
newval
;
*
conf
->
variable
=
newval
;
conf
->
gen
.
source
=
source
;
conf
->
gen
.
source
=
source
;
}
}
if
(
makeDefault
)
if
(
makeDefault
)
{
{
GucStack
*
stack
;
GucStack
*
stack
;
...
@@ -4032,51 +4249,22 @@ set_config_option(const char *name, const char *value,
...
@@ -4032,51 +4249,22 @@ set_config_option(const char *name, const char *value,
struct
config_real
*
conf
=
(
struct
config_real
*
)
record
;
struct
config_real
*
conf
=
(
struct
config_real
*
)
record
;
double
newval
;
double
newval
;
if
(
value
)
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
{
(
union
config_var_value
*
)
&
newval
))
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
;
return
false
;
}
if
(
changeVal
||
makeDefault
)
if
(
changeVal
||
makeDefault
)
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
if
(
changeVal
)
{
{
*
conf
->
variable
=
newval
;
*
conf
->
variable
=
newval
;
conf
->
gen
.
source
=
source
;
conf
->
gen
.
source
=
source
;
}
}
if
(
makeDefault
)
if
(
makeDefault
)
{
{
GucStack
*
stack
;
GucStack
*
stack
;
...
@@ -4116,82 +4304,22 @@ set_config_option(const char *name, const char *value,
...
@@ -4116,82 +4304,22 @@ set_config_option(const char *name, const char *value,
struct
config_string
*
conf
=
(
struct
config_string
*
)
record
;
struct
config_string
*
conf
=
(
struct
config_string
*
)
record
;
char
*
newval
;
char
*
newval
;
if
(
value
)
if
(
!
parse_value
(
elevel
,
record
,
value
,
&
source
,
changeVal
,
{
(
union
config_var_value
*
)
&
newval
))
newval
=
guc_strdup
(
elevel
,
value
);
if
(
newval
==
NULL
)
return
false
;
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
)
if
(
changeVal
||
makeDefault
)
{
{
/* Save old value to support transaction abort */
/* Save old value to support transaction abort */
if
(
!
makeDefault
)
if
(
!
makeDefault
)
push_old_value
(
&
conf
->
gen
);
push_old_value
(
&
conf
->
gen
);
if
(
changeVal
)
if
(
changeVal
)
{
{
set_string_field
(
conf
,
conf
->
variable
,
newval
);
set_string_field
(
conf
,
conf
->
variable
,
newval
);
conf
->
gen
.
source
=
source
;
conf
->
gen
.
source
=
source
;
}
}
if
(
makeDefault
)
if
(
makeDefault
)
{
{
GucStack
*
stack
;
GucStack
*
stack
;
...
@@ -4767,8 +4895,7 @@ GetPGVariableResultDesc(const char *name)
...
@@ -4767,8 +4895,7 @@ GetPGVariableResultDesc(const char *name)
/* need a tuple descriptor representing a single TEXT column */
/* need a tuple descriptor representing a single TEXT column */
tupdesc
=
CreateTemplateTupleDesc
(
1
,
false
);
tupdesc
=
CreateTemplateTupleDesc
(
1
,
false
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
1
,
varname
,
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
1
,
varname
,
TEXTOID
,
-
1
,
0
);
TEXTOID
,
-
1
,
0
);
}
}
return
tupdesc
;
return
tupdesc
;
}
}
...
@@ -4860,7 +4987,6 @@ ShowAllGUCConfig(DestReceiver *dest)
...
@@ -4860,7 +4987,6 @@ ShowAllGUCConfig(DestReceiver *dest)
/* send it to dest */
/* send it to dest */
do_tup_output
(
tstate
,
values
);
do_tup_output
(
tstate
,
values
);
/* clean up */
if
(
values
[
1
]
!=
NULL
)
if
(
values
[
1
]
!=
NULL
)
pfree
(
values
[
1
]);
pfree
(
values
[
1
]);
}
}
...
@@ -5314,6 +5440,9 @@ _ShowOption(struct config_generic * record, bool use_units)
...
@@ -5314,6 +5440,9 @@ _ShowOption(struct config_generic * record, bool use_units)
static
bool
static
bool
is_newvalue_equal
(
struct
config_generic
*
record
,
const
char
*
newvalue
)
is_newvalue_equal
(
struct
config_generic
*
record
,
const
char
*
newvalue
)
{
{
if
(
!
newvalue
)
return
false
;
switch
(
record
->
vartype
)
switch
(
record
->
vartype
)
{
{
case
PGC_BOOL
:
case
PGC_BOOL
:
...
...
src/include/utils/guc.h
View file @
e7da38bf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
*
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.7
3 2006/08/12 04:12:41
momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.7
4 2006/08/13 01:30:17
momjian Exp $
*--------------------------------------------------------------------
*--------------------------------------------------------------------
*/
*/
#ifndef GUC_H
#ifndef GUC_H
...
@@ -193,6 +193,9 @@ extern void ParseLongOption(const char *string, char **name, char **value);
...
@@ -193,6 +193,9 @@ extern void ParseLongOption(const char *string, char **name, char **value);
extern
bool
set_config_option
(
const
char
*
name
,
const
char
*
value
,
extern
bool
set_config_option
(
const
char
*
name
,
const
char
*
value
,
GucContext
context
,
GucSource
source
,
GucContext
context
,
GucSource
source
,
bool
isLocal
,
bool
changeVal
);
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
char
*
GetConfigOptionByName
(
const
char
*
name
,
const
char
**
varname
);
extern
void
GetConfigOptionByNum
(
int
varnum
,
const
char
**
values
,
bool
*
noshow
);
extern
void
GetConfigOptionByNum
(
int
varnum
,
const
char
**
values
,
bool
*
noshow
);
extern
int
GetNumConfigOptions
(
void
);
extern
int
GetNumConfigOptions
(
void
);
...
...
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