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

Reply via email to