Skip to content

Commit ff27db5

Browse files
committed
Optionally don't error out due to preexisting slots in commandline utilities.
pg_receivexlog and pg_recvlogical error out when --create-slot is specified and a slot with the same name already exists. In some cases, especially with pg_receivexlog, that's rather annoying and requires additional scripting. Backpatch to 9.5 as slot control functions have newly been added to pg_receivexlog, and there doesn't seem much point leaving it in a less useful state. Discussion: 20150619144755.GG29350@alap3.anarazel.de
1 parent 0a0fe2f commit ff27db5

File tree

6 files changed

+58
-30
lines changed

6 files changed

+58
-30
lines changed

doc/src/sgml/ref/pg_receivexlog.sgml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ PostgreSQL documentation
9292
</listitem>
9393
</varlistentry>
9494

95+
<varlistentry>
96+
<term><option>--if-not-exists</option></term>
97+
<listitem>
98+
<para>
99+
Do not not error out when <option>--create-slot</option> is specified
100+
and a slot with the specified name already exists.
101+
</para>
102+
</listitem>
103+
</varlistentry>
104+
95105
<varlistentry>
96106
<term><option>-n</option></term>
97107
<term><option>--no-loop</option></term>

doc/src/sgml/ref/pg_recvlogical.sgml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ PostgreSQL documentation
154154
</listitem>
155155
</varlistentry>
156156

157+
<varlistentry>
158+
<term><option>--if-not-exists</option></term>
159+
<listitem>
160+
<para>
161+
Do not not error out when <option>--create-slot</option> is specified
162+
and a slot with the specified name already exists.
163+
</para>
164+
</listitem>
165+
</varlistentry>
166+
157167
<varlistentry>
158168
<term><option>-n</option></term>
159169
<term><option>--no-loop</option></term>

src/bin/pg_basebackup/pg_receivexlog.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static int noloop = 0;
3838
static int standby_message_timeout = 10 * 1000; /* 10 sec = default */
3939
static volatile bool time_to_abort = false;
4040
static bool do_create_slot = false;
41+
static bool slot_exists_ok = false;
4142
static bool do_drop_slot = false;
4243
static bool synchronous = false;
4344

@@ -66,6 +67,7 @@ usage(void)
6667
printf(_(" %s [OPTION]...\n"), progname);
6768
printf(_("\nOptions:\n"));
6869
printf(_(" -D, --directory=DIR receive transaction log files into this directory\n"));
70+
printf(_(" --if-not-exists do not treat naming conflicts as an error when creating a slot\n"));
6971
printf(_(" -n, --no-loop do not loop on connection lost\n"));
7072
printf(_(" -s, --status-interval=SECS\n"
7173
" time between status packets sent to server (default: %d)\n"), (standby_message_timeout / 1000));
@@ -371,7 +373,8 @@ main(int argc, char **argv)
371373
/* action */
372374
{"create-slot", no_argument, NULL, 1},
373375
{"drop-slot", no_argument, NULL, 2},
374-
{"synchronous", no_argument, NULL, 3},
376+
{"if-not-exists", no_argument, NULL, 3},
377+
{"synchronous", no_argument, NULL, 4},
375378
{NULL, 0, NULL, 0}
376379
};
377380

@@ -455,6 +458,9 @@ main(int argc, char **argv)
455458
do_drop_slot = true;
456459
break;
457460
case 3:
461+
slot_exists_ok = true;
462+
break;
463+
case 4:
458464
synchronous = true;
459465
break;
460466
default:
@@ -575,7 +581,8 @@ main(int argc, char **argv)
575581
_("%s: creating replication slot \"%s\"\n"),
576582
progname, replication_slot);
577583

578-
if (!CreateReplicationSlot(conn, replication_slot, NULL, NULL, true))
584+
if (!CreateReplicationSlot(conn, replication_slot, NULL, true,
585+
slot_exists_ok))
579586
disconnect_and_exit(1);
580587
}
581588

src/bin/pg_basebackup/pg_recvlogical.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static int standby_message_timeout = 10 * 1000; /* 10 sec = default */
3838
static int fsync_interval = 10 * 1000; /* 10 sec = default */
3939
static XLogRecPtr startpos = InvalidXLogRecPtr;
4040
static bool do_create_slot = false;
41+
static bool slot_exists_ok = false;
4142
static bool do_start_slot = false;
4243
static bool do_drop_slot = false;
4344

@@ -75,6 +76,7 @@ usage(void)
7576
printf(_(" -f, --file=FILE receive log into this file, - for stdout\n"));
7677
printf(_(" -F --fsync-interval=SECS\n"
7778
" time between fsyncs to the output file (default: %d)\n"), (fsync_interval / 1000));
79+
printf(_(" --if-not-exists do not treat naming conflicts as an error when creating a slot\n"));
7880
printf(_(" -I, --startpos=LSN where in an existing slot should the streaming start\n"));
7981
printf(_(" -n, --no-loop do not loop on connection lost\n"));
8082
printf(_(" -o, --option=NAME[=VALUE]\n"
@@ -633,6 +635,7 @@ main(int argc, char **argv)
633635
{"create-slot", no_argument, NULL, 1},
634636
{"start", no_argument, NULL, 2},
635637
{"drop-slot", no_argument, NULL, 3},
638+
{"if-not-exists", no_argument, NULL, 4},
636639
{NULL, 0, NULL, 0}
637640
};
638641
int c;
@@ -764,6 +767,9 @@ main(int argc, char **argv)
764767
case 3:
765768
do_drop_slot = true;
766769
break;
770+
case 4:
771+
slot_exists_ok = true;
772+
break;
767773

768774
default:
769775

@@ -891,8 +897,9 @@ main(int argc, char **argv)
891897
progname, replication_slot);
892898

893899
if (!CreateReplicationSlot(conn, replication_slot, plugin,
894-
&startpos, false))
900+
false, slot_exists_ok))
895901
disconnect_and_exit(1);
902+
startpos = InvalidXLogRecPtr;
896903
}
897904

898905
if (!do_start_slot)

src/bin/pg_basebackup/streamutil.c

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "common/fe_memutils.h"
3232
#include "datatype/timestamp.h"
3333

34+
#define ERRCODE_DUPLICATE_OBJECT "42710"
35+
3436
const char *progname;
3537
char *connection_string = NULL;
3638
char *dbhost = NULL;
@@ -314,7 +316,7 @@ RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli,
314316
*/
315317
bool
316318
CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin,
317-
XLogRecPtr *startpos, bool is_physical)
319+
bool is_physical, bool slot_exists_ok)
318320
{
319321
PQExpBuffer query;
320322
PGresult *res;
@@ -336,12 +338,23 @@ CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin,
336338
res = PQexec(conn, query->data);
337339
if (PQresultStatus(res) != PGRES_TUPLES_OK)
338340
{
339-
fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
340-
progname, query->data, PQerrorMessage(conn));
341+
const char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
341342

342-
destroyPQExpBuffer(query);
343-
PQclear(res);
344-
return false;
343+
if (slot_exists_ok && strcmp(sqlstate, ERRCODE_DUPLICATE_OBJECT) == 0)
344+
{
345+
destroyPQExpBuffer(query);
346+
PQclear(res);
347+
return true;
348+
}
349+
else
350+
{
351+
fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
352+
progname, query->data, PQerrorMessage(conn));
353+
354+
destroyPQExpBuffer(query);
355+
PQclear(res);
356+
return false;
357+
}
345358
}
346359

347360
if (PQntuples(res) != 1 || PQnfields(res) != 4)
@@ -356,25 +369,6 @@ CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin,
356369
return false;
357370
}
358371

359-
/* Get LSN start position if necessary */
360-
if (startpos != NULL)
361-
{
362-
uint32 hi,
363-
lo;
364-
365-
if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &hi, &lo) != 2)
366-
{
367-
fprintf(stderr,
368-
_("%s: could not parse transaction log location \"%s\"\n"),
369-
progname, PQgetvalue(res, 0, 1));
370-
371-
destroyPQExpBuffer(query);
372-
PQclear(res);
373-
return false;
374-
}
375-
*startpos = ((uint64) hi) << 32 | lo;
376-
}
377-
378372
destroyPQExpBuffer(query);
379373
PQclear(res);
380374
return true;

src/bin/pg_basebackup/streamutil.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ extern PGconn *GetConnection(void);
3232

3333
/* Replication commands */
3434
extern bool CreateReplicationSlot(PGconn *conn, const char *slot_name,
35-
const char *plugin, XLogRecPtr *startpos,
36-
bool is_physical);
35+
const char *plugin, bool is_physical,
36+
bool slot_exists_ok);
3737
extern bool DropReplicationSlot(PGconn *conn, const char *slot_name);
3838
extern bool RunIdentifySystem(PGconn *conn, char **sysid,
3939
TimeLineID *starttli,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy