pg_dump: Dump subscriptions by default
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
This commit is contained in:
parent
73c1748d83
commit
c31671f9b5
@ -167,9 +167,10 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Subscriptions are not dumped by <command>pg_dump</command> by default, but
|
Subscriptions are dumped by <command>pg_dump</command> if the current user
|
||||||
this can be requested using the command-line
|
is a superuser. Otherwise a warning is written and subscriptions are
|
||||||
option <option>--include-subscriptions</option>.
|
skipped, because non-superusers cannot read all subscription information
|
||||||
|
from the <structname>pg_subscription</structname> catalog.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -755,15 +755,6 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--include-subscriptions</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Include logical replication subscriptions in the dump.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--inserts</option></term>
|
<term><option>--inserts</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -119,7 +119,6 @@ typedef struct _restoreOptions
|
|||||||
bool *idWanted; /* array showing which dump IDs to emit */
|
bool *idWanted; /* array showing which dump IDs to emit */
|
||||||
int enable_row_security;
|
int enable_row_security;
|
||||||
int sequence_data; /* dump sequence data even in schema-only mode */
|
int sequence_data; /* dump sequence data even in schema-only mode */
|
||||||
int include_subscriptions;
|
|
||||||
int binary_upgrade;
|
int binary_upgrade;
|
||||||
} RestoreOptions;
|
} RestoreOptions;
|
||||||
|
|
||||||
@ -154,7 +153,6 @@ typedef struct _dumpOptions
|
|||||||
int outputNoTablespaces;
|
int outputNoTablespaces;
|
||||||
int use_setsessauth;
|
int use_setsessauth;
|
||||||
int enable_row_security;
|
int enable_row_security;
|
||||||
int include_subscriptions;
|
|
||||||
int no_subscription_connect;
|
int no_subscription_connect;
|
||||||
|
|
||||||
/* default, if no "inclusion" switches appear, is to dump everything */
|
/* default, if no "inclusion" switches appear, is to dump everything */
|
||||||
|
@ -171,7 +171,6 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
|
|||||||
dopt->include_everything = ropt->include_everything;
|
dopt->include_everything = ropt->include_everything;
|
||||||
dopt->enable_row_security = ropt->enable_row_security;
|
dopt->enable_row_security = ropt->enable_row_security;
|
||||||
dopt->sequence_data = ropt->sequence_data;
|
dopt->sequence_data = ropt->sequence_data;
|
||||||
dopt->include_subscriptions = ropt->include_subscriptions;
|
|
||||||
|
|
||||||
return dopt;
|
return dopt;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,6 @@ main(int argc, char **argv)
|
|||||||
{"enable-row-security", no_argument, &dopt.enable_row_security, 1},
|
{"enable-row-security", no_argument, &dopt.enable_row_security, 1},
|
||||||
{"exclude-table-data", required_argument, NULL, 4},
|
{"exclude-table-data", required_argument, NULL, 4},
|
||||||
{"if-exists", no_argument, &dopt.if_exists, 1},
|
{"if-exists", no_argument, &dopt.if_exists, 1},
|
||||||
{"include-subscriptions", no_argument, &dopt.include_subscriptions, 1},
|
|
||||||
{"inserts", no_argument, &dopt.dump_inserts, 1},
|
{"inserts", no_argument, &dopt.dump_inserts, 1},
|
||||||
{"lock-wait-timeout", required_argument, NULL, 2},
|
{"lock-wait-timeout", required_argument, NULL, 2},
|
||||||
{"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
|
{"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
|
||||||
@ -868,7 +867,6 @@ main(int argc, char **argv)
|
|||||||
ropt->include_everything = dopt.include_everything;
|
ropt->include_everything = dopt.include_everything;
|
||||||
ropt->enable_row_security = dopt.enable_row_security;
|
ropt->enable_row_security = dopt.enable_row_security;
|
||||||
ropt->sequence_data = dopt.sequence_data;
|
ropt->sequence_data = dopt.sequence_data;
|
||||||
ropt->include_subscriptions = dopt.include_subscriptions;
|
|
||||||
ropt->binary_upgrade = dopt.binary_upgrade;
|
ropt->binary_upgrade = dopt.binary_upgrade;
|
||||||
|
|
||||||
if (compressLevel == -1)
|
if (compressLevel == -1)
|
||||||
@ -951,7 +949,6 @@ help(const char *progname)
|
|||||||
" access to)\n"));
|
" access to)\n"));
|
||||||
printf(_(" --exclude-table-data=TABLE do NOT dump data for the named table(s)\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(_(" --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(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
|
||||||
printf(_(" --no-security-labels do not dump security label assignments\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"));
|
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);
|
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
|
* getSubscriptions
|
||||||
@ -3649,7 +3662,6 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
|
|||||||
void
|
void
|
||||||
getSubscriptions(Archive *fout)
|
getSubscriptions(Archive *fout)
|
||||||
{
|
{
|
||||||
DumpOptions *dopt = fout->dopt;
|
|
||||||
PQExpBuffer query;
|
PQExpBuffer query;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
SubscriptionInfo *subinfo;
|
SubscriptionInfo *subinfo;
|
||||||
@ -3664,9 +3676,25 @@ getSubscriptions(Archive *fout)
|
|||||||
int i,
|
int i,
|
||||||
ntups;
|
ntups;
|
||||||
|
|
||||||
if (!dopt->include_subscriptions || fout->remoteVersion < 100000)
|
if (fout->remoteVersion < 100000)
|
||||||
return;
|
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();
|
query = createPQExpBuffer();
|
||||||
|
|
||||||
resetPQExpBuffer(query);
|
resetPQExpBuffer(query);
|
||||||
@ -3714,6 +3742,9 @@ getSubscriptions(Archive *fout)
|
|||||||
if (strlen(subinfo[i].rolname) == 0)
|
if (strlen(subinfo[i].rolname) == 0)
|
||||||
write_msg(NULL, "WARNING: owner of subscription \"%s\" appears to be invalid\n",
|
write_msg(NULL, "WARNING: owner of subscription \"%s\" appears to be invalid\n",
|
||||||
subinfo[i].dobj.name);
|
subinfo[i].dobj.name);
|
||||||
|
|
||||||
|
/* Decide whether we want to dump it */
|
||||||
|
selectDumpableObject(&(subinfo[i].dobj), fout);
|
||||||
}
|
}
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
@ -3735,7 +3766,7 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
|
|||||||
int npubnames = 0;
|
int npubnames = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (dopt->dataOnly)
|
if (!(subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
delq = createPQExpBuffer();
|
delq = createPQExpBuffer();
|
||||||
|
@ -67,7 +67,6 @@ main(int argc, char **argv)
|
|||||||
char *inputFileSpec;
|
char *inputFileSpec;
|
||||||
static int disable_triggers = 0;
|
static int disable_triggers = 0;
|
||||||
static int enable_row_security = 0;
|
static int enable_row_security = 0;
|
||||||
static int include_subscriptions = 0;
|
|
||||||
static int if_exists = 0;
|
static int if_exists = 0;
|
||||||
static int no_data_for_failed_tables = 0;
|
static int no_data_for_failed_tables = 0;
|
||||||
static int outputNoTablespaces = 0;
|
static int outputNoTablespaces = 0;
|
||||||
@ -112,7 +111,6 @@ main(int argc, char **argv)
|
|||||||
{"disable-triggers", no_argument, &disable_triggers, 1},
|
{"disable-triggers", no_argument, &disable_triggers, 1},
|
||||||
{"enable-row-security", no_argument, &enable_row_security, 1},
|
{"enable-row-security", no_argument, &enable_row_security, 1},
|
||||||
{"if-exists", no_argument, &if_exists, 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-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1},
|
||||||
{"no-tablespaces", no_argument, &outputNoTablespaces, 1},
|
{"no-tablespaces", no_argument, &outputNoTablespaces, 1},
|
||||||
{"role", required_argument, NULL, 2},
|
{"role", required_argument, NULL, 2},
|
||||||
@ -353,7 +351,6 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
opts->disable_triggers = disable_triggers;
|
opts->disable_triggers = disable_triggers;
|
||||||
opts->enable_row_security = enable_row_security;
|
opts->enable_row_security = enable_row_security;
|
||||||
opts->include_subscriptions = include_subscriptions;
|
|
||||||
opts->noDataForFailedTables = no_data_for_failed_tables;
|
opts->noDataForFailedTables = no_data_for_failed_tables;
|
||||||
opts->noTablespace = outputNoTablespaces;
|
opts->noTablespace = outputNoTablespaces;
|
||||||
opts->use_setsessauth = use_setsessauth;
|
opts->use_setsessauth = use_setsessauth;
|
||||||
|
@ -43,7 +43,6 @@ my %pgdump_runs = (
|
|||||||
'--format=custom',
|
'--format=custom',
|
||||||
"--file=$tempdir/binary_upgrade.dump",
|
"--file=$tempdir/binary_upgrade.dump",
|
||||||
'-w',
|
'-w',
|
||||||
'--include-subscriptions', # XXX Should not be necessary?
|
|
||||||
'--schema-only',
|
'--schema-only',
|
||||||
'--binary-upgrade',
|
'--binary-upgrade',
|
||||||
'-d', 'postgres', # alternative way to specify database
|
'-d', 'postgres', # alternative way to specify database
|
||||||
@ -58,7 +57,6 @@ my %pgdump_runs = (
|
|||||||
'pg_dump',
|
'pg_dump',
|
||||||
'--no-sync',
|
'--no-sync',
|
||||||
"--file=$tempdir/clean.sql",
|
"--file=$tempdir/clean.sql",
|
||||||
'--include-subscriptions',
|
|
||||||
'-c',
|
'-c',
|
||||||
'-d', 'postgres', # alternative way to specify database
|
'-d', 'postgres', # alternative way to specify database
|
||||||
], },
|
], },
|
||||||
@ -67,7 +65,6 @@ my %pgdump_runs = (
|
|||||||
'pg_dump',
|
'pg_dump',
|
||||||
'--no-sync',
|
'--no-sync',
|
||||||
"--file=$tempdir/clean_if_exists.sql",
|
"--file=$tempdir/clean_if_exists.sql",
|
||||||
'--include-subscriptions',
|
|
||||||
'-c',
|
'-c',
|
||||||
'--if-exists',
|
'--if-exists',
|
||||||
'--encoding=UTF8', # no-op, just tests that option is accepted
|
'--encoding=UTF8', # no-op, just tests that option is accepted
|
||||||
@ -85,7 +82,6 @@ my %pgdump_runs = (
|
|||||||
'pg_dump',
|
'pg_dump',
|
||||||
'--no-sync',
|
'--no-sync',
|
||||||
"--file=$tempdir/createdb.sql",
|
"--file=$tempdir/createdb.sql",
|
||||||
'--include-subscriptions',
|
|
||||||
'-C',
|
'-C',
|
||||||
'-R', # no-op, just for testing
|
'-R', # no-op, just for testing
|
||||||
'-v',
|
'-v',
|
||||||
@ -95,7 +91,6 @@ my %pgdump_runs = (
|
|||||||
'pg_dump',
|
'pg_dump',
|
||||||
'--no-sync',
|
'--no-sync',
|
||||||
"--file=$tempdir/data_only.sql",
|
"--file=$tempdir/data_only.sql",
|
||||||
'--include-subscriptions',
|
|
||||||
'-a',
|
'-a',
|
||||||
'--superuser=test_superuser',
|
'--superuser=test_superuser',
|
||||||
'--disable-triggers',
|
'--disable-triggers',
|
||||||
@ -253,7 +248,6 @@ my %pgdump_runs = (
|
|||||||
section_pre_data => {
|
section_pre_data => {
|
||||||
dump_cmd => [
|
dump_cmd => [
|
||||||
'pg_dump', "--file=$tempdir/section_pre_data.sql",
|
'pg_dump', "--file=$tempdir/section_pre_data.sql",
|
||||||
'--include-subscriptions',
|
|
||||||
'--section=pre-data', '--no-sync', 'postgres', ], },
|
'--section=pre-data', '--no-sync', 'postgres', ], },
|
||||||
section_data => {
|
section_data => {
|
||||||
dump_cmd => [
|
dump_cmd => [
|
||||||
@ -271,7 +265,7 @@ my %pgdump_runs = (
|
|||||||
with_oids => {
|
with_oids => {
|
||||||
dump_cmd => [
|
dump_cmd => [
|
||||||
'pg_dump', '--oids',
|
'pg_dump', '--oids',
|
||||||
'--include-subscriptions', '--no-sync',
|
'--no-sync',
|
||||||
"--file=$tempdir/with_oids.sql", 'postgres', ], },);
|
"--file=$tempdir/with_oids.sql", 'postgres', ], },);
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
@ -1405,7 +1399,7 @@ my %tests = (
|
|||||||
# catch-all for ALTER ... OWNER (except LARGE OBJECTs and PUBLICATIONs)
|
# catch-all for ALTER ... OWNER (except LARGE OBJECTs and PUBLICATIONs)
|
||||||
'ALTER ... OWNER commands (except LARGE OBJECTs and PUBLICATIONs)' => {
|
'ALTER ... OWNER commands (except LARGE OBJECTs and PUBLICATIONs)' => {
|
||||||
all_runs => 0, # catch-all
|
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
|
like => {}, # use more-specific options above
|
||||||
unlike => {
|
unlike => {
|
||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
@ -4318,25 +4312,25 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog
|
|||||||
clean => 1,
|
clean => 1,
|
||||||
clean_if_exists => 1,
|
clean_if_exists => 1,
|
||||||
createdb => 1,
|
createdb => 1,
|
||||||
with_oids => 1, },
|
|
||||||
unlike => {
|
|
||||||
defaults => 1,
|
defaults => 1,
|
||||||
exclude_test_table_data => 1,
|
exclude_test_table_data => 1,
|
||||||
exclude_dump_test_schema => 1,
|
exclude_dump_test_schema => 1,
|
||||||
exclude_test_table => 1,
|
exclude_test_table => 1,
|
||||||
section_pre_data => 1,
|
|
||||||
no_blobs => 1,
|
no_blobs => 1,
|
||||||
no_privs => 1,
|
no_privs => 1,
|
||||||
no_owner => 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_schema => 1,
|
||||||
only_dump_test_table => 1,
|
only_dump_test_table => 1,
|
||||||
pg_dumpall_dbprivs => 1,
|
|
||||||
pg_dumpall_globals => 1,
|
pg_dumpall_globals => 1,
|
||||||
pg_dumpall_globals_clean => 1,
|
pg_dumpall_globals_clean => 1,
|
||||||
schema_only => 1, # XXX Should be like?
|
|
||||||
role => 1,
|
role => 1,
|
||||||
section_pre_data => 1, # XXX Should be like?
|
section_pre_data => 1,
|
||||||
section_post_data => 1,
|
|
||||||
test_schema_plus_blobs => 1, }, },
|
test_schema_plus_blobs => 1, }, },
|
||||||
|
|
||||||
'ALTER PUBLICATION pub1 ADD TABLE test_table' => {
|
'ALTER PUBLICATION pub1 ADD TABLE test_table' => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user