Hi hackers!Upgraded the "Int64 GUC" patch in order to conform to f3f06b13308e3 updates. Rebased and tested upon the current master (3f9b9621766). The patch is still needed to be up to date as a part of the xid64 solution.
Best regards, Evgeny Voropaev, TantorLabs, LLC. <evo...@gmail.com> <evgeny.vorop...@tantorlabs.ru>
From 1ff7cc48d955e02463e6c0ff8a7c0f7673d83f8f Mon Sep 17 00:00:00 2001 From: Evgeny Voropaev <evo...@gmail.com> Date: Sun, 8 Dec 2024 21:29:31 +0800 Subject: [PATCH v4] Support 64-bit integer GUCs Author: Alexander Korotkov <aekorot...@gmail.com> Author: Teodor Sigaev <teo...@sigaev.ru> Author: Nikita Glukhov <n.glu...@postgrespro.ru> Author: Maxim Orlov <orlo...@gmail.com> Author: Pavel Borisov <pashkin.e...@gmail.com> Author: Yura Sokolov <y.soko...@postgrespro.ru> <funny.fal...@gmail.com> Author: Aleksander Alekseev <aleksan...@timescale.com> Reviewed-by: Li Japin <japi...@hotmail.com> Author(rebase onto PG18dev, Dec 8 2024): Evgeny Voropaev <evo...@gmail.com> <evgeny.vorop...@tantorlabs.ru> Discussion: https://postgr.es/m/CAJ7c6TMvPz8q+nC=jokniy7yxpzqycctnnfymsdp-nnwsao...@mail.gmail.com --- src/backend/access/common/reloptions.c | 129 ++++-- src/backend/postmaster/autovacuum.c | 6 +- src/backend/utils/misc/guc.c | 418 ++++++++++++++++++ src/backend/utils/misc/guc_funcs.c | 25 ++ src/backend/utils/misc/guc_tables.c | 64 +-- src/include/access/reloptions.h | 13 + src/include/postmaster/autovacuum.h | 6 +- src/include/utils/guc.h | 17 + src/include/utils/guc_tables.h | 19 + src/include/utils/rel.h | 6 +- .../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, 674 insertions(+), 103 deletions(-) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 49fd35bfc55..b989442942f 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -222,33 +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_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", @@ -380,7 +353,39 @@ 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_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}} }; @@ -595,6 +600,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, @@ -637,6 +648,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; @@ -792,6 +811,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; @@ -946,6 +968,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 @@ -1617,6 +1659,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; @@ -1772,6 +1836,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 : @@ -1841,11 +1910,11 @@ 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_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 180bb7e96ed..63c55c13e86 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -118,11 +118,11 @@ bool autovacuum_start_daemon = false; int autovacuum_max_workers; int autovacuum_work_mem = -1; int autovacuum_naptime; -int autovacuum_vac_thresh; +int64 autovacuum_vac_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 c10c0844ab6..fac919a0375 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 9c9edd3d2f5..d0625d18b3a 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 8cf1afbad20..08626cdaf2c 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -731,6 +731,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", @@ -3416,33 +3417,6 @@ struct config_int ConfigureNamesInt[] = 60, 1, INT_MAX / 1000, NULL, NULL, NULL }, - { - {"autovacuum_vacuum_threshold", PGC_SIGHUP, 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_insert_threshold", PGC_SIGHUP, AUTOVACUUM, - gettext_noop("Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums."), - NULL - }, - &autovacuum_vac_ins_thresh, - 1000, -1, INT_MAX, - NULL, NULL, NULL - }, - { - {"autovacuum_analyze_threshold", PGC_SIGHUP, 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, AUTOVACUUM, @@ -3740,6 +3714,42 @@ struct config_int ConfigureNamesInt[] = }; +struct config_int64 ConfigureNamesInt64[] = +{ + { + {"autovacuum_vacuum_threshold", PGC_SIGHUP, 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_insert_threshold", PGC_SIGHUP, AUTOVACUUM, + gettext_noop("Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums."), + NULL + }, + &autovacuum_vac_ins_thresh, + INT64CONST(1000), INT64CONST(-1), PG_INT64_MAX, + NULL, NULL, NULL + }, + { + {"autovacuum_analyze_threshold", PGC_SIGHUP, 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 df6923c9d50..309c82ebf4d 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; @@ -185,6 +195,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 cae1e8b3294..15f12ce24f9 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -31,11 +31,11 @@ extern PGDLLIMPORT bool autovacuum_start_daemon; 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 int64 autovacuum_vac_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 840b0fe57ff..0a3fe0b54f8 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -178,12 +178,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); @@ -348,6 +350,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, @@ -409,6 +424,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 0c0277c4230..c4dfe0afab3 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; @@ -225,6 +227,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; @@ -289,6 +307,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 87002049538..f89064e2744 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -308,9 +308,9 @@ typedef struct ForeignKeyCacheInfo typedef struct AutoVacOpts { bool enabled; - int vacuum_threshold; - int vacuum_ins_threshold; - int analyze_threshold; + int64 vacuum_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 fa4693a3f57..036a9c3e10b 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); <waiting ...> 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; <waiting ...> step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; <waiting ...> -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; <waiting ...> step s2remp: ALTER TABLE partrem DETACH PARTITION partrem2 CONCURRENTLY; <waiting ...> -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; <waiting ...> step s1execprep: EXECUTE ins(2); <waiting ...> -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; <waiting ...> -step s3lock: SELECT pg_advisory_lock(12543); +step s3lock: SELECT pg_advisory_lock(0x7766554433221100); pg_advisory_lock ---------------- (1 row) step s1execprep: EXECUTE ins(2); <waiting ...> -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; <waiting ...> step s1prepare: PREPARE ins AS INSERT INTO partrem VALUES ($1, 'GHI'); step s1execprep: EXECUTE ins(2); <waiting ...> -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.47.1