diff --git a/doc/src/sgml/ref/wait_for.sgml b/doc/src/sgml/ref/wait_for.sgml
index 0042825e702..77b7674f93e 100644
--- a/doc/src/sgml/ref/wait_for.sgml
+++ b/doc/src/sgml/ref/wait_for.sgml
@@ -145,13 +145,21 @@ WAIT FOR LSN 'lsn'
When specified and timeout is greater than zero,
the command waits until lsn is reached or
- the specified timeout has elapsed.
+ the specified timeout has elapsed. A value
+ of zero (the default) means the command waits indefinitely.
- The timeout might be given as integer number of
- milliseconds. Also it might be given as string literal with
- integer number of milliseconds or a number with unit
- (see ).
+ The timeout is an amount of time in
+ milliseconds. It may also be specified as a string containing the
+ numerical value followed by a time unit
+ (see ). The maximum
+ value is 2147483647 ms.
+
+
+ Fractional values are rounded to the nearest millisecond. Note
+ that a timeout of half a millisecond or
+ less therefore rounds down to zero, which means waiting
+ indefinitely.
diff --git a/src/backend/access/transam/xlogwait.c b/src/backend/access/transam/xlogwait.c
index 4fd11e66284..7170921ecdf 100644
--- a/src/backend/access/transam/xlogwait.c
+++ b/src/backend/access/transam/xlogwait.c
@@ -440,7 +440,7 @@ WaitLSNTypeRequiresRecovery(WaitLSNType t)
* or replica got promoted before the target LSN reached.
*/
WaitLSNResult
-WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN, int64 timeout)
+WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN, int timeout)
{
XLogRecPtr currentLSN;
WaitLSNProcInfo *procInfo;
diff --git a/src/backend/commands/repack_worker.c b/src/backend/commands/repack_worker.c
index b4ba9cfc67b..bf2bc2dca13 100644
--- a/src/backend/commands/repack_worker.c
+++ b/src/backend/commands/repack_worker.c
@@ -453,7 +453,7 @@ decode_concurrent_changes(LogicalDecodingContext *ctx,
if (record == NULL)
{
- int64 timeout = 0;
+ int timeout = 0;
WaitLSNResult res;
/*
@@ -472,7 +472,7 @@ decode_concurrent_changes(LogicalDecodingContext *ctx,
* should already have been flushed to disk.
*/
if (!XLogRecPtrIsValid(lsn_upto))
- timeout = 100L;
+ timeout = 100;
res = WaitForLSN(WAIT_LSN_TYPE_PRIMARY_FLUSH,
ctx->reader->EndRecPtr + 1,
timeout);
diff --git a/src/backend/commands/wait.c b/src/backend/commands/wait.c
index 160447eddfb..b6b11522ea6 100644
--- a/src/backend/commands/wait.c
+++ b/src/backend/commands/wait.c
@@ -13,8 +13,6 @@
*/
#include "postgres.h"
-#include
-
#include "access/xlog.h"
#include "access/xlogrecovery.h"
#include "access/xlogwait.h"
@@ -37,7 +35,7 @@ ExecWaitStmt(ParseState *pstate, WaitStmt *stmt, bool isTopLevel,
DestReceiver *dest)
{
XLogRecPtr lsn;
- int64 timeout = 0;
+ int timeout = 0;
WaitLSNResult waitLSNResult;
WaitLSNType lsnType = WAIT_LSN_TYPE_STANDBY_REPLAY; /* default */
bool throw = true;
@@ -94,7 +92,6 @@ ExecWaitStmt(ParseState *pstate, WaitStmt *stmt, bool isTopLevel,
{
char *timeout_str;
const char *hintmsg;
- double dval;
if (timeout_specified)
errorConflictingDefElem(defel, pstate);
@@ -102,33 +99,18 @@ ExecWaitStmt(ParseState *pstate, WaitStmt *stmt, bool isTopLevel,
timeout_str = defGetString(defel);
- if (!parse_real(timeout_str, &dval, GUC_UNIT_MS, &hintmsg))
- {
+ if (!parse_int(timeout_str, &timeout, GUC_UNIT_MS, &hintmsg))
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid timeout value: \"%s\"", timeout_str),
- hintmsg ? errhint("%s", _(hintmsg)) : 0);
- }
+ hintmsg ? errhint("%s", _(hintmsg)) : 0,
+ parser_errposition(pstate, defel->location));
- /*
- * Get rid of any fractional part in the input. This is so we
- * don't fail on just-out-of-range values that would round into
- * range.
- */
- dval = rint(dval);
-
- /* Range check */
- if (unlikely(isnan(dval) || !FLOAT8_FITS_IN_INT64(dval)))
- ereport(ERROR,
- errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("timeout value is out of range"));
-
- if (dval < 0)
+ if (timeout < 0)
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("timeout cannot be negative"));
-
- timeout = (int64) dval;
+ errmsg("timeout cannot be negative"),
+ parser_errposition(pstate, defel->location));
}
else if (strcmp(defel->defname, "no_throw") == 0)
{
diff --git a/src/include/access/xlogwait.h b/src/include/access/xlogwait.h
index 07157f220ea..2bf0263e9e2 100644
--- a/src/include/access/xlogwait.h
+++ b/src/include/access/xlogwait.h
@@ -104,6 +104,6 @@ extern XLogRecPtr GetCurrentLSNForWaitType(WaitLSNType lsnType);
extern void WaitLSNWakeup(WaitLSNType lsnType, XLogRecPtr currentLSN);
extern void WaitLSNCleanup(void);
extern WaitLSNResult WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN,
- int64 timeout);
+ int timeout);
#endif /* XLOG_WAIT_H */
diff --git a/src/test/recovery/t/049_wait_for_lsn.pl b/src/test/recovery/t/049_wait_for_lsn.pl
index 398fa8f6d5f..7769a0d80cc 100644
--- a/src/test/recovery/t/049_wait_for_lsn.pl
+++ b/src/test/recovery/t/049_wait_for_lsn.pl
@@ -343,6 +343,14 @@ $node_standby->psql(
stderr => \$stderr);
ok($stderr =~ /timeout cannot be negative/, "get error for negative timeout");
+# Test out of range timeout
+$node_standby->psql(
+ 'postgres',
+ "WAIT FOR LSN '${test_lsn}' WITH (timeout '2147483648ms');",
+ stderr => \$stderr);
+ok($stderr =~ /invalid timeout value: "2147483648ms"/,
+ "get error for out of range timeout");
+
# Test unknown parameter with WITH clause
$node_standby->psql(
'postgres',
@@ -407,6 +415,12 @@ $output = $node_standby->safe_psql(
ok($output eq "timeout",
"WAIT FOR WITH clause returns correct timeout status");
+# Test maximum timeout
+$output = $node_standby->safe_psql(
+ 'postgres', qq[
+ WAIT FOR LSN '${lsn2}' WITH (timeout '2147483647ms', no_throw);]);
+ok($output eq "success", "maximum timeout value is accepted");
+
# Test WITH clause error case - invalid option
$node_standby->psql(
'postgres',