diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index f8ae57901..ef96e70de 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -45,6 +45,17 @@
Create snapshot when listing contents of a path.
+
+
+
+
+
+
+
+
+ Force target-timeline=current when restore type=immediate.
+
+
diff --git a/src/command/restore/restore.c b/src/command/restore/restore.c
index 83b39a5fa..a282ccd4c 100644
--- a/src/command/restore/restore.c
+++ b/src/command/restore/restore.c
@@ -41,9 +41,11 @@ Recovery constants
#define RECOVERY_TARGET_XID "recovery_target_xid"
#define RECOVERY_TARGET_ACTION "recovery_target_action"
-
#define RECOVERY_TARGET_INCLUSIVE "recovery_target_inclusive"
+
#define RECOVERY_TARGET_TIMELINE "recovery_target_timeline"
+#define RECOVERY_TARGET_TIMELINE_CURRENT "current"
+
#define PAUSE_AT_RECOVERY_TARGET "pause_at_recovery_target"
#define STANDBY_MODE "standby_mode"
STRING_STATIC(STANDBY_MODE_STR, STANDBY_MODE);
@@ -1656,9 +1658,22 @@ restoreRecoveryOption(unsigned int pgVersion)
}
}
- // Write recovery_target_timeline
+ // Write recovery_target_timeline if set
if (cfgOptionTest(cfgOptTargetTimeline))
+ {
kvPut(result, VARSTRZ(RECOVERY_TARGET_TIMELINE), VARSTR(cfgOptionStr(cfgOptTargetTimeline)));
+ }
+ // Else explicitly set target timeline to "current" when type=immediate and PostgreSQL >= 12. We do this because
+ // type=immediate means there won't be any actual attempt to change timelines, but if we leave the target timeline as the
+ // default of "latest" then PostgreSQL might fail to restore because it can't reach the "latest" timeline in the repository
+ // from this backup.
+ //
+ // This is really a PostgreSQL bug and will hopefully be addressed there, but we'll handle it here for older versions, at
+ // least until they aren't really seen in the wild any longer.
+ //
+ // PostgreSQL < 12 defaults to "current" (but does not accept "current" as a parameter) so no need set it explicitly.
+ else if (cfgOptionStrId(cfgOptType) == CFGOPTVAL_TYPE_IMMEDIATE && pgVersion >= PG_VERSION_12)
+ kvPut(result, VARSTRZ(RECOVERY_TARGET_TIMELINE), VARSTRDEF(RECOVERY_TARGET_TIMELINE_CURRENT));
// Move to prior context
kvMove(result, memContextPrior());
diff --git a/test/src/module/command/restoreTest.c b/test/src/module/command/restoreTest.c
index eed3b3bf8..fedf4ed46 100644
--- a/test/src/module/command/restoreTest.c
+++ b/test/src/module/command/restoreTest.c
@@ -1599,19 +1599,34 @@ testRun(void)
"check recovery options");
// -------------------------------------------------------------------------------------------------------------------------
- TEST_TITLE("recovery target immediate");
+ TEST_TITLE("recovery target immediate, pg < 12");
argList = strLstDup(argBaseList);
hrnCfgArgRawZ(argList, cfgOptType, "immediate");
HRN_CFG_LOAD(cfgCmdRestore, argList);
TEST_RESULT_STR_Z(
- restoreRecoveryConf(PG_VERSION_94, restoreLabel),
+ restoreRecoveryConf(PG_VERSION_11, restoreLabel),
RECOVERY_SETTING_HEADER
"restore_command = 'my_restore_command'\n"
"recovery_target = 'immediate'\n",
"check recovery options");
+ // -------------------------------------------------------------------------------------------------------------------------
+ TEST_TITLE("recovery target immediate, pg >= 12");
+
+ argList = strLstDup(argBaseList);
+ hrnCfgArgRawZ(argList, cfgOptType, "immediate");
+ HRN_CFG_LOAD(cfgCmdRestore, argList);
+
+ TEST_RESULT_STR_Z(
+ restoreRecoveryConf(PG_VERSION_12, restoreLabel),
+ RECOVERY_SETTING_HEADER
+ "restore_command = 'my_restore_command'\n"
+ "recovery_target = 'immediate'\n"
+ "recovery_target_timeline = 'current'\n",
+ "check recovery options");
+
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("recovery target time with timeline");