@@ -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 with connection restrictions\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,67 @@ 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.
1969
+ * Internally, this is treated as if the user specified multiple --database
1970
+ * 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
+
2000
+ /* Check for errors during query execution */
2001
+ if (PQresultStatus (res ) != PGRES_TUPLES_OK )
2002
+ {
2003
+ pg_log_error ("could not obtain a list of databases: %s" , PQresultErrorMessage (res ));
2004
+ PQclear (res );
2005
+ disconnect_database (conn , true);
2006
+ }
2007
+
2008
+ for (int i = 0 ; i < PQntuples (res ); i ++ )
2009
+ {
2010
+ const char * dbname = PQgetvalue (res , i , 0 );
2011
+
2012
+ simple_string_list_append (& opt -> database_names , dbname );
2013
+
2014
+ /* Increment num_dbs to reflect multiple --database options */
2015
+ num_dbs ++ ;
2016
+ }
2017
+
2018
+ PQclear (res );
2019
+ disconnect_database (conn , false);
2020
+ }
2021
+
1962
2022
int
1963
2023
main (int argc , char * * argv )
1964
2024
{
1965
2025
static struct option long_options [] =
1966
2026
{
2027
+ {"all" , no_argument , NULL , 'a' },
1967
2028
{"database" , required_argument , NULL , 'd' },
1968
2029
{"pgdata" , required_argument , NULL , 'D' },
1969
2030
{"dry-run" , no_argument , NULL , 'n' },
@@ -2034,6 +2095,7 @@ main(int argc, char **argv)
2034
2095
0
2035
2096
};
2036
2097
opt .recovery_timeout = 0 ;
2098
+ opt .all_dbs = false;
2037
2099
2038
2100
/*
2039
2101
* Don't allow it to be run as root. It uses pg_ctl which does not allow
@@ -2051,11 +2113,14 @@ main(int argc, char **argv)
2051
2113
2052
2114
get_restricted_token ();
2053
2115
2054
- while ((c = getopt_long (argc , argv , "d :D:np:P:R:s:t:TU:v" ,
2116
+ while ((c = getopt_long (argc , argv , "ad :D:np:P:R:s:t:TU:v" ,
2055
2117
long_options , & option_index )) != -1 )
2056
2118
{
2057
2119
switch (c )
2058
2120
{
2121
+ case 'a' :
2122
+ opt .all_dbs = true;
2123
+ break ;
2059
2124
case 'd' :
2060
2125
if (!simple_string_list_member (& opt .database_names , optarg ))
2061
2126
{
@@ -2149,6 +2214,28 @@ main(int argc, char **argv)
2149
2214
}
2150
2215
}
2151
2216
2217
+ /* Validate that --all is not used with incompatible options */
2218
+ if (opt .all_dbs )
2219
+ {
2220
+ char * bad_switch = NULL ;
2221
+
2222
+ if (num_dbs > 0 )
2223
+ bad_switch = "--database" ;
2224
+ else if (num_pubs > 0 )
2225
+ bad_switch = "--publication" ;
2226
+ else if (num_replslots > 0 )
2227
+ bad_switch = "--replication-slot" ;
2228
+ else if (num_subs > 0 )
2229
+ bad_switch = "--subscription" ;
2230
+
2231
+ if (bad_switch )
2232
+ {
2233
+ pg_log_error ("%s cannot be used with --all" , bad_switch );
2234
+ pg_log_error_hint ("Try \"%s --help\" for more information." , progname );
2235
+ exit (1 );
2236
+ }
2237
+ }
2238
+
2152
2239
/* Any non-option arguments? */
2153
2240
if (optind < argc )
2154
2241
{
@@ -2202,14 +2289,25 @@ main(int argc, char **argv)
2202
2289
pg_log_info ("validating subscriber connection string" );
2203
2290
sub_base_conninfo = get_sub_conninfo (& opt );
2204
2291
2292
+ /*
2293
+ * Fetch all databases from the source (publisher) if --all is specified.
2294
+ * This is treated as if the user specified multiple --database options,
2295
+ * one for each source database.
2296
+ */
2297
+ if (opt .all_dbs )
2298
+ {
2299
+ bool dbnamespecified = (dbname_conninfo != NULL );
2300
+
2301
+ get_publisher_databases (& opt , dbnamespecified );
2302
+ }
2303
+
2205
2304
if (opt .database_names .head == NULL )
2206
2305
{
2207
2306
pg_log_info ("no database was specified" );
2208
2307
2209
2308
/*
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.
2309
+ * Try to obtain the dbname from the publisher conninfo. If dbname
2310
+ * parameter is not available, error out.
2213
2311
*/
2214
2312
if (dbname_conninfo )
2215
2313
{
0 commit comments