@@ -45,6 +45,7 @@ struct CreateSubscriberOptions
45
45
SimpleStringList sub_names ; /* list of subscription names */
46
46
SimpleStringList replslot_names ; /* list of replication slot names */
47
47
int recovery_timeout ; /* stop recovery after this time */
48
+ bool all_dbs ; /* all option */
48
49
SimpleStringList objecttypes_to_remove ; /* list of object types to remove */
49
50
};
50
51
@@ -124,6 +125,8 @@ static void check_and_drop_existing_subscriptions(PGconn *conn,
124
125
const struct LogicalRepInfo * dbinfo );
125
126
static void drop_existing_subscriptions (PGconn * conn , const char * subname ,
126
127
const char * dbname );
128
+ static void get_publisher_databases (struct CreateSubscriberOptions * opt ,
129
+ bool dbnamespecified );
127
130
128
131
#define USEC_PER_SEC 1000000
129
132
#define WAIT_INTERVAL 1 /* 1 second */
@@ -243,6 +246,8 @@ usage(void)
243
246
printf (_ ("Usage:\n" ));
244
247
printf (_ (" %s [OPTION]...\n" ), progname );
245
248
printf (_ ("\nOptions:\n" ));
249
+ printf (_ (" -a, --all create subscriptions for all databases except template\n"
250
+ " databases or databases that don't allow connections\n" ));
246
251
printf (_ (" -d, --database=DBNAME database in which to create a subscription\n" ));
247
252
printf (_ (" -D, --pgdata=DATADIR location for the subscriber data directory\n" ));
248
253
printf (_ (" -n, --dry-run dry run, just show what would be done\n" ));
@@ -1959,11 +1964,65 @@ enable_subscription(PGconn *conn, const struct LogicalRepInfo *dbinfo)
1959
1964
destroyPQExpBuffer (str );
1960
1965
}
1961
1966
1967
+ /*
1968
+ * Fetch a list of all not-template databases from the source server and form
1969
+ * a list such that they appear as if the user has specified multiple
1970
+ * --database options, one for each source database.
1971
+ */
1972
+ static void
1973
+ get_publisher_databases (struct CreateSubscriberOptions * opt ,
1974
+ bool dbnamespecified )
1975
+ {
1976
+ PGconn * conn ;
1977
+ PGresult * res ;
1978
+
1979
+ /* If a database name was specified, just connect to it. */
1980
+ if (dbnamespecified )
1981
+ conn = connect_database (opt -> pub_conninfo_str , true);
1982
+ else
1983
+ {
1984
+ /* Otherwise, try postgres first and then template1. */
1985
+ char * conninfo ;
1986
+
1987
+ conninfo = concat_conninfo_dbname (opt -> pub_conninfo_str , "postgres" );
1988
+ conn = connect_database (conninfo , false);
1989
+ pg_free (conninfo );
1990
+ if (!conn )
1991
+ {
1992
+ conninfo = concat_conninfo_dbname (opt -> pub_conninfo_str , "template1" );
1993
+ conn = connect_database (conninfo , true);
1994
+ pg_free (conninfo );
1995
+ }
1996
+ }
1997
+
1998
+ res = PQexec (conn , "SELECT datname FROM pg_database WHERE datistemplate = false AND datallowconn AND datconnlimit <> -2 ORDER BY 1" );
1999
+ if (PQresultStatus (res ) != PGRES_TUPLES_OK )
2000
+ {
2001
+ pg_log_error ("could not obtain a list of databases: %s" , PQresultErrorMessage (res ));
2002
+ PQclear (res );
2003
+ disconnect_database (conn , true);
2004
+ }
2005
+
2006
+ for (int i = 0 ; i < PQntuples (res ); i ++ )
2007
+ {
2008
+ const char * dbname = PQgetvalue (res , i , 0 );
2009
+
2010
+ simple_string_list_append (& opt -> database_names , dbname );
2011
+
2012
+ /* Increment num_dbs to reflect multiple --database options */
2013
+ num_dbs ++ ;
2014
+ }
2015
+
2016
+ PQclear (res );
2017
+ disconnect_database (conn , false);
2018
+ }
2019
+
1962
2020
int
1963
2021
main (int argc , char * * argv )
1964
2022
{
1965
2023
static struct option long_options [] =
1966
2024
{
2025
+ {"all" , no_argument , NULL , 'a' },
1967
2026
{"database" , required_argument , NULL , 'd' },
1968
2027
{"pgdata" , required_argument , NULL , 'D' },
1969
2028
{"dry-run" , no_argument , NULL , 'n' },
@@ -2034,6 +2093,7 @@ main(int argc, char **argv)
2034
2093
0
2035
2094
};
2036
2095
opt .recovery_timeout = 0 ;
2096
+ opt .all_dbs = false;
2037
2097
2038
2098
/*
2039
2099
* Don't allow it to be run as root. It uses pg_ctl which does not allow
@@ -2051,11 +2111,14 @@ main(int argc, char **argv)
2051
2111
2052
2112
get_restricted_token ();
2053
2113
2054
- while ((c = getopt_long (argc , argv , "d :D:np:P:R:s:t:TU:v" ,
2114
+ while ((c = getopt_long (argc , argv , "ad :D:np:P:R:s:t:TU:v" ,
2055
2115
long_options , & option_index )) != -1 )
2056
2116
{
2057
2117
switch (c )
2058
2118
{
2119
+ case 'a' :
2120
+ opt .all_dbs = true;
2121
+ break ;
2059
2122
case 'd' :
2060
2123
if (!simple_string_list_member (& opt .database_names , optarg ))
2061
2124
{
@@ -2149,6 +2212,28 @@ main(int argc, char **argv)
2149
2212
}
2150
2213
}
2151
2214
2215
+ /* Validate that --all is not used with incompatible options */
2216
+ if (opt .all_dbs )
2217
+ {
2218
+ char * bad_switch = NULL ;
2219
+
2220
+ if (num_dbs > 0 )
2221
+ bad_switch = "--database" ;
2222
+ else if (num_pubs > 0 )
2223
+ bad_switch = "--publication" ;
2224
+ else if (num_replslots > 0 )
2225
+ bad_switch = "--replication-slot" ;
2226
+ else if (num_subs > 0 )
2227
+ bad_switch = "--subscription" ;
2228
+
2229
+ if (bad_switch )
2230
+ {
2231
+ pg_log_error ("%s cannot be used with --all" , bad_switch );
2232
+ pg_log_error_hint ("Try \"%s --help\" for more information." , progname );
2233
+ exit (1 );
2234
+ }
2235
+ }
2236
+
2152
2237
/* Any non-option arguments? */
2153
2238
if (optind < argc )
2154
2239
{
@@ -2202,14 +2287,25 @@ main(int argc, char **argv)
2202
2287
pg_log_info ("validating subscriber connection string" );
2203
2288
sub_base_conninfo = get_sub_conninfo (& opt );
2204
2289
2290
+ /*
2291
+ * Fetch all databases from the source (publisher) and treat them as if
2292
+ * the user specified has multiple --database options, one for each source
2293
+ * database.
2294
+ */
2295
+ if (opt .all_dbs )
2296
+ {
2297
+ bool dbnamespecified = (dbname_conninfo != NULL );
2298
+
2299
+ get_publisher_databases (& opt , dbnamespecified );
2300
+ }
2301
+
2205
2302
if (opt .database_names .head == NULL )
2206
2303
{
2207
2304
pg_log_info ("no database was specified" );
2208
2305
2209
2306
/*
2210
- * If --database option is not provided, try to obtain the dbname from
2211
- * the publisher conninfo. If dbname parameter is not available, error
2212
- * out.
2307
+ * Try to obtain the dbname from the publisher conninfo. If dbname
2308
+ * parameter is not available, error out.
2213
2309
*/
2214
2310
if (dbname_conninfo )
2215
2311
{
0 commit comments