v9-0002-Enable-dumping-of-table-index-stats-in-pg_dump.patch
text/x-patch
Filename: v9-0002-Enable-dumping-of-table-index-stats-in-pg_dump.patch
Type: text/x-patch
Part: 1
Message:
Re: Statistics Import and Export
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v9-0002
Subject: Enable dumping of table/index stats in pg_dump.
| File | + | − |
|---|---|---|
| src/bin/pg_dump/pg_backup_archiver.c | 5 | 0 |
| src/bin/pg_dump/pg_backup.h | 2 | 0 |
| src/bin/pg_dump/pg_dumpall.c | 5 | 0 |
| src/bin/pg_dump/pg_dump.c | 60 | 0 |
| src/bin/pg_dump/pg_dump.h | 1 | 0 |
| src/bin/pg_dump/pg_restore.c | 3 | 0 |
| src/fe_utils/Makefile | 1 | 0 |
| src/fe_utils/meson.build | 1 | 0 |
| src/fe_utils/stats_export.c | 239 | 0 |
| src/include/fe_utils/stats_export.h | 38 | 0 |
From 7ff026f3bb1a7ffb663a7221a1a9a69df33a3e7a Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Thu, 14 Mar 2024 04:42:41 -0400
Subject: [PATCH v9 2/2] Enable dumping of table/index stats in pg_dump.
For each table/matview/index dumped, it will also generate a statement
that calls all of the pg_set_relation_stats() and
pg_set_attribute_stats() calls necessary to restore the statistics of
the current system onto the destination system.
As is the pattern with pg_dump options, this can be disabled with
--no-statistics.
---
src/include/fe_utils/stats_export.h | 38 +++++
src/fe_utils/Makefile | 1 +
src/fe_utils/meson.build | 1 +
src/fe_utils/stats_export.c | 239 +++++++++++++++++++++++++++
src/bin/pg_dump/pg_backup.h | 2 +
src/bin/pg_dump/pg_backup_archiver.c | 5 +
src/bin/pg_dump/pg_dump.c | 60 +++++++
src/bin/pg_dump/pg_dump.h | 1 +
src/bin/pg_dump/pg_dumpall.c | 5 +
src/bin/pg_dump/pg_restore.c | 3 +
10 files changed, 355 insertions(+)
create mode 100644 src/include/fe_utils/stats_export.h
create mode 100644 src/fe_utils/stats_export.c
diff --git a/src/include/fe_utils/stats_export.h b/src/include/fe_utils/stats_export.h
new file mode 100644
index 0000000000..eb2141d639
--- /dev/null
+++ b/src/include/fe_utils/stats_export.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * stats_export.h
+ * Queries to export statistics from current and past versions.
+ *
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1995, Regents of the University of California
+ *
+ * src/include/varatt.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef STATS_EXPORT_H
+#define STATS_EXPORT_H
+
+#include "postgres_fe.h"
+#include "libpq-fe.h"
+
+/*
+ * The minimum supported version number. No attempt is made to get statistics
+ * import to work on versions older than this. This version was initially chosen
+ * because that was the minimum version supported by pg_dump at the time.
+ */
+#define MIN_SERVER_NUM 90200
+
+extern bool exportStatsSupported(int server_version_num);
+extern bool exportExtStatsSupported(int server_version_num);
+
+extern const char *exportClassStatsSQL(int server_verson_num);
+extern const char *exportAttributeStatsSQL(int server_verson_num);
+
+extern char *exportRelationStatsSQL(int server_version_num);
+extern char *exportRelationStatsStmt(PGconn *conn, const char *srcrel,
+ const char *destrel);
+
+#endif
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index 946c05258f..c734f9f6d3 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -32,6 +32,7 @@ OBJS = \
query_utils.o \
recovery_gen.o \
simple_list.o \
+ stats_export.o \
string_utils.o
ifeq ($(PORTNAME), win32)
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index 14d0482a2c..fce503f641 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -12,6 +12,7 @@ fe_utils_sources = files(
'query_utils.c',
'recovery_gen.c',
'simple_list.c',
+ 'stats_export.c',
'string_utils.c',
)
diff --git a/src/fe_utils/stats_export.c b/src/fe_utils/stats_export.c
new file mode 100644
index 0000000000..cd2b38172c
--- /dev/null
+++ b/src/fe_utils/stats_export.c
@@ -0,0 +1,239 @@
+/*-------------------------------------------------------------------------
+ *
+ * Utility functions for extracting object statistics for frontend code
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/fe_utils/stats_export.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "fe_utils/stats_export.h"
+/*
+#include "libpq/libpq-fs.h"
+*/
+#include "fe_utils/string_utils.h"
+
+/*
+ * No-frills catalog queries that are named according to the statistics they
+ * fetch (relation, attribute, extended) and the earliest server version for
+ * which they work. These are presented so that if other use cases arise they
+ * can share the same base queries but utilize them in their own way.
+ *
+ * The queries themselves do not filter results, so it is up to the caller
+ * to append a WHERE clause filtering either on either c.oid or a combination
+ * of c.relname and n.nspname.
+ */
+
+const char *export_class_stats_query_v9_2 =
+ "SELECT c.oid, n.nspname, c.relname, c.reltuples, c.relpages, c.relallvisible "
+ "FROM pg_class AS c "
+ "JOIN pg_namespace AS n ON n.oid = c.relnamespace ";
+
+const char *export_attribute_stats_query_v9_2 =
+ "SELECT c.oid, n.nspname, c.relname, a.attnum, a.attname, s.stainherit, "
+ "s.stanullfrac, s.stawidth, s.stadistinct, s.stakind1, s.stakind2, "
+ "s.stakind3, s.stakind4, s.stakind5, s.stanumbers1, s.stanumbers2, "
+ "s.stanumbers3, s.stanumbers4, s.stanumbers5, "
+ "s.stavalues1::text AS stavalues1, s.stavalues2::text AS stavalues2, "
+ "s.stavalues3::text AS stavalues3, s.stavalues4::text AS stavalues4, "
+ "s.stavalues5::text AS stavalues5 "
+ "FROM pg_class AS c "
+ "JOIN pg_namespace AS n ON n.oid = c.relnamespace "
+ "JOIN pg_attribute AS a ON a.attrelid = c.oid AND not a.attisdropped "
+ "JOIN pg_statistic s ON s.starelid = a.attrelid AND s.staattnum = a.attnum ";
+
+/*
+ * Returns true if the server version number supports exporting regular
+ * (e.g. pg_statistic) statistics.
+ */
+bool
+exportStatsSupported(int server_version_num)
+{
+ return (server_version_num >= MIN_SERVER_NUM);
+}
+
+/*
+ * Returns true if the server version number supports exporting extended
+ * (e.g. pg_statistic_ext, pg_statitic_ext_data) statistics.
+ *
+ * Currently, none do.
+ */
+bool
+exportExtStatsSupported(int server_version_num)
+{
+ return false;
+}
+
+/*
+ * Return the query appropriate for extracting relation statistics for the
+ * given server version, if one exists.
+ */
+const char *
+exportClassStatsSQL(int server_version_num)
+{
+ if (server_version_num >= MIN_SERVER_NUM)
+ return export_class_stats_query_v9_2;
+ return NULL;
+}
+
+/*
+ * Return the query appropriate for extracting attribute statistics for the
+ * given server version, if one exists.
+ */
+const char *
+exportAttributeStatsSQL(int server_version_num)
+{
+ if (server_version_num >= MIN_SERVER_NUM)
+ return export_attribute_stats_query_v9_2;
+ return NULL;
+}
+
+/*
+ * Generate a SQL statement that will itself generate a SQL statement to
+ * import all regular stats from a given relation into another relation.
+ *
+ * The query generated takes two parameters.
+ *
+ * $1 is of type Oid, and represents the oid of the source relation.
+ *
+ * $2 is is a cstring, and represents the qualified name of the destination
+ * relation. If NULL, then the qualified name of the source relation will
+ * be used. In either case, the value is casted via ::regclass.
+ *
+ * The function will return NULL for invalid server version numbers.
+ * Otherwise,
+ *
+ * This function needs to work on databases back to 9.2.
+ * The format() function was introduced in 9.1.
+ * The string_agg() aggregate was introduced in 9.0.
+ *
+ */
+char *exportRelationStatsSQL(int server_version_num)
+{
+ const char *relsql = exportClassStatsSQL(server_version_num);
+ const char *attrsql = exportAttributeStatsSQL(server_version_num);
+ const char *filter = "WHERE c.oid = $1::regclass";
+ char *s;
+ PQExpBuffer sql;
+
+ if ((relsql == NULL) || (attrsql == NULL))
+ return NULL;
+
+ /*
+ * Set up the initial CTEs each with the same oid filter
+ */
+ sql = createPQExpBuffer();
+ appendPQExpBuffer(sql,
+ "WITH r AS (%s %s), a AS (%s %s), ",
+ relsql, filter, attrsql, filter);
+
+ /*
+ * Generate the pg_set_relation_stats function call for the relation
+ * and one pg_set_attribute_stats function call for each attribute with
+ * a pg_statistic entry. Give each row an order value such that the
+ * set relation stats call will be first, followed by the set attribute
+ * stats calls in attnum order (even though the attributes are identified
+ * by attname).
+ *
+ * Then aggregate the function calls into a single SELECT statement that
+ * puts the calls in the order described above.
+ */
+ appendPQExpBufferStr(sql,
+ "s(ord,sql) AS ( "
+ "SELECT 0, format('pg_catalog.pg_set_relation_stats("
+ "%L::regclass, %s::float4, %s::integer, %s::integer)', "
+ "coalesce($2, format('%I.%I', r.nspname, r.relname)), "
+ "r.reltuples, r.relpages, r.relallvisible) "
+ "FROM r "
+ "UNION ALL "
+ "SELECT a.attnum, format('pg_catalog.pg_set_attribute_stats( "
+ "relation => %L::regclass, attname => %L::name, "
+ "stainherit => %L::boolean, stanullfrac => %s::real, "
+ "stawidth => %s::integer, stadistinct => %s::real, "
+ "stakind1 => %s::smallint, stakind2 => %s::smallint, "
+ "stakind3 => %s::smallint, stakind4 => %s::smallint, "
+ "stakind5 => %s::smallint, "
+ "stanumbers1 => %L::real[], stanumbers2 => %L::real[], "
+ "stanumbers3 => %L::real[], stanumbers4 => %L::real[], "
+ "stanumbers5 => %L::real[], "
+ "stavalues1 => %L::text, stavalues2 => %L::text, "
+ "stavalues3 => %L::text, stavalues4 => %L::text, "
+ "stavalues5 => %L::text)', "
+ "coalesce($2, format('%I.%I', a.nspname, a.relname)), "
+ "a.attname, a.stainherit, a.stanullfrac, a.stawidth, "
+ "a.stadistinct, a.stakind1, a.stakind2, a.stakind3, a.stakind4, "
+ "a.stakind5, a.stanumbers1, a.stanumbers2, a.stanumbers3, "
+ "a.stanumbers4, a.stanumbers5, a.stavalues1, a.stavalues2, "
+ "a.stavalues3, a.stavalues4, a.stavalues5) "
+ "FROM a "
+ ") "
+ "SELECT 'SELECT ' || string_agg(s.sql, ', ' ORDER BY s.ord) "
+ "FROM s ");
+
+ s = strdup(sql->data);
+ destroyPQExpBuffer(sql);
+ return s;
+}
+
+/*
+ * Return the SQL command that will import all relation stats and attribute
+ * stats for a given relation.
+ *
+ * The return string is malloc()ed and must be freed by the caller.
+ *
+ * If the database is a version before 9.2, the function will return NULL
+ * with no corresponding error message. This can be verified beforehand via
+ * exportStatisticsSupported().
+ *
+ * Any other errors will result in the function returning NULL and the error
+ * message can be found via PQerrorMessage(conn).
+ *
+ */
+char *
+exportRelationStatsStmt(PGconn *conn, const char *srcrel, const char *destrel)
+{
+ const char *stmtname = "relstats";
+ const char *values[] = { srcrel, destrel };
+
+ static bool prepared = false;
+
+ PGresult *res;
+ char *out = NULL;
+
+ /*
+ * Most use-cases for this function involve invoking this function once for
+ * each of a large set of relations. As such, using a prepapred statement
+ * make sense.
+ */
+ if (!prepared)
+ {
+ char *sql = exportRelationStatsSQL(PQserverVersion(conn));
+
+ if (sql == NULL)
+ return NULL;
+
+ res = PQprepare(conn, stmtname, sql, 2, NULL);
+ if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ return NULL;
+ }
+
+ free(sql);
+ prepared = true;
+ }
+
+ res = PQexecPrepared(conn, stmtname, 2, values, NULL, NULL, 0);
+
+ /* Result set must be 1x1 */
+ if ((PQresultStatus(res) == PGRES_TUPLES_OK) && (PQntuples(res) == 1))
+ out = strdup(PQgetvalue(res, 0, 0));
+
+ PQclear(res);
+ return out;
+}
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 9ef2f2017e..1db5cf52eb 100644
--- a/src/bin/pg_dump/pg_backup.h
+++ b/src/bin/pg_dump/pg_backup.h
@@ -112,6 +112,7 @@ typedef struct _restoreOptions
int no_publications; /* Skip publication entries */
int no_security_labels; /* Skip security label entries */
int no_subscriptions; /* Skip subscription entries */
+ int no_statistics; /* Skip statistics import */
int strict_names;
const char *filename;
@@ -179,6 +180,7 @@ typedef struct _dumpOptions
int no_security_labels;
int no_publications;
int no_subscriptions;
+ int no_statistics;
int no_toast_compression;
int no_unlogged_table_data;
int serializable_deferrable;
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index d97ebaff5b..d5f61399d9 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -2833,6 +2833,10 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
return 0;
+ /* If it's a stats dump, maybe ignore it */
+ if (ropt->no_statistics && strcmp(te->desc, "STATISTICS") == 0)
+ return 0;
+
/* Ignore it if section is not to be dumped/restored */
switch (curSection)
{
@@ -2862,6 +2866,7 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
*/
if (strcmp(te->desc, "ACL") == 0 ||
strcmp(te->desc, "COMMENT") == 0 ||
+ strcmp(te->desc, "STATISTICS") == 0 ||
strcmp(te->desc, "SECURITY LABEL") == 0)
{
/* Database properties react to createDB, not selectivity options. */
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 171e591696..5a23034c7a 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -59,6 +59,7 @@
#include "compress_io.h"
#include "dumputils.h"
#include "fe_utils/option_utils.h"
+#include "fe_utils/stats_export.h"
#include "fe_utils/string_utils.h"
#include "filter.h"
#include "getopt_long.h"
@@ -425,6 +426,7 @@ main(int argc, char **argv)
{"no-comments", no_argument, &dopt.no_comments, 1},
{"no-publications", no_argument, &dopt.no_publications, 1},
{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
+ {"no-statistics", no_argument, &dopt.no_statistics, 1},
{"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
{"no-toast-compression", no_argument, &dopt.no_toast_compression, 1},
{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
@@ -1130,6 +1132,7 @@ help(const char *progname)
printf(_(" --no-comments do not dump comments\n"));
printf(_(" --no-publications do not dump publications\n"));
printf(_(" --no-security-labels do not dump security label assignments\n"));
+ printf(_(" --no-statistics do not dump statistics\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"));
@@ -6981,6 +6984,7 @@ getTables(Archive *fout, int *numTables)
/* Tables have data */
tblinfo[i].dobj.components |= DUMP_COMPONENT_DATA;
+ tblinfo[i].dobj.components |= DUMP_COMPONENT_STATISTICS;
/* Mark whether table has an ACL */
if (!PQgetisnull(res, i, i_relacl))
@@ -7478,6 +7482,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
AssignDumpId(&indxinfo[j].dobj);
+ indxinfo[j].dobj.components |= DUMP_COMPONENT_STATISTICS;
indxinfo[j].dobj.dump = tbinfo->dobj.dump;
indxinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_indexname));
indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
@@ -10224,6 +10229,53 @@ dumpComment(Archive *fout, const char *type,
catalogId, subid, dumpId, NULL);
}
+/*
+ * dumpRelationStats --
+ *
+ * Dump command to import stats into the relation on the new database.
+ */
+static void
+dumpRelationStats(Archive *fout, const DumpableObject *dobj, char *reltypename)
+{
+ PGconn *conn;
+ const char *qualname;
+ char *stmt;
+ PQExpBuffer query;
+ PQExpBuffer tag;
+
+ /* do nothing, if --no-statistics is supplied */
+ if (fout->dopt->no_statistics)
+ return;
+
+ conn = GetConnection(fout);
+
+ qualname = fmtQualifiedId(dobj->namespace->dobj.name,
+ dobj->name);
+
+ stmt = exportRelationStatsStmt(conn, qualname, NULL);
+
+ tag = createPQExpBuffer();
+ appendPQExpBuffer(tag, "%s %s", reltypename,
+ fmtId(dobj->name));
+
+ query = createPQExpBuffer();
+ appendPQExpBufferStr(query, stmt);
+ free(stmt);
+ appendPQExpBufferStr(query, ";\n");
+
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = dobj->namespace->dobj.name,
+ .description = "STATS IMPORT",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .deps = &(dobj->dumpId),
+ .nDeps = 1));
+
+ destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tag);
+}
+
/*
* dumpTableComment --
*
@@ -16657,6 +16709,10 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
dumpTableSecLabel(fout, tbinfo, reltypename);
+ /* Statistics are dependent on the definition, not the data */
+ if (tbinfo->dobj.dump & DUMP_COMPONENT_STATISTICS)
+ dumpRelationStats(fout, &tbinfo->dobj, reltypename);
+
/* Dump comments on inlined table constraints */
for (j = 0; j < tbinfo->ncheck; j++)
{
@@ -16979,6 +17035,10 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
is_constraint ? indxinfo->indexconstraint :
indxinfo->dobj.dumpId);
+ /* Dump Index Stats */
+ if (indxinfo->dobj.dump & DUMP_COMPONENT_STATISTICS)
+ dumpRelationStats(fout, &indxinfo->dobj, "INDEX");
+
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
free(qindxname);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 9bc93520b4..d6a071ec28 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -101,6 +101,7 @@ typedef uint32 DumpComponents;
#define DUMP_COMPONENT_ACL (1 << 4)
#define DUMP_COMPONENT_POLICY (1 << 5)
#define DUMP_COMPONENT_USERMAP (1 << 6)
+#define DUMP_COMPONENT_STATISTICS (1 << 7)
#define DUMP_COMPONENT_ALL (0xFFFF)
/*
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 491311fe79..37b6ba8a49 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -105,6 +105,7 @@ static int use_setsessauth = 0;
static int no_comments = 0;
static int no_publications = 0;
static int no_security_labels = 0;
+static int no_statistics = 0;
static int no_subscriptions = 0;
static int no_toast_compression = 0;
static int no_unlogged_table_data = 0;
@@ -174,6 +175,7 @@ main(int argc, char *argv[])
{"no-role-passwords", no_argument, &no_role_passwords, 1},
{"no-security-labels", no_argument, &no_security_labels, 1},
{"no-subscriptions", no_argument, &no_subscriptions, 1},
+ {"no-statistics", no_argument, &no_statistics, 1},
{"no-sync", no_argument, NULL, 4},
{"no-toast-compression", no_argument, &no_toast_compression, 1},
{"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
@@ -453,6 +455,8 @@ main(int argc, char *argv[])
appendPQExpBufferStr(pgdumpopts, " --no-publications");
if (no_security_labels)
appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
+ if (no_statistics)
+ appendPQExpBufferStr(pgdumpopts, " --no-statistics");
if (no_subscriptions)
appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
if (no_toast_compression)
@@ -668,6 +672,7 @@ help(void)
printf(_(" --no-publications do not dump publications\n"));
printf(_(" --no-role-passwords do not dump passwords for roles\n"));
printf(_(" --no-security-labels do not dump security label assignments\n"));
+ printf(_(" --no-statistics do not dump statistics\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-table-access-method do not dump table access methods\n"));
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index c3beacdec1..2d326dec72 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -75,6 +75,7 @@ main(int argc, char **argv)
static int no_publications = 0;
static int no_security_labels = 0;
static int no_subscriptions = 0;
+ static int no_statistics = 0;
static int strict_names = 0;
struct option cmdopts[] = {
@@ -126,6 +127,7 @@ main(int argc, char **argv)
{"no-security-labels", no_argument, &no_security_labels, 1},
{"no-subscriptions", no_argument, &no_subscriptions, 1},
{"filter", required_argument, NULL, 4},
+ {"no-statistics", no_argument, &no_statistics, 1},
{NULL, 0, NULL, 0}
};
@@ -358,6 +360,7 @@ main(int argc, char **argv)
opts->no_publications = no_publications;
opts->no_security_labels = no_security_labels;
opts->no_subscriptions = no_subscriptions;
+ opts->no_statistics = no_statistics;
if (if_exists && !opts->dropSchema)
pg_fatal("option --if-exists requires option -c/--clean");
--
2.44.0