Skip to content

Commit 4397abd

Browse files
committed
Prevent use of invalidated logical slot in CreateDecodingContext()
Previously we had checks for this in multiple places. Support for logical decoding on standbys will add other forms of invalidation, making it worth while to centralize the checks. This slightly changes the error message for both the walsender and SQL interface. Particularly the SQL interface error was inaccurate, as the "This slot has never previously reserved WAL" portion was unreachable. Reviewed-by: "Drouvot, Bertrand" <bertranddrouvot.pg@gmail.com> Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Discussion: https://postgr.es/m/20230407075009.igg7be27ha2htkbt@awork3.anarazel.de
1 parent 15f8203 commit 4397abd

File tree

3 files changed

+16
-20
lines changed

3 files changed

+16
-20
lines changed

src/backend/replication/logical/logical.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,22 @@ CreateDecodingContext(XLogRecPtr start_lsn,
518518
errmsg("replication slot \"%s\" was not created in this database",
519519
NameStr(slot->data.name))));
520520

521+
/*
522+
* Check if slot has been invalidated due to max_slot_wal_keep_size. Avoid
523+
* "cannot get changes" wording in this errmsg because that'd be
524+
* confusingly ambiguous about no changes being available when called from
525+
* pg_logical_slot_get_changes_guts().
526+
*/
527+
if (MyReplicationSlot->data.invalidated == RS_INVAL_WAL_REMOVED)
528+
ereport(ERROR,
529+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
530+
errmsg("can no longer get changes from replication slot \"%s\"",
531+
NameStr(MyReplicationSlot->data.name)),
532+
errdetail("This slot has been invalidated because it exceeded the maximum reserved size.")));
533+
534+
Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE);
535+
Assert(MyReplicationSlot->data.restart_lsn != InvalidXLogRecPtr);
536+
521537
if (start_lsn == InvalidXLogRecPtr)
522538
{
523539
/* continue from last position */

src/backend/replication/logical/logicalfuncs.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -214,19 +214,6 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
214214
LogicalOutputPrepareWrite,
215215
LogicalOutputWrite, NULL);
216216

217-
/*
218-
* After the sanity checks in CreateDecodingContext, make sure the
219-
* restart_lsn is valid. Avoid "cannot get changes" wording in this
220-
* errmsg because that'd be confusingly ambiguous about no changes
221-
* being available.
222-
*/
223-
if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
224-
ereport(ERROR,
225-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
226-
errmsg("can no longer get changes from replication slot \"%s\"",
227-
NameStr(*name)),
228-
errdetail("This slot has never previously reserved WAL, or it has been invalidated.")));
229-
230217
MemoryContextSwitchTo(oldcontext);
231218

232219
/*

src/backend/replication/walsender.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,13 +1253,6 @@ StartLogicalReplication(StartReplicationCmd *cmd)
12531253

12541254
ReplicationSlotAcquire(cmd->slotname, true);
12551255

1256-
if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
1257-
ereport(ERROR,
1258-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1259-
errmsg("cannot read from logical replication slot \"%s\"",
1260-
cmd->slotname),
1261-
errdetail("This slot has been invalidated because it exceeded the maximum reserved size.")));
1262-
12631256
/*
12641257
* Force a disconnect, so that the decoding code doesn't need to care
12651258
* about an eventual switch from running in recovery, to running in a

0 commit comments

Comments
 (0)