|
|
@ -46,7 +46,7 @@ struct CreateSubscriberOptions |
|
|
|
SimpleStringList replslot_names; /* list of replication slot names */ |
|
|
|
SimpleStringList replslot_names; /* list of replication slot names */ |
|
|
|
int recovery_timeout; /* stop recovery after this time */ |
|
|
|
int recovery_timeout; /* stop recovery after this time */ |
|
|
|
bool all_dbs; /* all option */ |
|
|
|
bool all_dbs; /* all option */ |
|
|
|
SimpleStringList objecttypes_to_remove; /* list of object types to remove */ |
|
|
|
SimpleStringList objecttypes_to_clean; /* list of object types to cleanup */ |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/* per-database publication/subscription info */ |
|
|
|
/* per-database publication/subscription info */ |
|
|
@ -71,8 +71,8 @@ struct LogicalRepInfos |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct LogicalRepInfo *dbinfo; |
|
|
|
struct LogicalRepInfo *dbinfo; |
|
|
|
bool two_phase; /* enable-two-phase option */ |
|
|
|
bool two_phase; /* enable-two-phase option */ |
|
|
|
bits32 objecttypes_to_remove; /* flags indicating which object types
|
|
|
|
bits32 objecttypes_to_clean; /* flags indicating which object types
|
|
|
|
* to remove on subscriber */ |
|
|
|
* to clean up on subscriber */ |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void cleanup_objects_atexit(void); |
|
|
|
static void cleanup_objects_atexit(void); |
|
|
@ -253,13 +253,13 @@ usage(void) |
|
|
|
printf(_(" -n, --dry-run dry run, just show what would be done\n")); |
|
|
|
printf(_(" -n, --dry-run dry run, just show what would be done\n")); |
|
|
|
printf(_(" -p, --subscriber-port=PORT subscriber port number (default %s)\n"), DEFAULT_SUB_PORT); |
|
|
|
printf(_(" -p, --subscriber-port=PORT subscriber port number (default %s)\n"), DEFAULT_SUB_PORT); |
|
|
|
printf(_(" -P, --publisher-server=CONNSTR publisher connection string\n")); |
|
|
|
printf(_(" -P, --publisher-server=CONNSTR publisher connection string\n")); |
|
|
|
printf(_(" -R, --remove=OBJECTTYPE remove all objects of the specified type from specified\n" |
|
|
|
|
|
|
|
" databases on the subscriber; accepts: \"%s\"\n"), "publications"); |
|
|
|
|
|
|
|
printf(_(" -s, --socketdir=DIR socket directory to use (default current dir.)\n")); |
|
|
|
printf(_(" -s, --socketdir=DIR socket directory to use (default current dir.)\n")); |
|
|
|
printf(_(" -t, --recovery-timeout=SECS seconds to wait for recovery to end\n")); |
|
|
|
printf(_(" -t, --recovery-timeout=SECS seconds to wait for recovery to end\n")); |
|
|
|
printf(_(" -T, --enable-two-phase enable two-phase commit for all subscriptions\n")); |
|
|
|
printf(_(" -T, --enable-two-phase enable two-phase commit for all subscriptions\n")); |
|
|
|
printf(_(" -U, --subscriber-username=NAME user name for subscriber connection\n")); |
|
|
|
printf(_(" -U, --subscriber-username=NAME user name for subscriber connection\n")); |
|
|
|
printf(_(" -v, --verbose output verbose messages\n")); |
|
|
|
printf(_(" -v, --verbose output verbose messages\n")); |
|
|
|
|
|
|
|
printf(_(" --clean=OBJECTTYPE drop all objects of the specified type from specified\n" |
|
|
|
|
|
|
|
" databases on the subscriber; accepts: \"%s\"\n"), "publications"); |
|
|
|
printf(_(" --config-file=FILENAME use specified main server configuration\n" |
|
|
|
printf(_(" --config-file=FILENAME use specified main server configuration\n" |
|
|
|
" file when running target cluster\n")); |
|
|
|
" file when running target cluster\n")); |
|
|
|
printf(_(" --publication=NAME publication name\n")); |
|
|
|
printf(_(" --publication=NAME publication name\n")); |
|
|
@ -1730,7 +1730,7 @@ static void |
|
|
|
check_and_drop_publications(PGconn *conn, struct LogicalRepInfo *dbinfo) |
|
|
|
check_and_drop_publications(PGconn *conn, struct LogicalRepInfo *dbinfo) |
|
|
|
{ |
|
|
|
{ |
|
|
|
PGresult *res; |
|
|
|
PGresult *res; |
|
|
|
bool drop_all_pubs = dbinfos.objecttypes_to_remove & OBJECTTYPE_PUBLICATIONS; |
|
|
|
bool drop_all_pubs = dbinfos.objecttypes_to_clean & OBJECTTYPE_PUBLICATIONS; |
|
|
|
|
|
|
|
|
|
|
|
Assert(conn != NULL); |
|
|
|
Assert(conn != NULL); |
|
|
|
|
|
|
|
|
|
|
@ -2026,7 +2026,6 @@ main(int argc, char **argv) |
|
|
|
{"dry-run", no_argument, NULL, 'n'}, |
|
|
|
{"dry-run", no_argument, NULL, 'n'}, |
|
|
|
{"subscriber-port", required_argument, NULL, 'p'}, |
|
|
|
{"subscriber-port", required_argument, NULL, 'p'}, |
|
|
|
{"publisher-server", required_argument, NULL, 'P'}, |
|
|
|
{"publisher-server", required_argument, NULL, 'P'}, |
|
|
|
{"remove", required_argument, NULL, 'R'}, |
|
|
|
|
|
|
|
{"socketdir", required_argument, NULL, 's'}, |
|
|
|
{"socketdir", required_argument, NULL, 's'}, |
|
|
|
{"recovery-timeout", required_argument, NULL, 't'}, |
|
|
|
{"recovery-timeout", required_argument, NULL, 't'}, |
|
|
|
{"enable-two-phase", no_argument, NULL, 'T'}, |
|
|
|
{"enable-two-phase", no_argument, NULL, 'T'}, |
|
|
@ -2038,6 +2037,7 @@ main(int argc, char **argv) |
|
|
|
{"publication", required_argument, NULL, 2}, |
|
|
|
{"publication", required_argument, NULL, 2}, |
|
|
|
{"replication-slot", required_argument, NULL, 3}, |
|
|
|
{"replication-slot", required_argument, NULL, 3}, |
|
|
|
{"subscription", required_argument, NULL, 4}, |
|
|
|
{"subscription", required_argument, NULL, 4}, |
|
|
|
|
|
|
|
{"clean", required_argument, NULL, 5}, |
|
|
|
{NULL, 0, NULL, 0} |
|
|
|
{NULL, 0, NULL, 0} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -2109,7 +2109,7 @@ main(int argc, char **argv) |
|
|
|
|
|
|
|
|
|
|
|
get_restricted_token(); |
|
|
|
get_restricted_token(); |
|
|
|
|
|
|
|
|
|
|
|
while ((c = getopt_long(argc, argv, "ad:D:np:P:R:s:t:TU:v", |
|
|
|
while ((c = getopt_long(argc, argv, "ad:D:np:P:s:t:TU:v", |
|
|
|
long_options, &option_index)) != -1) |
|
|
|
long_options, &option_index)) != -1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
switch (c) |
|
|
|
switch (c) |
|
|
@ -2139,12 +2139,6 @@ main(int argc, char **argv) |
|
|
|
case 'P': |
|
|
|
case 'P': |
|
|
|
opt.pub_conninfo_str = pg_strdup(optarg); |
|
|
|
opt.pub_conninfo_str = pg_strdup(optarg); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case 'R': |
|
|
|
|
|
|
|
if (!simple_string_list_member(&opt.objecttypes_to_remove, optarg)) |
|
|
|
|
|
|
|
simple_string_list_append(&opt.objecttypes_to_remove, optarg); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
pg_fatal("object type \"%s\" specified more than once for -R/--remove", optarg); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 's': |
|
|
|
case 's': |
|
|
|
opt.socket_dir = pg_strdup(optarg); |
|
|
|
opt.socket_dir = pg_strdup(optarg); |
|
|
|
canonicalize_path(opt.socket_dir); |
|
|
|
canonicalize_path(opt.socket_dir); |
|
|
@ -2191,6 +2185,12 @@ main(int argc, char **argv) |
|
|
|
else |
|
|
|
else |
|
|
|
pg_fatal("subscription \"%s\" specified more than once for --subscription", optarg); |
|
|
|
pg_fatal("subscription \"%s\" specified more than once for --subscription", optarg); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case 5: |
|
|
|
|
|
|
|
if (!simple_string_list_member(&opt.objecttypes_to_clean, optarg)) |
|
|
|
|
|
|
|
simple_string_list_append(&opt.objecttypes_to_clean, optarg); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
pg_fatal("object type \"%s\" specified more than once for --clean", optarg); |
|
|
|
|
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
/* getopt_long already emitted a complaint */ |
|
|
|
/* getopt_long already emitted a complaint */ |
|
|
|
pg_log_error_hint("Try \"%s --help\" for more information.", progname); |
|
|
|
pg_log_error_hint("Try \"%s --help\" for more information.", progname); |
|
|
@ -2334,13 +2334,13 @@ main(int argc, char **argv) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Verify the object types specified for removal from the subscriber */ |
|
|
|
/* Verify the object types specified for removal from the subscriber */ |
|
|
|
for (SimpleStringListCell *cell = opt.objecttypes_to_remove.head; cell; cell = cell->next) |
|
|
|
for (SimpleStringListCell *cell = opt.objecttypes_to_clean.head; cell; cell = cell->next) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (pg_strcasecmp(cell->val, "publications") == 0) |
|
|
|
if (pg_strcasecmp(cell->val, "publications") == 0) |
|
|
|
dbinfos.objecttypes_to_remove |= OBJECTTYPE_PUBLICATIONS; |
|
|
|
dbinfos.objecttypes_to_clean |= OBJECTTYPE_PUBLICATIONS; |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
pg_log_error("invalid object type \"%s\" specified for -R/--remove", cell->val); |
|
|
|
pg_log_error("invalid object type \"%s\" specified for --clean", cell->val); |
|
|
|
pg_log_error_hint("The valid value is: \"%s\"", "publications"); |
|
|
|
pg_log_error_hint("The valid value is: \"%s\"", "publications"); |
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|