hi. after watching https://www.youtube.com/live/k4A9-WZET_4?si=vz3lTud735s2vcCO then trying to hack it too.
the implemented feature is as the $subject description, making pg_dump also includes the ANALYZE command in its output. if option --include-analyze not specified, then pg_dump will not dump ANALYZE, that's the status quo. option --include-analyze support table relkind: RELKIND_PARTITIONED_TABLE, RELKIND_MATVIEW, RELKIND_RELATION. this option cannot be used with option --schema-only. for materialized view, it will dump after the refresh materialized view command. (tested in several cases, ANALYZE will really be at the end of the dump). By default, pg_restore does not restore the ANALYZE commands. This means that if the archive contains ANALYZE commands, you still need to explicitly specify the --include-analyze option to restore them. doc added. demo for dump: create materialized view mvw as select a from generate_series(1, 3) a; ---<<<<<<<<<<<<<<portion of pg_dump output starts>>>>>>>>>>>>>>>>>>>>>> -- -- Name: mvw; Type: MATERIALIZED VIEW DATA; Schema: public; Owner: jian -- REFRESH MATERIALIZED VIEW public.mvw; -- -- Name: mvw; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE public.mvw; ---<<<<<<<<<<<<<<portion of pg_dump output ends>>>>>>>>>>>>>>>>>>>>>> demo for dump partitioned table: CREATE TABLE prt1 (a int, b int, c text) PARTITION BY RANGE(a) ; CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (5); CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (8) TO (11); INSERT INTO prt1 SELECT i, i+11, to_char(i, 'FM0000') FROM generate_series(0, 2) i; pg_dump --table=*prt1* --include-analyze ---<<<<<<<<<<<<<<portion of output ends>>>>>>>>>>>>>>>>>>>>>> -- -- Data for Name: prt1_p1; Type: TABLE DATA; Schema: public; Owner: jian -- COPY public.prt1_p1 (a, b, c) FROM stdin; 0 11 0000 1 12 0001 2 13 0002 \. -- -- Data for Name: prt1_p2; Type: TABLE DATA; Schema: public; Owner: jian -- COPY public.prt1_p2 (a, b, c) FROM stdin; \. -- -- Name: prt1; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE ONLY public.prt1; -- -- Name: prt1_p1; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE public.prt1_p1; -- -- Name: prt1_p2; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE public.prt1_p2; ---<<<<<<<<<<<<<<portion of output starts>>>>>>>>>>>>>>>>>>>>>> TODO item: writing tests. idea credits to Andrey Borodin, Nikolay Samokhvalov, Kirk Wolak what do you think?
From c2ca01f95428dce498618c1a87fda62b3e2467dd Mon Sep 17 00:00:00 2001 From: jian he <jian.universal...@gmail.com> Date: Tue, 14 Jan 2025 16:39:31 +0800 Subject: [PATCH v1 1/1] Support --include-analyze in pg_dump, pg_dumpall, pg_restore The default is false. Maybe it should be true. support table relkind: RELKIND_PARTITIONED_TABLE, RELKIND_MATVIEW, RELKIND_RELATION. it cannot be used with option --schema-only. for materialized view, it will dump after refresh materialized view command By default, pg_restore does not restore the ANALYZE commands. This means that if the archive contains ANALYZE commands, you still need need explicitly specify the --include-analyze option to restore them. doc added. demo for dump: create materialized view mvw as select a from generate_series(1, 3) a; ---<<<<<<<<<<<<<<portion of output starts>>>>>>>>>>>>>>>>>>>>>> -- -- Name: mvw; Type: MATERIALIZED VIEW DATA; Schema: public; Owner: jian -- REFRESH MATERIALIZED VIEW public.mvw; -- -- Name: mvw; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE public.mvw; ---<<<<<<<<<<<<<<portion of output ends>>>>>>>>>>>>>>>>>>>>>> demo for dump partitioned table: CREATE TABLE prt1 (a int, b int, c text) PARTITION BY RANGE(a) ; CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (5); CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (8) TO (11); INSERT INTO prt1 SELECT i, i+11, to_char(i, 'FM0000') FROM generate_series(0, 2) i; pg_dump --table=*prt1* --include-analyze ---<<<<<<<<<<<<<<portion of output ends>>>>>>>>>>>>>>>>>>>>>> -- -- Data for Name: prt1_p1; Type: TABLE DATA; Schema: public; Owner: jian -- COPY public.prt1_p1 (a, b, c) FROM stdin; 0 11 0000 1 12 0001 2 13 0002 \. -- -- Data for Name: prt1_p2; Type: TABLE DATA; Schema: public; Owner: jian -- COPY public.prt1_p2 (a, b, c) FROM stdin; \. -- -- Name: prt1; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE ONLY public.prt1; -- -- Name: prt1_p1; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE public.prt1_p1; -- -- Name: prt1_p2; Type: ANALYZE; Schema: public; Owner: jian -- ANALYZE public.prt1_p2; ---<<<<<<<<<<<<<<portion of output starts>>>>>>>>>>>>>>>>>>>>>> TODO writing tests. discussion: https://postgr.es/m/ --- doc/src/sgml/ref/pg_dump.sgml | 10 +++ doc/src/sgml/ref/pg_dumpall.sgml | 10 +++ doc/src/sgml/ref/pg_restore.sgml | 13 +++ src/bin/pg_dump/common.c | 3 + src/bin/pg_dump/pg_backup.h | 2 + src/bin/pg_dump/pg_backup_archiver.c | 7 +- src/bin/pg_dump/pg_dump.c | 113 +++++++++++++++++++++++++++ src/bin/pg_dump/pg_dump.h | 13 +++ src/bin/pg_dump/pg_dump_sort.c | 9 ++- src/bin/pg_dump/pg_dumpall.c | 5 ++ src/bin/pg_dump/pg_restore.c | 7 ++ src/bin/pg_dump/t/001_basic.pl | 12 +++ src/tools/pgindent/typedefs.list | 1 + 13 files changed, 203 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index d66e901f51..6f0bbdec20 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -982,6 +982,16 @@ PostgreSQL documentation </listitem> </varlistentry> + <varlistentry> + <term><option>--include-analyze</option></term> + <listitem> + <para> + Do dump <command>ANALYZE</command> commands. + This option only applys to regular table, materialized view or partitioned table. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>--include-foreign-data=<replaceable class="parameter">foreignserver</replaceable></option></term> <listitem> diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index 014f279258..a540fae5d3 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -367,6 +367,16 @@ exclude database <replaceable class="parameter">PATTERN</replaceable> </listitem> </varlistentry> + <varlistentry> + <term><option>--include-analyze</option></term> + <listitem> + <para> + Do dump <command>ANALYZE</command> commands. + This option only applys to regular table, materialized view or partitioned table. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>--inserts</option></term> <listitem> diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index b8b27e1719..a745400f63 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -671,6 +671,17 @@ PostgreSQL documentation </listitem> </varlistentry> + <varlistentry> + <term><option>--include-analyze</option></term> + <listitem> + <para> + Do output <command>ANALYZE</command> commands for analyzing tables if the archive contains them. + If <application>pg_dump</application> specified <option>--include-analyze</option> option, + the archive may contain <command>ANALYZE</command> commands. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>--no-comments</option></term> <listitem> @@ -1044,6 +1055,8 @@ CREATE DATABASE foo WITH TEMPLATE template0; restored table so the optimizer has useful statistics; see <xref linkend="vacuum-for-statistics"/> and <xref linkend="autovacuum"/> for more information. + You can achieve the same effect by including the <option>--include-analyze</option> option + when running <application>pg_restore</application>. </para> </refsect1> diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 56b6c368ac..c44ac4993f 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -228,6 +228,9 @@ getSchemaData(Archive *fout, int *numTablesPtr) pg_log_info("reading rewrite rules"); getRules(fout); + pg_log_info("reading analyze info"); + getAnalyzes(fout, tblinfo, numTables); + pg_log_info("reading policies"); getPolicies(fout, tblinfo, numTables); diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index f0f19bb0b2..dfb5b4c121 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -109,6 +109,7 @@ typedef struct _restoreOptions int dump_inserts; /* 0 = COPY, otherwise rows per INSERT */ int column_inserts; int if_exists; + int include_analyze; int no_comments; /* Skip comments */ int no_publications; /* Skip publication entries */ int no_security_labels; /* Skip security label entries */ @@ -178,6 +179,7 @@ typedef struct _dumpOptions int disable_dollar_quoting; int column_inserts; int if_exists; + int include_analyze; int no_comments; int no_security_labels; int no_publications; diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 707a3fc844..365bd78551 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -170,6 +170,7 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt) dopt->dumpData = ropt->dumpData; dopt->dumpSchema = ropt->dumpSchema; dopt->if_exists = ropt->if_exists; + dopt->include_analyze = ropt->include_analyze; dopt->column_inserts = ropt->column_inserts; dopt->dumpSections = ropt->dumpSections; dopt->aclsSkip = ropt->aclsSkip; @@ -2940,6 +2941,9 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) if (ropt->aclsSkip && _tocEntryIsACL(te)) return 0; + if (!ropt->include_analyze && strcmp(te->desc, "ANALYZE") == 0) + return 0; + /* If it's a comment, maybe ignore it */ if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0) return 0; @@ -3196,7 +3200,8 @@ _tocEntryRestorePass(TocEntry *te) strcmp(te->desc, "DEFAULT ACL") == 0) return RESTORE_PASS_ACL; if (strcmp(te->desc, "EVENT TRIGGER") == 0 || - strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0) + strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 || + strcmp(te->desc, "ANALYZE") == 0) return RESTORE_PASS_POST_ACL; /* diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 8f73a5df95..7bd48c37cc 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -359,6 +359,7 @@ static void getLOs(Archive *fout); static void dumpLO(Archive *fout, const LoInfo *loinfo); static int dumpLOs(Archive *fout, const void *arg); static void dumpPolicy(Archive *fout, const PolicyInfo *polinfo); +static void dumpAnalyze(Archive *fout, const AnalyzeInfo *analyzeinfo); static void dumpPublication(Archive *fout, const PublicationInfo *pubinfo); static void dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo); static void dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo); @@ -479,6 +480,7 @@ main(int argc, char **argv) {"exclude-table-data", required_argument, NULL, 4}, {"extra-float-digits", required_argument, NULL, 8}, {"if-exists", no_argument, &dopt.if_exists, 1}, + {"include-analyze", no_argument, &dopt.include_analyze, 1}, {"inserts", no_argument, NULL, 9}, {"lock-wait-timeout", required_argument, NULL, 2}, {"no-table-access-method", no_argument, &dopt.outputNoTableAm, 1}, @@ -788,6 +790,9 @@ main(int argc, char **argv) if (schema_only && foreign_servers_include_patterns.head != NULL) pg_fatal("options -s/--schema-only and --include-foreign-data cannot be used together"); + if (schema_only && dopt.include_analyze) + pg_fatal("options -s/--schema-only and --include-analyze cannot be used together"); + if (numWorkers > 1 && foreign_servers_include_patterns.head != NULL) pg_fatal("option --include-foreign-data is not supported with parallel backup"); @@ -1100,6 +1105,7 @@ main(int argc, char **argv) ropt->dumpData = dopt.dumpData; ropt->dumpSchema = dopt.dumpSchema; ropt->if_exists = dopt.if_exists; + ropt->include_analyze = dopt.include_analyze; ropt->column_inserts = dopt.column_inserts; ropt->dumpSections = dopt.dumpSections; ropt->aclsSkip = dopt.aclsSkip; @@ -1213,6 +1219,7 @@ help(const char *progname) printf(_(" --filter=FILENAME include or exclude objects and data from dump\n" " based on expressions in FILENAME\n")); printf(_(" --if-exists use IF EXISTS when dropping objects\n")); + printf(_(" --include-analyze do dump analyze commands\n")); printf(_(" --include-foreign-data=PATTERN\n" " include data of foreign tables on foreign\n" " servers matching PATTERN\n")); @@ -4151,6 +4158,68 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables) destroyPQExpBuffer(tbloids); } +/* + * getAnalyzes + * get information about tables (regular table, partitioned table, materialized + * view) to be analyzed. + */ +void +getAnalyzes(Archive *fout, TableInfo tblinfo[], int numTables) +{ + int i = 0; + int ntbl = 0; + AnalyzeInfo *analyze_info = NULL; + TableInfo *tbinfo = NULL; + Oid *tabldids = NULL; + + if(!fout->dopt->include_analyze || + fout->remoteVersion < 180000) + return; + + tabldids = pg_malloc0(numTables * sizeof(Oid)); + for (i = 0; i < numTables; i++) + { + tbinfo = &tblinfo[i]; + + /* It can't have RLS or policies if it's not a table */ + if (!(tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_MATVIEW || + tbinfo->relkind == RELKIND_PARTITIONED_TABLE)) + continue; + + if (tbinfo->relpersistence != RELPERSISTENCE_PERMANENT) + continue; + + if (!tbinfo->dobj.dump) + continue; + + if (!tbinfo->interesting) + continue; + + tabldids[ntbl] = tbinfo->dobj.catId.oid; + ntbl++; + } + + if(ntbl >0) + { + analyze_info = pg_malloc(ntbl * sizeof(AnalyzeInfo)); + + for (i = 0; i < ntbl; i++) + { + tbinfo = findTableByOid(tabldids[i]); + analyze_info[i].dobj.objType = DO_ANALYZE; + analyze_info[i].dobj.catId.tableoid = 0; + analyze_info[i].dobj.catId.oid = tbinfo->dobj.catId.oid; + AssignDumpId(&analyze_info[i].dobj); + analyze_info[i].dobj.catId.tableoid = RelationRelationId; + analyze_info[i].dobj.namespace = tbinfo->dobj.namespace; + analyze_info[i].dobj.name = pg_strdup(tbinfo->dobj.name); + analyze_info[i].analyzetable = tbinfo; + } + } + free(tabldids); +} + /* * dumpPolicy * dump the definition of the given policy @@ -4269,6 +4338,45 @@ dumpPolicy(Archive *fout, const PolicyInfo *polinfo) free(qtabname); } +/* + * dumpAnalyze + * dump the definition of the ANALYZE command for appliable table. + */ +static void +dumpAnalyze(Archive *fout, const AnalyzeInfo *analyzeinfo) +{ + PQExpBuffer q; + TableInfo * tbinfo = NULL; + DumpOptions *dopt = fout->dopt; + + /* Do nothing if not include_analyze specified */ + if (!dopt->include_analyze) + return; + Assert(dopt->dumpData); + + tbinfo = (TableInfo *) analyzeinfo->analyzetable; + q = createPQExpBuffer(); + if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE) + appendPQExpBuffer(q, "ANALYZE ONLY %s;", + fmtQualifiedDumpable(tbinfo)); + else + { + appendPQExpBuffer(q, "ANALYZE %s;", + fmtQualifiedDumpable(tbinfo)); + Assert(tbinfo->relkind == RELKIND_MATVIEW || tbinfo->relkind == RELKIND_RELATION); + } + + ArchiveEntry(fout, analyzeinfo->dobj.catId, analyzeinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = analyzeinfo->dobj.namespace->dobj.name, + .relkind = tbinfo->relkind, + .owner = tbinfo->rolname, + .description = "ANALYZE", + .section = SECTION_POST_DATA, + .createStmt = q->data)); + destroyPQExpBuffer(q); +} + /* * getPublications * get information about publications @@ -10635,6 +10743,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj) case DO_REFRESH_MATVIEW: refreshMatViewData(fout, (const TableDataInfo *) dobj); break; + case DO_ANALYZE: + dumpAnalyze(fout, (const AnalyzeInfo *) dobj); + break; case DO_RULE: dumpRule(fout, (const RuleInfo *) dobj); break; @@ -16888,6 +16999,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) free(qualrelname); } + /* * dumpTableAttach * write to fout the commands to attach a child partition @@ -18940,6 +19052,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs, case DO_INDEX_ATTACH: case DO_STATSEXT: case DO_REFRESH_MATVIEW: + case DO_ANALYZE: case DO_TRIGGER: case DO_EVENT_TRIGGER: case DO_DEFAULT_ACL: diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index f62b564ed1..4573039bd4 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -78,6 +78,7 @@ typedef enum DO_POST_DATA_BOUNDARY, DO_EVENT_TRIGGER, DO_REFRESH_MATVIEW, + DO_ANALYZE, DO_POLICY, DO_PUBLICATION, DO_PUBLICATION_REL, @@ -625,6 +626,17 @@ typedef struct _policyInfo char *polwithcheck; } PolicyInfo; + +/* + * The AnalyzeInfo struct is used to represent ANALYZE command on a table and to + * indicate if a table need ANALYZE + */ +typedef struct _analyzeInfo +{ + DumpableObject dobj; + TableInfo *analyzetable; +} AnalyzeInfo; + /* * The PublicationInfo struct is used to represent publications. */ @@ -784,6 +796,7 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], int numExtensions); extern void getEventTriggers(Archive *fout); extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables); +extern void getAnalyzes(Archive *fout, TableInfo tblinfo[], int numTables); extern void getPublications(Archive *fout); extern void getPublicationNamespaces(Archive *fout); extern void getPublicationTables(Archive *fout, TableInfo tblinfo[], diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index dc9a28924b..5b78e72a45 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -97,7 +97,8 @@ enum dbObjectTypePriorities PRIO_SUBSCRIPTION_REL, PRIO_DEFAULT_ACL, /* done in ACL pass */ PRIO_EVENT_TRIGGER, /* must be next to last! */ - PRIO_REFRESH_MATVIEW /* must be last! */ + PRIO_REFRESH_MATVIEW, /* must be last! */ + PRIO_ANALYZE, /* must really be last! */ }; /* This table is indexed by enum DumpableObjectType */ @@ -144,6 +145,7 @@ static const int dbObjectTypePriority[] = [DO_POST_DATA_BOUNDARY] = PRIO_POST_DATA_BOUNDARY, [DO_EVENT_TRIGGER] = PRIO_EVENT_TRIGGER, [DO_REFRESH_MATVIEW] = PRIO_REFRESH_MATVIEW, + [DO_ANALYZE] = PRIO_ANALYZE, [DO_POLICY] = PRIO_POLICY, [DO_PUBLICATION] = PRIO_PUBLICATION, [DO_PUBLICATION_REL] = PRIO_PUBLICATION_REL, @@ -1356,6 +1358,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize) "REFRESH MATERIALIZED VIEW %s (ID %d OID %u)", obj->name, obj->dumpId, obj->catId.oid); return; + case DO_ANALYZE: + snprintf(buf, bufsize, + "ANALYZE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; case DO_RULE: snprintf(buf, bufsize, "RULE %s (ID %d OID %u)", diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 396f79781c..976b5b47ad 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -96,6 +96,7 @@ static int column_inserts = 0; static int disable_dollar_quoting = 0; static int disable_triggers = 0; static int if_exists = 0; +static int include_analyze = 0; static int inserts = 0; static int no_table_access_method = 0; static int no_tablespaces = 0; @@ -159,6 +160,7 @@ main(int argc, char *argv[]) {"exclude-database", required_argument, NULL, 6}, {"extra-float-digits", required_argument, NULL, 5}, {"if-exists", no_argument, &if_exists, 1}, + {"include-analyze", no_argument, &include_analyze, 1}, {"inserts", no_argument, &inserts, 1}, {"lock-wait-timeout", required_argument, NULL, 2}, {"no-table-access-method", no_argument, &no_table_access_method, 1}, @@ -435,6 +437,8 @@ main(int argc, char *argv[]) appendPQExpBufferStr(pgdumpopts, " --disable-triggers"); if (inserts) appendPQExpBufferStr(pgdumpopts, " --inserts"); + if (include_analyze) + appendPQExpBufferStr(pgdumpopts, " --include-analyze"); if (no_table_access_method) appendPQExpBufferStr(pgdumpopts, " --no-table-access-method"); if (no_tablespaces) @@ -660,6 +664,7 @@ help(void) printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n")); printf(_(" --filter=FILENAME exclude databases based on expressions in FILENAME\n")); printf(_(" --if-exists use IF EXISTS when dropping objects\n")); + printf(_(" --include-analyze do dump analyze commands\n")); printf(_(" --inserts dump data as INSERT commands, rather than COPY\n")); printf(_(" --load-via-partition-root load partitions via the root table\n")); printf(_(" --no-comments do not dump comment commands\n")); diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index 88ae39d938..25dfa1a800 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -70,6 +70,7 @@ main(int argc, char **argv) static int outputNoTableAm = 0; static int outputNoTablespaces = 0; static int use_setsessauth = 0; + static int include_analyze = 0; static int no_comments = 0; static int no_publications = 0; static int no_security_labels = 0; @@ -115,6 +116,7 @@ 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-analyze", no_argument, &include_analyze, 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}, @@ -361,6 +363,9 @@ main(int argc, char **argv) if (opts->single_txn && numWorkers > 1) pg_fatal("cannot specify both --single-transaction and multiple jobs"); + if (schema_only && include_analyze) + pg_fatal("options -s/--schema-only and --include-analyze cannot be used together"); + /* set derivative flags */ opts->dumpSchema = (!data_only); opts->dumpData = (!schema_only); @@ -379,6 +384,7 @@ main(int argc, char **argv) if (if_exists && !opts->dropSchema) pg_fatal("option --if-exists requires option -c/--clean"); opts->if_exists = if_exists; + opts->include_analyze = include_analyze; opts->strict_names = strict_names; if (opts->formatName) @@ -490,6 +496,7 @@ usage(const char *progname) printf(_(" --filter=FILENAME restore or skip objects based on expressions\n" " in FILENAME\n")); printf(_(" --if-exists use IF EXISTS when dropping objects\n")); + printf(_(" --include-analyze do restore analyze commands\n")); printf(_(" --no-comments do not restore comment commands\n")); printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n" " created\n")); diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl index 214240f1ae..c3ad062c2d 100644 --- a/src/bin/pg_dump/t/001_basic.pl +++ b/src/bin/pg_dump/t/001_basic.pl @@ -50,6 +50,12 @@ command_fails_like( 'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together' ); +command_fails_like( + [ 'pg_dump', '-s', '--include-analyze' ], + qr/\Qpg_dump: error: options -s\/--schema-only and --include-analyze cannot be used together\E/, + 'pg_dump: error: options -s/--schema-only and --include-analyze cannot be used together' +); + command_fails_like( [ 'pg_dump', '-s', '--include-foreign-data=xxx' ], qr/\Qpg_dump: error: options -s\/--schema-only and --include-foreign-data cannot be used together\E/, @@ -62,6 +68,12 @@ command_fails_like( 'pg_dump: option --include-foreign-data is not supported with parallel backup' ); +command_fails_like( + [ 'pg_restore', '-s', '-f -', '--include-analyze' ], + qr/\Qg_restore: error: options -s\/--schema-only and --include-analyze cannot be used together\E/, + 'pg_restore: error: options -s/--schema-only and --include-analyze cannot be used together' +); + command_fails_like( ['pg_restore'], qr{\Qpg_restore: error: one of -d/--dbname and -f/--file must be specified\E}, diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index eb93debe10..d25aa15eaa 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2,6 +2,7 @@ ACCESS_ALLOWED_ACE ACL ACL_SIZE_INFORMATION AFFIX +AnalyzeInfo ASN1_INTEGER ASN1_OBJECT ASN1_OCTET_STRING -- 2.34.1