pg_dump: Dump subscriptions by default
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 12 Apr 2017 02:02:59 +0000 (22:02 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Thu, 13 Apr 2017 16:01:27 +0000 (12:01 -0400)
Dump subscriptions if the current user is a superuser, otherwise write a
warning and skip them.  Remove the pg_dump option
--include-subscriptions.

Discussion: https://www.postgresql.org/message-id/e4fbfad5-c6ac-fd50-6777-18c84b34eb2f@2ndquadrant.com

doc/src/sgml/logical-replication.sgml
doc/src/sgml/ref/pg_dump.sgml
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_restore.c
src/bin/pg_dump/t/002_pg_dump.pl

index 48db9cd08b7cd6fd33759937528e5ab7c31db340..8c70ce3b6e40403cb50d432f106fbb6b4be16d2c 100644 (file)
   </para>
 
   <para>
-   Subscriptions are not dumped by <command>pg_dump</command> by default, but
-   this can be requested using the command-line
-   option <option>--include-subscriptions</option>.
+   Subscriptions are dumped by <command>pg_dump</command> if the current user
+   is a superuser.  Otherwise a warning is written and subscriptions are
+   skipped, because non-superusers cannot read all subscription information
+   from the <structname>pg_subscription</structname> catalog.
   </para>
 
   <para>
index 4f19b89232173eff92c7ea95efff2d2a24a33925..53b5dd52394ed5c43d13a7954cb5ed43fb939d08 100644 (file)
@@ -755,15 +755,6 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
-     <varlistentry>
-      <term><option>--include-subscriptions</option></term>
-      <listitem>
-       <para>
-        Include logical replication subscriptions in the dump.
-       </para>
-      </listitem>
-     </varlistentry>
-
      <varlistentry>
       <term><option>--inserts</option></term>
       <listitem>
index d82938141e4dbc3408e91a307b608fe72099ccca..1d14b689837268674c8fea4695a998d1efeac399 100644 (file)
@@ -119,7 +119,6 @@ typedef struct _restoreOptions
    bool       *idWanted;       /* array showing which dump IDs to emit */
    int         enable_row_security;
    int         sequence_data;  /* dump sequence data even in schema-only mode */
-   int         include_subscriptions;
    int         binary_upgrade;
 } RestoreOptions;
 
@@ -154,7 +153,6 @@ typedef struct _dumpOptions
    int         outputNoTablespaces;
    int         use_setsessauth;
    int         enable_row_security;
-   int         include_subscriptions;
    int         no_subscription_connect;
 
    /* default, if no "inclusion" switches appear, is to dump everything */
index 79bfbdf1a1db0977d3bc7f5c4246e75cb1956400..b622506a00d504d0ce0856d06305b2e868646aef 100644 (file)
@@ -171,7 +171,6 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
    dopt->include_everything = ropt->include_everything;
    dopt->enable_row_security = ropt->enable_row_security;
    dopt->sequence_data = ropt->sequence_data;
-   dopt->include_subscriptions = ropt->include_subscriptions;
 
    return dopt;
 }
index 5bd4af22c97fc6fa68b7e3d1648f88c274944ced..dcefe975d89287a60367f79634f79db0aa6d276d 100644 (file)
@@ -342,7 +342,6 @@ main(int argc, char **argv)
        {"enable-row-security", no_argument, &dopt.enable_row_security, 1},
        {"exclude-table-data", required_argument, NULL, 4},
        {"if-exists", no_argument, &dopt.if_exists, 1},
-       {"include-subscriptions", no_argument, &dopt.include_subscriptions, 1},
        {"inserts", no_argument, &dopt.dump_inserts, 1},
        {"lock-wait-timeout", required_argument, NULL, 2},
        {"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
@@ -868,7 +867,6 @@ main(int argc, char **argv)
    ropt->include_everything = dopt.include_everything;
    ropt->enable_row_security = dopt.enable_row_security;
    ropt->sequence_data = dopt.sequence_data;
-   ropt->include_subscriptions = dopt.include_subscriptions;
    ropt->binary_upgrade = dopt.binary_upgrade;
 
    if (compressLevel == -1)
@@ -951,7 +949,6 @@ help(const char *progname)
             "                               access to)\n"));
    printf(_("  --exclude-table-data=TABLE   do NOT dump data for the named table(s)\n"));
    printf(_("  --if-exists                  use IF EXISTS when dropping objects\n"));
-   printf(_("  --include-subscriptions      dump logical replication subscriptions\n"));
    printf(_("  --inserts                    dump data as INSERT commands, rather than COPY\n"));
    printf(_("  --no-security-labels         do not dump security label assignments\n"));
    printf(_("  --no-subscription-connect    dump subscriptions so they don't connect on restore\n"));
@@ -3641,6 +3638,22 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
    destroyPQExpBuffer(query);
 }
 
+/*
+ * Is the currently connected user a superuser?
+ */
+static bool
+is_superuser(Archive *fout)
+{
+   ArchiveHandle *AH = (ArchiveHandle *) fout;
+   const char *val;
+
+   val = PQparameterStatus(AH->connection, "is_superuser");
+
+   if (val && strcmp(val, "on") == 0)
+       return true;
+
+   return false;
+}
 
 /*
  * getSubscriptions
@@ -3649,7 +3662,6 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
 void
 getSubscriptions(Archive *fout)
 {
-   DumpOptions *dopt = fout->dopt;
    PQExpBuffer query;
    PGresult   *res;
    SubscriptionInfo *subinfo;
@@ -3664,9 +3676,25 @@ getSubscriptions(Archive *fout)
    int         i,
                ntups;
 
-   if (!dopt->include_subscriptions || fout->remoteVersion < 100000)
+   if (fout->remoteVersion < 100000)
        return;
 
+   if (!is_superuser(fout))
+   {
+       int n;
+
+       res = ExecuteSqlQuery(fout,
+                             "SELECT count(*) FROM pg_subscription "
+                             "WHERE subdbid = (SELECT oid FROM pg_catalog.pg_database"
+                             "                 WHERE datname = current_database())",
+                             PGRES_TUPLES_OK);
+       n = atoi(PQgetvalue(res, 0, 0));
+       if (n > 0)
+           write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
+       PQclear(res);
+       return;
+   }
+
    query = createPQExpBuffer();
 
    resetPQExpBuffer(query);
@@ -3714,6 +3742,9 @@ getSubscriptions(Archive *fout)
        if (strlen(subinfo[i].rolname) == 0)
            write_msg(NULL, "WARNING: owner of subscription \"%s\" appears to be invalid\n",
                      subinfo[i].dobj.name);
+
+       /* Decide whether we want to dump it */
+       selectDumpableObject(&(subinfo[i].dobj), fout);
    }
    PQclear(res);
 
@@ -3735,7 +3766,7 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
    int         npubnames = 0;
    int         i;
 
-   if (dopt->dataOnly)
+   if (!(subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
        return;
 
    delq = createPQExpBuffer();
index 5f61fb2764ea73a7af7b30368d899608a2fe6309..ddd79429b4bd2e9a9f74e0de0322737bbd58e42d 100644 (file)
@@ -67,7 +67,6 @@ main(int argc, char **argv)
    char       *inputFileSpec;
    static int  disable_triggers = 0;
    static int  enable_row_security = 0;
-   static int  include_subscriptions = 0;
    static int  if_exists = 0;
    static int  no_data_for_failed_tables = 0;
    static int  outputNoTablespaces = 0;
@@ -112,7 +111,6 @@ main(int argc, char **argv)
        {"disable-triggers", no_argument, &disable_triggers, 1},
        {"enable-row-security", no_argument, &enable_row_security, 1},
        {"if-exists", no_argument, &if_exists, 1},
-       {"include-subscriptions", no_argument, &include_subscriptions, 1},
        {"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1},
        {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
        {"role", required_argument, NULL, 2},
@@ -353,7 +351,6 @@ main(int argc, char **argv)
 
    opts->disable_triggers = disable_triggers;
    opts->enable_row_security = enable_row_security;
-   opts->include_subscriptions = include_subscriptions;
    opts->noDataForFailedTables = no_data_for_failed_tables;
    opts->noTablespace = outputNoTablespaces;
    opts->use_setsessauth = use_setsessauth;
index cccad04ab622b7a6dbbb65c3ef81ca28f39296fb..1db3767f46dbbfa2e99087e0909e8f10fd4ca4ee 100644 (file)
@@ -43,7 +43,6 @@ my %pgdump_runs = (
            '--format=custom',
            "--file=$tempdir/binary_upgrade.dump",
            '-w',
-           '--include-subscriptions', # XXX Should not be necessary?
            '--schema-only',
            '--binary-upgrade',
            '-d', 'postgres',    # alternative way to specify database
@@ -58,7 +57,6 @@ my %pgdump_runs = (
            'pg_dump',
            '--no-sync',
            "--file=$tempdir/clean.sql",
-           '--include-subscriptions',
            '-c',
            '-d', 'postgres',    # alternative way to specify database
        ], },
@@ -67,7 +65,6 @@ my %pgdump_runs = (
            'pg_dump',
            '--no-sync',
            "--file=$tempdir/clean_if_exists.sql",
-           '--include-subscriptions',
            '-c',
            '--if-exists',
            '--encoding=UTF8',    # no-op, just tests that option is accepted
@@ -85,7 +82,6 @@ my %pgdump_runs = (
            'pg_dump',
            '--no-sync',
            "--file=$tempdir/createdb.sql",
-           '--include-subscriptions',
            '-C',
            '-R',                 # no-op, just for testing
            '-v',
@@ -95,7 +91,6 @@ my %pgdump_runs = (
            'pg_dump',
            '--no-sync',
            "--file=$tempdir/data_only.sql",
-           '--include-subscriptions',
            '-a',
            '--superuser=test_superuser',
            '--disable-triggers',
@@ -253,7 +248,6 @@ my %pgdump_runs = (
    section_pre_data => {
        dump_cmd => [
            'pg_dump',            "--file=$tempdir/section_pre_data.sql",
-           '--include-subscriptions',
            '--section=pre-data', '--no-sync', 'postgres', ], },
    section_data => {
        dump_cmd => [
@@ -271,7 +265,7 @@ my %pgdump_runs = (
    with_oids => {
        dump_cmd => [
            'pg_dump',                       '--oids',
-           '--include-subscriptions',       '--no-sync',
+           '--no-sync',
            "--file=$tempdir/with_oids.sql", 'postgres', ], },);
 
 ###############################################################
@@ -1405,7 +1399,7 @@ my %tests = (
    # catch-all for ALTER ... OWNER (except LARGE OBJECTs and PUBLICATIONs)
    'ALTER ... OWNER commands (except LARGE OBJECTs and PUBLICATIONs)' => {
        all_runs => 0,    # catch-all
-       regexp => qr/^ALTER (?!LARGE OBJECT|PUBLICATION)(.*) OWNER TO .*;/m,
+       regexp => qr/^ALTER (?!LARGE OBJECT|PUBLICATION|SUBSCRIPTION)(.*) OWNER TO .*;/m,
        like   => {},     # use more-specific options above
        unlike => {
            column_inserts           => 1,
@@ -4318,25 +4312,25 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog
            clean                    => 1,
            clean_if_exists          => 1,
            createdb                 => 1,
-           with_oids                => 1, },
-       unlike => {
            defaults                 => 1,
            exclude_test_table_data  => 1,
            exclude_dump_test_schema => 1,
            exclude_test_table       => 1,
-           section_pre_data         => 1,
            no_blobs                 => 1,
            no_privs                 => 1,
            no_owner                 => 1,
+           pg_dumpall_dbprivs       => 1,
+           schema_only              => 1,
+           section_post_data        => 1,
+           with_oids                => 1, },
+       unlike => {
+           section_pre_data         => 1,
            only_dump_test_schema    => 1,
            only_dump_test_table     => 1,
-           pg_dumpall_dbprivs       => 1,
            pg_dumpall_globals       => 1,
            pg_dumpall_globals_clean => 1,
-           schema_only              => 1, # XXX Should be like?
            role                     => 1,
-           section_pre_data         => 1, # XXX Should be like?
-           section_post_data        => 1,
+           section_pre_data         => 1,
            test_schema_plus_blobs   => 1, }, },
 
    'ALTER PUBLICATION pub1 ADD TABLE test_table' => {