From 9b59fd6e63cb531117d3dcad0a7f4a337770eb7b Mon Sep 17 00:00:00 2001 From: Evgeny Voropaev Date: Thu, 13 Mar 2025 14:33:51 +0800 Subject: [PATCH v60 05/15] Support 64-bit integer GUCs Author: Alexander Korotkov Author: Teodor Sigaev Author: Nikita Glukhov Author: Maxim Orlov Author: Pavel Borisov Author: Yura Sokolov Author: Aleksander Alekseev Reviewed-by: Li Japin Author(rebase onto PG18dev, Mar 13 2025): Evgeny Voropaev Discussion: https://postgr.es/m/CAJ7c6TMvPz8q+nC=JoKniy7yxPzQYcCTnNFYmsDP-nnWsAOJ2g@mail.gmail.com --- src/backend/access/common/reloptions.c | 149 +++++-- src/backend/postmaster/autovacuum.c | 8 +- src/backend/utils/misc/guc.c | 418 ++++++++++++++++++ src/backend/utils/misc/guc_funcs.c | 25 ++ src/backend/utils/misc/guc_tables.c | 82 ++-- src/include/access/reloptions.h | 13 + src/include/postmaster/autovacuum.h | 8 +- src/include/utils/guc.h | 17 + src/include/utils/guc_tables.h | 19 + src/include/utils/rel.h | 8 +- .../modules/delay_execution/delay_execution.c | 28 +- .../expected/partition-addition.out | 6 +- .../expected/partition-removal-1.out | 28 +- .../specs/partition-addition.spec | 6 +- .../specs/partition-removal-1.spec | 6 +- 15 files changed, 696 insertions(+), 125 deletions(-) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 645b5c00467..b9da375880b 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -222,42 +222,6 @@ static relopt_int intRelOpts[] = }, SPGIST_DEFAULT_FILLFACTOR, SPGIST_MIN_FILLFACTOR, 100 }, - { - { - "autovacuum_vacuum_threshold", - "Minimum number of tuple updates or deletes prior to vacuum", - RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, - ShareUpdateExclusiveLock - }, - -1, 0, INT_MAX - }, - { - { - "autovacuum_vacuum_max_threshold", - "Maximum number of tuple updates or deletes prior to vacuum", - RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, - ShareUpdateExclusiveLock - }, - -2, -1, INT_MAX - }, - { - { - "autovacuum_vacuum_insert_threshold", - "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums", - RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, - ShareUpdateExclusiveLock - }, - -2, -1, INT_MAX - }, - { - { - "autovacuum_analyze_threshold", - "Minimum number of tuple inserts, updates or deletes prior to analyze", - RELOPT_KIND_HEAP, - ShareUpdateExclusiveLock - }, - -1, 0, INT_MAX - }, { { "autovacuum_vacuum_cost_limit", @@ -389,7 +353,48 @@ static relopt_int intRelOpts[] = }, -1, 0, 1024 }, + /* list terminator */ + {{NULL}} +}; +static relopt_int64 int64RelOpts[] = +{ + { + { + "autovacuum_vacuum_threshold", + "Minimum number of tuple updates or deletes prior to vacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + INT64CONST(-1), INT64CONST(0), PG_INT64_MAX + }, + { + { + "autovacuum_vacuum_max_threshold", + "Maximum number of tuple updates or deletes prior to vacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + INT64CONST(-2), INT64CONST(-1), PG_INT64_MAX + }, + { + { + "autovacuum_vacuum_insert_threshold", + "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + INT64CONST(-2), INT64CONST(-1), PG_INT64_MAX + }, + { + { + "autovacuum_analyze_threshold", + "Minimum number of tuple inserts, updates or deletes prior to analyze", + RELOPT_KIND_HEAP, + ShareUpdateExclusiveLock + }, + INT64CONST(-1), INT64CONST(0), PG_INT64_MAX + }, /* list terminator */ {{NULL}} }; @@ -614,6 +619,12 @@ initialize_reloptions(void) intRelOpts[i].gen.lockmode)); j++; } + for (i = 0; int64RelOpts[i].gen.name; i++) + { + Assert(DoLockModesConflict(int64RelOpts[i].gen.lockmode, + int64RelOpts[i].gen.lockmode)); + j++; + } for (i = 0; realRelOpts[i].gen.name; i++) { Assert(DoLockModesConflict(realRelOpts[i].gen.lockmode, @@ -656,6 +667,14 @@ initialize_reloptions(void) j++; } + for (i = 0; int64RelOpts[i].gen.name; i++) + { + relOpts[j] = &int64RelOpts[i].gen; + relOpts[j]->type = RELOPT_TYPE_INT64; + relOpts[j]->namelen = strlen(relOpts[j]->name); + j++; + } + for (i = 0; realRelOpts[i].gen.name; i++) { relOpts[j] = &realRelOpts[i].gen; @@ -811,6 +830,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc, case RELOPT_TYPE_INT: size = sizeof(relopt_int); break; + case RELOPT_TYPE_INT64: + size = sizeof(relopt_int64); + break; case RELOPT_TYPE_REAL: size = sizeof(relopt_real); break; @@ -965,6 +987,26 @@ init_real_reloption(bits32 kinds, const char *name, const char *desc, return newoption; } +/* + * add_int64_reloption + * Add a new 64-bit integer reloption + */ +void +add_int64_reloption(bits32 kinds, const char *name, char *desc, + int64 default_val, int64 min_val, int64 max_val, + LOCKMODE lockmode) +{ + relopt_int64 *newoption; + + newoption = (relopt_int64 *) allocate_reloption(kinds, RELOPT_TYPE_INT64, + name, desc, lockmode); + newoption->default_val = default_val; + newoption->min = min_val; + newoption->max = max_val; + + add_reloption((relopt_gen *) newoption); +} + /* * add_real_reloption * Add a new float reloption @@ -1636,6 +1678,28 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len, optint->min, optint->max))); } break; + case RELOPT_TYPE_INT64: + { + relopt_int64 *optint = (relopt_int64 *) option->gen; + + parsed = parse_int64(value, &option->values.int64_val, 0, NULL); + if (validate && !parsed) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid value for 64-bit integer option \"%s\": %s", + option->gen->name, value))); + if (validate && (option->values.int64_val < optint->min || + option->values.int64_val > optint->max)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("value %s out of bounds for option \"%s\"", + value, option->gen->name), + errdetail("Valid values are between \"%lld" + "\" and \"%lld\".", + (long long ) optint->min, + (long long) optint->max))); + } + break; case RELOPT_TYPE_REAL: { relopt_real *optreal = (relopt_real *) option->gen; @@ -1802,6 +1866,11 @@ fillRelOptions(void *rdopts, Size basesize, options[i].values.int_val : ((relopt_int *) options[i].gen)->default_val; break; + case RELOPT_TYPE_INT64: + *(int64 *) itempos = options[i].isset ? + options[i].values.int64_val : + ((relopt_int64 *) options[i].gen)->default_val; + break; case RELOPT_TYPE_REAL: *(double *) itempos = options[i].isset ? options[i].values.real_val : @@ -1871,13 +1940,13 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)}, {"autovacuum_enabled", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)}, - {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, + {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT64, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)}, - {"autovacuum_vacuum_max_threshold", RELOPT_TYPE_INT, + {"autovacuum_vacuum_max_threshold", RELOPT_TYPE_INT64, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_max_threshold)}, - {"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT, + {"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT64, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)}, - {"autovacuum_analyze_threshold", RELOPT_TYPE_INT, + {"autovacuum_analyze_threshold", RELOPT_TYPE_INT64, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)}, {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)}, diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 1328b880be5..4ca3acdccd8 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -120,12 +120,12 @@ int autovacuum_worker_slots; int autovacuum_max_workers; int autovacuum_work_mem = -1; int autovacuum_naptime; -int autovacuum_vac_thresh; -int autovacuum_vac_max_thresh; +int64 autovacuum_vac_thresh; +int64 autovacuum_vac_max_thresh; double autovacuum_vac_scale; -int autovacuum_vac_ins_thresh; +int64 autovacuum_vac_ins_thresh; double autovacuum_vac_ins_scale; -int autovacuum_anl_thresh; +int64 autovacuum_anl_thresh; double autovacuum_anl_scale; int autovacuum_freeze_max_age; int autovacuum_multixact_freeze_max_age; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 12192445218..2a06170bf8d 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -263,6 +263,8 @@ static bool call_bool_check_hook(struct config_bool *conf, bool *newval, void **extra, GucSource source, int elevel); static bool call_int_check_hook(struct config_int *conf, int *newval, void **extra, GucSource source, int elevel); +static bool call_int64_check_hook(struct config_int64 *conf, int64 *newval, + void **extra, GucSource source, int elevel); static bool call_real_check_hook(struct config_real *conf, double *newval, void **extra, GucSource source, int elevel); static bool call_string_check_hook(struct config_string *conf, char **newval, @@ -760,6 +762,10 @@ extra_field_used(struct config_generic *gconf, void *extra) if (extra == ((struct config_int *) gconf)->reset_extra) return true; break; + case PGC_INT64: + if (extra == ((struct config_int64 *) gconf)->reset_extra) + return true; + break; case PGC_REAL: if (extra == ((struct config_real *) gconf)->reset_extra) return true; @@ -821,6 +827,10 @@ set_stack_value(struct config_generic *gconf, config_var_value *val) val->val.intval = *((struct config_int *) gconf)->variable; break; + case PGC_INT64: + val->val.int64val = + *((struct config_int64 *) gconf)->variable; + break; case PGC_REAL: val->val.realval = *((struct config_real *) gconf)->variable; @@ -849,6 +859,7 @@ discard_stack_value(struct config_generic *gconf, config_var_value *val) { case PGC_BOOL: case PGC_INT: + case PGC_INT64: case PGC_REAL: case PGC_ENUM: /* no need to do anything */ @@ -937,6 +948,14 @@ build_guc_variables(void) num_vars++; } + for (i = 0; ConfigureNamesInt64[i].gen.name; i++) + { + struct config_int64 *conf = &ConfigureNamesInt64[i]; + + conf->gen.vartype = PGC_INT64; + num_vars++; + } + for (i = 0; ConfigureNamesReal[i].gen.name; i++) { struct config_real *conf = &ConfigureNamesReal[i]; @@ -1000,6 +1019,18 @@ build_guc_variables(void) hentry->gucvar = gucvar; } + for (i = 0; ConfigureNamesInt64[i].gen.name; i++) + { + struct config_generic *gucvar = &ConfigureNamesInt64[i].gen; + + hentry = (GUCHashEntry *) hash_search(guc_hashtab, + &gucvar->name, + HASH_ENTER, + &found); + Assert(!found); + hentry->gucvar = gucvar; + } + for (i = 0; ConfigureNamesReal[i].gen.name; i++) { struct config_generic *gucvar = &ConfigureNamesReal[i].gen; @@ -1427,6 +1458,7 @@ check_GUC_name_for_parameter_acl(const char *name) * The following validation rules apply for the values: * bool - can be false, otherwise must be same as the boot_val * int - can be 0, otherwise must be same as the boot_val + * int64 - can be 0, otherwise must be same as the boot_val * real - can be 0.0, otherwise must be same as the boot_val * string - can be NULL, otherwise must be strcmp equal to the boot_val * enum - must be same as the boot_val @@ -1462,6 +1494,20 @@ check_GUC_init(struct config_generic *gconf) } break; } + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + + if (*conf->variable != 0 && *conf->variable != conf->boot_val) + { + elog(LOG, "GUC (PGC_INT64) %s, boot_val=%lld, C-var=%lld", + conf->gen.name, + (long long) conf->boot_val, + (long long) *conf->variable); + return false; + } + break; + } case PGC_REAL: { struct config_real *conf = (struct config_real *) gconf; @@ -1692,6 +1738,24 @@ InitializeOneGUCOption(struct config_generic *gconf) conf->gen.extra = conf->reset_extra = extra; break; } + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + int64 newval = conf->boot_val; + void *extra = NULL; + + Assert(newval >= conf->min); + Assert(newval <= conf->max); + if (!call_int64_check_hook(conf, &newval, &extra, + PGC_S_DEFAULT, LOG)) + elog(FATAL, "failed to initialize %s to %lld", + conf->gen.name, (long long) newval); + if (conf->assign_hook) + (*conf->assign_hook) (newval, extra); + *conf->variable = conf->reset_val = newval; + conf->gen.extra = conf->reset_extra = extra; + break; + } case PGC_REAL: { struct config_real *conf = (struct config_real *) gconf; @@ -2042,6 +2106,18 @@ ResetAllOptions(void) { struct config_int *conf = (struct config_int *) gconf; + if (conf->assign_hook) + conf->assign_hook(conf->reset_val, + conf->reset_extra); + *conf->variable = conf->reset_val; + set_extra_field(&conf->gen, &conf->gen.extra, + conf->reset_extra); + break; + } + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + if (conf->assign_hook) conf->assign_hook(conf->reset_val, conf->reset_extra); @@ -2425,6 +2501,24 @@ AtEOXact_GUC(bool isCommit, int nestLevel) int newval = newvalue.val.intval; void *newextra = newvalue.extra; + if (*conf->variable != newval || + conf->gen.extra != newextra) + { + if (conf->assign_hook) + conf->assign_hook(newval, newextra); + *conf->variable = newval; + set_extra_field(&conf->gen, &conf->gen.extra, + newextra); + changed = true; + } + break; + } + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + int64 newval = newvalue.val.int64val; + void *newextra = newvalue.extra; + if (*conf->variable != newval || conf->gen.extra != newextra) { @@ -2947,6 +3041,71 @@ 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. + * + * If the string parses okay, return true, else false. + * If okay and result is not NULL, return the value in *result. + * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable + * HINT message, or NULL if no hint provided. + */ +bool +parse_int64(const char *value, int64 *result, int flags, const char **hintmsg) +{ + int64 val; + char *endptr; + + /* To suppress compiler warnings, always set output params */ + if (result) + *result = 0; + if (hintmsg) + *hintmsg = NULL; + + /* We assume here that int64 is at least as wide as long */ + errno = 0; + val = strtoi64(value, &endptr, 0); + + if (endptr == value) + return false; /* no HINT for integer syntax error */ + + if (errno == ERANGE) + { + if (hintmsg) + *hintmsg = gettext_noop("Value exceeds 64-bit integer range."); + return false; + } + + /* + * got double format and/or units. For now we attempts parse it as double + * and throw error on 53bit overflow + */ + if (*endptr != '\0') + { + double dval; + bool ok; + + ok = parse_real(value, &dval, flags, hintmsg); + if (!ok) + return false; + + dval = rint(val); + + if (fabs(dval) >= (double) ((uint64) 1 << 53)) + { + *hintmsg = gettext_noop("Int64 value with units should be positive number < 2^53"); + return false; + } + + val = (int64) dval; + } + + + if (result) + *result = val; + return true; +} + /* * Try to parse value as a floating point number in the usual format. * Optionally, the value can be followed by a unit name if "flags" indicates @@ -3192,6 +3351,36 @@ parse_and_validate_value(struct config_generic *record, return false; } break; + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) record; + const char *hintmsg; + + if (!parse_int64(value, &newval->int64val, conf->gen.flags, &hintmsg)) + { + ereport(elevel, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid value for parameter \"%s\": \"%s\"", + conf->gen.name, value), + hintmsg ? errhint("%s", _(hintmsg)) : 0)); + return false; + } + + if (newval->int64val < conf->min || newval->int64val > conf->max) + { + ereport(elevel, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("%lld is outside the valid range for parameter \"%s\" (%lld .. %lld)", + (long long) newval->int64val, conf->gen.name, + (long long) conf->min, (long long) conf->max))); + return false; + } + + if (!call_int64_check_hook(conf, &newval->int64val, newextra, + source, elevel)) + return false; + } + break; case PGC_REAL: { struct config_real *conf = (struct config_real *) record; @@ -3895,6 +4084,96 @@ set_config_with_handle(const char *name, config_handle *handle, guc_free(newextra); break; +#undef newval + } + + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) record; + +#define newval (newval_union.int64val) + + if (value) + { + if (!parse_and_validate_value(record, value, + source, elevel, + &newval_union, &newextra)) + return 0; + } + else if (source == PGC_S_DEFAULT) + { + newval = conf->boot_val; + if (!call_int64_check_hook(conf, &newval, &newextra, + source, elevel)) + return 0; + } + else + { + newval = conf->reset_val; + newextra = conf->reset_extra; + source = conf->gen.reset_source; + context = conf->gen.reset_scontext; + } + + if (prohibitValueChange) + { + if (*conf->variable != newval) + { + record->status |= GUC_PENDING_RESTART; + ereport(elevel, + (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), + errmsg("parameter \"%s\" cannot be changed without restarting the server", + name))); + return 0; + } + record->status &= ~GUC_PENDING_RESTART; + return -1; + } + + if (changeVal) + { + /* Save old value to support transaction abort */ + if (!makeDefault) + push_old_value(&conf->gen, action); + + if (conf->assign_hook) + (*conf->assign_hook) (newval, newextra); + *conf->variable = newval; + set_extra_field(&conf->gen, &conf->gen.extra, + newextra); + conf->gen.source = source; + conf->gen.scontext = context; + } + if (makeDefault) + { + GucStack *stack; + + if (conf->gen.reset_source <= source) + { + conf->reset_val = newval; + set_extra_field(&conf->gen, &conf->reset_extra, + newextra); + conf->gen.reset_source = source; + conf->gen.reset_scontext = context; + } + for (stack = conf->gen.stack; stack; stack = stack->prev) + { + if (stack->source <= source) + { + stack->prior.val.intval = newval; + set_extra_field(&conf->gen, &stack->prior.extra, + newextra); + stack->source = source; + stack->scontext = context; + } + } + } + + /* Perhaps we didn't install newextra anywhere */ + if (newextra && !extra_field_used(&conf->gen, newextra)) + guc_free(newextra); + break; + #undef newval } @@ -4378,6 +4657,11 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged) *((struct config_int *) record)->variable); return buffer; + case PGC_INT64: + snprintf(buffer, sizeof(buffer), "%lld", + (long long) *((struct config_int64 *) record)->variable); + return buffer; + case PGC_REAL: snprintf(buffer, sizeof(buffer), "%g", *((struct config_real *) record)->variable); @@ -4426,6 +4710,11 @@ GetConfigOptionResetString(const char *name) ((struct config_int *) record)->reset_val); return buffer; + case PGC_INT64: + snprintf(buffer, sizeof(buffer), "%lld", + (long long) ((struct config_int64 *) record)->reset_val); + return buffer; + case PGC_REAL: snprintf(buffer, sizeof(buffer), "%g", ((struct config_real *) record)->reset_val); @@ -5184,6 +5473,36 @@ DefineCustomIntVariable(const char *name, define_custom_variable(&var->gen); } +void +DefineCustomInt64Variable(const char *name, + const char *short_desc, + const char *long_desc, + int64 *valueAddr, + int64 bootValue, + int64 minValue, + int64 maxValue, + GucContext context, + int flags, + GucInt64CheckHook check_hook, + GucInt64AssignHook assign_hook, + GucShowHook show_hook) +{ + struct config_int64 *var; + + var = (struct config_int64 *) + init_custom_variable(name, short_desc, long_desc, context, flags, + PGC_INT64, sizeof(struct config_int64)); + var->variable = valueAddr; + var->boot_val = bootValue; + var->reset_val = bootValue; + var->min = minValue; + var->max = maxValue; + var->check_hook = check_hook; + var->assign_hook = assign_hook; + var->show_hook = show_hook; + define_custom_variable(&var->gen); +} + void DefineCustomRealVariable(const char *name, const char *short_desc, @@ -5377,6 +5696,14 @@ get_explain_guc_options(int *num) } break; + case PGC_INT64: + { + struct config_int64 *lconf = (struct config_int64 *) conf; + + modified = (lconf->boot_val != *(lconf->variable)); + } + break; + case PGC_REAL: { struct config_real *lconf = (struct config_real *) conf; @@ -5509,6 +5836,21 @@ ShowGUCOption(struct config_generic *record, bool use_units) } break; + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) record; + + if (conf->show_hook) + val = (*conf->show_hook) (); + else + { + snprintf(buffer, sizeof(buffer), "%lld", + (long long) *conf->variable); + val = buffer; + } + } + break; + case PGC_REAL: { struct config_real *conf = (struct config_real *) record; @@ -5611,6 +5953,14 @@ write_one_nondefault_variable(FILE *fp, struct config_generic *gconf) } break; + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + + fprintf(fp, "%lld", (long long) *conf->variable); + } + break; + case PGC_REAL: { struct config_real *conf = (struct config_real *) gconf; @@ -5883,6 +6233,24 @@ estimate_variable_size(struct config_generic *gconf) } break; + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + + /* + * Instead of getting the exact display length, use max + * length. Also reduce the max length for typical ranges of + * small values. Maximum value is 2^63, i.e. 20 chars. + * Include one byte for sign. + */ +#define ABS(x) ((x) >= 0 ? (x) : -(x)) + if (ABS(*conf->variable) < 1000) + valsize = 3 + 1; + else + valsize = 20 + 1; + } + break; + case PGC_REAL: { /* @@ -6049,6 +6417,14 @@ serialize_variable(char **destptr, Size *maxbytes, } break; + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + + do_serialize(destptr, maxbytes, "%lld", (long long) *conf->variable); + } + break; + case PGC_REAL: { struct config_real *conf = (struct config_real *) gconf; @@ -6262,6 +6638,14 @@ RestoreGUCState(void *gucstate) { struct config_int *conf = (struct config_int *) gconf; + if (conf->reset_extra && conf->reset_extra != gconf->extra) + guc_free(conf->reset_extra); + break; + } + case PGC_INT64: + { + struct config_int64 *conf = (struct config_int64 *) gconf; + if (conf->reset_extra && conf->reset_extra != gconf->extra) guc_free(conf->reset_extra); break; @@ -6862,6 +7246,40 @@ call_int_check_hook(struct config_int *conf, int *newval, void **extra, return true; } +static bool +call_int64_check_hook(struct config_int64 *conf, int64 *newval, void **extra, + GucSource source, int elevel) +{ + /* Quick success if no hook */ + if (!conf->check_hook) + return true; + + /* Reset variables that might be set by hook */ + GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE; + GUC_check_errmsg_string = NULL; + GUC_check_errdetail_string = NULL; + GUC_check_errhint_string = NULL; + + if (!(*conf->check_hook) (newval, extra, source)) + { + ereport(elevel, + (errcode(GUC_check_errcode_value), + GUC_check_errmsg_string ? + errmsg_internal("%s", GUC_check_errmsg_string) : + errmsg("invalid value for parameter \"%s\": %lld", + conf->gen.name, (long long) *newval), + GUC_check_errdetail_string ? + errdetail_internal("%s", GUC_check_errdetail_string) : 0, + GUC_check_errhint_string ? + errhint("%s", GUC_check_errhint_string) : 0)); + /* Flush any strings created in ErrorContext */ + FlushErrorState(); + return false; + } + + return true; +} + static bool call_real_check_hook(struct config_real *conf, double *newval, void **extra, GucSource source, int elevel) diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c index b9e26982abd..4f94b9b844c 100644 --- a/src/backend/utils/misc/guc_funcs.c +++ b/src/backend/utils/misc/guc_funcs.c @@ -673,6 +673,31 @@ GetConfigOptionValues(struct config_generic *conf, const char **values) } break; + case PGC_INT64: + { + struct config_int64 *lconf = (struct config_int64 *) conf; + + /* min_val */ + snprintf(buffer, sizeof(buffer), "%lld", (long long) lconf->min); + values[9] = pstrdup(buffer); + + /* max_val */ + snprintf(buffer, sizeof(buffer), "%lld", (long long) lconf->max); + values[10] = pstrdup(buffer); + + /* enumvals */ + values[11] = NULL; + + /* boot_val */ + snprintf(buffer, sizeof(buffer), "%lld", (long long) lconf->boot_val); + values[12] = pstrdup(buffer); + + /* reset_val */ + snprintf(buffer, sizeof(buffer), "%lld", (long long) lconf->reset_val); + values[13] = pstrdup(buffer); + } + break; + case PGC_REAL: { struct config_real *lconf = (struct config_real *) conf; diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 989825d3a9c..5d173c83c58 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -739,6 +739,7 @@ const char *const config_type_names[] = { [PGC_BOOL] = "bool", [PGC_INT] = "integer", + [PGC_INT64] = "int64", [PGC_REAL] = "real", [PGC_STRING] = "string", [PGC_ENUM] = "enum", @@ -3524,42 +3525,6 @@ struct config_int ConfigureNamesInt[] = 60, 1, INT_MAX / 1000, NULL, NULL, NULL }, - { - {"autovacuum_vacuum_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, - gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."), - NULL - }, - &autovacuum_vac_thresh, - 50, 0, INT_MAX, - NULL, NULL, NULL - }, - { - {"autovacuum_vacuum_max_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, - gettext_noop("Maximum number of tuple updates or deletes prior to vacuum."), - gettext_noop("-1 disables the maximum threshold.") - }, - &autovacuum_vac_max_thresh, - 100000000, -1, INT_MAX, - NULL, NULL, NULL - }, - { - {"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, - gettext_noop("Minimum number of tuple inserts prior to vacuum."), - gettext_noop("-1 disables insert vacuums.") - }, - &autovacuum_vac_ins_thresh, - 1000, -1, INT_MAX, - NULL, NULL, NULL - }, - { - {"autovacuum_analyze_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, - gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."), - NULL - }, - &autovacuum_anl_thresh, - 50, 0, INT_MAX, - NULL, NULL, NULL - }, { /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */ {"autovacuum_freeze_max_age", PGC_POSTMASTER, VACUUM_AUTOVACUUM, @@ -3865,6 +3830,51 @@ struct config_int ConfigureNamesInt[] = }; +struct config_int64 ConfigureNamesInt64[] = +{ + { + {"autovacuum_vacuum_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, + gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."), + NULL + }, + &autovacuum_vac_thresh, + INT64CONST(50), INT64CONST(0), PG_INT64_MAX, + NULL, NULL, NULL + }, + { + {"autovacuum_vacuum_max_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, + gettext_noop("Maximum number of tuple updates or deletes prior to vacuum."), + gettext_noop("-1 disables the maximum threshold.") + }, + &autovacuum_vac_max_thresh, + INT64CONST(100000000), INT64CONST(-1), PG_INT64_MAX, + NULL, NULL, NULL + }, + { + {"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, + gettext_noop("Minimum number of tuple inserts prior to vacuum."), + gettext_noop("-1 disables insert vacuums.") + }, + &autovacuum_vac_ins_thresh, + INT64CONST(1000), INT64CONST(-1), PG_INT64_MAX, + NULL, NULL, NULL + }, + { + {"autovacuum_analyze_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, + gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."), + NULL + }, + &autovacuum_anl_thresh, + INT64CONST(50), INT64CONST(0), PG_INT64_MAX, + NULL, NULL, NULL + }, + /* End-of-list marker */ + { + {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL + } +}; + + struct config_real ConfigureNamesReal[] = { { diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index dfbb4c85460..d0520f19d64 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -30,6 +30,7 @@ typedef enum relopt_type { RELOPT_TYPE_BOOL, RELOPT_TYPE_INT, + RELOPT_TYPE_INT64, RELOPT_TYPE_REAL, RELOPT_TYPE_ENUM, RELOPT_TYPE_STRING, @@ -81,6 +82,7 @@ typedef struct relopt_value { bool bool_val; int int_val; + int64 int64_val; double real_val; int enum_val; char *string_val; /* allocated separately */ @@ -102,6 +104,14 @@ typedef struct relopt_int int max; } relopt_int; +typedef struct relopt_int64 +{ + relopt_gen gen; + int64 default_val; + int64 min; + int64 max; +} relopt_int64; + typedef struct relopt_real { relopt_gen gen; @@ -198,6 +208,9 @@ extern void add_bool_reloption(bits32 kinds, const char *name, const char *desc, extern void add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val, int min_val, int max_val, LOCKMODE lockmode); +extern void add_int64_reloption(bits32 kinds, const char *name, char *desc, + int64 default_val, int64 min_val, int64 max_val, + LOCKMODE lockmode); extern void add_real_reloption(bits32 kinds, const char *name, const char *desc, double default_val, double min_val, double max_val, LOCKMODE lockmode); diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index e8135f41a1c..d80817adc8e 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -32,12 +32,12 @@ extern PGDLLIMPORT int autovacuum_worker_slots; extern PGDLLIMPORT int autovacuum_max_workers; extern PGDLLIMPORT int autovacuum_work_mem; extern PGDLLIMPORT int autovacuum_naptime; -extern PGDLLIMPORT int autovacuum_vac_thresh; -extern PGDLLIMPORT int autovacuum_vac_max_thresh; +extern PGDLLIMPORT int64 autovacuum_vac_thresh; +extern PGDLLIMPORT int64 autovacuum_vac_max_thresh; extern PGDLLIMPORT double autovacuum_vac_scale; -extern PGDLLIMPORT int autovacuum_vac_ins_thresh; +extern PGDLLIMPORT int64 autovacuum_vac_ins_thresh; extern PGDLLIMPORT double autovacuum_vac_ins_scale; -extern PGDLLIMPORT int autovacuum_anl_thresh; +extern PGDLLIMPORT int64 autovacuum_anl_thresh; extern PGDLLIMPORT double autovacuum_anl_scale; extern PGDLLIMPORT int autovacuum_freeze_max_age; extern PGDLLIMPORT int autovacuum_multixact_freeze_max_age; diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index f619100467d..72f2b17f58e 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -182,12 +182,14 @@ struct config_enum_entry */ typedef bool (*GucBoolCheckHook) (bool *newval, void **extra, GucSource source); typedef bool (*GucIntCheckHook) (int *newval, void **extra, GucSource source); +typedef bool (*GucInt64CheckHook) (int64 *newval, void **extra, GucSource source); typedef bool (*GucRealCheckHook) (double *newval, void **extra, GucSource source); typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource source); typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source); typedef void (*GucBoolAssignHook) (bool newval, void *extra); typedef void (*GucIntAssignHook) (int newval, void *extra); +typedef void (*GucInt64AssignHook) (int64 newval, void *extra); typedef void (*GucRealAssignHook) (double newval, void *extra); typedef void (*GucStringAssignHook) (const char *newval, void *extra); typedef void (*GucEnumAssignHook) (int newval, void *extra); @@ -353,6 +355,19 @@ extern void DefineCustomIntVariable(const char *name, GucIntAssignHook assign_hook, GucShowHook show_hook) pg_attribute_nonnull(1, 4); +extern void DefineCustomInt64Variable(const char *name, + const char *short_desc, + const char *long_desc, + int64 *valueAddr, + int64 bootValue, + int64 minValue, + int64 maxValue, + GucContext context, + int flags, + GucInt64CheckHook check_hook, + GucInt64AssignHook assign_hook, + GucShowHook show_hook) pg_attribute_nonnull(1, 4); + extern void DefineCustomRealVariable(const char *name, const char *short_desc, const char *long_desc, @@ -414,6 +429,8 @@ extern void ParseLongOption(const char *string, char **name, char **value); extern const char *get_config_unit_name(int flags); extern bool parse_int(const char *value, int *result, int flags, const char **hintmsg); +extern bool parse_int64(const char *value, int64 *result, int flags, + const char **hintmsg); extern bool parse_real(const char *value, double *result, int flags, const char **hintmsg); extern int set_config_option(const char *name, const char *value, diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index f72ce944d7f..4a3bbecabe3 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -24,6 +24,7 @@ enum config_type { PGC_BOOL, PGC_INT, + PGC_INT64, PGC_REAL, PGC_STRING, PGC_ENUM, @@ -33,6 +34,7 @@ union config_var_val { bool boolval; int intval; + int64 int64val; double realval; char *stringval; int enumval; @@ -243,6 +245,22 @@ struct config_int void *reset_extra; }; +struct config_int64 +{ + struct config_generic gen; + /* constant fields, must be set correctly in initial value: */ + int64 *variable; + int64 boot_val; + int64 min; + int64 max; + GucInt64CheckHook check_hook; + GucInt64AssignHook assign_hook; + GucShowHook show_hook; + /* variable fields, initialized at runtime: */ + int64 reset_val; + void *reset_extra; +}; + struct config_real { struct config_generic gen; @@ -307,6 +325,7 @@ extern PGDLLIMPORT const char *const GucSource_Names[]; /* data arrays defining all the built-in GUC variables */ extern PGDLLIMPORT struct config_bool ConfigureNamesBool[]; extern PGDLLIMPORT struct config_int ConfigureNamesInt[]; +extern PGDLLIMPORT struct config_int64 ConfigureNamesInt64[]; extern PGDLLIMPORT struct config_real ConfigureNamesReal[]; extern PGDLLIMPORT struct config_string ConfigureNamesString[]; extern PGDLLIMPORT struct config_enum ConfigureNamesEnum[]; diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index d94fddd7cef..dbe6c64e1af 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -308,10 +308,10 @@ typedef struct ForeignKeyCacheInfo typedef struct AutoVacOpts { bool enabled; - int vacuum_threshold; - int vacuum_max_threshold; - int vacuum_ins_threshold; - int analyze_threshold; + int64 vacuum_threshold; + int64 vacuum_max_threshold; + int64 vacuum_ins_threshold; + int64 analyze_threshold; int vacuum_cost_limit; int freeze_min_age; int freeze_max_age; diff --git a/src/test/modules/delay_execution/delay_execution.c b/src/test/modules/delay_execution/delay_execution.c index 7bc97f84a1c..3c4e9e56ead 100644 --- a/src/test/modules/delay_execution/delay_execution.c +++ b/src/test/modules/delay_execution/delay_execution.c @@ -31,7 +31,7 @@ PG_MODULE_MAGIC; /* GUC: advisory lock ID to use. Zero disables the feature. */ -static int post_planning_lock_id = 0; +static int64 post_planning_lock_id = 0; /* Save previous planner hook user to be a good citizen */ static planner_hook_type prev_planner_hook = NULL; @@ -56,9 +56,9 @@ delay_execution_planner(Query *parse, const char *query_string, if (post_planning_lock_id != 0) { DirectFunctionCall1(pg_advisory_lock_int8, - Int64GetDatum((int64) post_planning_lock_id)); + Int64GetDatum(post_planning_lock_id)); DirectFunctionCall1(pg_advisory_unlock_int8, - Int64GetDatum((int64) post_planning_lock_id)); + Int64GetDatum(post_planning_lock_id)); /* * Ensure that we notice any pending invalidations, since the advisory @@ -75,17 +75,17 @@ void _PG_init(void) { /* Set up the GUC to control which lock is used */ - DefineCustomIntVariable("delay_execution.post_planning_lock_id", - "Sets the advisory lock ID to be locked/unlocked after planning.", - "Zero disables the delay.", - &post_planning_lock_id, - 0, - 0, INT_MAX, - PGC_USERSET, - 0, - NULL, - NULL, - NULL); + DefineCustomInt64Variable("delay_execution.post_planning_lock_id", + "Sets the advisory lock ID to be locked/unlocked after planning.", + "Zero disables the delay.", + &post_planning_lock_id, + 0, + 0, PG_INT64_MAX, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); MarkGUCPrefixReserved("delay_execution"); diff --git a/src/test/modules/delay_execution/expected/partition-addition.out b/src/test/modules/delay_execution/expected/partition-addition.out index 7d6572b2db2..57750db1603 100644 --- a/src/test/modules/delay_execution/expected/partition-addition.out +++ b/src/test/modules/delay_execution/expected/partition-addition.out @@ -1,19 +1,19 @@ Parsed test spec with 2 sessions starting permutation: s2lock s1exec s2addp s2unlock -step s2lock: SELECT pg_advisory_lock(12345); +step s2lock: SELECT pg_advisory_lock(0x1122334455667788); pg_advisory_lock ---------------- (1 row) step s1exec: LOAD 'delay_execution'; - SET delay_execution.post_planning_lock_id = 12345; + SET delay_execution.post_planning_lock_id = 0x1122334455667788; SELECT * FROM foo WHERE a <> 1 AND a <> (SELECT 3); step s2addp: CREATE TABLE foo2 (LIKE foo); ALTER TABLE foo ATTACH PARTITION foo2 FOR VALUES IN (2); INSERT INTO foo VALUES (2, 'ADD2'); -step s2unlock: SELECT pg_advisory_unlock(12345); +step s2unlock: SELECT pg_advisory_unlock(0x1122334455667788); pg_advisory_unlock ------------------ t diff --git a/src/test/modules/delay_execution/expected/partition-removal-1.out b/src/test/modules/delay_execution/expected/partition-removal-1.out index b81b9995e9a..a2e453fdaa9 100644 --- a/src/test/modules/delay_execution/expected/partition-removal-1.out +++ b/src/test/modules/delay_execution/expected/partition-removal-1.out @@ -1,7 +1,7 @@ Parsed test spec with 3 sessions starting permutation: s3lock s1b s1exec s2remp s3check s3unlock s3check s1c -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- @@ -17,7 +17,7 @@ a|b 3|DEF (2 rows) -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t @@ -40,7 +40,7 @@ step s1c: COMMIT; step s2remp: <... completed> starting permutation: s3lock s1brr s1exec s2remp s3check s3unlock s3check s1c -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- @@ -56,7 +56,7 @@ a|b 3|DEF (2 rows) -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t @@ -79,7 +79,7 @@ step s1c: COMMIT; step s2remp: <... completed> starting permutation: s3lock s1b s1exec2 s2remp s3unlock s1c -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- @@ -88,7 +88,7 @@ pg_advisory_lock step s1b: BEGIN; step s1exec2: SELECT * FROM partrem WHERE a <> (SELECT 2) AND a <> 1; step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t @@ -104,7 +104,7 @@ step s1c: COMMIT; step s2remp: <... completed> starting permutation: s3lock s1brr s1exec2 s2remp s3unlock s1c -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- @@ -113,7 +113,7 @@ pg_advisory_lock step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; step s1exec2: SELECT * FROM partrem WHERE a <> (SELECT 2) AND a <> 1; step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t @@ -129,7 +129,7 @@ step s1c: COMMIT; step s2remp: <... completed> starting permutation: s3lock s1brr s1prepare s2remp s1execprep s3unlock s1check s1c s1check s1dealloc -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- @@ -139,7 +139,7 @@ step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; step s1prepare: PREPARE ins AS INSERT INTO partrem VALUES ($1, 'GHI'); step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; step s1execprep: EXECUTE ins(2); -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t @@ -165,14 +165,14 @@ starting permutation: s1brr s1prepare s2remp s3lock s1execprep s3unlock s1check step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; step s1prepare: PREPARE ins AS INSERT INTO partrem VALUES ($1, 'GHI'); step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- (1 row) step s1execprep: EXECUTE ins(2); -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t @@ -201,7 +201,7 @@ a|b -+- (0 rows) -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- @@ -210,7 +210,7 @@ pg_advisory_lock step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; step s1prepare: PREPARE ins AS INSERT INTO partrem VALUES ($1, 'GHI'); step s1execprep: EXECUTE ins(2); -step s3unlock: SELECT pg_advisory_unlock(12543); +step s3unlock: SELECT pg_advisory_unlock(0x7766554433221100); pg_advisory_unlock ------------------ t diff --git a/src/test/modules/delay_execution/specs/partition-addition.spec b/src/test/modules/delay_execution/specs/partition-addition.spec index 99010dfad5c..4a68e88cc74 100644 --- a/src/test/modules/delay_execution/specs/partition-addition.spec +++ b/src/test/modules/delay_execution/specs/partition-addition.spec @@ -25,12 +25,12 @@ teardown session "s1" step "s1exec" { LOAD 'delay_execution'; - SET delay_execution.post_planning_lock_id = 12345; + SET delay_execution.post_planning_lock_id = 0x1122334455667788; SELECT * FROM foo WHERE a <> 1 AND a <> (SELECT 3); } session "s2" -step "s2lock" { SELECT pg_advisory_lock(12345); } -step "s2unlock" { SELECT pg_advisory_unlock(12345); } +step "s2lock" { SELECT pg_advisory_lock(0x1122334455667788); } +step "s2unlock" { SELECT pg_advisory_unlock(0x1122334455667788); } step "s2addp" { CREATE TABLE foo2 (LIKE foo); ALTER TABLE foo ATTACH PARTITION foo2 FOR VALUES IN (2); INSERT INTO foo VALUES (2, 'ADD2'); } diff --git a/src/test/modules/delay_execution/specs/partition-removal-1.spec b/src/test/modules/delay_execution/specs/partition-removal-1.spec index 5ee27501294..25b40b89a46 100644 --- a/src/test/modules/delay_execution/specs/partition-removal-1.spec +++ b/src/test/modules/delay_execution/specs/partition-removal-1.spec @@ -18,7 +18,7 @@ teardown session "s1" setup { LOAD 'delay_execution'; - SET delay_execution.post_planning_lock_id = 12543; } + SET delay_execution.post_planning_lock_id = 0x7766554433221100; } step "s1b" { BEGIN; } step "s1brr" { BEGIN ISOLATION LEVEL REPEATABLE READ; } step "s1exec" { SELECT * FROM partrem WHERE a <> 1 AND a <> (SELECT 3); } @@ -33,8 +33,8 @@ session "s2" step "s2remp" { ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; } session "s3" -step "s3lock" { SELECT pg_advisory_lock(12543); } -step "s3unlock" { SELECT pg_advisory_unlock(12543); } +step "s3lock" { SELECT pg_advisory_lock(0x7766554433221100); } +step "s3unlock" { SELECT pg_advisory_unlock(0x7766554433221100); } step "s3check" { SELECT * FROM partrem; } # The SELECT will be planned with all three partitions shown above, -- 2.48.1