From c092a3cf55085725924417af1bb5c11dbcba31e2 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 10 Feb 2021 13:02:06 +1100 Subject: [PATCH v2] ReplicationSlotDropAtPubNode detect slot does not exist. A new sqlstate member was added to WalRcvExecResult. This allows walrcv_exec calling code to know the detailed cause of any error. Specifically, here it means the ReplicationSlotDropAtPubNode function can now identify the "slot does not exist error", and so can handle "missing_ok" more correctly. Also, minor updates to PG docs now that ALTER SUBSCRIPTION may give ERROR instead of WARNING. --- doc/src/sgml/ref/alter_subscription.sgml | 7 +------ src/backend/commands/subscriptioncmds.c | 3 ++- src/backend/replication/libpqwalreceiver/libpqwalreceiver.c | 8 ++++++++ src/include/replication/walreceiver.h | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml index 1ca2437..bd81ea4 100644 --- a/doc/src/sgml/ref/alter_subscription.sgml +++ b/doc/src/sgml/ref/alter_subscription.sgml @@ -55,12 +55,7 @@ ALTER SUBSCRIPTION name RENAME TO < any. It is necessary to remove tablesync slots so that the resources allocated for the subscription on the remote host are released. If due to network breakdown or some other error, PostgreSQL - is unable to remove the slots, a WARNING will be reported. The user needs to - manually remove such slots later or the - should be configured on the - remote host as otherwise, they will continue to reserve WAL and might - eventually cause the disk to fill up. See also - . + is unable to remove the slots, an ERROR will be reported. diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 8046153..ff295c7 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -1314,7 +1314,8 @@ ReplicationSlotDropAtPubNode(WalReceiverConn *wrconn, char *slotname, bool missi (errmsg("dropped replication slot \"%s\" on publisher", slotname))); } - else if (res->status == WALRCV_ERROR && missing_ok) + else if (res->status == WALRCV_ERROR && + missing_ok && res->sqlstate == ERRCODE_UNDEFINED_OBJECT) { /* WARNING. Error, but missing_ok = true. */ ereport(WARNING, diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index e958274..7714696 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -982,6 +982,7 @@ libpqrcv_exec(WalReceiverConn *conn, const char *query, { PGresult *pgres = NULL; WalRcvExecResult *walres = palloc0(sizeof(WalRcvExecResult)); + char *diag_sqlstate; if (MyDatabaseId == InvalidOid) ereport(ERROR, @@ -1025,6 +1026,13 @@ libpqrcv_exec(WalReceiverConn *conn, const char *query, case PGRES_BAD_RESPONSE: walres->status = WALRCV_ERROR; walres->err = pchomp(PQerrorMessage(conn->streamConn)); + diag_sqlstate = PQresultErrorField(pgres, PG_DIAG_SQLSTATE); + if (diag_sqlstate) + walres->sqlstate = MAKE_SQLSTATE(diag_sqlstate[0], + diag_sqlstate[1], + diag_sqlstate[2], + diag_sqlstate[3], + diag_sqlstate[4]); break; } diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h index 4313f51..a97a59a 100644 --- a/src/include/replication/walreceiver.h +++ b/src/include/replication/walreceiver.h @@ -210,6 +210,7 @@ typedef enum typedef struct WalRcvExecResult { WalRcvExecStatus status; + int sqlstate; char *err; Tuplestorestate *tuplestore; TupleDesc tupledesc; -- 1.8.3.1