diff --git a/src/bin/gs_guc/cluster_guc.conf b/src/bin/gs_guc/cluster_guc.conf index c479d89bc..7a3723d07 100644 --- a/src/bin/gs_guc/cluster_guc.conf +++ b/src/bin/gs_guc/cluster_guc.conf @@ -341,7 +341,7 @@ partition_max_cache_size|int|4096,1073741823|kB|NULL| partition_mem_batch|int|1,65535|NULL|NULL| password_effect_time|real|0,999|NULL|NULL| password_encryption_type|int|0,2|NULL|NULL| -password_lock_time|real|0,365|NULL|password_lock_time and failed_login_attempts must have positive for lock and unlock functions to work as.| +password_lock_time|real|0,365|d|password_lock_time and failed_login_attempts must have positive for lock and unlock functions to work as.| password_max_length|int|6,999|NULL|NULL| password_min_digital|int|0,999|NULL|NULL| password_min_length|int|6,999|NULL|NULL| diff --git a/src/common/backend/utils/misc/guc-file.l b/src/common/backend/utils/misc/guc-file.l index 90eccd60d..9f8bd9d86 100644 --- a/src/common/backend/utils/misc/guc-file.l +++ b/src/common/backend/utils/misc/guc-file.l @@ -75,7 +75,7 @@ UNIT_LETTER [a-zA-Z] INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}* EXPONENT [Ee]{SIGN}?{DIGIT}+ -REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}? +REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?{UNIT_LETTER}* LETTER [A-Za-z_\200-\377] LETTER_OR_DIGIT [A-Za-z_0-9\200-\377] diff --git a/src/common/backend/utils/misc/guc.cpp b/src/common/backend/utils/misc/guc.cpp index 5627ad383..032e82608 100644 --- a/src/common/backend/utils/misc/guc.cpp +++ b/src/common/backend/utils/misc/guc.cpp @@ -1231,20 +1231,20 @@ static void init_configure_names_bool() NULL, NULL }, - { - { - "enable_hypo_index", - PGC_USERSET, - QUERY_TUNING_METHOD, - gettext_noop("Enable hypothetical index for explain."), - NULL - }, - &u_sess->attr.attr_sql.enable_hypo_index, - false, - NULL, - NULL, - NULL - }, + { + { + "enable_hypo_index", + PGC_USERSET, + QUERY_TUNING_METHOD, + gettext_noop("Enable hypothetical index for explain."), + NULL + }, + &u_sess->attr.attr_sql.enable_hypo_index, + false, + NULL, + NULL, + NULL + }, #ifdef ENABLE_MULTIPLE_NODES { { @@ -1689,16 +1689,16 @@ static void init_configure_names_bool() }, { { - "enable_parallel_hash", - PGC_USERSET, + "enable_parallel_hash", + PGC_USERSET, QUERY_TUNING_METHOD, gettext_noop("Enables the planner's user of parallel hash plans."), NULL }, &u_sess->attr.attr_sql.enable_parallel_hash, true, - NULL, - NULL, + NULL, + NULL, NULL }, { @@ -4730,8 +4730,8 @@ static void init_configure_names_int() }, { { - "vacuum_gtt_defer_check_age", - PGC_USERSET, + "vacuum_gtt_defer_check_age", + PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("The defer check age of GTT, used to check expired data after vacuum."), NULL @@ -9858,7 +9858,8 @@ static void init_configure_names_real() PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("password lock time"), - NULL + NULL, + GUC_UNIT_DAY }, &u_sess->attr.attr_security.Password_lock_time, 1.0, @@ -12646,7 +12647,7 @@ static void init_single_node_unsupport_guc() u_sess->attr.attr_storage.gds_debug_mod = false; u_sess->attr.attr_sql.enable_slot_log = false; u_sess->attr.attr_storage.enable_twophase_commit = false; - + /* for Int Guc Variables */ u_sess->attr.attr_resource.max_active_statements = -1; u_sess->attr.attr_resource.dynamic_memory_quota = 80; @@ -14337,160 +14338,9 @@ bool parse_int(const char* value, int* result, int flags, const char** hintmsg) * but seems necessary to avoid intermediate-value overflows. */ if (flags & GUC_UNIT_MEMORY) { - /* Set hint for use if no match or trailing garbage */ - if (hintmsg != NULL) { - *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\"."); - } - -#if BLCKSZ < 1024 || BLCKSZ > (1024 * 1024) -#error BLCKSZ must be between 1KB and 1MB -#endif -#if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024 * 1024) -#error XLOG_BLCKSZ must be between 1KB and 1MB -#endif - - if (strncmp(endptr, "kB", 2) == 0) { - endptr += 2; - - switch (flags & GUC_UNIT_MEMORY) { - case GUC_UNIT_BLOCKS: - val /= (BLCKSZ / 1024); - break; - - case GUC_UNIT_XBLOCKS: - val /= (XLOG_BLCKSZ / 1024); - break; - default: - break; - } - } else if (strncmp(endptr, "MB", 2) == 0) { - endptr += 2; - - switch (flags & GUC_UNIT_MEMORY) { - case GUC_UNIT_KB: - val *= KB_PER_MB; - break; - - case GUC_UNIT_BLOCKS: - val *= KB_PER_MB / (BLCKSZ / 1024); - break; - - case GUC_UNIT_XBLOCKS: - val *= KB_PER_MB / (XLOG_BLCKSZ / 1024); - break; - default: - break; - } - } else if (strncmp(endptr, "GB", 2) == 0) { - endptr += 2; - - switch (flags & GUC_UNIT_MEMORY) { - case GUC_UNIT_KB: - val *= KB_PER_GB; - break; - - case GUC_UNIT_BLOCKS: - val *= KB_PER_GB / (BLCKSZ / 1024); - break; - - case GUC_UNIT_XBLOCKS: - val *= KB_PER_GB / (XLOG_BLCKSZ / 1024); - break; - default: - break; - } - } + val = (int64)memory_unit_convert(&endptr, val, flags, hintmsg); } else if (flags & GUC_UNIT_TIME) { - /* Set hint for use if no match or trailing garbage */ - if (hintmsg != NULL) { - *hintmsg = gettext_noop("Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\"."); - } - if (strncmp(endptr, "ms", 2) == 0) { - endptr += 2; - - switch (flags & GUC_UNIT_TIME) { - case GUC_UNIT_S: - val /= MS_PER_S; - break; - - case GUC_UNIT_MIN: - val /= MS_PER_MIN; - break; - case GUC_UNIT_HOUR: - val /= MS_PER_H; - break; - default: - break; - } - } else if (strncmp(endptr, "s", 1) == 0) { - endptr += 1; - switch (flags & GUC_UNIT_TIME) { - case GUC_UNIT_MS: - val *= MS_PER_S; - break; - - case GUC_UNIT_MIN: - val /= S_PER_MIN; - break; - case GUC_UNIT_HOUR: - val /= S_PER_H; - break; - default: - break; - } - } else if (strncmp(endptr, "min", 3) == 0) { - endptr += 3; - switch (flags & GUC_UNIT_TIME) { - case GUC_UNIT_MS: - val *= MS_PER_MIN; - break; - - case GUC_UNIT_S: - val *= S_PER_MIN; - break; - case GUC_UNIT_HOUR: - val /= MIN_PER_H; - break; - default: - break; - } - } else if (strncmp(endptr, "h", 1) == 0) { - endptr += 1; - switch (flags & GUC_UNIT_TIME) { - case GUC_UNIT_MS: - val *= MS_PER_H; - break; - - case GUC_UNIT_S: - val *= S_PER_H; - break; - - case GUC_UNIT_MIN: - val *= MIN_PER_H; - break; - default: - break; - } - } else if (strncmp(endptr, "d", 1) == 0) { - endptr += 1; - switch (flags & GUC_UNIT_TIME) { - case GUC_UNIT_MS: - val *= MS_PER_D; - break; - - case GUC_UNIT_S: - val *= S_PER_D; - break; - - case GUC_UNIT_MIN: - val *= MIN_PER_D; - break; - case GUC_UNIT_HOUR: - val *= H_PER_D; - default: - break; - } - } + val = (int64)time_unit_convert(&endptr, val, flags, hintmsg); } /* allow whitespace after unit */ @@ -14519,6 +14369,7 @@ bool parse_int(const char* value, int* result, int flags, const char** hintmsg) return true; } + /* * Try to parse value as an 64-bit integer. The accepted format is * decimal number. @@ -14573,7 +14424,7 @@ bool parse_int64(const char* value, int64* result, const char** hintmsg) * If the string parses okay, return true, else false. * If okay and result is not NULL, return the value in *result. */ -bool parse_real(const char* value, double* result) +bool parse_real(const char* value, double* result, int flags, const char** hintmsg) { double val; char* endptr = NULL; @@ -14600,7 +14451,25 @@ bool parse_real(const char* value, double* result) } if (*endptr != '\0') { - return false; + /* + * Note: the multiple-switch coding technique here is a bit tedious, + * but seems necessary to avoid intermediate-value overflows. + */ + if (flags & GUC_UNIT_MEMORY) { + val = memory_unit_convert(&endptr, val, flags, hintmsg); + } else if (flags & GUC_UNIT_TIME) { + val = time_unit_convert(&endptr, val, flags, hintmsg); + } + + /* allow whitespace after unit */ + while (isspace((unsigned char)*endptr)) { + endptr++; + } + + if (*endptr != '\0') { + return false; /* appropriate hint, if any, already set */ + } + } if (result != NULL) { @@ -14610,6 +14479,187 @@ bool parse_real(const char* value, double* result) return true; } +/* + * The reference is used because auto-increment of formal parameters does not change the value of the actual parameter. + * As a result, an error is reported. + */ +double memory_unit_convert(char** endptr, double value, int flags, const char** hintmsg) +{ + double val = value; + + /* Set hint for use if no match or trailing garbage */ + if (hintmsg != NULL) { + *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\"."); + } + +#if BLCKSZ < 1024 || BLCKSZ > (1024 * 1024) +#error BLCKSZ must be between 1KB and 1MB +#endif +#if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024 * 1024) +#error XLOG_BLCKSZ must be between 1KB and 1MB +#endif + + if (strncmp(*endptr, "kB", 2) == 0) { + *endptr += 2; + + switch (flags & GUC_UNIT_MEMORY) { + case GUC_UNIT_BLOCKS: + val /= (double)(BLCKSZ / 1024); + break; + + case GUC_UNIT_XBLOCKS: + val /= (double)(XLOG_BLCKSZ / 1024); + break; + default: + break; + } + } else if (strncmp(*endptr, "MB", 2) == 0) { + *endptr += 2; + + switch (flags & GUC_UNIT_MEMORY) { + case GUC_UNIT_KB: + val *= KB_PER_MB; + break; + + case GUC_UNIT_BLOCKS: + val *= KB_PER_MB / ((double)BLCKSZ / 1024); + break; + + case GUC_UNIT_XBLOCKS: + val *= KB_PER_MB / ((double)XLOG_BLCKSZ / 1024); + break; + default: + break; + } + } else if (strncmp(*endptr, "GB", 2) == 0) { + *endptr += 2; + + switch (flags & GUC_UNIT_MEMORY) { + case GUC_UNIT_KB: + val *= KB_PER_GB; + break; + + case GUC_UNIT_BLOCKS: + val *= KB_PER_GB / ((double)BLCKSZ / 1024); + break; + + case GUC_UNIT_XBLOCKS: + val *= KB_PER_GB / ((double)XLOG_BLCKSZ / 1024); + break; + default: + break; + } + } + return val; +} +double time_unit_convert(char** endptr, double value, int flags, const char** hintmsg) +{ + double val = value; + + /* Set hint for use if no match or trailing garbage */ + if (hintmsg != NULL) { + *hintmsg = gettext_noop("Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\"."); + } + if (strncmp(*endptr, "ms", 2) == 0) { + *endptr += 2; + + switch (flags & GUC_UNIT_TIME) { + case GUC_UNIT_S: + val /= MS_PER_S; + break; + case GUC_UNIT_MIN: + val /= MS_PER_MIN; + break; + case GUC_UNIT_HOUR: + val /= MS_PER_H; + break; + case GUC_UNIT_DAY: + val /= MS_PER_D; + break; + default: + break; + } + } else if (strncmp(*endptr, "s", 1) == 0) { + *endptr += 1; + switch (flags & GUC_UNIT_TIME) { + case GUC_UNIT_MS: + val *= MS_PER_S; + break; + + case GUC_UNIT_MIN: + val /= S_PER_MIN; + break; + case GUC_UNIT_HOUR: + val /= S_PER_H; + break; + case GUC_UNIT_DAY: + val /= S_PER_D; + break; + default: + break; + } + } else if (strncmp(*endptr, "min", 3) == 0) { + *endptr += 3; + switch (flags & GUC_UNIT_TIME) { + case GUC_UNIT_MS: + val *= MS_PER_MIN; + break; + + case GUC_UNIT_S: + val *= S_PER_MIN; + break; + case GUC_UNIT_HOUR: + val /= MIN_PER_H; + break; + case GUC_UNIT_DAY: + val /= MIN_PER_D; + break; + default: + break; + } + } else if (strncmp(*endptr, "h", 1) == 0) { + *endptr += 1; + switch (flags & GUC_UNIT_TIME) { + case GUC_UNIT_MS: + val *= MS_PER_H; + break; + + case GUC_UNIT_S: + val *= S_PER_H; + break; + + case GUC_UNIT_MIN: + val *= MIN_PER_H; + break; + case GUC_UNIT_DAY: + val /= H_PER_D; + break; + default: + break; + } + } else if (strncmp(*endptr, "d", 1) == 0) { + *endptr += 1; + switch (flags & GUC_UNIT_TIME) { + case GUC_UNIT_MS: + val *= MS_PER_D; + break; + + case GUC_UNIT_S: + val *= S_PER_D; + break; + + case GUC_UNIT_MIN: + val *= MIN_PER_D; + break; + case GUC_UNIT_HOUR: + val *= H_PER_D; + default: + break; + } + } + return val; +} + /* * @Description: Get guc string value according to val. * @in record: Enum configure struct. @@ -14888,8 +14938,9 @@ bool validate_conf_option(struct config_generic * record, const char *name, cons struct config_real *conf = (struct config_real *) record; double tmpnewval; double* newval = (newvalue == NULL ? &tmpnewval : (double*)newvalue); + const char *hintmsg = NULL; - if (!parse_real(value, newval)) { + if (!parse_real(value, newval, conf->gen.flags, &hintmsg)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("parameter \"%s\" requires a numeric value", name))); @@ -17142,7 +17193,7 @@ void GetConfigOptionByNum(int varnum, const char** values, bool* noshow) values[1] = _show_option(conf, false); /* unit */ - if (conf->vartype == PGC_INT) { + if (conf->vartype == PGC_INT || conf->vartype == PGC_REAL) { char buf[8]; switch (conf->flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME)) { @@ -17178,6 +17229,10 @@ void GetConfigOptionByNum(int varnum, const char** values, bool* noshow) values[2] = "hour"; break; + case GUC_UNIT_DAY: + values[2] = "d"; + break; + default: values[2] = ""; break; @@ -17549,15 +17604,15 @@ static char* _show_option(struct config_generic* record, bool use_units) */ int64 result = *conf->variable; const char* unit = NULL; + int flags = record->flags; if (use_units && result > 0 && (record->flags & GUC_UNIT_MEMORY)) { - switch (record->flags & GUC_UNIT_MEMORY) { + switch (flags & GUC_UNIT_MEMORY) { case GUC_UNIT_BLOCKS: - result *= BLCKSZ / 1024; + result *= (double)BLCKSZ / 1024; break; - case GUC_UNIT_XBLOCKS: - result *= XLOG_BLCKSZ / 1024; + result *= (double)XLOG_BLCKSZ / 1024; break; default: break; @@ -17573,17 +17628,19 @@ static char* _show_option(struct config_generic* record, bool use_units) unit = "kB"; } } else if (use_units && result > 0 && (record->flags & GUC_UNIT_TIME)) { - switch (record->flags & GUC_UNIT_TIME) { + switch (flags & GUC_UNIT_TIME) { case GUC_UNIT_S: result *= MS_PER_S; break; - case GUC_UNIT_MIN: result *= MS_PER_MIN; break; case GUC_UNIT_HOUR: result *= MS_PER_H; break; + case GUC_UNIT_DAY: + result *= MS_PER_D; + break; default: break; } @@ -17631,7 +17688,69 @@ static char* _show_option(struct config_generic* record, bool use_units) if (conf->show_hook) { val = (*conf->show_hook)(); } else { - rc = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%g", *conf->variable); + double result = *conf->variable; + const char* unit = NULL; + int flags = record->flags; + + if (use_units && result > 0 && (record->flags & GUC_UNIT_MEMORY)) { + switch (flags & GUC_UNIT_MEMORY) { + case GUC_UNIT_BLOCKS: + result *= (double)BLCKSZ / 1024; + break; + case GUC_UNIT_XBLOCKS: + result *= (double)XLOG_BLCKSZ / 1024; + break; + default: + break; + } + + if (result / KB_PER_GB >= 1.0) { + result /= KB_PER_GB; + unit = "GB"; + } else if (result / KB_PER_MB >= 1.0) { + result /= KB_PER_MB; + unit = "MB"; + } else { + unit = "kB"; + } + } else if (use_units && result > 0 && (record->flags & GUC_UNIT_TIME)) { + switch (flags & GUC_UNIT_TIME) { + case GUC_UNIT_S: + result *= MS_PER_S; + break; + case GUC_UNIT_MIN: + result *= MS_PER_MIN; + break; + case GUC_UNIT_HOUR: + result *= MS_PER_H; + break; + case GUC_UNIT_DAY: + result *= MS_PER_D; + break; + default: + break; + } + + if (result / MS_PER_D >= 1.0) { + result /= MS_PER_D; + unit = "d"; + } else if (result / MS_PER_H >= 1.0) { + result /= MS_PER_H; + unit = "h"; + } else if (result / MS_PER_MIN >= 1.0) { + result /= MS_PER_MIN; + unit = "min"; + } else if (result / MS_PER_S >= 1.0) { + result /= MS_PER_S; + unit = "s"; + } else { + unit = "ms"; + } + } else { + unit = ""; + } + + rc = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%g%s", result, unit); securec_check_ss(rc, "\0", "\0"); val = buffer; } diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index d99e9e4f8..9f84276eb 100755 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -184,6 +184,7 @@ typedef struct { #define GUC_UNIT_S 0x2000 /* value is in seconds */ #define GUC_UNIT_MIN 0x4000 /* value is in minutes */ #define GUC_UNIT_HOUR 0x5000 /* value is in hour */ +#define GUC_UNIT_DAY 0x6000 /* value is in day */ #define GUC_UNIT_TIME 0x7000 /* mask for MS, S, MIN */ #define GUC_NOT_WHILE_SEC_REST 0x8000 /* can't set if security restricted */ @@ -242,7 +243,9 @@ extern void BeginReportingGUCOptions(void); extern void ParseLongOption(const char* string, char** name, char** value); extern bool parse_int(const char* value, int* result, int flags, const char** hintmsg); extern bool parse_int64(const char* value, int64* result, const char** hintmsg); -extern bool parse_real(const char* value, double* result); +extern bool parse_real(const char* value, double* result, int flags = 0, const char** hintmsg = NULL); +double time_unit_convert(char** endptr, double value, int flags, const char** hintmsg); +double memory_unit_convert(char** endptr, double value, int flags, const char** hintmsg); 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); diff --git a/src/test/regress/expected/alter_system_set.out b/src/test/regress/expected/alter_system_set.out index e395ed16a..77a6fd6a2 100644 --- a/src/test/regress/expected/alter_system_set.out +++ b/src/test/regress/expected/alter_system_set.out @@ -88,7 +88,7 @@ NOTICE: please restart the database for the POSTMASTER level parameter to take SHOW password_lock_time; password_lock_time -------------------- - 1 + 1d (1 row) ALTER SYSTEM SET password_lock_time to 1.1; @@ -137,7 +137,7 @@ select pg_sleep(2); -- wait to reload postgres.conf file SHOW password_lock_time; password_lock_time -------------------- - 1.1 + 1.1d (1 row) ALTER SYSTEM SET password_lock_time to 1; @@ -185,7 +185,7 @@ select pg_sleep(2); -- wait to reload postgres.conf file SHOW password_lock_time; password_lock_time -------------------- - 1 + 1d (1 row) SHOW autovacuum; @@ -243,7 +243,7 @@ select pg_sleep(2); -- wait to reload postgres.conf file SHOW password_lock_time; password_lock_time -------------------- - 1 + 1d (1 row) SHOW autovacuum; diff --git a/src/test/regress/expected/double_support_unit.out b/src/test/regress/expected/double_support_unit.out new file mode 100644 index 000000000..6bbcd9a1e --- /dev/null +++ b/src/test/regress/expected/double_support_unit.out @@ -0,0 +1,97 @@ +alter system set password_lock_time to '1s'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 1s +(1 row) + +--------------------------------------------------------------------------- +alter system set password_lock_time to '1.1s'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 1.1s +(1 row) + +--------------------------------------------------------------------------- +alter system set password_lock_time to '1min'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 1min +(1 row) + +--------------------------------------------------------------------------- +alter system set password_lock_time to '1h'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 1h +(1 row) + +--------------------------------------------------------------------------- +alter system set password_lock_time to '1d'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 1d +(1 row) + +--------------------------------------------------------------------------- +alter system set password_lock_time to '0.1h'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 6min +(1 row) + +--------------------------------------------------------------------------- +alter system set password_lock_time to '0.1d'; +select pg_sleep(5); + pg_sleep +---------- + +(1 row) + +show password_lock_time; + password_lock_time +-------------------- + 2.4h +(1 row) + diff --git a/src/test/regress/parallel_schedule10 b/src/test/regress/parallel_schedule10 index 24b5d40ab..352ab5566 100644 --- a/src/test/regress/parallel_schedule10 +++ b/src/test/regress/parallel_schedule10 @@ -86,3 +86,4 @@ test: synchronous_commit_test test: alter_set_same_parameter test: gs_guc_value_range test: global_temporary_table_get_table_def +test: double_support_unit \ No newline at end of file diff --git a/src/test/regress/sql/double_support_unit.sql b/src/test/regress/sql/double_support_unit.sql new file mode 100644 index 000000000..f7cdfc4a7 --- /dev/null +++ b/src/test/regress/sql/double_support_unit.sql @@ -0,0 +1,33 @@ +alter system set password_lock_time to '1s'; +select pg_sleep(5); +show password_lock_time; +--------------------------------------------------------------------------- + +alter system set password_lock_time to '1.1s'; +select pg_sleep(5); +show password_lock_time; +--------------------------------------------------------------------------- + +alter system set password_lock_time to '1min'; +select pg_sleep(5); +show password_lock_time; +--------------------------------------------------------------------------- + +alter system set password_lock_time to '1h'; +select pg_sleep(5); +show password_lock_time; +--------------------------------------------------------------------------- + +alter system set password_lock_time to '1d'; +select pg_sleep(5); +show password_lock_time; +--------------------------------------------------------------------------- + +alter system set password_lock_time to '0.1h'; +select pg_sleep(5); +show password_lock_time; +--------------------------------------------------------------------------- + +alter system set password_lock_time to '0.1d'; +select pg_sleep(5); +show password_lock_time;