1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Disallow negative values for max_retention_duration.

The subscription option max_retention_duration accepts an integer value
representing a timeout in milliseconds, where zero means unlimited
retention (no timeout).  Negative values have no useful meaning, but were
silently accepted and stored in the subscription catalog.

A negative value causes should_stop_conflict_info_retention() to always
return true, because TimestampDifferenceExceeds() treats a negative
threshold as already exceeded.  This stops dead tuple retention
immediately rather than honoring the configured timeout.

Fix by rejecting negative values for max_retention_duration during CREATE
SUBSCRIPTION and ALTER SUBSCRIPTION.

Author: Chao Li <lic@highgo.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/9232401A-DEEE-49E1-9D11-D14A776DB82B@gmail.com
This commit is contained in:
Amit Kapila
2026-06-11 11:17:54 +05:30
parent 9d33a5a804
commit 987440b33a
3 changed files with 17 additions and 0 deletions

View File

@@ -356,6 +356,11 @@ parse_subscription_options(ParseState *pstate, List *stmt_options,
opts->specified_opts |= SUBOPT_MAX_RETENTION_DURATION;
opts->maxretention = defGetInt32(defel);
if (opts->maxretention < 0)
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("max_retention_duration cannot be negative"));
}
else if (IsSet(supported_opts, SUBOPT_ORIGIN) &&
strcmp(defel->defname, "origin") == 0)

View File

@@ -518,6 +518,9 @@ DROP SUBSCRIPTION regress_testsub;
-- fail - max_retention_duration must be integer
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = foo);
ERROR: max_retention_duration requires an integer value
-- fail - max_retention_duration must be non-negative
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = -1);
ERROR: max_retention_duration cannot be negative
-- ok
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = 1000);
NOTICE: max_retention_duration is ineffective when retain_dead_tuples is disabled
@@ -530,6 +533,9 @@ HINT: To initiate replication, you must manually create the replication slot, e
regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | | f | 1000 | f | off | dbname=regress_doesnotexist | -1 | 0/00000000 |
(1 row)
-- fail - max_retention_duration must be non-negative
ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = -1);
ERROR: max_retention_duration cannot be negative
-- ok
ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = 0);
\dRs+

View File

@@ -378,11 +378,17 @@ DROP SUBSCRIPTION regress_testsub;
-- fail - max_retention_duration must be integer
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = foo);
-- fail - max_retention_duration must be non-negative
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = -1);
-- ok
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = 1000);
\dRs+
-- fail - max_retention_duration must be non-negative
ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = -1);
-- ok
ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = 0);