diff --git a/doc/src/sgml/ref/pg_recvlogical.sgml b/doc/src/sgml/ref/pg_recvlogical.sgml
index eaea94d..2c638d3 100644
--- a/doc/src/sgml/ref/pg_recvlogical.sgml
+++ b/doc/src/sgml/ref/pg_recvlogical.sgml
@@ -199,6 +199,16 @@ PostgreSQL documentation
+
+
+
+ Do not error out when or
+
+
+
+
diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c
index 370d871..ace5372 100644
--- a/src/bin/pg_basebackup/pg_receivewal.c
+++ b/src/bin/pg_basebackup/pg_receivewal.c
@@ -686,7 +686,7 @@ main(int argc, char **argv)
_("%s: dropping replication slot \"%s\"\n"),
progname, replication_slot);
- if (!DropReplicationSlot(conn, replication_slot))
+ if (!DropReplicationSlot(conn, replication_slot, false))
disconnect_and_exit(1);
disconnect_and_exit(0);
}
diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
index 6b081bd..46ea5a3 100644
--- a/src/bin/pg_basebackup/pg_recvlogical.c
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -33,6 +33,8 @@
/* Time to sleep between reconnection attempts */
#define RECONNECT_SLEEP_TIME 5
+#define ERRCODE_UNKNOWN_OBJECT "42704"
+
/* Global Options */
static char *outfile = NULL;
static int verbose = 0;
@@ -43,6 +45,7 @@ static XLogRecPtr startpos = InvalidXLogRecPtr;
static XLogRecPtr endpos = InvalidXLogRecPtr;
static bool do_create_slot = false;
static bool slot_exists_ok = false;
+static bool slot_not_exists_ok = false;
static bool do_start_slot = false;
static bool do_drop_slot = false;
static char *replication_slot = NULL;
@@ -84,6 +87,7 @@ usage(void)
printf(_(" -f, --file=FILE receive log into this file, - for stdout\n"));
printf(_(" -F --fsync-interval=SECS\n"
" time between fsyncs to the output file (default: %d)\n"), (fsync_interval / 1000));
+ printf(_(" --if-exists do not error if slot does not exist\n"));
printf(_(" --if-not-exists do not error if slot already exists when creating a slot\n"));
printf(_(" -I, --startpos=LSN where in an existing slot should the streaming start\n"));
printf(_(" -E, --endpos=LSN exit after receiving the specified LSN\n"));
@@ -267,6 +271,17 @@ StreamLogicalLog(void)
res = PQexec(conn, query->data);
if (PQresultStatus(res) != PGRES_COPY_BOTH)
{
+ const char* sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+
+ if (slot_not_exists_ok &&
+ sqlstate &&
+ strcmp(sqlstate, ERRCODE_UNKNOWN_OBJECT) == 0)
+ {
+ destroyPQExpBuffer(query);
+ PQclear(res);
+ disconnect_and_exit(0);
+ }
+
fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
progname, query->data, PQresultErrorMessage(res));
PQclear(res);
@@ -699,6 +716,7 @@ main(int argc, char **argv)
{"start", no_argument, NULL, 2},
{"drop-slot", no_argument, NULL, 3},
{"if-not-exists", no_argument, NULL, 4},
+ {"if-exists", no_argument, NULL, 5},
{NULL, 0, NULL, 0}
};
int c;
@@ -843,6 +861,9 @@ main(int argc, char **argv)
case 4:
slot_exists_ok = true;
break;
+ case 5:
+ slot_not_exists_ok = true;
+ break;
default:
@@ -903,6 +924,14 @@ main(int argc, char **argv)
exit(1);
}
+ if (do_create_slot && slot_not_exists_ok)
+ {
+ fprintf(stderr, _("%s: cannot use --create-slot with --if-exists\n"), progname);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+ progname);
+ exit(1);
+ }
+
if (do_drop_slot && (do_create_slot || do_start_slot))
{
fprintf(stderr, _("%s: cannot use --create-slot or --start together with --drop-slot\n"), progname);
@@ -967,7 +996,7 @@ main(int argc, char **argv)
_("%s: dropping replication slot \"%s\"\n"),
progname, replication_slot);
- if (!DropReplicationSlot(conn, replication_slot))
+ if (!DropReplicationSlot(conn, replication_slot, slot_not_exists_ok))
disconnect_and_exit(1);
}
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 7ea3b0f..84dd135 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -29,6 +29,7 @@
#include "datatype/timestamp.h"
#define ERRCODE_DUPLICATE_OBJECT "42710"
+#define ERRCODE_UNKNOWN_OBJECT "42704"
const char *progname;
char *connection_string = NULL;
@@ -391,7 +392,7 @@ CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin,
* returns true in case of success.
*/
bool
-DropReplicationSlot(PGconn *conn, const char *slot_name)
+DropReplicationSlot(PGconn *conn, const char *slot_name, bool slot_not_exists_ok)
{
PQExpBuffer query;
PGresult *res;
@@ -406,6 +407,17 @@ DropReplicationSlot(PGconn *conn, const char *slot_name)
res = PQexec(conn, query->data);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
+ const char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+
+ if (slot_not_exists_ok &&
+ sqlstate &&
+ strcmp(sqlstate, ERRCODE_UNKNOWN_OBJECT) == 0)
+ {
+ destroyPQExpBuffer(query);
+ PQclear(res);
+ return true;
+ }
+
fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
progname, query->data, PQerrorMessage(conn));
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 460dcb5..845e48a 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -34,7 +34,8 @@ extern PGconn *GetConnection(void);
extern bool CreateReplicationSlot(PGconn *conn, const char *slot_name,
const char *plugin, bool is_physical,
bool slot_exists_ok);
-extern bool DropReplicationSlot(PGconn *conn, const char *slot_name);
+extern bool DropReplicationSlot(PGconn *conn, const char *slot_name,
+ bool slot_not_exists_ok);
extern bool RunIdentifySystem(PGconn *conn, char **sysid,
TimeLineID *starttli,
XLogRecPtr *startpos,