add: AlterSystemSet

This commit is contained in:
gentle_hu 2020-08-12 00:29:42 +08:00
parent 5eaa986a1e
commit 36ef69d49a
14 changed files with 1070 additions and 151 deletions

View File

@ -87,6 +87,7 @@
static void CopyMemInfoFields(const OpMemInfo* from, OpMemInfo* newnode);
static ReplicaIdentityStmt* _copyReplicaIdentityStmt(const ReplicaIdentityStmt* from);
static AlterSystemStmt* _copyAlterSystemStmt(const AlterSystemStmt * from);
static void CopyCursorFields(const Cursor_Data* from, Cursor_Data* newnode);
/* ****************************************************************
@ -6401,6 +6402,9 @@ void* copyObject(const void* from)
case T_ReplicaIdentityStmt:
retval = _copyReplicaIdentityStmt((ReplicaIdentityStmt*)from);
break;
case T_AlterSystemStmt:
retval = _copyAlterSystemStmt((AlterSystemStmt*)from);
break;
case T_CreateSeqStmt:
retval = _copyCreateSeqStmt((CreateSeqStmt*)from);
break;
@ -6827,6 +6831,13 @@ static ReplicaIdentityStmt* _copyReplicaIdentityStmt(const ReplicaIdentityStmt*
return newnode;
}
static AlterSystemStmt* _copyAlterSystemStmt(const AlterSystemStmt * from)
{
AlterSystemStmt* newnode = makeNode(AlterSystemStmt);
COPY_NODE_FIELD(setstmt);
return newnode;
}
/*
* CopyCursorFields -
* copy Cursor_Data structure from "from" node to "newnode"

View File

@ -1567,6 +1567,12 @@ static bool _equalReplicaIdentityStmt(const ReplicaIdentityStmt* a, const Replic
return true;
}
static bool _equalAlterSystemStmt(const AlterSystemStmt * a, const AlterSystemStmt * b)
{
COMPARE_NODE_FIELD(setstmt);
return true;
}
static bool _equalCreateSeqStmt(const CreateSeqStmt* a, const CreateSeqStmt* b)
{
COMPARE_NODE_FIELD(sequence);
@ -3130,6 +3136,9 @@ bool equal(const void* a, const void* b)
case T_ReplicaIdentityStmt:
retval = _equalReplicaIdentityStmt((ReplicaIdentityStmt*)a, (ReplicaIdentityStmt*)b);
break;
case T_AlterSystemStmt:
retval = _equalAlterSystemStmt((AlterSystemStmt*)a, (AlterSystemStmt*)b);
break;
case T_AlterSeqStmt:
retval = _equalAlterSeqStmt((AlterSeqStmt*)a, (AlterSeqStmt*)b);
break;

View File

@ -165,7 +165,6 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
bool *deferrable, bool *initdeferred, bool *not_valid,
bool *no_inherit, core_yyscan_t yyscanner);
static Expr *makeNodeDecodeCondtion(Expr* firstCond,Expr* secondCond);
static void is_kill_session(List *actionlist);
static List *make_action_func(List *arguments);
static List *get_func_args(char *sid);
static char *pg_strsep(char **stringp, const char *delim);
@ -451,7 +450,7 @@ static void ParseUpdateMultiSet(List *set_target_list, SelectStmt *stmt, core_yy
%type <mergewhen> merge_insert merge_update
%type <vsetstmt> set_rest set_rest_more SetResetClause FunctionSetResetClause
%type <vsetstmt> generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause
%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
ForeignTableElement
@ -637,7 +636,7 @@ static void ParseUpdateMultiSet(List *set_target_list, SelectStmt *stmt, core_yy
/* PGXC_BEGIN */
DICTIONARY DIRECT DIRECTORY DISABLE_P DISCARD DISTINCT DISTRIBUTE DISTRIBUTION DO DOCUMENT_P DOMAIN_P DOUBLE_P
/* PGXC_END */
DROP DUPLICATE
DROP DUPLICATE DISCONNECT
EACH ELASTIC ELSE ENABLE_P ENCODING ENCRYPTED END_P ENFORCED ENUM_P ERRORS ESCAPE EOL ESCAPING EVERY EXCEPT EXCHANGE
EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN
@ -657,7 +656,7 @@ static void ParseUpdateMultiSet(List *set_target_list, SelectStmt *stmt, core_yy
JOIN
KEY
KEY KILL
LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING LEAKPROOF
LEAST LESS LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
@ -1507,17 +1506,19 @@ AlterSessionStmt:
/* "alter system" */
/*****************************************************************************
*
* Alter SYSTEM (kill a session)
* Alter SYSTEM
* (1. kill a session by "select pg_terminate_backend(pid)", so it only needs a SelectStmt node.)
* (2. disconnect a session. unsupported currently.)
* (3. set system parameter to, this is used to change configuration parameters persistently.)
*
*****************************************************************************/
AlterSystemStmt:
ALTER SYSTEM_P name_list SESSION Sconst altersys_option
ALTER SYSTEM_P KILL SESSION Sconst altersys_option
{
SelectStmt *n = NULL;
List *pid = NULL;
is_kill_session($3);
pid = get_func_args($5);
n = makeNode(SelectStmt);
@ -1531,7 +1532,22 @@ AlterSystemStmt:
n->windowClause = NIL;
$$ = (Node *)n;
}
| ALTER SYSTEM_P DISCONNECT SESSION Sconst altersys_option
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unsupported action \"DISCONNECT\" for statement \" alter system \"")));
}
| ALTER SYSTEM_P SET generic_set
{
AlterSystemStmt *n = makeNode(AlterSystemStmt);
n->setstmt = $4;
$$ = (Node *)n;
}
;
altersys_option:
IMMEDIATE {/* empty */}
| {/* empty */}
@ -1666,7 +1682,7 @@ set_rest:
| set_rest_more
;
set_rest_more: /* Generic SET syntaxes: */
generic_set:
var_name TO var_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
@ -1751,6 +1767,13 @@ set_rest_more: /* Generic SET syntaxes: */
n->name = "current_schema";
$$ = n;
}
;
set_rest_more: /* Generic SET syntaxes: */
generic_set
{
$$ = $1;
}
| var_name FROM CURRENT_P
{
VariableSetStmt *n = makeNode(VariableSetStmt);
@ -11398,7 +11421,6 @@ DropdbStmt: DROP DATABASE database_name
}
;
/*****************************************************************************
*
* Manipulate a domain
@ -17671,6 +17693,7 @@ unreserved_keyword:
| DIRECTORY
| DISABLE_P
| DISCARD
| DISCONNECT
/* PGXC_BEGIN */
| DISTRIBUTE
| DISTRIBUTION
@ -17742,6 +17765,7 @@ unreserved_keyword:
| ISNULL
| ISOLATION
| KEY
| KILL
| LABEL
| LANGUAGE
| LARGE_P
@ -18858,45 +18882,6 @@ makeNodeDecodeCondtion(Expr* firstCond,Expr* secondCond)
return (Expr*)c;
}
// check weather is an action of "kill session"
// unsupported action "disconnect"
static void
is_kill_session(List *actionlist)
{
char *actionopt = NULL;
ListCell *lc = NULL;
if (1 != actionlist->length)
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("undefined or invalid action for statement \" alter system \"")));
return;
}
lc = list_head(actionlist);
actionopt = ((Value *)(lfirst(lc)))->val.str;
if (!pg_strcasecmp(actionopt, "KILL"))
return;
else if (!pg_strcasecmp(actionopt, "DISCONNECT"))
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unsupported action \"%s\" for statement \" alter system \"",
actionopt)));
return;
}
else
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("undefined action \"%s\" for statement \" alter system \"",
actionopt)));
return;
}
}
// make function infomation to kill the session
// make "ResTarget" for invoking function "pg_terminate_backend",
// only the first cell of arguments is effective, it is treated as pid

View File

@ -483,6 +483,8 @@ static const char* show_unix_socket_permissions(void);
static const char* show_log_file_mode(void);
static char* config_enum_get_options(
struct config_enum* record, const char* prefix, const char* suffix, const char* separator);
static bool validate_conf_option(struct config_generic * record, const char *name, const char *value,
GucSource source, int elevel, bool freemem, void *newval, void **newextra);
/* Database Security: Support password complexity */
static bool check_int_parameter(int* newval, void** extra, GucSource source);
@ -11885,6 +11887,7 @@ static void show_guc_config_option(const char* name, DestReceiver* dest);
static void show_all_guc_config(DestReceiver* dest);
static char* _show_option(struct config_generic* record, bool use_units);
static bool validate_option_array_item(const char* name, const char* value, bool skip_if_no_permissions);
static void replace_config_value(char** optlines, char* name, char* value, config_type vartype);
/*
* Some infrastructure for checking malloc/strdup/realloc calls
@ -14324,6 +14327,202 @@ static char* config_enum_get_options(
return retstr.data;
}
/*
* Validates configuration parameter and value, by calling check hook functions
* depending on record's vartype. It validates if the parameter
* value given is in range of expected predefined value for that parameter.
*
* freemem - true indicates memory for newval and newextra will be
* freed in this function, false indicates it will be freed
* by caller.
* Return value:
* true : the value is valid
* false: the name or value is invalid
*/
bool validate_conf_option(struct config_generic * record, const char *name, const char *value, GucSource source,
int elevel, bool freemem, void *newvalue, void **newextra)
{
Assert(value != NULL);
/*
* Validate the value for the passed record, to ensure it is in expected range.
*/
switch (record->vartype)
{
case PGC_BOOL:
{
struct config_bool *conf = (struct config_bool *) record;
bool tmpnewval;
bool* newval = (newvalue == NULL ? &tmpnewval : (bool*)newvalue);
if (!parse_bool(value, newval)) {
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("parameter \"%s\" requires a Boolean value", name)));
return false;
}
if (!call_bool_check_hook(conf, newval, newextra, source, elevel))
return false;
if (*newextra && freemem)
pfree(*newextra);
}
break;
case PGC_INT:
{
struct config_int *conf = (struct config_int *) record;
int tmpnewval;
int* newval = (newvalue == NULL ? &tmpnewval : (int*)newvalue);
const char *hintmsg = NULL;
if (!parse_int(value, newval, conf->gen.flags, &hintmsg)) {
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid value for parameter \"%s\": \"%s\"",
name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0));
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;
}
if (!call_int_check_hook(conf, newval, newextra, source, elevel))
return false;
if (*newextra && freemem)
pfree(*newextra);
}
break;
case PGC_INT64:
{
struct config_int64* conf = (struct config_int64*)record;
int64 tmpnewval;
int64* newval = (newvalue == NULL ? &tmpnewval : (int64*)newvalue);
const char* hintmsg = NULL;
if (!parse_int64(value, newval, &hintmsg)) {
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("%ld is outside the valid range for parameter \"%s\" (%ld .. %ld)",
*newval, name, conf->min, conf->max)));
return false;
}
if (!call_int64_check_hook(conf, newval, newextra, source, elevel))
return false;
if (*newextra && freemem)
pfree(newextra);
}
break;
case PGC_REAL:
{
struct config_real *conf = (struct config_real *) record;
double tmpnewval;
double* newval = (newvalue == NULL ? &tmpnewval : (double*)newvalue);
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;
}
if (!call_real_check_hook(conf, newval, newextra, source, elevel))
return false;
if (*newextra && freemem)
pfree(*newextra);
}
break;
case PGC_STRING:
{
struct config_string *conf = (struct config_string *) record;
char* tmpnewval = NULL;
char** newval = newvalue == NULL ? &tmpnewval : (char**)newvalue;
/* The value passed by the caller could be transient, so we always strdup it. */
*newval = guc_strdup(elevel, value);
if (*newval == NULL)
return false;
/* The only built-in "parsing" check we have is to apply truncation if GUC_IS_NAME. */
if (conf->gen.flags & GUC_IS_NAME)
truncate_identifier(*newval, strlen(*newval), true);
if (!call_string_check_hook(conf, newval, newextra, source, elevel)) {
pfree(*newval);
return false;
}
/* Free the malloc'd data if any */
if (freemem) {
if (*newval != NULL)
pfree(*newval);
if (*newextra != NULL)
pfree(*newextra);
}
}
break;
case PGC_ENUM:
{
struct config_enum *conf = (struct config_enum *) record;
int tmpnewval;
int* newval = (newvalue == NULL ? &tmpnewval : (int*)newvalue);
if (!config_enum_lookup_by_name(conf, value, newval)) {
char* hintmsg;
hintmsg = config_enum_get_options(conf, "Available values: ", ".", ", ");
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid value for parameter \"%s\": \"%s\"", name, value),
hintmsg ? errhint("%s", _(hintmsg)) : 0));
if (hintmsg != NULL)
pfree(hintmsg);
return false;
}
if (!call_enum_check_hook(conf, newval, newextra, source, LOG))
return false;
if (*newextra && freemem)
pfree(*newextra);
}
break;
default:
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_ATTRIBUTE),
errmsg("unknow guc variable type: %d", record->vartype)));
}
break;
}
return true;
}
void SetThreadLocalGUC(knl_session_context* session)
{
default_statistics_target = session->attr.attr_sql.default_statistics_target;
@ -14590,14 +14789,7 @@ int set_config_option(const char* name, const char* value, GucContext context, G
void* newextra = NULL;
if (value != NULL) {
if (!parse_bool(value, &newval)) {
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("parameter \"%s\" requires a Boolean value", name)));
return 0;
}
if (!call_bool_check_hook(conf, &newval, &newextra, source, elevel)) {
if (!validate_conf_option(record, name, value, source, elevel, false, &newval, &newextra)) {
return 0;
}
} else if (source == PGC_S_DEFAULT) {
@ -14681,27 +14873,7 @@ int set_config_option(const char* name, const char* value, GucContext context, G
void* newextra = NULL;
if (value != NULL) {
const char* hintmsg = NULL;
if (!parse_int(value, &newval, conf->gen.flags, &hintmsg)) {
ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid value for parameter \"%s\": \"%s\"", name, value),
hintmsg ? errhint("%s", _(hintmsg)) : 0));
return 0;
}
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 0;
}
if (!call_int_check_hook(conf, &newval, &newextra, source, elevel)) {
if (!validate_conf_option(record, name, value, source, elevel, false, &newval, &newextra)) {
return 0;
}
} else if (source == PGC_S_DEFAULT) {
@ -14780,26 +14952,7 @@ int set_config_option(const char* name, const char* value, GucContext context, G
void* newextra = NULL;
if (value != NULL) {
const char* hintmsg = NULL;
if (!parse_int64(value, &newval, &hintmsg)) {
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("parameter \"%s\" requires a numeric value", name)));
return 0;
}
if (newval < conf->min || newval > conf->max) {
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("%ld is outside the valid range for parameter \"%s\" (%ld .. %ld)",
newval,
name,
conf->min,
conf->max)));
return 0;
}
if (!call_int64_check_hook(conf, &newval, &newextra, source, elevel)) {
if (!validate_conf_option(record, name, value, source, elevel, false, &newval, &newextra)) {
return 0;
}
} else if (source == PGC_S_DEFAULT) {
@ -14872,25 +15025,7 @@ int set_config_option(const char* name, const char* value, GucContext context, G
void* newextra = NULL;
if (value != NULL) {
if (!parse_real(value, &newval)) {
ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("parameter \"%s\" requires a numeric value", name)));
return 0;
}
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 0;
}
if (!call_real_check_hook(conf, &newval, &newextra, source, elevel)) {
if (!validate_conf_option(record, name, value, source, elevel, false, &newval, &newextra)) {
return 0;
}
} else if (source == PGC_S_DEFAULT) {
@ -14978,14 +15113,6 @@ int set_config_option(const char* name, const char* value, GucContext context, G
}
if (value != NULL) {
/*
* The value passed by the caller could be transient, so
* we always strdup it.
*/
newval = guc_strdup(elevel, value);
if (newval == NULL) {
return 0;
}
// when \parallel in gsql is on, we use "set search_path to pg_temp_XXX"
// to tell new started parallel postgres which temp namespace should use.
@ -15016,16 +15143,7 @@ int set_config_option(const char* name, const char* value, GucContext context, G
return 1;
}
/*
* The only built-in "parsing" check we have is to apply
* truncation if GUC_IS_NAME.
*/
if (conf->gen.flags & GUC_IS_NAME) {
truncate_identifier(newval, strlen(newval), true);
}
if (!call_string_check_hook(conf, &newval, &newextra, source, elevel)) {
pfree(newval);
if (!validate_conf_option(record, name, value, source, elevel, false, &newval, &newextra)) {
return 0;
}
} else if (source == PGC_S_DEFAULT) {
@ -15119,20 +15237,7 @@ int set_config_option(const char* name, const char* value, GucContext context, G
void* newextra = NULL;
if (value != NULL) {
if (!config_enum_lookup_by_name(conf, value, &newval)) {
char* hintmsg = NULL;
hintmsg = config_enum_get_options(conf, "Available values: ", ".", ", ");
ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid value for parameter \"%s\": \"%s\"", name, value),
hintmsg ? errhint("%s", _(hintmsg)) : 0));
if (hintmsg != NULL) {
pfree(hintmsg);
}
return 0;
}
if (!call_enum_check_hook(conf, &newval, &newextra, source, elevel)) {
if (!validate_conf_option(record, name, value, source, elevel, false, &newval, &newextra)) {
return 0;
}
} else if (source == PGC_S_DEFAULT) {
@ -15500,6 +15605,228 @@ static char* flatten_set_variable_args(const char* name, List* args)
return buf.data;
}
/*
* This function takes list of all configuration parameters in
* postgresql.conf and parameter to be updated as input arguments and
* replace the updated configuration parameter value in a list. If the
* parameter to be updated is new then it is appended to the list of
* parameters.
*/
static void replace_config_value(char** optlines, char* name, char* value, config_type vartype)
{
Assert(optlines != NULL);
int index = 0;
int optvalue_off = 0;
int optvalue_len = 0;
char* newline = (char*)pg_malloc(MAX_PARAM_LEN);
int rc = 0;
switch (vartype) {
case PGC_BOOL:
case PGC_INT:
case PGC_INT64:
case PGC_REAL:
case PGC_ENUM:
rc = snprintf_s(newline, MAX_PARAM_LEN, MAX_PARAM_LEN - 1, "%s = %s\n", name, value);
break;
case PGC_STRING:
rc = snprintf_s(newline, MAX_PARAM_LEN, MAX_PARAM_LEN - 1, "%s = '%s'\n", name, value);
break;
}
securec_check_ss(rc, "\0", "\0");
index = find_guc_option(optlines, name, NULL, NULL, &optvalue_off, &optvalue_len);
/* add or replace */
if (index == INVALID_LINES_IDX) {
/* find the first NULL point reserved. */
for (index = 0; optlines[index] != NULL; index++);
} else {
/* copy comment to newline and pfree old line */
rc = strncpy_s(newline + rc - 1, MAX_PARAM_LEN - rc,
optlines[index] + optvalue_off + optvalue_len, MAX_PARAM_LEN - rc - 1);
securec_check(rc, "\0", "\0");
pfree(optlines[index]);
}
optlines[index] = newline;
}
/*
* Persist the configuration parameter value.
*
* This function takes all previous configuration parameters
* set by ALTER SYSTEM command and the currently set ones
* and write them all to the automatic configuration file.
*
* The configuration parameters are written to a temporary
* file then renamed to the final name. The template for the
* temporary file is postgresql.auto.conf.temp.
*
* An LWLock is used to serialize writing to the same file.
*
* In case of an error, we leave the original automatic
* configuration file (postgresql.auto.conf) intact.
*/
void AlterSystemSetConfigFile(AlterSystemStmt * altersysstmt)
{
#define GUCCONF_FILE "postgresql.conf"
#define GUCCONF_FILE_BAK "postgresql.conf.bak"
#define GUCCONF_FILE_BAK_BAK "postgresql.conf.bak_bak"
#define GUCCONF_FILE_LOCK "postgresql.conf.lock"
char *name = NULL;
char *value = NULL;
struct config_generic *record = NULL;
char ConfFileName[MAXPGPATH];
char ConfTmpFileName[MAXPGPATH];
char ConfTmpBakFileName[MAXPGPATH];
char ConfLockFileName[MAXPGPATH];
struct stat st;
void *newextra = NULL;
ConfFileLock filelock = {NULL, 0};
errno_t rc;
ErrCode ret;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to execute ALTER SYSTEM SET command"))));
/*
* Validate the name and arguments [value1, value2 ... ].
*/
name = altersysstmt->setstmt->name;
switch (altersysstmt->setstmt->kind) {
case VAR_SET_VALUE:
value = ExtractSetVariableArgs(altersysstmt->setstmt);
break;
case VAR_SET_DEFAULT:
ereport(ERROR,
(errcode(ERRCODE_OPERATE_NOT_SUPPORTED),
(errmsg("ALTER SYSTEM SET does not support 'set to default'."))));
value = NULL;
break;
default:
elog(ERROR, "unrecognized ALTER SYSTEM SET stmt type: %d",
altersysstmt->setstmt->kind);
break;
}
record = find_option(name, false, LOG);
if (record == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unrecognized configuration parameter \"%s\"", name)));
if ((record->context != PGC_POSTMASTER && record->context != PGC_SIGHUP && record->context != PGC_BACKEND) ||
record->flags & GUC_DISALLOW_IN_FILE)
ereport(ERROR,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("unsupport parameter: %s\n"
"ALTER SYSTEM SET only support POSTMASTER-level, SIGHUP-level and BACKEND-level guc variable,\n"
"and it must be allowed to set in postgresql.conf.", name)));
if (!validate_conf_option(record, name, value, PGC_S_FILE, ERROR, true, NULL, &newextra))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid value for parameter \"%s\": \"%s\"", name, value)));
rc = snprintf_s(ConfFileName, MAXPGPATH, MAXPGPATH - 1, "%s/%s", t_thrd.proc_cxt.DataDir, GUCCONF_FILE);
securec_check_ss(rc, "\0", "\0");
rc = snprintf_s(ConfTmpFileName, MAXPGPATH, MAXPGPATH - 1, "%s/%s", t_thrd.proc_cxt.DataDir, GUCCONF_FILE_BAK);
securec_check_ss(rc, "\0", "\0");
rc = snprintf_s(ConfLockFileName, MAXPGPATH, MAXPGPATH - 1, "%s/%s", t_thrd.proc_cxt.DataDir, GUCCONF_FILE_LOCK);
securec_check_ss(rc, "\0", "\0");
rc = snprintf_s(ConfTmpBakFileName, MAXPGPATH, MAXPGPATH - 1,
"%s/%s", t_thrd.proc_cxt.DataDir, GUCCONF_FILE_BAK_BAK);
securec_check_ss(rc, "\0", "\0");
/*
* one backend is allowed to operate on postgresql.conf.bak file, to
* ensure that we need to update the contents of the file with
* AutoFileLock. To ensure crash safety, first the contents are written to
* temporary file and then rename it to postgresql.auto.conf. In case
* there exists a temp file from previous crash, that can be reused.
*/
char** opt_lines = NULL;
if (stat(ConfFileName, &st) == 0 && get_file_lock(ConfLockFileName, &filelock) == CODE_OK) {
opt_lines = read_guc_file(ConfFileName);
} else {
ereport(ERROR,
(errcode(ERRCODE_FILE_READ_FAILED),
errmsg("File does not exits or it is being used.Can not open file: %s.", ConfFileName)));
}
/*
* replace with new value if the configuration parameter already
* exists OR add it as a new cofiguration parameter in the file.
*/
replace_config_value(opt_lines, name, value, record->vartype);
ret = write_guc_file(ConfTmpFileName, opt_lines);
release_opt_lines(opt_lines);
if (ret != CODE_OK) {
release_file_lock(&filelock);
ereport(ERROR,
(errcode(ERRCODE_FILE_WRITE_FAILED),
errmsg("write %s failed: %s.", ConfTmpFileName, gs_strerror(ret))));
}
/* we should leave postgresql.conf.bak like gs_guc */
opt_lines = read_guc_file(ConfTmpFileName);
ret = write_guc_file(ConfTmpBakFileName, opt_lines);
release_opt_lines(opt_lines);
opt_lines = NULL;
if (ret != CODE_OK) {
release_file_lock(&filelock);
ereport(ERROR,
(errcode(ERRCODE_FILE_WRITE_FAILED),
errmsg("write %s failed: %s.", ConfTmpBakFileName, gs_strerror(ret))));
}
/*
* As the rename is atomic operation, if any problem occurs after this
* at max it can loose the parameters set by last ALTER SYSTEM SET
* command.
*/
if (rename(ConfTmpBakFileName, ConfFileName) < 0) {
release_file_lock(&filelock);
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\"", ConfTmpFileName, ConfFileName)));
}
release_file_lock(&filelock);
/*
* send signal to postmaster to reload postgresql.conf, POSTMASTER-level variable
* takes effect only after restarting the database, but we still need to send the
* signal so that we can send the postgresql.conf to standby node.
*/
if (gs_signal_send(PostmasterPid, SIGHUP)) {
ereport(WARNING, (errmsg("Failed to send signal to postmaster to reload guc config file.")));
return;
}
/* print notice message */
switch (record->context) {
case PGC_POSTMASTER:
ereport(NOTICE,
(errmsg("please restart the database for the POSTMASTER level parameter to take effect.")));
break;
case PGC_BACKEND:
ereport(NOTICE,
(errmsg("please reconnect the database for the BACKEND level parameter to take effect.")));
break;
default:
break;
}
}
/*
* SET command
*/
@ -20066,7 +20393,7 @@ char** read_guc_file(const char* path)
}
/* set up the result and the line buffer */
result = (char**)pg_malloc((nlines + 1) * sizeof(char*));
result = (char**)pg_malloc((nlines + 2) * sizeof(char*)); // Reserve one extra for alter system set.
buffer = (char*)pg_malloc(maxlength + 1);
/* now reprocess the file and store the lines */
@ -20078,7 +20405,7 @@ char** read_guc_file(const char* path)
}
(void)fclose(infile);
pfree(buffer);
result[nlines] = NULL;
result[nlines] = result[nlines + 1] = NULL;
return result;
}

View File

@ -1313,6 +1313,10 @@ static void pgaudit_ProcessUtility(Node* parsetree, const char* queryString, Par
VariableSetStmt* variablesetstmt = (VariableSetStmt*)(parsetree);
pgaudit_process_set_parameter(variablesetstmt->name, queryString);
} break;
case T_AlterSystemStmt: {
AlterSystemStmt* altersystemstmt = (AlterSystemStmt*)(parsetree);
pgaudit_process_set_parameter(altersystemstmt->setstmt->name, queryString);
} break;
case T_CreateDataSourceStmt: {
CreateDataSourceStmt* createdatasourcestmt = (CreateDataSourceStmt*)(parsetree);
pgaudit_ddl_datasource(createdatasourcestmt->srcname, queryString);

View File

@ -4787,6 +4787,11 @@ void standard_ProcessUtility(Node* parse_tree, const char* query_string, ParamLi
ExecCreateTableAs((CreateTableAsStmt*)parse_tree, query_string, params, completion_tag);
break;
case T_AlterSystemStmt:
PreventTransactionChain(is_top_level, "ALTER SYSTEM SET");
AlterSystemSetConfigFile((AlterSystemStmt*)parse_tree);
break;
case T_VariableSetStmt:
ExecSetVariableStmt((VariableSetStmt*)parse_tree);
#ifdef PGXC
@ -7175,6 +7180,10 @@ const char* CreateCommandTag(Node* parse_tree)
tag = "CREATE TABLE AS";
break;
case T_AlterSystemStmt:
tag = "ALTER SYSTEM SET";
break;
case T_VariableSetStmt:
switch (((VariableSetStmt*)parse_tree)->kind) {
case VAR_SET_VALUE:
@ -8020,6 +8029,10 @@ LogStmtLevel GetCommandLogLevel(Node* parse_tree)
lev = LOGSTMT_DDL;
break;
case T_AlterSystemStmt:
lev = LOGSTMT_DDL;
break;
case T_VariableSetStmt:
lev = LOGSTMT_ALL;
break;

View File

@ -452,6 +452,7 @@ typedef enum NodeTag {
T_DropDirectoryStmt,
T_CreateRlsPolicyStmt,
T_AlterRlsPolicyStmt,
T_AlterSystemStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)

View File

@ -2901,6 +2901,15 @@ typedef struct DropdbStmt {
bool missing_ok; /* skip error if db is missing? */
} DropdbStmt;
/* ----------------------
* Alter System Statement
* ----------------------
*/
typedef struct AlterSystemStmt {
NodeTag type;
VariableSetStmt *setstmt; /* SET subcommand */
} AlterSystemStmt;
/* ----------------------
* Cluster Statement (support pbrown's cluster index implementation)
* ----------------------

View File

@ -162,6 +162,7 @@ PG_KEYWORD("direct", DIRECT, UNRESERVED_KEYWORD)
PG_KEYWORD("directory", DIRECTORY, UNRESERVED_KEYWORD)
PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD)
PG_KEYWORD("disconnect", DISCONNECT, UNRESERVED_KEYWORD)
PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD)
#ifdef PGXC
PG_KEYWORD("distribute", DISTRIBUTE, UNRESERVED_KEYWORD)
@ -269,6 +270,7 @@ PG_KEYWORD("isnull", ISNULL, UNRESERVED_KEYWORD)
PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
PG_KEYWORD("kill", KILL, UNRESERVED_KEYWORD)
PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)
PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD)

View File

@ -245,6 +245,7 @@ extern bool parse_int64(const char* value, int64* result, const char** hintmsg);
extern bool parse_real(const char* value, double* result);
extern int set_config_option(const char* name, const char* value, GucContext context, GucSource source,
GucAction action, bool changeVal, int elevel, bool isReload = false);
extern void AlterSystemSetConfigFile(AlterSystemStmt * setstmt);
extern char* GetConfigOptionByName(const char* name, const char** varname);
extern void GetConfigOptionByNum(int varnum, const char** values, bool* noshow);
extern int GetNumConfigOptions(void);

View File

@ -0,0 +1,406 @@
----------------------------------------------------------
-- The common user should not have the permission.
---------------------------------------------------------
DROP ROLE IF EXISTS alter_system_testuser;
NOTICE: role "alter_system_testuser" does not exist, skipping
CREATE USER alter_system_testuser PASSWORD 'test@1233';
SET SESSION AUTHORIZATION alter_system_testuser PASSWORD 'test@1233';
show use_workload_manager;
use_workload_manager
----------------------
on
(1 row)
ALTER SYSTEM SET use_workload_manager to off;
ERROR: must be superuser to execute ALTER SYSTEM SET command
show io_limits;
io_limits
-----------
0
(1 row)
ALTER SYSTEM SET io_limits to 100;
ERROR: must be superuser to execute ALTER SYSTEM SET command
select pg_sleep(1); -- wait to reload postgres.conf file
pg_sleep
----------
(1 row)
show use_workload_manager;
use_workload_manager
----------------------
on
(1 row)
show io_limits;
io_limits
-----------
0
(1 row)
\c
DROP user alter_system_testuser;
-------------------------------------------------------
-- clear pg_query_audit for the last test
-------------------------------------------------------
show audit_enabled;
audit_enabled
---------------
on
(1 row)
show audit_set_parameter;
audit_set_parameter
---------------------
1
(1 row)
show audit_user_violation;
audit_user_violation
----------------------
1
(1 row)
SELECT pg_delete_audit('2000-01-01 ','9999-01-01');
pg_delete_audit
-----------------
(1 row)
--------------------------------------------------------
-- for POSTMASTER GUC
--------------------------------------------------------
SHOW enable_thread_pool;
enable_thread_pool
--------------------
on
(1 row)
ALTER SYSTEM SET enable_thread_pool to off;
NOTICE: please restart the database for the POSTMASTER level parameter to take effect.
ALTER SYSTEM SET enable_thread_pool to on;
NOTICE: please restart the database for the POSTMASTER level parameter to take effect.
------------------------------------------------------
-- for SIGHUP GUC
------------------------------------------------------
-- change
SHOW password_lock_time;
password_lock_time
--------------------
1
(1 row)
ALTER SYSTEM SET password_lock_time to 1.1;
SHOW autovacuum;
autovacuum
------------
on
(1 row)
ALTER SYSTEM SET autovacuum to off;
SHOW log_destination;
log_destination
-----------------
stderr
(1 row)
ALTER SYSTEM SET log_destination to 'stderr,csvlog';
SHOW autovacuum_mode;
autovacuum_mode
-----------------
mix
(1 row)
ALTER SYSTEM SET autovacuum_mode to 'analyze';
SHOW parctl_min_cost;
parctl_min_cost
-----------------
100000
(1 row)
ALTER SYSTEM SET parctl_min_cost TO 1000;
select pg_sleep(2); -- wait to reload postgres.conf file
pg_sleep
----------
(1 row)
-- check result and change back.
SHOW password_lock_time;
password_lock_time
--------------------
1.1
(1 row)
ALTER SYSTEM SET password_lock_time to 1;
SHOW autovacuum;
autovacuum
------------
off
(1 row)
ALTER SYSTEM SET autovacuum to on;
SHOW log_destination;
log_destination
-----------------
stderr,csvlog
(1 row)
ALTER SYSTEM SET log_destination to 'stderr';
SHOW autovacuum_mode;
autovacuum_mode
-----------------
analyze
(1 row)
ALTER SYSTEM SET autovacuum_mode to mix;
SHOW parctl_min_cost;
parctl_min_cost
-----------------
1000
(1 row)
ALTER SYSTEM SET parctl_min_cost TO 100000;
select pg_sleep(2); -- wait to reload postgres.conf file
pg_sleep
----------
(1 row)
SHOW password_lock_time;
password_lock_time
--------------------
1
(1 row)
SHOW autovacuum;
autovacuum
------------
on
(1 row)
SHOW log_destination;
log_destination
-----------------
stderr
(1 row)
SHOW autovacuum_mode;
autovacuum_mode
-----------------
mix
(1 row)
SHOW parctl_min_cost;
parctl_min_cost
-----------------
100000
(1 row)
-- some err case
ALTER SYSTEM SET password_lock_time to true;
ERROR: parameter "password_lock_time" requires a numeric value
ALTER SYSTEM SET autovacuum to 'lalala';
ERROR: parameter "autovacuum" requires a Boolean value
ALTER SYSTEM SET log_destination to 'abcdefg';
ERROR: invalid value for parameter "log_destination": "abcdefg"
DETAIL: Unrecognized key word: "abcdefg".
ALTER SYSTEM SET autovacuum_mode to 123;
ERROR: invalid value for parameter "autovacuum_mode": "123"
HINT: Available values: analyze, vacuum, mix, none.
ALTER SYSTEM SET autovacuum_mode to lalala;
ERROR: invalid value for parameter "autovacuum_mode": "lalala"
HINT: Available values: analyze, vacuum, mix, none.
ALTER SYSTEM SET parctl_min_cost TO -100;
ERROR: -100 is outside the valid range for parameter "parctl_min_cost" (-1 .. 2147483647)
ALTER SYSTEM SET parctl_min_cost TO 1.1;
ERROR: invalid value for parameter "parctl_min_cost": "1.1"
select pg_sleep(2); -- wait to reload postgres.conf file
pg_sleep
----------
(1 row)
SHOW password_lock_time;
password_lock_time
--------------------
1
(1 row)
SHOW autovacuum;
autovacuum
------------
on
(1 row)
SHOW log_destination;
log_destination
-----------------
stderr
(1 row)
SHOW autovacuum_mode;
autovacuum_mode
-----------------
mix
(1 row)
SHOW parctl_min_cost;
parctl_min_cost
-----------------
100000
(1 row)
------------------------------------------------------
-- FOR BACKEND GUC
------------------------------------------------------
show ignore_system_indexes;
ignore_system_indexes
-----------------------
off
(1 row)
ALTER SYSTEM SET ignore_system_indexes TO on;
NOTICE: please reconnect the database for the BACKEND level parameter to take effect.
show ignore_system_indexes;
ignore_system_indexes
-----------------------
off
(1 row)
ALTER SYSTEM SET ignore_system_indexes TO off;
NOTICE: please reconnect the database for the BACKEND level parameter to take effect.
show ignore_system_indexes;
ignore_system_indexes
-----------------------
off
(1 row)
----------------------------------------------------
-- for USERSET GUC
----------------------------------------------------
show io_limits;
io_limits
-----------
0
(1 row)
ALTER SYSTEM SET io_limits to 100;
ERROR: unsupport parameter: io_limits
ALTER SYSTEM SET only support POSTMASTER-level, SIGHUP-level and BACKEND-level guc variable,
and it must be allowed to set in postgresql.conf.
show io_limits;
io_limits
-----------
0
(1 row)
ALTER SYSTEM SET io_limits to 0;
ERROR: unsupport parameter: io_limits
ALTER SYSTEM SET only support POSTMASTER-level, SIGHUP-level and BACKEND-level guc variable,
and it must be allowed to set in postgresql.conf.
show io_limits;
io_limits
-----------
0
(1 row)
-----------------------------------------------------
-- for SUSET GUC
----------------------------------------------------
show autoanalyze;
autoanalyze
-------------
off
(1 row)
ALTER SYSTEM SET autoanalyze to on;
ERROR: unsupport parameter: autoanalyze
ALTER SYSTEM SET only support POSTMASTER-level, SIGHUP-level and BACKEND-level guc variable,
and it must be allowed to set in postgresql.conf.
show autoanalyze;
autoanalyze
-------------
off
(1 row)
ALTER SYSTEM SET autoanalyze to off;
ERROR: unsupport parameter: autoanalyze
ALTER SYSTEM SET only support POSTMASTER-level, SIGHUP-level and BACKEND-level guc variable,
and it must be allowed to set in postgresql.conf.
show autoanalyze;
autoanalyze
-------------
off
(1 row)
-----------------------------------------------------
-- UNSUPPORT SET TO DEFAULT
-----------------------------------------------------
SHOW parctl_min_cost;
parctl_min_cost
-----------------
100000
(1 row)
ALTER SYSTEM SET parctl_min_cost TO 1000;
ALTER SYSTEM SET parctl_min_cost TO default;
ERROR: ALTER SYSTEM SET does not support 'set to default'.
select pg_sleep(1);
pg_sleep
----------
(1 row)
SHOW parctl_min_cost;
parctl_min_cost
-----------------
1000
(1 row)
ALTER SYSTEM SET parctl_min_cost TO 100000;
-------------------------------------------------------
-- can not in a transaction
-------------------------------------------------------
BEGIN;
SHOW autovacuum;
autovacuum
------------
on
(1 row)
ALTER SYSTEM SET autovacuum to off;
ERROR: ALTER SYSTEM SET cannot run inside a transaction block
SHOW autovacuum;
ERROR: current transaction is aborted, commands ignored until end of transaction block
ALTER SYSTEM SET autovacuum to on;
ERROR: current transaction is aborted, commands ignored until end of transaction block
SHOW autovacuum;
ERROR: current transaction is aborted, commands ignored until end of transaction block
END;
-------------------------------------------------------
-- shoule be audited.
------------------------------------------------------
SELECT type,result,userid,database,client_conninfo,object_name,detail_info FROM pg_query_audit('2000-01-01 08:00:00','9999-01-01 08:00:00');
type | result | userid | database | client_conninfo | object_name | detail_info
----------------+--------+--------+------------+-----------------+-----------------------+------------------------------------------------------
internal_event | ok | 10 | regression | gsql@[local] | null | SELECT pg_delete_audit('2000-01-01 ','9999-01-01');
set_parameter | ok | 10 | regression | gsql@[local] | enable_thread_pool | ALTER SYSTEM SET enable_thread_pool to off;
set_parameter | ok | 10 | regression | gsql@[local] | enable_thread_pool | ALTER SYSTEM SET enable_thread_pool to on;
set_parameter | ok | 10 | regression | gsql@[local] | password_lock_time | ALTER SYSTEM SET password_lock_time to 1.1;
set_parameter | ok | 10 | regression | gsql@[local] | autovacuum | ALTER SYSTEM SET autovacuum to off;
set_parameter | ok | 10 | regression | gsql@[local] | log_destination | ALTER SYSTEM SET log_destination to 'stderr,csvlog';
set_parameter | ok | 10 | regression | gsql@[local] | autovacuum_mode | ALTER SYSTEM SET autovacuum_mode to 'analyze';
set_parameter | ok | 10 | regression | gsql@[local] | parctl_min_cost | ALTER SYSTEM SET parctl_min_cost TO 1000;
set_parameter | ok | 10 | regression | gsql@[local] | password_lock_time | ALTER SYSTEM SET password_lock_time to 1;
set_parameter | ok | 10 | regression | gsql@[local] | autovacuum | ALTER SYSTEM SET autovacuum to on;
set_parameter | ok | 10 | regression | gsql@[local] | log_destination | ALTER SYSTEM SET log_destination to 'stderr';
set_parameter | ok | 10 | regression | gsql@[local] | autovacuum_mode | ALTER SYSTEM SET autovacuum_mode to mix;
set_parameter | ok | 10 | regression | gsql@[local] | parctl_min_cost | ALTER SYSTEM SET parctl_min_cost TO 100000;
set_parameter | ok | 10 | regression | gsql@[local] | ignore_system_indexes | ALTER SYSTEM SET ignore_system_indexes TO on;
set_parameter | ok | 10 | regression | gsql@[local] | ignore_system_indexes | ALTER SYSTEM SET ignore_system_indexes TO off;
set_parameter | ok | 10 | regression | gsql@[local] | parctl_min_cost | ALTER SYSTEM SET parctl_min_cost TO 1000;
set_parameter | ok | 10 | regression | gsql@[local] | parctl_min_cost | ALTER SYSTEM SET parctl_min_cost TO 100000;
(17 rows)

View File

@ -25,6 +25,7 @@ test: create_view1 create_view2 create_view3 create_view4 create_view5 int8
test: select
test: misc
test: stats
test: alter_system_set
#dispatch from 13
test: function

View File

@ -21,4 +21,5 @@ test: create_view1 create_view2 create_view3 create_view4 create_view5 int8
#dupliacated select int8
test: select
test: misc
test: stats
test: stats
test: alter_system_set

View File

@ -0,0 +1,149 @@
----------------------------------------------------------
-- The common user should not have the permission.
---------------------------------------------------------
DROP ROLE IF EXISTS alter_system_testuser;
CREATE USER alter_system_testuser PASSWORD 'test@1233';
SET SESSION AUTHORIZATION alter_system_testuser PASSWORD 'test@1233';
show use_workload_manager;
ALTER SYSTEM SET use_workload_manager to off;
show io_limits;
ALTER SYSTEM SET io_limits to 100;
select pg_sleep(1); -- wait to reload postgres.conf file
show use_workload_manager;
show io_limits;
\c
DROP user alter_system_testuser;
-------------------------------------------------------
-- clear pg_query_audit for the last test
-------------------------------------------------------
show audit_enabled;
show audit_set_parameter;
show audit_user_violation;
SELECT pg_delete_audit('2000-01-01 ','9999-01-01');
--------------------------------------------------------
-- for POSTMASTER GUC
--------------------------------------------------------
SHOW enable_thread_pool;
ALTER SYSTEM SET enable_thread_pool to off;
ALTER SYSTEM SET enable_thread_pool to on;
------------------------------------------------------
-- for SIGHUP GUC
------------------------------------------------------
-- change
SHOW password_lock_time;
ALTER SYSTEM SET password_lock_time to 1.1;
SHOW autovacuum;
ALTER SYSTEM SET autovacuum to off;
SHOW log_destination;
ALTER SYSTEM SET log_destination to 'stderr,csvlog';
SHOW autovacuum_mode;
ALTER SYSTEM SET autovacuum_mode to 'analyze';
SHOW parctl_min_cost;
ALTER SYSTEM SET parctl_min_cost TO 1000;
select pg_sleep(2); -- wait to reload postgres.conf file
-- check result and change back.
SHOW password_lock_time;
ALTER SYSTEM SET password_lock_time to 1;
SHOW autovacuum;
ALTER SYSTEM SET autovacuum to on;
SHOW log_destination;
ALTER SYSTEM SET log_destination to 'stderr';
SHOW autovacuum_mode;
ALTER SYSTEM SET autovacuum_mode to mix;
SHOW parctl_min_cost;
ALTER SYSTEM SET parctl_min_cost TO 100000;
select pg_sleep(2); -- wait to reload postgres.conf file
SHOW password_lock_time;
SHOW autovacuum;
SHOW log_destination;
SHOW autovacuum_mode;
SHOW parctl_min_cost;
-- some err case
ALTER SYSTEM SET password_lock_time to true;
ALTER SYSTEM SET autovacuum to 'lalala';
ALTER SYSTEM SET log_destination to 'abcdefg';
ALTER SYSTEM SET autovacuum_mode to 123;
ALTER SYSTEM SET autovacuum_mode to lalala;
ALTER SYSTEM SET parctl_min_cost TO -100;
ALTER SYSTEM SET parctl_min_cost TO 1.1;
select pg_sleep(2); -- wait to reload postgres.conf file
SHOW password_lock_time;
SHOW autovacuum;
SHOW log_destination;
SHOW autovacuum_mode;
SHOW parctl_min_cost;
------------------------------------------------------
-- FOR BACKEND GUC
------------------------------------------------------
show ignore_system_indexes;
ALTER SYSTEM SET ignore_system_indexes TO on;
show ignore_system_indexes;
ALTER SYSTEM SET ignore_system_indexes TO off;
show ignore_system_indexes;
----------------------------------------------------
-- for USERSET GUC
----------------------------------------------------
show io_limits;
ALTER SYSTEM SET io_limits to 100;
show io_limits;
ALTER SYSTEM SET io_limits to 0;
show io_limits;
-----------------------------------------------------
-- for SUSET GUC
----------------------------------------------------
show autoanalyze;
ALTER SYSTEM SET autoanalyze to on;
show autoanalyze;
ALTER SYSTEM SET autoanalyze to off;
show autoanalyze;
-----------------------------------------------------
-- UNSUPPORT SET TO DEFAULT
-----------------------------------------------------
SHOW parctl_min_cost;
ALTER SYSTEM SET parctl_min_cost TO 1000;
ALTER SYSTEM SET parctl_min_cost TO default;
select pg_sleep(1);
SHOW parctl_min_cost;
ALTER SYSTEM SET parctl_min_cost TO 100000;
-------------------------------------------------------
-- can not in a transaction
-------------------------------------------------------
BEGIN;
SHOW autovacuum;
ALTER SYSTEM SET autovacuum to off;
SHOW autovacuum;
ALTER SYSTEM SET autovacuum to on;
SHOW autovacuum;
END;
-------------------------------------------------------
-- shoule be audited.
------------------------------------------------------
SELECT type,result,userid,database,client_conninfo,object_name,detail_info FROM pg_query_audit('2000-01-01 08:00:00','9999-01-01 08:00:00');