From 2158628864cfbc03c838834a46c193bde5807361 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 17 Jan 2022 14:51:46 +0900 Subject: [PATCH] Add support for --no-table-access-method in pg_{dump,dumpall,restore} The logic is similar to default_tablespace in some ways, so as no SET queries on default_table_access_method are generated before dumping or restoring an object (table or materialized view support table AMs) when specifying this new option. This option is useful to enforce the use of a default access method even if some tables included in a dump use an AM different than the system's default. There are already two cases in the TAP tests of pg_dump with a table and a materialized view that use a non-default table AM, and these are extended that the new option does not generate SET clauses on default_table_access_method. Author: Justin Pryzby Discussion: https://postgr.es/m/20211207153930.GR17618@telsasoft.com --- doc/src/sgml/ref/pg_dump.sgml | 17 +++++++++++++++++ doc/src/sgml/ref/pg_dumpall.sgml | 11 +++++++++++ doc/src/sgml/ref/pg_restore.sgml | 11 +++++++++++ src/bin/pg_dump/pg_backup.h | 2 ++ src/bin/pg_dump/pg_backup_archiver.c | 12 ++++++++++++ src/bin/pg_dump/pg_dump.c | 3 +++ src/bin/pg_dump/pg_dumpall.c | 5 +++++ src/bin/pg_dump/pg_restore.c | 4 ++++ src/bin/pg_dump/t/002_pg_dump.pl | 16 ++++++++++++++-- 9 files changed, 79 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index 0e1cfe0f8d..2f0042fd96 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -931,6 +931,23 @@ PostgreSQL documentation + + + + + Do not output commands to select table access methods. + With this option, all objects will be created with whichever + table access method is the default during restore. + + + + This option is ignored when emitting an archive (non-text) output + file. For the archive formats, you can specify the option when you + call pg_restore. + + + + diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index ddffbf85ed..c9aef776eb 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -446,6 +446,17 @@ PostgreSQL documentation + + + + + Do not output commands to select table access methods. + With this option, all objects will be created with whichever + table access method is the default during restore. + + + + diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index 93ea937ac8..526986eadb 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -649,6 +649,17 @@ PostgreSQL documentation + + + + + Do not output commands to select table access methods. + With this option, all objects will be created with whichever + access method is the default during restore. + + + + diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 753252e05e..fcc5f6bd05 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -93,6 +93,7 @@ typedef struct _restoreOptions { int createDB; /* Issue commands to create the database */ int noOwner; /* Don't try to match original object owner */ + int noTableAm; /* Don't issue table-AM-related commands */ int noTablespace; /* Don't issue tablespace-related commands */ int disable_triggers; /* disable triggers during data-only * restore */ @@ -179,6 +180,7 @@ typedef struct _dumpOptions int no_unlogged_table_data; int serializable_deferrable; int disable_triggers; + int outputNoTableAm; int outputNoTablespaces; int use_setsessauth; int enable_row_security; diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 8903a694ae..49bf0907cd 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -194,6 +194,7 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt) dopt->outputSuperuser = ropt->superuser; dopt->outputCreateDB = ropt->createDB; dopt->outputNoOwner = ropt->noOwner; + dopt->outputNoTableAm = ropt->noTableAm; dopt->outputNoTablespaces = ropt->noTablespace; dopt->disable_triggers = ropt->disable_triggers; dopt->use_setsessauth = ropt->use_setsessauth; @@ -3171,6 +3172,11 @@ _reconnectToDB(ArchiveHandle *AH, const char *dbname) if (AH->currSchema) free(AH->currSchema); AH->currSchema = NULL; + + if (AH->currTableAm) + free(AH->currTableAm); + AH->currTableAm = NULL; + if (AH->currTablespace) free(AH->currTablespace); AH->currTablespace = NULL; @@ -3340,10 +3346,15 @@ _selectTablespace(ArchiveHandle *AH, const char *tablespace) static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam) { + RestoreOptions *ropt = AH->public.ropt; PQExpBuffer cmd; const char *want, *have; + /* do nothing in --no-table-access-method mode */ + if (ropt->noTableAm) + return; + have = AH->currTableAm; want = tableam; @@ -4770,6 +4781,7 @@ CloneArchive(ArchiveHandle *AH) clone->connCancel = NULL; clone->currUser = NULL; clone->currSchema = NULL; + clone->currTableAm = NULL; clone->currTablespace = NULL; /* savedPassword must be local in case we change it while connecting */ diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 92ab95724d..c5f231118b 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -389,6 +389,7 @@ main(int argc, char **argv) {"if-exists", no_argument, &dopt.if_exists, 1}, {"inserts", no_argument, NULL, 9}, {"lock-wait-timeout", required_argument, NULL, 2}, + {"no-table-access-method", no_argument, &dopt.outputNoTableAm, 1}, {"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1}, {"quote-all-identifiers", no_argument, "e_all_identifiers, 1}, {"load-via-partition-root", no_argument, &dopt.load_via_partition_root, 1}, @@ -933,6 +934,7 @@ main(int argc, char **argv) ropt->superuser = dopt.outputSuperuser; ropt->createDB = dopt.outputCreateDB; ropt->noOwner = dopt.outputNoOwner; + ropt->noTableAm = dopt.outputNoTableAm; ropt->noTablespace = dopt.outputNoTablespaces; ropt->disable_triggers = dopt.disable_triggers; ropt->use_setsessauth = dopt.use_setsessauth; @@ -1038,6 +1040,7 @@ help(const char *progname) printf(_(" --no-publications do not dump publications\n")); printf(_(" --no-security-labels do not dump security label assignments\n")); printf(_(" --no-subscriptions do not dump subscriptions\n")); + printf(_(" --no-table-access-method do not dump table access methods\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n")); printf(_(" --no-toast-compression do not dump TOAST compression methods\n")); printf(_(" --no-unlogged-table-data do not dump unlogged table data\n")); diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 868f15ed37..1cab0dfdc7 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -70,6 +70,7 @@ static int disable_dollar_quoting = 0; static int disable_triggers = 0; static int if_exists = 0; static int inserts = 0; +static int no_table_access_method = 0; static int no_tablespaces = 0; static int use_setsessauth = 0; static int no_comments = 0; @@ -133,6 +134,7 @@ main(int argc, char *argv[]) {"if-exists", no_argument, &if_exists, 1}, {"inserts", no_argument, &inserts, 1}, {"lock-wait-timeout", required_argument, NULL, 2}, + {"no-table-access-method", no_argument, &no_table_access_method, 1}, {"no-tablespaces", no_argument, &no_tablespaces, 1}, {"quote-all-identifiers", no_argument, "e_all_identifiers, 1}, {"load-via-partition-root", no_argument, &load_via_partition_root, 1}, @@ -413,6 +415,8 @@ main(int argc, char *argv[]) appendPQExpBufferStr(pgdumpopts, " --disable-triggers"); if (inserts) appendPQExpBufferStr(pgdumpopts, " --inserts"); + if (no_table_access_method) + appendPQExpBufferStr(pgdumpopts, " --no-table-access-method"); if (no_tablespaces) appendPQExpBufferStr(pgdumpopts, " --no-tablespaces"); if (quote_all_identifiers) @@ -649,6 +653,7 @@ help(void) printf(_(" --no-security-labels do not dump security label assignments\n")); printf(_(" --no-subscriptions do not dump subscriptions\n")); printf(_(" --no-sync do not wait for changes to be written safely to disk\n")); + printf(_(" --no-tables-access-method do not dump table access methods\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n")); printf(_(" --no-toast-compression do not dump TOAST compression methods\n")); printf(_(" --no-unlogged-table-data do not dump unlogged table data\n")); diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index 64aaa80eee..55bf1b6975 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -66,6 +66,7 @@ main(int argc, char **argv) static int enable_row_security = 0; static int if_exists = 0; static int no_data_for_failed_tables = 0; + static int outputNoTableAm = 0; static int outputNoTablespaces = 0; static int use_setsessauth = 0; static int no_comments = 0; @@ -112,6 +113,7 @@ main(int argc, char **argv) {"enable-row-security", no_argument, &enable_row_security, 1}, {"if-exists", no_argument, &if_exists, 1}, {"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1}, + {"no-table-access-method", no_argument, &outputNoTableAm, 1}, {"no-tablespaces", no_argument, &outputNoTablespaces, 1}, {"role", required_argument, NULL, 2}, {"section", required_argument, NULL, 3}, @@ -358,6 +360,7 @@ main(int argc, char **argv) opts->disable_triggers = disable_triggers; opts->enable_row_security = enable_row_security; opts->noDataForFailedTables = no_data_for_failed_tables; + opts->noTableAm = outputNoTableAm; opts->noTablespace = outputNoTablespaces; opts->use_setsessauth = use_setsessauth; opts->no_comments = no_comments; @@ -487,6 +490,7 @@ usage(const char *progname) printf(_(" --no-publications do not restore publications\n")); printf(_(" --no-security-labels do not restore security labels\n")); printf(_(" --no-subscriptions do not restore subscriptions\n")); + printf(_(" --no-table-access-method do not restore table access methods\n")); printf(_(" --no-tablespaces do not restore tablespace assignments\n")); printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n")); printf(_(" --strict-names require table and/or schema include patterns to\n" diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 4200bcb0d7..39fa1952e7 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -275,6 +275,13 @@ my %pgdump_runs = ( 'postgres', ], }, + no_table_access_method => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_table_access_method.sql", + '--no-table-access-method', 'postgres', + ], + }, only_dump_test_schema => { dump_cmd => [ 'pg_dump', '--no-sync', @@ -426,6 +433,7 @@ my %full_runs = ( no_blobs => 1, no_owner => 1, no_privs => 1, + no_table_access_method => 1, pg_dumpall_dbprivs => 1, pg_dumpall_exclude => 1, schema_only => 1,); @@ -2972,6 +2980,7 @@ my %tests = ( no_blobs => 1, no_privs => 1, no_owner => 1, + no_table_access_method => 1, only_dump_test_schema => 1, pg_dumpall_dbprivs => 1, pg_dumpall_exclude => 1, @@ -3045,6 +3054,7 @@ my %tests = ( no_blobs => 1, no_privs => 1, no_owner => 1, + no_table_access_method => 1, pg_dumpall_dbprivs => 1, pg_dumpall_exclude => 1, role => 1, @@ -3648,7 +3658,8 @@ my %tests = ( like => { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, - unlike => { exclude_dump_test_schema => 1 }, + unlike => + { exclude_dump_test_schema => 1, no_table_access_method => 1 }, }, 'CREATE MATERIALIZED VIEW regress_pg_dump_matview_am' => { @@ -3668,7 +3679,8 @@ my %tests = ( like => { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, - unlike => { exclude_dump_test_schema => 1 }, + unlike => + { exclude_dump_test_schema => 1, no_table_access_method => 1 }, }); #########################################