mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Transfer statistics during pg_upgrade.
Add support to pg_dump for dumping stats, and use that during pg_upgrade so that statistics are transferred during upgrade. In most cases this removes the need for a costly re-analyze after upgrade. Some statistics are not transferred, such as extended statistics or statistics with a custom stakind. Now pg_dump accepts the options --schema-only, --no-schema, --data-only, --no-data, --statistics-only, and --no-statistics; which allow all combinations of schema, data, and/or stats. The options are named this way to preserve compatibility with the previous --schema-only and --data-only options. Statistics are in SECTION_DATA, unless the object itself is in SECTION_POST_DATA. The stats are represented as calls to pg_restore_relation_stats() and pg_restore_attribute_stats(). Author: Corey Huinker, Jeff Davis Reviewed-by: Jian He Discussion: https://postgr.es/m/CADkLM=fzX7QX6r78fShWDjNN3Vcr4PVAnvXxQ4DiGy6V=0bCUA@mail.gmail.com Discussion: https://postgr.es/m/CADkLM%3DcB0rF3p_FuWRTMSV0983ihTRpsH%2BOCpNyiqE7Wk0vUWA%40mail.gmail.com
This commit is contained in:
@ -123,7 +123,7 @@ PostgreSQL documentation
|
|||||||
<term><option>--data-only</option></term>
|
<term><option>--data-only</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Dump only the data, not the schema (data definitions).
|
Dump only the data, not the schema (data definitions) or statistics.
|
||||||
Table data, large objects, and sequence values are dumped.
|
Table data, large objects, and sequence values are dumped.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -141,13 +141,15 @@ PostgreSQL documentation
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Include large objects in the dump. This is the default behavior
|
Include large objects in the dump. This is the default behavior
|
||||||
except when <option>--schema</option>, <option>--table</option>, or
|
except when <option>--schema</option>, <option>--table</option>,
|
||||||
<option>--schema-only</option> is specified. The <option>-b</option>
|
<option>--schema-only</option>, <option>--statistics-only</option>, or
|
||||||
switch is therefore only useful to add large objects to dumps
|
<option>--no-data</option> is specified. The <option>-b</option>
|
||||||
where a specific schema or table has been requested. Note that
|
switch is therefore only useful to add large objects to dumps where a
|
||||||
large objects are considered data and therefore will be included when
|
specific schema or table has been requested. Note that large objects
|
||||||
<option>--data-only</option> is used, but not
|
are considered data and therefore will be included when
|
||||||
when <option>--schema-only</option> is.
|
<option>--data-only</option> is used, but not when
|
||||||
|
<option>--schema-only</option> or <option>--statistics-only</option>
|
||||||
|
is.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -516,10 +518,11 @@ PostgreSQL documentation
|
|||||||
<term><option>--schema-only</option></term>
|
<term><option>--schema-only</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Dump only the object definitions (schema), not data.
|
Dump only the object definitions (schema), not data or statistics.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This option is the inverse of <option>--data-only</option>.
|
This option is mutually exclusive to <option>--data-only</option>
|
||||||
|
and <option>--statistics-only</option>.
|
||||||
It is similar to, but for historical reasons not identical to,
|
It is similar to, but for historical reasons not identical to,
|
||||||
specifying
|
specifying
|
||||||
<option>--section=pre-data --section=post-data</option>.
|
<option>--section=pre-data --section=post-data</option>.
|
||||||
@ -652,6 +655,17 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--statistics-only</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Dump only the statistics, not the schema (data definitions) or data.
|
||||||
|
Statistics for tables, materialized views, and indexes are dumped.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-Z <replaceable class="parameter">level</replaceable></option></term>
|
<term><option>-Z <replaceable class="parameter">level</replaceable></option></term>
|
||||||
<term><option>-Z <replaceable class="parameter">method</replaceable></option>[:<replaceable>detail</replaceable>]</term>
|
<term><option>-Z <replaceable class="parameter">method</replaceable></option>[:<replaceable>detail</replaceable>]</term>
|
||||||
@ -741,7 +755,8 @@ PostgreSQL documentation
|
|||||||
<term><option>--disable-triggers</option></term>
|
<term><option>--disable-triggers</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This option is relevant only when creating a data-only dump.
|
This option is relevant only when creating a dump that includes data
|
||||||
|
but does not include schema.
|
||||||
It instructs <application>pg_dump</application> to include commands
|
It instructs <application>pg_dump</application> to include commands
|
||||||
to temporarily disable triggers on the target tables while
|
to temporarily disable triggers on the target tables while
|
||||||
the data is restored. Use this if you have referential
|
the data is restored. Use this if you have referential
|
||||||
@ -833,7 +848,8 @@ PostgreSQL documentation
|
|||||||
though you do not need the data in it.
|
though you do not need the data in it.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To exclude data for all tables in the database, see <option>--schema-only</option>.
|
To exclude data for all tables in the database, see <option>--schema-only</option>
|
||||||
|
or <option>--statistics-only</option>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -1080,6 +1096,15 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-data</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not dump data.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-publications</option></term>
|
<term><option>--no-publications</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -1098,6 +1123,24 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-schema</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not dump schema (data definitions).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-statistics</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not dump statistics.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-subscriptions</option></term>
|
<term><option>--no-subscriptions</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -1236,9 +1279,11 @@ PostgreSQL documentation
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The data section contains actual table data, large-object
|
The data section contains actual table data, large-object
|
||||||
contents, and sequence values.
|
contents, statitistics for tables and materialized views and
|
||||||
|
sequence values.
|
||||||
Post-data items include definitions of indexes, triggers, rules,
|
Post-data items include definitions of indexes, triggers, rules,
|
||||||
and constraints other than validated check constraints.
|
statistics for indexes, and constraints other than validated check
|
||||||
|
constraints.
|
||||||
Pre-data items include all other data definition items.
|
Pre-data items include all other data definition items.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -1581,7 +1626,7 @@ CREATE DATABASE foo WITH TEMPLATE template0;
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When a data-only dump is chosen and the option <option>--disable-triggers</option>
|
When a dump without schema is chosen and the option <option>--disable-triggers</option>
|
||||||
is used, <application>pg_dump</application> emits commands
|
is used, <application>pg_dump</application> emits commands
|
||||||
to disable triggers on user tables before inserting the data,
|
to disable triggers on user tables before inserting the data,
|
||||||
and then commands to re-enable them after the data has been
|
and then commands to re-enable them after the data has been
|
||||||
|
@ -81,7 +81,7 @@ PostgreSQL documentation
|
|||||||
<term><option>--data-only</option></term>
|
<term><option>--data-only</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Dump only the data, not the schema (data definitions).
|
Dump only the data, not the schema (data definitions) or statistics.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -265,6 +265,16 @@ exclude database <replaceable class="parameter">PATTERN</replaceable>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--statistics-only</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Dump only the statistics, not the schema (data definitions) or data.
|
||||||
|
Statistics for tables, materialized views, and indexes are dumped.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--binary-upgrade</option></term>
|
<term><option>--binary-upgrade</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -307,7 +317,7 @@ exclude database <replaceable class="parameter">PATTERN</replaceable>
|
|||||||
<term><option>--disable-triggers</option></term>
|
<term><option>--disable-triggers</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This option is relevant only when creating a data-only dump.
|
This option is relevant only when creating a dump with data and without schema.
|
||||||
It instructs <application>pg_dumpall</application> to include commands
|
It instructs <application>pg_dumpall</application> to include commands
|
||||||
to temporarily disable triggers on the target tables while
|
to temporarily disable triggers on the target tables while
|
||||||
the data is restored. Use this if you have referential
|
the data is restored. Use this if you have referential
|
||||||
@ -422,6 +432,15 @@ exclude database <replaceable class="parameter">PATTERN</replaceable>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-data</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not dump data.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-publications</option></term>
|
<term><option>--no-publications</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -447,6 +466,15 @@ exclude database <replaceable class="parameter">PATTERN</replaceable>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-schema</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not dump schema (data definitions).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-security-labels</option></term>
|
<term><option>--no-security-labels</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -456,6 +484,15 @@ exclude database <replaceable class="parameter">PATTERN</replaceable>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-statistics</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not dump statistics.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-subscriptions</option></term>
|
<term><option>--no-subscriptions</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -94,7 +94,7 @@ PostgreSQL documentation
|
|||||||
<term><option>--data-only</option></term>
|
<term><option>--data-only</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Restore only the data, not the schema (data definitions).
|
Restore only the data, not the schema (data definitions) or statistics.
|
||||||
Table data, large objects, and sequence values are restored,
|
Table data, large objects, and sequence values are restored,
|
||||||
if present in the archive.
|
if present in the archive.
|
||||||
</para>
|
</para>
|
||||||
@ -483,10 +483,11 @@ PostgreSQL documentation
|
|||||||
to the extent that schema entries are present in the archive.
|
to the extent that schema entries are present in the archive.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This option is the inverse of <option>--data-only</option>.
|
This option is mutually exclusive of <option>--data-only</option>
|
||||||
|
and <option>--statistics-only</option>.
|
||||||
It is similar to, but for historical reasons not identical to,
|
It is similar to, but for historical reasons not identical to,
|
||||||
specifying
|
specifying
|
||||||
<option>--section=pre-data --section=post-data</option>.
|
<option>--section=pre-data --section=post-data --no-statistics</option>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
(Do not confuse this with the <option>--schema</option> option, which
|
(Do not confuse this with the <option>--schema</option> option, which
|
||||||
@ -599,6 +600,15 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--statistics-only</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Restore only the statistics, not schema (data definitions) or data.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-1</option></term>
|
<term><option>-1</option></term>
|
||||||
<term><option>--single-transaction</option></term>
|
<term><option>--single-transaction</option></term>
|
||||||
@ -617,7 +627,7 @@ PostgreSQL documentation
|
|||||||
<term><option>--disable-triggers</option></term>
|
<term><option>--disable-triggers</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
This option is relevant only when performing a data-only restore.
|
This option is relevant only when performing a restore without schema.
|
||||||
It instructs <application>pg_restore</application> to execute commands
|
It instructs <application>pg_restore</application> to execute commands
|
||||||
to temporarily disable triggers on the target tables while
|
to temporarily disable triggers on the target tables while
|
||||||
the data is restored. Use this if you have referential
|
the data is restored. Use this if you have referential
|
||||||
@ -681,6 +691,16 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-data</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not output commands to restore data, even if the archive
|
||||||
|
contains them.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-data-for-failed-tables</option></term>
|
<term><option>--no-data-for-failed-tables</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -713,6 +733,16 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-schema</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not output commands to restore schema (data definitions), even if
|
||||||
|
the archive contains them.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-security-labels</option></term>
|
<term><option>--no-security-labels</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -723,6 +753,16 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-statistics</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not output commands to restore statistics, even if the archive
|
||||||
|
contains them.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-subscriptions</option></term>
|
<term><option>--no-subscriptions</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -145,6 +145,15 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-statistics</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not restore statistics from the old cluster into the new cluster.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-o</option> <replaceable class="parameter">options</replaceable></term>
|
<term><option>-o</option> <replaceable class="parameter">options</replaceable></term>
|
||||||
<term><option>--old-options</option> <replaceable class="parameter">options</replaceable></term>
|
<term><option>--old-options</option> <replaceable class="parameter">options</replaceable></term>
|
||||||
|
@ -160,6 +160,7 @@ typedef struct _restoreOptions
|
|||||||
/* flags derived from the user-settable flags */
|
/* flags derived from the user-settable flags */
|
||||||
bool dumpSchema;
|
bool dumpSchema;
|
||||||
bool dumpData;
|
bool dumpData;
|
||||||
|
bool dumpStatistics;
|
||||||
} RestoreOptions;
|
} RestoreOptions;
|
||||||
|
|
||||||
typedef struct _dumpOptions
|
typedef struct _dumpOptions
|
||||||
@ -208,6 +209,7 @@ typedef struct _dumpOptions
|
|||||||
/* flags derived from the user-settable flags */
|
/* flags derived from the user-settable flags */
|
||||||
bool dumpSchema;
|
bool dumpSchema;
|
||||||
bool dumpData;
|
bool dumpData;
|
||||||
|
bool dumpStatistics;
|
||||||
} DumpOptions;
|
} DumpOptions;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -46,6 +46,9 @@
|
|||||||
#define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
|
#define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
|
||||||
#define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n"
|
#define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n"
|
||||||
|
|
||||||
|
#define TOC_PREFIX_NONE ""
|
||||||
|
#define TOC_PREFIX_DATA "Data for "
|
||||||
|
#define TOC_PREFIX_STATS "Statistics for "
|
||||||
|
|
||||||
static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
|
static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
|
||||||
const pg_compress_specification compression_spec,
|
const pg_compress_specification compression_spec,
|
||||||
@ -53,7 +56,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
|
|||||||
SetupWorkerPtrType setupWorkerPtr,
|
SetupWorkerPtrType setupWorkerPtr,
|
||||||
DataDirSyncMethod sync_method);
|
DataDirSyncMethod sync_method);
|
||||||
static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te);
|
static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te);
|
||||||
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData);
|
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx);
|
||||||
static char *sanitize_line(const char *str, bool want_hyphen);
|
static char *sanitize_line(const char *str, bool want_hyphen);
|
||||||
static void _doSetFixedOutputState(ArchiveHandle *AH);
|
static void _doSetFixedOutputState(ArchiveHandle *AH);
|
||||||
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
|
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
|
||||||
@ -149,6 +152,7 @@ InitDumpOptions(DumpOptions *opts)
|
|||||||
opts->dumpSections = DUMP_UNSECTIONED;
|
opts->dumpSections = DUMP_UNSECTIONED;
|
||||||
opts->dumpSchema = true;
|
opts->dumpSchema = true;
|
||||||
opts->dumpData = true;
|
opts->dumpData = true;
|
||||||
|
opts->dumpStatistics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -169,9 +173,10 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
|
|||||||
dopt->outputClean = ropt->dropSchema;
|
dopt->outputClean = ropt->dropSchema;
|
||||||
dopt->dumpData = ropt->dumpData;
|
dopt->dumpData = ropt->dumpData;
|
||||||
dopt->dumpSchema = ropt->dumpSchema;
|
dopt->dumpSchema = ropt->dumpSchema;
|
||||||
|
dopt->dumpSections = ropt->dumpSections;
|
||||||
|
dopt->dumpStatistics = ropt->dumpStatistics;
|
||||||
dopt->if_exists = ropt->if_exists;
|
dopt->if_exists = ropt->if_exists;
|
||||||
dopt->column_inserts = ropt->column_inserts;
|
dopt->column_inserts = ropt->column_inserts;
|
||||||
dopt->dumpSections = ropt->dumpSections;
|
|
||||||
dopt->aclsSkip = ropt->aclsSkip;
|
dopt->aclsSkip = ropt->aclsSkip;
|
||||||
dopt->outputSuperuser = ropt->superuser;
|
dopt->outputSuperuser = ropt->superuser;
|
||||||
dopt->outputCreateDB = ropt->createDB;
|
dopt->outputCreateDB = ropt->createDB;
|
||||||
@ -418,8 +423,8 @@ RestoreArchive(Archive *AHX)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Work out if we have an implied data-only restore. This can happen if
|
* Work out if we have an implied schema-less restore. This can happen if
|
||||||
* the dump was data only or if the user has used a toc list to exclude
|
* the dump excluded the schema or the user has used a toc list to exclude
|
||||||
* all of the schema data. All we do is look for schema entries - if none
|
* all of the schema data. All we do is look for schema entries - if none
|
||||||
* are found then we unset the dumpSchema flag.
|
* are found then we unset the dumpSchema flag.
|
||||||
*
|
*
|
||||||
@ -428,20 +433,20 @@ RestoreArchive(Archive *AHX)
|
|||||||
*/
|
*/
|
||||||
if (ropt->dumpSchema)
|
if (ropt->dumpSchema)
|
||||||
{
|
{
|
||||||
int impliedDataOnly = 1;
|
bool no_schema_found = true;
|
||||||
|
|
||||||
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
||||||
{
|
{
|
||||||
if ((te->reqs & REQ_SCHEMA) != 0)
|
if ((te->reqs & REQ_SCHEMA) != 0)
|
||||||
{ /* It's schema, and it's wanted */
|
{
|
||||||
impliedDataOnly = 0;
|
no_schema_found = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (impliedDataOnly)
|
if (no_schema_found)
|
||||||
{
|
{
|
||||||
ropt->dumpSchema = false;
|
ropt->dumpSchema = false;
|
||||||
pg_log_info("implied data-only restore");
|
pg_log_info("implied no-schema restore");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +744,7 @@ RestoreArchive(Archive *AHX)
|
|||||||
|
|
||||||
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
||||||
{
|
{
|
||||||
if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
|
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
|
||||||
continue; /* ignore if not to be dumped at all */
|
continue; /* ignore if not to be dumped at all */
|
||||||
|
|
||||||
switch (_tocEntryRestorePass(te))
|
switch (_tocEntryRestorePass(te))
|
||||||
@ -760,7 +765,7 @@ RestoreArchive(Archive *AHX)
|
|||||||
{
|
{
|
||||||
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
||||||
{
|
{
|
||||||
if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 &&
|
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 &&
|
||||||
_tocEntryRestorePass(te) == RESTORE_PASS_ACL)
|
_tocEntryRestorePass(te) == RESTORE_PASS_ACL)
|
||||||
(void) restore_toc_entry(AH, te, false);
|
(void) restore_toc_entry(AH, te, false);
|
||||||
}
|
}
|
||||||
@ -770,7 +775,7 @@ RestoreArchive(Archive *AHX)
|
|||||||
{
|
{
|
||||||
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
||||||
{
|
{
|
||||||
if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 &&
|
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 &&
|
||||||
_tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL)
|
_tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL)
|
||||||
(void) restore_toc_entry(AH, te, false);
|
(void) restore_toc_entry(AH, te, false);
|
||||||
}
|
}
|
||||||
@ -869,7 +874,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
|
|||||||
pg_log_info("creating %s \"%s\"",
|
pg_log_info("creating %s \"%s\"",
|
||||||
te->desc, te->tag);
|
te->desc, te->tag);
|
||||||
|
|
||||||
_printTocEntry(AH, te, false);
|
_printTocEntry(AH, te, TOC_PREFIX_NONE);
|
||||||
defnDumped = true;
|
defnDumped = true;
|
||||||
|
|
||||||
if (strcmp(te->desc, "TABLE") == 0)
|
if (strcmp(te->desc, "TABLE") == 0)
|
||||||
@ -938,7 +943,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
|
|||||||
*/
|
*/
|
||||||
if (AH->PrintTocDataPtr != NULL)
|
if (AH->PrintTocDataPtr != NULL)
|
||||||
{
|
{
|
||||||
_printTocEntry(AH, te, true);
|
_printTocEntry(AH, te, TOC_PREFIX_DATA);
|
||||||
|
|
||||||
if (strcmp(te->desc, "BLOBS") == 0 ||
|
if (strcmp(te->desc, "BLOBS") == 0 ||
|
||||||
strcmp(te->desc, "BLOB COMMENTS") == 0)
|
strcmp(te->desc, "BLOB COMMENTS") == 0)
|
||||||
@ -1036,15 +1041,21 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
|
|||||||
{
|
{
|
||||||
/* If we haven't already dumped the defn part, do so now */
|
/* If we haven't already dumped the defn part, do so now */
|
||||||
pg_log_info("executing %s %s", te->desc, te->tag);
|
pg_log_info("executing %s %s", te->desc, te->tag);
|
||||||
_printTocEntry(AH, te, false);
|
_printTocEntry(AH, te, TOC_PREFIX_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If it has a statistics component that we want, then process that
|
||||||
|
*/
|
||||||
|
if ((reqs & REQ_STATS) != 0)
|
||||||
|
_printTocEntry(AH, te, TOC_PREFIX_STATS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we emitted anything for this TOC entry, that counts as one action
|
* If we emitted anything for this TOC entry, that counts as one action
|
||||||
* against the transaction-size limit. Commit if it's time to.
|
* against the transaction-size limit. Commit if it's time to.
|
||||||
*/
|
*/
|
||||||
if ((reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && ropt->txn_size > 0)
|
if ((reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 && ropt->txn_size > 0)
|
||||||
{
|
{
|
||||||
if (++AH->txnCount >= ropt->txn_size)
|
if (++AH->txnCount >= ropt->txn_size)
|
||||||
{
|
{
|
||||||
@ -1084,6 +1095,7 @@ NewRestoreOptions(void)
|
|||||||
opts->compression_spec.level = 0;
|
opts->compression_spec.level = 0;
|
||||||
opts->dumpSchema = true;
|
opts->dumpSchema = true;
|
||||||
opts->dumpData = true;
|
opts->dumpData = true;
|
||||||
|
opts->dumpStatistics = true;
|
||||||
|
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
@ -1329,7 +1341,7 @@ PrintTOCSummary(Archive *AHX)
|
|||||||
te->reqs = _tocEntryRequired(te, curSection, AH);
|
te->reqs = _tocEntryRequired(te, curSection, AH);
|
||||||
/* Now, should we print it? */
|
/* Now, should we print it? */
|
||||||
if (ropt->verbose ||
|
if (ropt->verbose ||
|
||||||
(te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0)
|
(te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0)
|
||||||
{
|
{
|
||||||
char *sanitized_name;
|
char *sanitized_name;
|
||||||
char *sanitized_schema;
|
char *sanitized_schema;
|
||||||
@ -2582,7 +2594,7 @@ WriteToc(ArchiveHandle *AH)
|
|||||||
tocCount = 0;
|
tocCount = 0;
|
||||||
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
||||||
{
|
{
|
||||||
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0)
|
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) != 0)
|
||||||
tocCount++;
|
tocCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2592,7 +2604,7 @@ WriteToc(ArchiveHandle *AH)
|
|||||||
|
|
||||||
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
for (te = AH->toc->next; te != AH->toc; te = te->next)
|
||||||
{
|
{
|
||||||
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0)
|
if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
WriteInt(AH, te->dumpId);
|
WriteInt(AH, te->dumpId);
|
||||||
@ -2904,8 +2916,9 @@ StrictNamesCheck(RestoreOptions *ropt)
|
|||||||
* Determine whether we want to restore this TOC entry.
|
* Determine whether we want to restore this TOC entry.
|
||||||
*
|
*
|
||||||
* Returns 0 if entry should be skipped, or some combination of the
|
* Returns 0 if entry should be skipped, or some combination of the
|
||||||
* REQ_SCHEMA and REQ_DATA bits if we want to restore schema and/or data
|
* REQ_SCHEMA, REQ_DATA, and REQ_STATS bits if we want to restore schema, data
|
||||||
* portions of this TOC entry, or REQ_SPECIAL if it's a special entry.
|
* and/or statistics portions of this TOC entry, or REQ_SPECIAL if it's a
|
||||||
|
* special entry.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
_tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
_tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
||||||
@ -2919,6 +2932,14 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
|||||||
strcmp(te->desc, "SEARCHPATH") == 0)
|
strcmp(te->desc, "SEARCHPATH") == 0)
|
||||||
return REQ_SPECIAL;
|
return REQ_SPECIAL;
|
||||||
|
|
||||||
|
if (strcmp(te->desc, "STATISTICS DATA") == 0)
|
||||||
|
{
|
||||||
|
if (!ropt->dumpStatistics)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
res = REQ_STATS;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DATABASE and DATABASE PROPERTIES also have a special rule: they are
|
* DATABASE and DATABASE PROPERTIES also have a special rule: they are
|
||||||
* restored in createDB mode, and not restored otherwise, independently of
|
* restored in createDB mode, and not restored otherwise, independently of
|
||||||
@ -2963,6 +2984,10 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
|||||||
if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
|
if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* If it's statistics and we don't want statistics, maybe ignore it */
|
||||||
|
if (!ropt->dumpStatistics && strcmp(te->desc, "STATISTICS DATA") == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Ignore it if section is not to be dumped/restored */
|
/* Ignore it if section is not to be dumped/restored */
|
||||||
switch (curSection)
|
switch (curSection)
|
||||||
{
|
{
|
||||||
@ -2992,6 +3017,7 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
|||||||
*/
|
*/
|
||||||
if (strcmp(te->desc, "ACL") == 0 ||
|
if (strcmp(te->desc, "ACL") == 0 ||
|
||||||
strcmp(te->desc, "COMMENT") == 0 ||
|
strcmp(te->desc, "COMMENT") == 0 ||
|
||||||
|
strcmp(te->desc, "STATISTICS DATA") == 0 ||
|
||||||
strcmp(te->desc, "SECURITY LABEL") == 0)
|
strcmp(te->desc, "SECURITY LABEL") == 0)
|
||||||
{
|
{
|
||||||
/* Database properties react to createDB, not selectivity options. */
|
/* Database properties react to createDB, not selectivity options. */
|
||||||
@ -3108,6 +3134,7 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine whether the TOC entry contains schema and/or data components,
|
* Determine whether the TOC entry contains schema and/or data components,
|
||||||
* and mask off inapplicable REQ bits. If it had a dataDumper, assume
|
* and mask off inapplicable REQ bits. If it had a dataDumper, assume
|
||||||
@ -3173,12 +3200,12 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
|
|||||||
strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
|
strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
|
||||||
(strcmp(te->desc, "SECURITY LABEL") == 0 &&
|
(strcmp(te->desc, "SECURITY LABEL") == 0 &&
|
||||||
strncmp(te->tag, "LARGE OBJECT", 12) == 0))))
|
strncmp(te->tag, "LARGE OBJECT", 12) == 0))))
|
||||||
res = res & REQ_SCHEMA;
|
res = res & (REQ_SCHEMA | REQ_STATS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mask it if we don't want schema */
|
/* Mask it if we don't want schema */
|
||||||
if (!ropt->dumpSchema)
|
if (!ropt->dumpSchema)
|
||||||
res = res & REQ_DATA;
|
res = res & (REQ_DATA | REQ_STATS);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -3730,7 +3757,7 @@ _getObjectDescription(PQExpBuffer buf, const TocEntry *te)
|
|||||||
* will remain at default, until the matching ACL TOC entry is restored.
|
* will remain at default, until the matching ACL TOC entry is restored.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
|
_printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx)
|
||||||
{
|
{
|
||||||
RestoreOptions *ropt = AH->public.ropt;
|
RestoreOptions *ropt = AH->public.ropt;
|
||||||
|
|
||||||
@ -3749,16 +3776,10 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
|
|||||||
/* Emit header comment for item */
|
/* Emit header comment for item */
|
||||||
if (!AH->noTocComments)
|
if (!AH->noTocComments)
|
||||||
{
|
{
|
||||||
const char *pfx;
|
|
||||||
char *sanitized_name;
|
char *sanitized_name;
|
||||||
char *sanitized_schema;
|
char *sanitized_schema;
|
||||||
char *sanitized_owner;
|
char *sanitized_owner;
|
||||||
|
|
||||||
if (isData)
|
|
||||||
pfx = "Data for ";
|
|
||||||
else
|
|
||||||
pfx = "";
|
|
||||||
|
|
||||||
ahprintf(AH, "--\n");
|
ahprintf(AH, "--\n");
|
||||||
if (AH->public.verbose)
|
if (AH->public.verbose)
|
||||||
{
|
{
|
||||||
@ -4325,7 +4346,7 @@ restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate,
|
|||||||
if (next_work_item != NULL)
|
if (next_work_item != NULL)
|
||||||
{
|
{
|
||||||
/* If not to be restored, don't waste time launching a worker */
|
/* If not to be restored, don't waste time launching a worker */
|
||||||
if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
|
if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
|
||||||
{
|
{
|
||||||
pg_log_info("skipping item %d %s %s",
|
pg_log_info("skipping item %d %s %s",
|
||||||
next_work_item->dumpId,
|
next_work_item->dumpId,
|
||||||
|
@ -209,7 +209,8 @@ typedef enum
|
|||||||
|
|
||||||
#define REQ_SCHEMA 0x01 /* want schema */
|
#define REQ_SCHEMA 0x01 /* want schema */
|
||||||
#define REQ_DATA 0x02 /* want data */
|
#define REQ_DATA 0x02 /* want data */
|
||||||
#define REQ_SPECIAL 0x04 /* for special TOC entries */
|
#define REQ_STATS 0x04
|
||||||
|
#define REQ_SPECIAL 0x08 /* for special TOC entries */
|
||||||
|
|
||||||
struct _archiveHandle
|
struct _archiveHandle
|
||||||
{
|
{
|
||||||
|
@ -780,7 +780,7 @@ _PrepParallelRestore(ArchiveHandle *AH)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* We may ignore items not due to be restored */
|
/* We may ignore items not due to be restored */
|
||||||
if ((te->reqs & REQ_DATA) == 0)
|
if ((te->reqs & (REQ_DATA | REQ_STATS)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -431,6 +431,10 @@ main(int argc, char **argv)
|
|||||||
DataDirSyncMethod sync_method = DATA_DIR_SYNC_METHOD_FSYNC;
|
DataDirSyncMethod sync_method = DATA_DIR_SYNC_METHOD_FSYNC;
|
||||||
bool data_only = false;
|
bool data_only = false;
|
||||||
bool schema_only = false;
|
bool schema_only = false;
|
||||||
|
bool statistics_only = false;
|
||||||
|
bool no_data = false;
|
||||||
|
bool no_schema = false;
|
||||||
|
bool no_statistics = false;
|
||||||
|
|
||||||
static DumpOptions dopt;
|
static DumpOptions dopt;
|
||||||
|
|
||||||
@ -490,11 +494,15 @@ main(int argc, char **argv)
|
|||||||
{"section", required_argument, NULL, 5},
|
{"section", required_argument, NULL, 5},
|
||||||
{"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
|
{"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
|
||||||
{"snapshot", required_argument, NULL, 6},
|
{"snapshot", required_argument, NULL, 6},
|
||||||
|
{"statistics-only", no_argument, NULL, 18},
|
||||||
{"strict-names", no_argument, &strict_names, 1},
|
{"strict-names", no_argument, &strict_names, 1},
|
||||||
{"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
|
{"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
|
||||||
{"no-comments", no_argument, &dopt.no_comments, 1},
|
{"no-comments", no_argument, &dopt.no_comments, 1},
|
||||||
|
{"no-data", no_argument, NULL, 19},
|
||||||
{"no-publications", no_argument, &dopt.no_publications, 1},
|
{"no-publications", no_argument, &dopt.no_publications, 1},
|
||||||
|
{"no-schema", no_argument, NULL, 20},
|
||||||
{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
|
{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
|
||||||
|
{"no-statistics", no_argument, NULL, 21},
|
||||||
{"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
|
{"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
|
||||||
{"no-toast-compression", no_argument, &dopt.no_toast_compression, 1},
|
{"no-toast-compression", no_argument, &dopt.no_toast_compression, 1},
|
||||||
{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
|
{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
|
||||||
@ -540,7 +548,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
InitDumpOptions(&dopt);
|
InitDumpOptions(&dopt);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
|
while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxXZ:",
|
||||||
long_options, &optindex)) != -1)
|
long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
@ -748,6 +756,22 @@ main(int argc, char **argv)
|
|||||||
optarg);
|
optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 18:
|
||||||
|
statistics_only = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 19:
|
||||||
|
no_data = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 20:
|
||||||
|
no_schema = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 21:
|
||||||
|
no_statistics = true;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* getopt_long already emitted a complaint */
|
/* getopt_long already emitted a complaint */
|
||||||
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
|
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
|
||||||
@ -785,6 +809,17 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (data_only && schema_only)
|
if (data_only && schema_only)
|
||||||
pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together");
|
pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together");
|
||||||
|
if (schema_only && statistics_only)
|
||||||
|
pg_fatal("options -s/--schema-only and --statistics-only cannot be used together");
|
||||||
|
if (data_only && statistics_only)
|
||||||
|
pg_fatal("options -a/--data-only and --statistics-only cannot be used together");
|
||||||
|
|
||||||
|
if (data_only && no_data)
|
||||||
|
pg_fatal("options -a/--data-only and --no-data cannot be used together");
|
||||||
|
if (schema_only && no_schema)
|
||||||
|
pg_fatal("options -s/--schema-only and --no-schema cannot be used together");
|
||||||
|
if (statistics_only && no_statistics)
|
||||||
|
pg_fatal("options --statistics-only and --no-statistics cannot be used together");
|
||||||
|
|
||||||
if (schema_only && foreign_servers_include_patterns.head != NULL)
|
if (schema_only && foreign_servers_include_patterns.head != NULL)
|
||||||
pg_fatal("options -s/--schema-only and --include-foreign-data cannot be used together");
|
pg_fatal("options -s/--schema-only and --include-foreign-data cannot be used together");
|
||||||
@ -799,8 +834,9 @@ main(int argc, char **argv)
|
|||||||
pg_fatal("option --if-exists requires option -c/--clean");
|
pg_fatal("option --if-exists requires option -c/--clean");
|
||||||
|
|
||||||
/* set derivative flags */
|
/* set derivative flags */
|
||||||
dopt.dumpSchema = (!data_only);
|
dopt.dumpData = data_only || (!schema_only && !statistics_only && !no_data);
|
||||||
dopt.dumpData = (!schema_only);
|
dopt.dumpSchema = schema_only || (!data_only && !statistics_only && !no_schema);
|
||||||
|
dopt.dumpStatistics = statistics_only || (!data_only && !schema_only && !no_statistics);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --inserts are already implied above if --column-inserts or
|
* --inserts are already implied above if --column-inserts or
|
||||||
@ -1100,6 +1136,7 @@ main(int argc, char **argv)
|
|||||||
ropt->dropSchema = dopt.outputClean;
|
ropt->dropSchema = dopt.outputClean;
|
||||||
ropt->dumpData = dopt.dumpData;
|
ropt->dumpData = dopt.dumpData;
|
||||||
ropt->dumpSchema = dopt.dumpSchema;
|
ropt->dumpSchema = dopt.dumpSchema;
|
||||||
|
ropt->dumpStatistics = dopt.dumpStatistics;
|
||||||
ropt->if_exists = dopt.if_exists;
|
ropt->if_exists = dopt.if_exists;
|
||||||
ropt->column_inserts = dopt.column_inserts;
|
ropt->column_inserts = dopt.column_inserts;
|
||||||
ropt->dumpSections = dopt.dumpSections;
|
ropt->dumpSections = dopt.dumpSections;
|
||||||
@ -1178,7 +1215,7 @@ help(const char *progname)
|
|||||||
printf(_(" -?, --help show this help, then exit\n"));
|
printf(_(" -?, --help show this help, then exit\n"));
|
||||||
|
|
||||||
printf(_("\nOptions controlling the output content:\n"));
|
printf(_("\nOptions controlling the output content:\n"));
|
||||||
printf(_(" -a, --data-only dump only the data, not the schema\n"));
|
printf(_(" -a, --data-only dump only the data, not the schema or statistics\n"));
|
||||||
printf(_(" -b, --large-objects include large objects in dump\n"));
|
printf(_(" -b, --large-objects include large objects in dump\n"));
|
||||||
printf(_(" --blobs (same as --large-objects, deprecated)\n"));
|
printf(_(" --blobs (same as --large-objects, deprecated)\n"));
|
||||||
printf(_(" -B, --no-large-objects exclude large objects in dump\n"));
|
printf(_(" -B, --no-large-objects exclude large objects in dump\n"));
|
||||||
@ -1191,7 +1228,7 @@ help(const char *progname)
|
|||||||
printf(_(" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n"));
|
printf(_(" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n"));
|
||||||
printf(_(" -O, --no-owner skip restoration of object ownership in\n"
|
printf(_(" -O, --no-owner skip restoration of object ownership in\n"
|
||||||
" plain-text format\n"));
|
" plain-text format\n"));
|
||||||
printf(_(" -s, --schema-only dump only the schema, no data\n"));
|
printf(_(" -s, --schema-only dump only the schema, no data or statistics\n"));
|
||||||
printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
|
printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
|
||||||
printf(_(" -t, --table=PATTERN dump only the specified table(s)\n"));
|
printf(_(" -t, --table=PATTERN dump only the specified table(s)\n"));
|
||||||
printf(_(" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n"));
|
printf(_(" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n"));
|
||||||
@ -1220,8 +1257,11 @@ help(const char *progname)
|
|||||||
printf(_(" --inserts dump data as INSERT commands, rather than COPY\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(_(" --load-via-partition-root load partitions via the root table\n"));
|
||||||
printf(_(" --no-comments do not dump comment commands\n"));
|
printf(_(" --no-comments do not dump comment commands\n"));
|
||||||
|
printf(_(" --no-data do not dump data\n"));
|
||||||
printf(_(" --no-publications do not dump publications\n"));
|
printf(_(" --no-publications do not dump publications\n"));
|
||||||
|
printf(_(" --no-schema do not dump schema\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-statistics do not dump statistics\n"));
|
||||||
printf(_(" --no-subscriptions do not dump subscriptions\n"));
|
printf(_(" --no-subscriptions do not dump subscriptions\n"));
|
||||||
printf(_(" --no-table-access-method do not dump table access methods\n"));
|
printf(_(" --no-table-access-method do not dump table access methods\n"));
|
||||||
printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
|
printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
|
||||||
@ -1233,6 +1273,7 @@ help(const char *progname)
|
|||||||
printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n"));
|
printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n"));
|
||||||
printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
|
printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
|
||||||
printf(_(" --snapshot=SNAPSHOT use given snapshot for the dump\n"));
|
printf(_(" --snapshot=SNAPSHOT use given snapshot for the dump\n"));
|
||||||
|
printf(_(" --statistics-only dump only the statistics, not schema or data\n"));
|
||||||
printf(_(" --strict-names require table and/or schema include patterns to\n"
|
printf(_(" --strict-names require table and/or schema include patterns to\n"
|
||||||
" match at least one entity each\n"));
|
" match at least one entity each\n"));
|
||||||
printf(_(" --table-and-children=PATTERN dump only the specified table(s), including\n"
|
printf(_(" --table-and-children=PATTERN dump only the specified table(s), including\n"
|
||||||
@ -6767,6 +6808,45 @@ getFuncs(Archive *fout)
|
|||||||
destroyPQExpBuffer(query);
|
destroyPQExpBuffer(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getRelationStatistics
|
||||||
|
* register the statistics object as a dependent of the relation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static RelStatsInfo *
|
||||||
|
getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
|
||||||
|
{
|
||||||
|
if (!fout->dopt->dumpStatistics)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((relkind == RELKIND_RELATION) ||
|
||||||
|
(relkind == RELKIND_PARTITIONED_TABLE) ||
|
||||||
|
(relkind == RELKIND_INDEX) ||
|
||||||
|
(relkind == RELKIND_PARTITIONED_INDEX) ||
|
||||||
|
(relkind == RELKIND_MATVIEW))
|
||||||
|
{
|
||||||
|
RelStatsInfo *info = pg_malloc0(sizeof(RelStatsInfo));
|
||||||
|
DumpableObject *dobj = &info->dobj;
|
||||||
|
|
||||||
|
dobj->objType = DO_REL_STATS;
|
||||||
|
dobj->catId.tableoid = 0;
|
||||||
|
dobj->catId.oid = 0;
|
||||||
|
AssignDumpId(dobj);
|
||||||
|
dobj->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
|
||||||
|
dobj->dependencies[0] = rel->dumpId;
|
||||||
|
dobj->nDeps = 1;
|
||||||
|
dobj->allocDeps = 1;
|
||||||
|
dobj->components |= DUMP_COMPONENT_STATISTICS;
|
||||||
|
dobj->name = pg_strdup(rel->name);
|
||||||
|
dobj->namespace = rel->namespace;
|
||||||
|
info->relkind = relkind;
|
||||||
|
info->postponed_def = false;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getTables
|
* getTables
|
||||||
* read all the tables (no indexes) in the system catalogs,
|
* read all the tables (no indexes) in the system catalogs,
|
||||||
@ -7126,8 +7206,8 @@ getTables(Archive *fout, int *numTables)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Now, consider the table "interesting" if we need to dump its
|
* Now, consider the table "interesting" if we need to dump its
|
||||||
* definition or its data. Later on, we'll skip a lot of data
|
* definition, data or its statistics. Later on, we'll skip a lot of
|
||||||
* collection for uninteresting tables.
|
* data collection for uninteresting tables.
|
||||||
*
|
*
|
||||||
* Note: the "interesting" flag will also be set by flagInhTables for
|
* Note: the "interesting" flag will also be set by flagInhTables for
|
||||||
* parents of interesting tables, so that we collect necessary
|
* parents of interesting tables, so that we collect necessary
|
||||||
@ -7137,7 +7217,8 @@ getTables(Archive *fout, int *numTables)
|
|||||||
*/
|
*/
|
||||||
tblinfo[i].interesting = (tblinfo[i].dobj.dump &
|
tblinfo[i].interesting = (tblinfo[i].dobj.dump &
|
||||||
(DUMP_COMPONENT_DEFINITION |
|
(DUMP_COMPONENT_DEFINITION |
|
||||||
DUMP_COMPONENT_DATA)) != 0;
|
DUMP_COMPONENT_DATA |
|
||||||
|
DUMP_COMPONENT_STATISTICS)) != 0;
|
||||||
|
|
||||||
tblinfo[i].dummy_view = false; /* might get set during sort */
|
tblinfo[i].dummy_view = false; /* might get set during sort */
|
||||||
tblinfo[i].postponed_def = false; /* might get set during sort */
|
tblinfo[i].postponed_def = false; /* might get set during sort */
|
||||||
@ -7150,6 +7231,10 @@ getTables(Archive *fout, int *numTables)
|
|||||||
tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
|
tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
|
||||||
tblinfo[i].hascolumnACLs = false; /* may get set later */
|
tblinfo[i].hascolumnACLs = false; /* may get set later */
|
||||||
|
|
||||||
|
/* Add statistics */
|
||||||
|
if (tblinfo[i].interesting)
|
||||||
|
getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relkind);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read-lock target tables to make sure they aren't DROPPED or altered
|
* Read-lock target tables to make sure they aren't DROPPED or altered
|
||||||
* in schema before we get around to dumping them.
|
* in schema before we get around to dumping them.
|
||||||
@ -7638,6 +7723,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
|||||||
for (int c = 0; c < numinds; c++, j++)
|
for (int c = 0; c < numinds; c++, j++)
|
||||||
{
|
{
|
||||||
char contype;
|
char contype;
|
||||||
|
char indexkind;
|
||||||
|
RelStatsInfo *relstats;
|
||||||
|
|
||||||
indxinfo[j].dobj.objType = DO_INDEX;
|
indxinfo[j].dobj.objType = DO_INDEX;
|
||||||
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
|
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
|
||||||
@ -7665,7 +7752,14 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
|||||||
{
|
{
|
||||||
NULL, NULL
|
NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (indxinfo[j].parentidx == 0)
|
||||||
|
indexkind = RELKIND_INDEX;
|
||||||
|
else
|
||||||
|
indexkind = RELKIND_PARTITIONED_INDEX;
|
||||||
|
|
||||||
contype = *(PQgetvalue(res, j, i_contype));
|
contype = *(PQgetvalue(res, j, i_contype));
|
||||||
|
relstats = getRelationStatistics(fout, &indxinfo[j].dobj, indexkind);
|
||||||
|
|
||||||
if (contype == 'p' || contype == 'u' || contype == 'x')
|
if (contype == 'p' || contype == 'u' || contype == 'x')
|
||||||
{
|
{
|
||||||
@ -7699,6 +7793,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
|||||||
constrinfo->separate = true;
|
constrinfo->separate = true;
|
||||||
|
|
||||||
indxinfo[j].indexconstraint = constrinfo->dobj.dumpId;
|
indxinfo[j].indexconstraint = constrinfo->dobj.dumpId;
|
||||||
|
if (relstats != NULL)
|
||||||
|
addObjectDependency(&relstats->dobj, constrinfo->dobj.dumpId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -10287,6 +10383,296 @@ dumpComment(Archive *fout, const char *type,
|
|||||||
catalogId, subid, dumpId, NULL);
|
catalogId, subid, dumpId, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tabular description of the parameters to pg_restore_relation_stats()
|
||||||
|
* param_name, param_type
|
||||||
|
*/
|
||||||
|
static const char *rel_stats_arginfo[][2] = {
|
||||||
|
{"relation", "regclass"},
|
||||||
|
{"version", "integer"},
|
||||||
|
{"relpages", "integer"},
|
||||||
|
{"reltuples", "real"},
|
||||||
|
{"relallvisible", "integer"},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tabular description of the parameters to pg_restore_attribute_stats()
|
||||||
|
* param_name, param_type
|
||||||
|
*/
|
||||||
|
static const char *att_stats_arginfo[][2] = {
|
||||||
|
{"relation", "regclass"},
|
||||||
|
{"attname", "name"},
|
||||||
|
{"inherited", "boolean"},
|
||||||
|
{"version", "integer"},
|
||||||
|
{"null_frac", "float4"},
|
||||||
|
{"avg_width", "integer"},
|
||||||
|
{"n_distinct", "float4"},
|
||||||
|
{"most_common_vals", "text"},
|
||||||
|
{"most_common_freqs", "float4[]"},
|
||||||
|
{"histogram_bounds", "text"},
|
||||||
|
{"correlation", "float4"},
|
||||||
|
{"most_common_elems", "text"},
|
||||||
|
{"most_common_elem_freqs", "float4[]"},
|
||||||
|
{"elem_count_histogram", "float4[]"},
|
||||||
|
{"range_length_histogram", "text"},
|
||||||
|
{"range_empty_frac", "float4"},
|
||||||
|
{"range_bounds_histogram", "text"},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getRelStatsExportQuery --
|
||||||
|
*
|
||||||
|
* Generate a query that will fetch all relation (e.g. pg_class)
|
||||||
|
* stats for a given relation.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
getRelStatsExportQuery(PQExpBuffer query, Archive *fout,
|
||||||
|
const char *schemaname, const char *relname)
|
||||||
|
{
|
||||||
|
resetPQExpBuffer(query);
|
||||||
|
appendPQExpBufferStr(query,
|
||||||
|
"SELECT c.oid::regclass AS relation, "
|
||||||
|
"current_setting('server_version_num') AS version, "
|
||||||
|
"c.relpages, c.reltuples, c.relallvisible "
|
||||||
|
"FROM pg_class c "
|
||||||
|
"JOIN pg_namespace n "
|
||||||
|
"ON n.oid = c.relnamespace "
|
||||||
|
"WHERE n.nspname = ");
|
||||||
|
appendStringLiteralAH(query, schemaname, fout);
|
||||||
|
appendPQExpBufferStr(query, " AND c.relname = ");
|
||||||
|
appendStringLiteralAH(query, relname, fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getAttStatsExportQuery --
|
||||||
|
*
|
||||||
|
* Generate a query that will fetch all attribute (e.g. pg_statistic)
|
||||||
|
* stats for a given relation.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
getAttStatsExportQuery(PQExpBuffer query, Archive *fout,
|
||||||
|
const char *schemaname, const char *relname)
|
||||||
|
{
|
||||||
|
resetPQExpBuffer(query);
|
||||||
|
appendPQExpBufferStr(query,
|
||||||
|
"SELECT c.oid::regclass AS relation, "
|
||||||
|
"s.attname,"
|
||||||
|
"s.inherited,"
|
||||||
|
"current_setting('server_version_num') AS version, "
|
||||||
|
"s.null_frac,"
|
||||||
|
"s.avg_width,"
|
||||||
|
"s.n_distinct,"
|
||||||
|
"s.most_common_vals,"
|
||||||
|
"s.most_common_freqs,"
|
||||||
|
"s.histogram_bounds,"
|
||||||
|
"s.correlation,"
|
||||||
|
"s.most_common_elems,"
|
||||||
|
"s.most_common_elem_freqs,"
|
||||||
|
"s.elem_count_histogram,");
|
||||||
|
|
||||||
|
if (fout->remoteVersion >= 170000)
|
||||||
|
appendPQExpBufferStr(query,
|
||||||
|
"s.range_length_histogram,"
|
||||||
|
"s.range_empty_frac,"
|
||||||
|
"s.range_bounds_histogram ");
|
||||||
|
else
|
||||||
|
appendPQExpBufferStr(query,
|
||||||
|
"NULL AS range_length_histogram,"
|
||||||
|
"NULL AS range_empty_frac,"
|
||||||
|
"NULL AS range_bounds_histogram ");
|
||||||
|
|
||||||
|
appendPQExpBufferStr(query,
|
||||||
|
"FROM pg_stats s "
|
||||||
|
"JOIN pg_namespace n "
|
||||||
|
"ON n.nspname = s.schemaname "
|
||||||
|
"JOIN pg_class c "
|
||||||
|
"ON c.relname = s.tablename "
|
||||||
|
"AND c.relnamespace = n.oid "
|
||||||
|
"WHERE s.schemaname = ");
|
||||||
|
appendStringLiteralAH(query, schemaname, fout);
|
||||||
|
appendPQExpBufferStr(query, " AND s.tablename = ");
|
||||||
|
appendStringLiteralAH(query, relname, fout);
|
||||||
|
appendPQExpBufferStr(query, " ORDER BY s.attname, s.inherited");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* appendNamedArgument --
|
||||||
|
*
|
||||||
|
* Convenience routine for constructing parameters of the form:
|
||||||
|
* 'paraname', 'value'::type
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname,
|
||||||
|
const char *argval, const char *argtype)
|
||||||
|
{
|
||||||
|
appendPQExpBufferStr(out, "\t");
|
||||||
|
|
||||||
|
appendStringLiteralAH(out, argname, fout);
|
||||||
|
appendPQExpBufferStr(out, ", ");
|
||||||
|
|
||||||
|
appendStringLiteralAH(out, argval, fout);
|
||||||
|
appendPQExpBuffer(out, "::%s", argtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* appendRelStatsImport --
|
||||||
|
*
|
||||||
|
* Append a formatted pg_restore_relation_stats statement.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
appendRelStatsImport(PQExpBuffer out, Archive *fout, PGresult *res)
|
||||||
|
{
|
||||||
|
const char *sep = "";
|
||||||
|
|
||||||
|
if (PQntuples(res) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
|
||||||
|
|
||||||
|
for (int argno = 0; argno < lengthof(rel_stats_arginfo); argno++)
|
||||||
|
{
|
||||||
|
const char *argname = rel_stats_arginfo[argno][0];
|
||||||
|
const char *argtype = rel_stats_arginfo[argno][1];
|
||||||
|
int fieldno = PQfnumber(res, argname);
|
||||||
|
|
||||||
|
if (fieldno < 0)
|
||||||
|
pg_fatal("relation stats export query missing field '%s'",
|
||||||
|
argname);
|
||||||
|
|
||||||
|
if (PQgetisnull(res, 0, fieldno))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
appendPQExpBufferStr(out, sep);
|
||||||
|
appendNamedArgument(out, fout, argname, PQgetvalue(res, 0, fieldno), argtype);
|
||||||
|
|
||||||
|
sep = ",\n";
|
||||||
|
}
|
||||||
|
appendPQExpBufferStr(out, "\n);\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* appendAttStatsImport --
|
||||||
|
*
|
||||||
|
* Append a series of formatted pg_restore_attribute_stats statements.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
appendAttStatsImport(PQExpBuffer out, Archive *fout, PGresult *res)
|
||||||
|
{
|
||||||
|
for (int rownum = 0; rownum < PQntuples(res); rownum++)
|
||||||
|
{
|
||||||
|
const char *sep = "";
|
||||||
|
|
||||||
|
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
|
||||||
|
for (int argno = 0; argno < lengthof(att_stats_arginfo); argno++)
|
||||||
|
{
|
||||||
|
const char *argname = att_stats_arginfo[argno][0];
|
||||||
|
const char *argtype = att_stats_arginfo[argno][1];
|
||||||
|
int fieldno = PQfnumber(res, argname);
|
||||||
|
|
||||||
|
if (fieldno < 0)
|
||||||
|
pg_fatal("attribute stats export query missing field '%s'",
|
||||||
|
argname);
|
||||||
|
|
||||||
|
if (PQgetisnull(res, rownum, fieldno))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
appendPQExpBufferStr(out, sep);
|
||||||
|
appendNamedArgument(out, fout, argname, PQgetvalue(res, rownum, fieldno), argtype);
|
||||||
|
sep = ",\n";
|
||||||
|
}
|
||||||
|
appendPQExpBufferStr(out, "\n);\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decide which section to use based on the relkind of the parent object.
|
||||||
|
*
|
||||||
|
* NB: materialized views may be postponed from SECTION_PRE_DATA to
|
||||||
|
* SECTION_POST_DATA to resolve some kinds of dependency problems. If so, the
|
||||||
|
* matview stats will also be postponed to SECTION_POST_DATA. See
|
||||||
|
* repairMatViewBoundaryMultiLoop().
|
||||||
|
*/
|
||||||
|
static teSection
|
||||||
|
statisticsDumpSection(const RelStatsInfo *rsinfo)
|
||||||
|
{
|
||||||
|
switch (rsinfo->relkind)
|
||||||
|
{
|
||||||
|
case RELKIND_RELATION:
|
||||||
|
case RELKIND_PARTITIONED_TABLE:
|
||||||
|
case RELKIND_MATVIEW:
|
||||||
|
return SECTION_DATA;
|
||||||
|
case RELKIND_INDEX:
|
||||||
|
case RELKIND_PARTITIONED_INDEX:
|
||||||
|
return SECTION_POST_DATA;
|
||||||
|
default:
|
||||||
|
pg_fatal("cannot dump statistics for relation kind '%c'",
|
||||||
|
rsinfo->relkind);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* keep compiler quiet */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dumpRelationStats --
|
||||||
|
*
|
||||||
|
* Dump command to import stats into the relation on the new database.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
|
||||||
|
{
|
||||||
|
PGresult *res;
|
||||||
|
PQExpBuffer query;
|
||||||
|
PQExpBuffer out;
|
||||||
|
PQExpBuffer tag;
|
||||||
|
DumpableObject *dobj = (DumpableObject *) &rsinfo->dobj;
|
||||||
|
DumpId *deps = NULL;
|
||||||
|
int ndeps = 0;
|
||||||
|
|
||||||
|
/* nothing to do if we are not dumping statistics */
|
||||||
|
if (!fout->dopt->dumpStatistics)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* dependent on the relation definition, if doing schema */
|
||||||
|
if (fout->dopt->dumpSchema)
|
||||||
|
{
|
||||||
|
deps = dobj->dependencies;
|
||||||
|
ndeps = dobj->nDeps;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = createPQExpBuffer();
|
||||||
|
appendPQExpBufferStr(tag, fmtId(dobj->name));
|
||||||
|
|
||||||
|
query = createPQExpBuffer();
|
||||||
|
out = createPQExpBuffer();
|
||||||
|
|
||||||
|
getRelStatsExportQuery(query, fout, dobj->namespace->dobj.name,
|
||||||
|
dobj->name);
|
||||||
|
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
|
||||||
|
appendRelStatsImport(out, fout, res);
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
getAttStatsExportQuery(query, fout, dobj->namespace->dobj.name,
|
||||||
|
dobj->name);
|
||||||
|
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
|
||||||
|
appendAttStatsImport(out, fout, res);
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
ArchiveEntry(fout, nilCatalogId, createDumpId(),
|
||||||
|
ARCHIVE_OPTS(.tag = tag->data,
|
||||||
|
.namespace = dobj->namespace->dobj.name,
|
||||||
|
.description = "STATISTICS DATA",
|
||||||
|
.section = rsinfo->postponed_def ?
|
||||||
|
SECTION_POST_DATA : statisticsDumpSection(rsinfo),
|
||||||
|
.createStmt = out->data,
|
||||||
|
.deps = deps,
|
||||||
|
.nDeps = ndeps));
|
||||||
|
|
||||||
|
destroyPQExpBuffer(query);
|
||||||
|
destroyPQExpBuffer(out);
|
||||||
|
destroyPQExpBuffer(tag);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dumpTableComment --
|
* dumpTableComment --
|
||||||
*
|
*
|
||||||
@ -10735,6 +11121,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
|
|||||||
case DO_SUBSCRIPTION_REL:
|
case DO_SUBSCRIPTION_REL:
|
||||||
dumpSubscriptionTable(fout, (const SubRelInfo *) dobj);
|
dumpSubscriptionTable(fout, (const SubRelInfo *) dobj);
|
||||||
break;
|
break;
|
||||||
|
case DO_REL_STATS:
|
||||||
|
dumpRelationStats(fout, (const RelStatsInfo *) dobj);
|
||||||
|
break;
|
||||||
case DO_PRE_DATA_BOUNDARY:
|
case DO_PRE_DATA_BOUNDARY:
|
||||||
case DO_POST_DATA_BOUNDARY:
|
case DO_POST_DATA_BOUNDARY:
|
||||||
/* never dumped, nothing to do */
|
/* never dumped, nothing to do */
|
||||||
@ -18964,6 +19353,16 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
|
|||||||
/* must come after the pre-data boundary */
|
/* must come after the pre-data boundary */
|
||||||
addObjectDependency(dobj, preDataBound->dumpId);
|
addObjectDependency(dobj, preDataBound->dumpId);
|
||||||
break;
|
break;
|
||||||
|
case DO_REL_STATS:
|
||||||
|
/* stats section varies by parent object type, DATA or POST */
|
||||||
|
if (statisticsDumpSection((RelStatsInfo *) dobj) == SECTION_DATA)
|
||||||
|
{
|
||||||
|
addObjectDependency(dobj, preDataBound->dumpId);
|
||||||
|
addObjectDependency(postDataBound, dobj->dumpId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addObjectDependency(dobj, postDataBound->dumpId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,10 +83,13 @@ typedef enum
|
|||||||
DO_PUBLICATION,
|
DO_PUBLICATION,
|
||||||
DO_PUBLICATION_REL,
|
DO_PUBLICATION_REL,
|
||||||
DO_PUBLICATION_TABLE_IN_SCHEMA,
|
DO_PUBLICATION_TABLE_IN_SCHEMA,
|
||||||
|
DO_REL_STATS,
|
||||||
DO_SUBSCRIPTION,
|
DO_SUBSCRIPTION,
|
||||||
DO_SUBSCRIPTION_REL, /* see note for SubRelInfo */
|
DO_SUBSCRIPTION_REL, /* see note for SubRelInfo */
|
||||||
} DumpableObjectType;
|
} DumpableObjectType;
|
||||||
|
|
||||||
|
#define NUM_DUMPABLE_OBJECT_TYPES (DO_SUBSCRIPTION_REL + 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DumpComponents is a bitmask of the potentially dumpable components of
|
* DumpComponents is a bitmask of the potentially dumpable components of
|
||||||
* a database object: its core definition, plus optional attributes such
|
* a database object: its core definition, plus optional attributes such
|
||||||
@ -110,6 +113,7 @@ typedef uint32 DumpComponents;
|
|||||||
#define DUMP_COMPONENT_ACL (1 << 4)
|
#define DUMP_COMPONENT_ACL (1 << 4)
|
||||||
#define DUMP_COMPONENT_POLICY (1 << 5)
|
#define DUMP_COMPONENT_POLICY (1 << 5)
|
||||||
#define DUMP_COMPONENT_USERMAP (1 << 6)
|
#define DUMP_COMPONENT_USERMAP (1 << 6)
|
||||||
|
#define DUMP_COMPONENT_STATISTICS (1 << 7)
|
||||||
#define DUMP_COMPONENT_ALL (0xFFFF)
|
#define DUMP_COMPONENT_ALL (0xFFFF)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -137,6 +141,7 @@ typedef uint32 DumpComponents;
|
|||||||
#define DUMP_COMPONENTS_REQUIRING_LOCK (\
|
#define DUMP_COMPONENTS_REQUIRING_LOCK (\
|
||||||
DUMP_COMPONENT_DEFINITION |\
|
DUMP_COMPONENT_DEFINITION |\
|
||||||
DUMP_COMPONENT_DATA |\
|
DUMP_COMPONENT_DATA |\
|
||||||
|
DUMP_COMPONENT_STATISTICS |\
|
||||||
DUMP_COMPONENT_POLICY)
|
DUMP_COMPONENT_POLICY)
|
||||||
|
|
||||||
typedef struct _dumpableObject
|
typedef struct _dumpableObject
|
||||||
@ -430,6 +435,13 @@ typedef struct _indexAttachInfo
|
|||||||
IndxInfo *partitionIdx; /* link to index on partition */
|
IndxInfo *partitionIdx; /* link to index on partition */
|
||||||
} IndexAttachInfo;
|
} IndexAttachInfo;
|
||||||
|
|
||||||
|
typedef struct _relStatsInfo
|
||||||
|
{
|
||||||
|
DumpableObject dobj;
|
||||||
|
char relkind; /* 'r', 'm', 'i', etc */
|
||||||
|
bool postponed_def; /* stats must be postponed into post-data */
|
||||||
|
} RelStatsInfo;
|
||||||
|
|
||||||
typedef struct _statsExtInfo
|
typedef struct _statsExtInfo
|
||||||
{
|
{
|
||||||
DumpableObject dobj;
|
DumpableObject dobj;
|
||||||
|
@ -81,6 +81,7 @@ enum dbObjectTypePriorities
|
|||||||
PRIO_TABLE_DATA,
|
PRIO_TABLE_DATA,
|
||||||
PRIO_SEQUENCE_SET,
|
PRIO_SEQUENCE_SET,
|
||||||
PRIO_LARGE_OBJECT_DATA,
|
PRIO_LARGE_OBJECT_DATA,
|
||||||
|
PRIO_STATISTICS_DATA_DATA,
|
||||||
PRIO_POST_DATA_BOUNDARY, /* boundary! */
|
PRIO_POST_DATA_BOUNDARY, /* boundary! */
|
||||||
PRIO_CONSTRAINT,
|
PRIO_CONSTRAINT,
|
||||||
PRIO_INDEX,
|
PRIO_INDEX,
|
||||||
@ -148,11 +149,12 @@ static const int dbObjectTypePriority[] =
|
|||||||
[DO_PUBLICATION] = PRIO_PUBLICATION,
|
[DO_PUBLICATION] = PRIO_PUBLICATION,
|
||||||
[DO_PUBLICATION_REL] = PRIO_PUBLICATION_REL,
|
[DO_PUBLICATION_REL] = PRIO_PUBLICATION_REL,
|
||||||
[DO_PUBLICATION_TABLE_IN_SCHEMA] = PRIO_PUBLICATION_TABLE_IN_SCHEMA,
|
[DO_PUBLICATION_TABLE_IN_SCHEMA] = PRIO_PUBLICATION_TABLE_IN_SCHEMA,
|
||||||
|
[DO_REL_STATS] = PRIO_STATISTICS_DATA_DATA,
|
||||||
[DO_SUBSCRIPTION] = PRIO_SUBSCRIPTION,
|
[DO_SUBSCRIPTION] = PRIO_SUBSCRIPTION,
|
||||||
[DO_SUBSCRIPTION_REL] = PRIO_SUBSCRIPTION_REL,
|
[DO_SUBSCRIPTION_REL] = PRIO_SUBSCRIPTION_REL,
|
||||||
};
|
};
|
||||||
|
|
||||||
StaticAssertDecl(lengthof(dbObjectTypePriority) == (DO_SUBSCRIPTION_REL + 1),
|
StaticAssertDecl(lengthof(dbObjectTypePriority) == NUM_DUMPABLE_OBJECT_TYPES,
|
||||||
"array length mismatch");
|
"array length mismatch");
|
||||||
|
|
||||||
static DumpId preDataBoundId;
|
static DumpId preDataBoundId;
|
||||||
@ -801,11 +803,22 @@ repairMatViewBoundaryMultiLoop(DumpableObject *boundaryobj,
|
|||||||
{
|
{
|
||||||
/* remove boundary's dependency on object after it in loop */
|
/* remove boundary's dependency on object after it in loop */
|
||||||
removeObjectDependency(boundaryobj, nextobj->dumpId);
|
removeObjectDependency(boundaryobj, nextobj->dumpId);
|
||||||
/* if that object is a matview, mark it as postponed into post-data */
|
|
||||||
|
/*
|
||||||
|
* If that object is a matview or matview stats, mark it as postponed into
|
||||||
|
* post-data.
|
||||||
|
*/
|
||||||
if (nextobj->objType == DO_TABLE)
|
if (nextobj->objType == DO_TABLE)
|
||||||
{
|
{
|
||||||
TableInfo *nextinfo = (TableInfo *) nextobj;
|
TableInfo *nextinfo = (TableInfo *) nextobj;
|
||||||
|
|
||||||
|
if (nextinfo->relkind == RELKIND_MATVIEW)
|
||||||
|
nextinfo->postponed_def = true;
|
||||||
|
}
|
||||||
|
else if (nextobj->objType == DO_REL_STATS)
|
||||||
|
{
|
||||||
|
RelStatsInfo *nextinfo = (RelStatsInfo *) nextobj;
|
||||||
|
|
||||||
if (nextinfo->relkind == RELKIND_MATVIEW)
|
if (nextinfo->relkind == RELKIND_MATVIEW)
|
||||||
nextinfo->postponed_def = true;
|
nextinfo->postponed_def = true;
|
||||||
}
|
}
|
||||||
@ -1018,6 +1031,21 @@ repairDependencyLoop(DumpableObject **loop,
|
|||||||
{
|
{
|
||||||
DumpableObject *nextobj;
|
DumpableObject *nextobj;
|
||||||
|
|
||||||
|
nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
|
||||||
|
repairMatViewBoundaryMultiLoop(loop[j], nextobj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (loop[i]->objType == DO_REL_STATS &&
|
||||||
|
((RelStatsInfo *) loop[i])->relkind == RELKIND_MATVIEW)
|
||||||
|
{
|
||||||
|
for (j = 0; j < nLoop; j++)
|
||||||
|
{
|
||||||
|
if (loop[j]->objType == DO_POST_DATA_BOUNDARY)
|
||||||
|
{
|
||||||
|
DumpableObject *nextobj;
|
||||||
|
|
||||||
nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
|
nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0];
|
||||||
repairMatViewBoundaryMultiLoop(loop[j], nextobj);
|
repairMatViewBoundaryMultiLoop(loop[j], nextobj);
|
||||||
return;
|
return;
|
||||||
@ -1500,6 +1528,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
|
|||||||
"POST-DATA BOUNDARY (ID %d)",
|
"POST-DATA BOUNDARY (ID %d)",
|
||||||
obj->dumpId);
|
obj->dumpId);
|
||||||
return;
|
return;
|
||||||
|
case DO_REL_STATS:
|
||||||
|
snprintf(buf, bufsize,
|
||||||
|
"RELATION STATISTICS FOR %s (ID %d OID %u)",
|
||||||
|
obj->name, obj->dumpId, obj->catId.oid);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/* shouldn't get here */
|
/* shouldn't get here */
|
||||||
snprintf(buf, bufsize,
|
snprintf(buf, bufsize,
|
||||||
|
@ -103,6 +103,9 @@ static int use_setsessauth = 0;
|
|||||||
static int no_comments = 0;
|
static int no_comments = 0;
|
||||||
static int no_publications = 0;
|
static int no_publications = 0;
|
||||||
static int no_security_labels = 0;
|
static int no_security_labels = 0;
|
||||||
|
static int no_data = 0;
|
||||||
|
static int no_schema = 0;
|
||||||
|
static int no_statistics = 0;
|
||||||
static int no_subscriptions = 0;
|
static int no_subscriptions = 0;
|
||||||
static int no_toast_compression = 0;
|
static int no_toast_compression = 0;
|
||||||
static int no_unlogged_table_data = 0;
|
static int no_unlogged_table_data = 0;
|
||||||
@ -110,6 +113,7 @@ static int no_role_passwords = 0;
|
|||||||
static int server_version;
|
static int server_version;
|
||||||
static int load_via_partition_root = 0;
|
static int load_via_partition_root = 0;
|
||||||
static int on_conflict_do_nothing = 0;
|
static int on_conflict_do_nothing = 0;
|
||||||
|
static int statistics_only = 0;
|
||||||
|
|
||||||
static char role_catalog[10];
|
static char role_catalog[10];
|
||||||
#define PG_AUTHID "pg_authid"
|
#define PG_AUTHID "pg_authid"
|
||||||
@ -168,15 +172,19 @@ main(int argc, char *argv[])
|
|||||||
{"role", required_argument, NULL, 3},
|
{"role", required_argument, NULL, 3},
|
||||||
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
|
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
|
||||||
{"no-comments", no_argument, &no_comments, 1},
|
{"no-comments", no_argument, &no_comments, 1},
|
||||||
|
{"no-data", no_argument, &no_data, 1},
|
||||||
{"no-publications", no_argument, &no_publications, 1},
|
{"no-publications", no_argument, &no_publications, 1},
|
||||||
{"no-role-passwords", no_argument, &no_role_passwords, 1},
|
{"no-role-passwords", no_argument, &no_role_passwords, 1},
|
||||||
|
{"no-schema", no_argument, &no_schema, 1},
|
||||||
{"no-security-labels", no_argument, &no_security_labels, 1},
|
{"no-security-labels", no_argument, &no_security_labels, 1},
|
||||||
{"no-subscriptions", no_argument, &no_subscriptions, 1},
|
{"no-subscriptions", no_argument, &no_subscriptions, 1},
|
||||||
|
{"no-statistics", no_argument, &no_statistics, 1},
|
||||||
{"no-sync", no_argument, NULL, 4},
|
{"no-sync", no_argument, NULL, 4},
|
||||||
{"no-toast-compression", no_argument, &no_toast_compression, 1},
|
{"no-toast-compression", no_argument, &no_toast_compression, 1},
|
||||||
{"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
|
{"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
|
||||||
{"on-conflict-do-nothing", no_argument, &on_conflict_do_nothing, 1},
|
{"on-conflict-do-nothing", no_argument, &on_conflict_do_nothing, 1},
|
||||||
{"rows-per-insert", required_argument, NULL, 7},
|
{"rows-per-insert", required_argument, NULL, 7},
|
||||||
|
{"statistics-only", no_argument, &statistics_only, 1},
|
||||||
{"filter", required_argument, NULL, 8},
|
{"filter", required_argument, NULL, 8},
|
||||||
|
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
@ -447,10 +455,16 @@ main(int argc, char *argv[])
|
|||||||
appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
|
appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
|
||||||
if (no_comments)
|
if (no_comments)
|
||||||
appendPQExpBufferStr(pgdumpopts, " --no-comments");
|
appendPQExpBufferStr(pgdumpopts, " --no-comments");
|
||||||
|
if (no_data)
|
||||||
|
appendPQExpBufferStr(pgdumpopts, " --no-data");
|
||||||
if (no_publications)
|
if (no_publications)
|
||||||
appendPQExpBufferStr(pgdumpopts, " --no-publications");
|
appendPQExpBufferStr(pgdumpopts, " --no-publications");
|
||||||
if (no_security_labels)
|
if (no_security_labels)
|
||||||
appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
|
appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
|
||||||
|
if (no_schema)
|
||||||
|
appendPQExpBufferStr(pgdumpopts, " --no-schema");
|
||||||
|
if (no_statistics)
|
||||||
|
appendPQExpBufferStr(pgdumpopts, " --no-statistics");
|
||||||
if (no_subscriptions)
|
if (no_subscriptions)
|
||||||
appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
|
appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
|
||||||
if (no_toast_compression)
|
if (no_toast_compression)
|
||||||
@ -459,6 +473,8 @@ main(int argc, char *argv[])
|
|||||||
appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
|
appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
|
||||||
if (on_conflict_do_nothing)
|
if (on_conflict_do_nothing)
|
||||||
appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing");
|
appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing");
|
||||||
|
if (statistics_only)
|
||||||
|
appendPQExpBufferStr(pgdumpopts, " --statistics-only");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there was a database specified on the command line, use that,
|
* If there was a database specified on the command line, use that,
|
||||||
@ -643,13 +659,13 @@ help(void)
|
|||||||
printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
|
printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
|
||||||
printf(_(" -?, --help show this help, then exit\n"));
|
printf(_(" -?, --help show this help, then exit\n"));
|
||||||
printf(_("\nOptions controlling the output content:\n"));
|
printf(_("\nOptions controlling the output content:\n"));
|
||||||
printf(_(" -a, --data-only dump only the data, not the schema\n"));
|
printf(_(" -a, --data-only dump only the data, not the schema or statistics\n"));
|
||||||
printf(_(" -c, --clean clean (drop) databases before recreating\n"));
|
printf(_(" -c, --clean clean (drop) databases before recreating\n"));
|
||||||
printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
|
printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
|
||||||
printf(_(" -g, --globals-only dump only global objects, no databases\n"));
|
printf(_(" -g, --globals-only dump only global objects, no databases\n"));
|
||||||
printf(_(" -O, --no-owner skip restoration of object ownership\n"));
|
printf(_(" -O, --no-owner skip restoration of object ownership\n"));
|
||||||
printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
|
printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
|
||||||
printf(_(" -s, --schema-only dump only the schema, no data\n"));
|
printf(_(" -s, --schema-only dump only the schema, no data or statistics\n"));
|
||||||
printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
|
printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
|
||||||
printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
|
printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
|
||||||
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
|
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
|
||||||
@ -664,9 +680,12 @@ help(void)
|
|||||||
printf(_(" --inserts dump data as INSERT commands, rather than COPY\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(_(" --load-via-partition-root load partitions via the root table\n"));
|
||||||
printf(_(" --no-comments do not dump comment commands\n"));
|
printf(_(" --no-comments do not dump comment commands\n"));
|
||||||
|
printf(_(" --no-data do not dump data\n"));
|
||||||
printf(_(" --no-publications do not dump publications\n"));
|
printf(_(" --no-publications do not dump publications\n"));
|
||||||
printf(_(" --no-role-passwords do not dump passwords for roles\n"));
|
printf(_(" --no-role-passwords do not dump passwords for roles\n"));
|
||||||
|
printf(_(" --no-schema do not dump schema\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-statistics do not dump statistics\n"));
|
||||||
printf(_(" --no-subscriptions do not dump subscriptions\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-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"));
|
printf(_(" --no-table-access-method do not dump table access methods\n"));
|
||||||
@ -676,6 +695,7 @@ help(void)
|
|||||||
printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
|
printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
|
||||||
printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
|
printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
|
||||||
printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n"));
|
printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n"));
|
||||||
|
printf(_(" --statistics-only dump only the statistics, not schema or data\n"));
|
||||||
printf(_(" --use-set-session-authorization\n"
|
printf(_(" --use-set-session-authorization\n"
|
||||||
" use SET SESSION AUTHORIZATION commands instead of\n"
|
" use SET SESSION AUTHORIZATION commands instead of\n"
|
||||||
" ALTER OWNER commands to set ownership\n"));
|
" ALTER OWNER commands to set ownership\n"));
|
||||||
|
@ -63,6 +63,8 @@ main(int argc, char **argv)
|
|||||||
int numWorkers = 1;
|
int numWorkers = 1;
|
||||||
Archive *AH;
|
Archive *AH;
|
||||||
char *inputFileSpec;
|
char *inputFileSpec;
|
||||||
|
bool data_only = false;
|
||||||
|
bool schema_only = false;
|
||||||
static int disable_triggers = 0;
|
static int disable_triggers = 0;
|
||||||
static int enable_row_security = 0;
|
static int enable_row_security = 0;
|
||||||
static int if_exists = 0;
|
static int if_exists = 0;
|
||||||
@ -71,12 +73,14 @@ main(int argc, char **argv)
|
|||||||
static int outputNoTablespaces = 0;
|
static int outputNoTablespaces = 0;
|
||||||
static int use_setsessauth = 0;
|
static int use_setsessauth = 0;
|
||||||
static int no_comments = 0;
|
static int no_comments = 0;
|
||||||
|
static int no_data = 0;
|
||||||
static int no_publications = 0;
|
static int no_publications = 0;
|
||||||
|
static int no_schema = 0;
|
||||||
static int no_security_labels = 0;
|
static int no_security_labels = 0;
|
||||||
|
static int no_statistics = 0;
|
||||||
static int no_subscriptions = 0;
|
static int no_subscriptions = 0;
|
||||||
static int strict_names = 0;
|
static int strict_names = 0;
|
||||||
bool data_only = false;
|
static int statistics_only = 0;
|
||||||
bool schema_only = false;
|
|
||||||
|
|
||||||
struct option cmdopts[] = {
|
struct option cmdopts[] = {
|
||||||
{"clean", 0, NULL, 'c'},
|
{"clean", 0, NULL, 'c'},
|
||||||
@ -124,9 +128,13 @@ main(int argc, char **argv)
|
|||||||
{"transaction-size", required_argument, NULL, 5},
|
{"transaction-size", required_argument, NULL, 5},
|
||||||
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
|
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
|
||||||
{"no-comments", no_argument, &no_comments, 1},
|
{"no-comments", no_argument, &no_comments, 1},
|
||||||
|
{"no-data", no_argument, &no_data, 1},
|
||||||
{"no-publications", no_argument, &no_publications, 1},
|
{"no-publications", no_argument, &no_publications, 1},
|
||||||
|
{"no-schema", no_argument, &no_schema, 1},
|
||||||
{"no-security-labels", no_argument, &no_security_labels, 1},
|
{"no-security-labels", no_argument, &no_security_labels, 1},
|
||||||
{"no-subscriptions", no_argument, &no_subscriptions, 1},
|
{"no-subscriptions", no_argument, &no_subscriptions, 1},
|
||||||
|
{"no-statistics", no_argument, &no_statistics, 1},
|
||||||
|
{"statistics-only", no_argument, &statistics_only, 1},
|
||||||
{"filter", required_argument, NULL, 4},
|
{"filter", required_argument, NULL, 4},
|
||||||
|
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
@ -343,6 +351,10 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (data_only && schema_only)
|
if (data_only && schema_only)
|
||||||
pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together");
|
pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together");
|
||||||
|
if (data_only && statistics_only)
|
||||||
|
pg_fatal("options -a/--data-only and --statistics-only cannot be used together");
|
||||||
|
if (schema_only && statistics_only)
|
||||||
|
pg_fatal("options -s/--schema-only and --statistics-only cannot be used together");
|
||||||
|
|
||||||
if (data_only && opts->dropSchema)
|
if (data_only && opts->dropSchema)
|
||||||
pg_fatal("options -c/--clean and -a/--data-only cannot be used together");
|
pg_fatal("options -c/--clean and -a/--data-only cannot be used together");
|
||||||
@ -362,8 +374,9 @@ main(int argc, char **argv)
|
|||||||
pg_fatal("cannot specify both --single-transaction and multiple jobs");
|
pg_fatal("cannot specify both --single-transaction and multiple jobs");
|
||||||
|
|
||||||
/* set derivative flags */
|
/* set derivative flags */
|
||||||
opts->dumpSchema = (!data_only);
|
opts->dumpData = data_only || (!no_data && !schema_only && !statistics_only);
|
||||||
opts->dumpData = (!schema_only);
|
opts->dumpSchema = schema_only || (!no_schema && !data_only && !statistics_only);
|
||||||
|
opts->dumpStatistics = statistics_only || (!no_statistics && !data_only && !schema_only);
|
||||||
|
|
||||||
opts->disable_triggers = disable_triggers;
|
opts->disable_triggers = disable_triggers;
|
||||||
opts->enable_row_security = enable_row_security;
|
opts->enable_row_security = enable_row_security;
|
||||||
@ -489,14 +502,18 @@ usage(const char *progname)
|
|||||||
" in FILENAME\n"));
|
" in FILENAME\n"));
|
||||||
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
|
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
|
||||||
printf(_(" --no-comments do not restore comment commands\n"));
|
printf(_(" --no-comments do not restore comment commands\n"));
|
||||||
|
printf(_(" --no-data do not restore data\n"));
|
||||||
printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n"
|
printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n"
|
||||||
" created\n"));
|
" created\n"));
|
||||||
printf(_(" --no-publications do not restore publications\n"));
|
printf(_(" --no-publications do not restore publications\n"));
|
||||||
|
printf(_(" --no-schema do not restore schema\n"));
|
||||||
printf(_(" --no-security-labels do not restore security labels\n"));
|
printf(_(" --no-security-labels do not restore security labels\n"));
|
||||||
|
printf(_(" --no-statistics do not restore statistics\n"));
|
||||||
printf(_(" --no-subscriptions do not restore subscriptions\n"));
|
printf(_(" --no-subscriptions do not restore subscriptions\n"));
|
||||||
printf(_(" --no-table-access-method do not restore table access methods\n"));
|
printf(_(" --no-table-access-method do not restore table access methods\n"));
|
||||||
printf(_(" --no-tablespaces do not restore tablespace assignments\n"));
|
printf(_(" --no-tablespaces do not restore tablespace assignments\n"));
|
||||||
printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n"));
|
printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n"));
|
||||||
|
printf(_(" --statistics-only restore only the statistics, not schema or data\n"));
|
||||||
printf(_(" --strict-names require table and/or schema include patterns to\n"
|
printf(_(" --strict-names require table and/or schema include patterns to\n"
|
||||||
" match at least one entity each\n"));
|
" match at least one entity each\n"));
|
||||||
printf(_(" --transaction-size=N commit after every N objects\n"));
|
printf(_(" --transaction-size=N commit after every N objects\n"));
|
||||||
|
@ -50,12 +50,30 @@ command_fails_like(
|
|||||||
'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together'
|
'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
command_fails_like(
|
||||||
|
[ 'pg_dump', '-s', '--statistics-only' ],
|
||||||
|
qr/\Qpg_dump: error: options -s\/--schema-only and --statistics-only cannot be used together\E/,
|
||||||
|
'pg_dump: error: options -s/--schema-only and --statistics-only cannot be used together'
|
||||||
|
);
|
||||||
|
|
||||||
|
command_fails_like(
|
||||||
|
[ 'pg_dump', '-a', '--statistics-only' ],
|
||||||
|
qr/\Qpg_dump: error: options -a\/--data-only and --statistics-only cannot be used together\E/,
|
||||||
|
'pg_dump: error: options -a/--data-only and --statistics-only cannot be used together'
|
||||||
|
);
|
||||||
|
|
||||||
command_fails_like(
|
command_fails_like(
|
||||||
[ 'pg_dump', '-s', '--include-foreign-data=xxx' ],
|
[ 'pg_dump', '-s', '--include-foreign-data=xxx' ],
|
||||||
qr/\Qpg_dump: error: options -s\/--schema-only and --include-foreign-data cannot be used together\E/,
|
qr/\Qpg_dump: error: options -s\/--schema-only and --include-foreign-data cannot be used together\E/,
|
||||||
'pg_dump: options -s/--schema-only and --include-foreign-data cannot be used together'
|
'pg_dump: options -s/--schema-only and --include-foreign-data cannot be used together'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
command_fails_like(
|
||||||
|
[ 'pg_dump', '--statistics-only', '--no-statistics' ],
|
||||||
|
qr/\Qpg_dump: error: options --statistics-only and --no-statistics cannot be used together\E/,
|
||||||
|
'pg_dump: options --statistics-only and --no-statistics cannot be used together'
|
||||||
|
);
|
||||||
|
|
||||||
command_fails_like(
|
command_fails_like(
|
||||||
[ 'pg_dump', '-j2', '--include-foreign-data=xxx' ],
|
[ 'pg_dump', '-j2', '--include-foreign-data=xxx' ],
|
||||||
qr/\Qpg_dump: error: option --include-foreign-data is not supported with parallel backup\E/,
|
qr/\Qpg_dump: error: option --include-foreign-data is not supported with parallel backup\E/,
|
||||||
|
@ -65,7 +65,7 @@ my %pgdump_runs = (
|
|||||||
'--format' => 'custom',
|
'--format' => 'custom',
|
||||||
'--file' => "$tempdir/binary_upgrade.dump",
|
'--file' => "$tempdir/binary_upgrade.dump",
|
||||||
'--no-password',
|
'--no-password',
|
||||||
'--schema-only',
|
'--no-data',
|
||||||
'--binary-upgrade',
|
'--binary-upgrade',
|
||||||
'--dbname' => 'postgres', # alternative way to specify database
|
'--dbname' => 'postgres', # alternative way to specify database
|
||||||
],
|
],
|
||||||
@ -710,6 +710,34 @@ my %pgdump_runs = (
|
|||||||
'--no-large-objects',
|
'--no-large-objects',
|
||||||
'postgres',
|
'postgres',
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
no_statistics => {
|
||||||
|
dump_cmd => [
|
||||||
|
'pg_dump', '--no-sync',
|
||||||
|
"--file=$tempdir/no_statistics.sql", '--no-statistics',
|
||||||
|
'postgres',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
no_data_no_schema => {
|
||||||
|
dump_cmd => [
|
||||||
|
'pg_dump', '--no-sync',
|
||||||
|
"--file=$tempdir/no_data_no_schema.sql", '--no-data',
|
||||||
|
'--no-schema', 'postgres',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
statistics_only => {
|
||||||
|
dump_cmd => [
|
||||||
|
'pg_dump', '--no-sync',
|
||||||
|
"--file=$tempdir/statistics_only.sql", '--statistics-only',
|
||||||
|
'postgres',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
no_schema => {
|
||||||
|
dump_cmd => [
|
||||||
|
'pg_dump', '--no-sync',
|
||||||
|
"--file=$tempdir/no_schema.sql", '--no-schema',
|
||||||
|
'postgres',
|
||||||
|
],
|
||||||
},);
|
},);
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
@ -776,6 +804,7 @@ my %full_runs = (
|
|||||||
no_large_objects => 1,
|
no_large_objects => 1,
|
||||||
no_owner => 1,
|
no_owner => 1,
|
||||||
no_privs => 1,
|
no_privs => 1,
|
||||||
|
no_statistics => 1,
|
||||||
no_table_access_method => 1,
|
no_table_access_method => 1,
|
||||||
pg_dumpall_dbprivs => 1,
|
pg_dumpall_dbprivs => 1,
|
||||||
pg_dumpall_exclude => 1,
|
pg_dumpall_exclude => 1,
|
||||||
@ -977,6 +1006,7 @@ my %tests = (
|
|||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
inserts => 1,
|
inserts => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
},
|
},
|
||||||
@ -1390,6 +1420,7 @@ my %tests = (
|
|||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
inserts => 1,
|
inserts => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
},
|
},
|
||||||
@ -1411,6 +1442,7 @@ my %tests = (
|
|||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
inserts => 1,
|
inserts => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
},
|
},
|
||||||
@ -1432,6 +1464,7 @@ my %tests = (
|
|||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
inserts => 1,
|
inserts => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
},
|
},
|
||||||
@ -1598,6 +1631,7 @@ my %tests = (
|
|||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
inserts => 1,
|
inserts => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
},
|
},
|
||||||
@ -1751,6 +1785,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
only_dump_test_table => 1,
|
only_dump_test_table => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
@ -1778,6 +1813,7 @@ my %tests = (
|
|||||||
data_only => 1,
|
data_only => 1,
|
||||||
exclude_test_table => 1,
|
exclude_test_table => 1,
|
||||||
exclude_test_table_data => 1,
|
exclude_test_table_data => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
unlike => {
|
unlike => {
|
||||||
@ -1798,7 +1834,10 @@ my %tests = (
|
|||||||
\QCOPY dump_test.fk_reference_test_table (col1) FROM stdin;\E
|
\QCOPY dump_test.fk_reference_test_table (col1) FROM stdin;\E
|
||||||
\n(?:\d\n){5}\\\.\n
|
\n(?:\d\n){5}\\\.\n
|
||||||
/xms,
|
/xms,
|
||||||
like => { data_only => 1, },
|
like => {
|
||||||
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
'COPY test_second_table' => {
|
'COPY test_second_table' => {
|
||||||
@ -1814,6 +1853,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
unlike => {
|
unlike => {
|
||||||
@ -1836,6 +1876,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
unlike => {
|
unlike => {
|
||||||
@ -1859,6 +1900,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
unlike => {
|
unlike => {
|
||||||
@ -1881,6 +1923,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
unlike => {
|
unlike => {
|
||||||
@ -1903,6 +1946,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
},
|
},
|
||||||
unlike => {
|
unlike => {
|
||||||
@ -3310,6 +3354,7 @@ my %tests = (
|
|||||||
like => {
|
like => {
|
||||||
%full_runs,
|
%full_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
only_dump_test_schema => 1,
|
only_dump_test_schema => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
@ -3480,6 +3525,7 @@ my %tests = (
|
|||||||
%full_runs,
|
%full_runs,
|
||||||
%dump_test_schema_runs,
|
%dump_test_schema_runs,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
|
no_schema => 1,
|
||||||
only_dump_measurement => 1,
|
only_dump_measurement => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
only_dump_test_schema => 1,
|
only_dump_test_schema => 1,
|
||||||
@ -4364,6 +4410,7 @@ my %tests = (
|
|||||||
column_inserts => 1,
|
column_inserts => 1,
|
||||||
data_only => 1,
|
data_only => 1,
|
||||||
inserts => 1,
|
inserts => 1,
|
||||||
|
no_schema => 1,
|
||||||
section_data => 1,
|
section_data => 1,
|
||||||
test_schema_plus_large_objects => 1,
|
test_schema_plus_large_objects => 1,
|
||||||
binary_upgrade => 1,
|
binary_upgrade => 1,
|
||||||
@ -4664,6 +4711,61 @@ my %tests = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#
|
||||||
|
# TABLE and MATVIEW stats will end up in SECTION_DATA.
|
||||||
|
# INDEX stats (expression columns only) will end up in SECTION_POST_DATA.
|
||||||
|
#
|
||||||
|
'statistics_import' => {
|
||||||
|
create_sql => '
|
||||||
|
CREATE TABLE dump_test.has_stats
|
||||||
|
AS SELECT g.g AS x, g.g / 2 AS y FROM generate_series(1,100) AS g(g);
|
||||||
|
CREATE MATERIALIZED VIEW dump_test.has_stats_mv AS SELECT * FROM dump_test.has_stats;
|
||||||
|
CREATE INDEX dup_test_post_data_ix ON dump_test.has_stats((x - 1));
|
||||||
|
ANALYZE dump_test.has_stats, dump_test.has_stats_mv;',
|
||||||
|
regexp => qr/pg_catalog.pg_restore_attribute_stats/,
|
||||||
|
like => {
|
||||||
|
%full_runs,
|
||||||
|
%dump_test_schema_runs,
|
||||||
|
no_data_no_schema => 1,
|
||||||
|
no_schema => 1,
|
||||||
|
section_data => 1,
|
||||||
|
section_post_data => 1,
|
||||||
|
statistics_only => 1,
|
||||||
|
},
|
||||||
|
unlike => {
|
||||||
|
exclude_dump_test_schema => 1,
|
||||||
|
no_statistics => 1,
|
||||||
|
only_dump_measurement => 1,
|
||||||
|
schema_only => 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
#
|
||||||
|
# While attribute stats (aka pg_statistic stats) only appear for tables
|
||||||
|
# that have been analyzed, all tables will have relation stats because
|
||||||
|
# those come from pg_class.
|
||||||
|
#
|
||||||
|
'relstats_on_unanalyzed_tables' => {
|
||||||
|
regexp => qr/pg_catalog.pg_restore_relation_stats/,
|
||||||
|
|
||||||
|
like => {
|
||||||
|
%full_runs,
|
||||||
|
%dump_test_schema_runs,
|
||||||
|
no_data_no_schema => 1,
|
||||||
|
no_schema => 1,
|
||||||
|
only_dump_test_table => 1,
|
||||||
|
role => 1,
|
||||||
|
role_parallel => 1,
|
||||||
|
section_data => 1,
|
||||||
|
section_post_data => 1,
|
||||||
|
statistics_only => 1,
|
||||||
|
},
|
||||||
|
unlike => {
|
||||||
|
no_statistics => 1,
|
||||||
|
schema_only => 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
# CREATE TABLE with partitioned table and various AMs. One
|
# CREATE TABLE with partitioned table and various AMs. One
|
||||||
# partition uses the same default as the parent, and a second
|
# partition uses the same default as the parent, and a second
|
||||||
# uses its own AM.
|
# uses its own AM.
|
||||||
|
@ -52,10 +52,11 @@ generate_old_dump(void)
|
|||||||
snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
|
snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid);
|
||||||
|
|
||||||
parallel_exec_prog(log_file_name, NULL,
|
parallel_exec_prog(log_file_name, NULL,
|
||||||
"\"%s/pg_dump\" %s --schema-only --quote-all-identifiers "
|
"\"%s/pg_dump\" %s --no-data %s --quote-all-identifiers "
|
||||||
"--binary-upgrade --format=custom %s --no-sync --file=\"%s/%s\" %s",
|
"--binary-upgrade --format=custom %s --no-sync --file=\"%s/%s\" %s",
|
||||||
new_cluster.bindir, cluster_conn_opts(&old_cluster),
|
new_cluster.bindir, cluster_conn_opts(&old_cluster),
|
||||||
log_opts.verbose ? "--verbose" : "",
|
log_opts.verbose ? "--verbose" : "",
|
||||||
|
user_opts.do_statistics ? "" : "--no-statistics",
|
||||||
log_opts.dumpdir,
|
log_opts.dumpdir,
|
||||||
sql_file_name, escaped_connstr.data);
|
sql_file_name, escaped_connstr.data);
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ parseCommandLine(int argc, char *argv[])
|
|||||||
{"copy", no_argument, NULL, 2},
|
{"copy", no_argument, NULL, 2},
|
||||||
{"copy-file-range", no_argument, NULL, 3},
|
{"copy-file-range", no_argument, NULL, 3},
|
||||||
{"sync-method", required_argument, NULL, 4},
|
{"sync-method", required_argument, NULL, 4},
|
||||||
|
{"no-statistics", no_argument, NULL, 5},
|
||||||
|
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
@ -70,6 +71,7 @@ parseCommandLine(int argc, char *argv[])
|
|||||||
|
|
||||||
user_opts.do_sync = true;
|
user_opts.do_sync = true;
|
||||||
user_opts.transfer_mode = TRANSFER_MODE_COPY;
|
user_opts.transfer_mode = TRANSFER_MODE_COPY;
|
||||||
|
user_opts.do_statistics = true;
|
||||||
|
|
||||||
os_info.progname = get_progname(argv[0]);
|
os_info.progname = get_progname(argv[0]);
|
||||||
|
|
||||||
@ -212,6 +214,10 @@ parseCommandLine(int argc, char *argv[])
|
|||||||
user_opts.sync_method = pg_strdup(optarg);
|
user_opts.sync_method = pg_strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
user_opts.do_statistics = false;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
|
||||||
os_info.progname);
|
os_info.progname);
|
||||||
@ -306,6 +312,7 @@ usage(void)
|
|||||||
printf(_(" --clone clone instead of copying files to new cluster\n"));
|
printf(_(" --clone clone instead of copying files to new cluster\n"));
|
||||||
printf(_(" --copy copy files to new cluster (default)\n"));
|
printf(_(" --copy copy files to new cluster (default)\n"));
|
||||||
printf(_(" --copy-file-range copy files to new cluster with copy_file_range\n"));
|
printf(_(" --copy-file-range copy files to new cluster with copy_file_range\n"));
|
||||||
|
printf(_(" --no-statistics do not import statistics from old cluster\n"));
|
||||||
printf(_(" --sync-method=METHOD set method for syncing files to disk\n"));
|
printf(_(" --sync-method=METHOD set method for syncing files to disk\n"));
|
||||||
printf(_(" -?, --help show this help, then exit\n"));
|
printf(_(" -?, --help show this help, then exit\n"));
|
||||||
printf(_("\n"
|
printf(_("\n"
|
||||||
|
@ -327,6 +327,7 @@ typedef struct
|
|||||||
int jobs; /* number of processes/threads to use */
|
int jobs; /* number of processes/threads to use */
|
||||||
char *socketdir; /* directory to use for Unix sockets */
|
char *socketdir; /* directory to use for Unix sockets */
|
||||||
char *sync_method;
|
char *sync_method;
|
||||||
|
bool do_statistics; /* carry over statistics from old cluster */
|
||||||
} UserOpts;
|
} UserOpts;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -278,6 +278,9 @@ push @initdb_params, ('--locale-provider', 'libc');
|
|||||||
$node_params{extra} = \@initdb_params;
|
$node_params{extra} = \@initdb_params;
|
||||||
$newnode->init(%node_params);
|
$newnode->init(%node_params);
|
||||||
|
|
||||||
|
# Stabilize stats for comparison.
|
||||||
|
$newnode->append_conf('postgresql.conf', 'autovacuum = off');
|
||||||
|
|
||||||
my $newbindir = $newnode->config_data('--bindir');
|
my $newbindir = $newnode->config_data('--bindir');
|
||||||
my $oldbindir = $oldnode->config_data('--bindir');
|
my $oldbindir = $oldnode->config_data('--bindir');
|
||||||
|
|
||||||
@ -314,6 +317,10 @@ if (defined($ENV{oldinstall}))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Stabilize stats before pg_dumpall.
|
||||||
|
$oldnode->append_conf('postgresql.conf', 'autovacuum = off');
|
||||||
|
$oldnode->restart;
|
||||||
|
|
||||||
# Take a dump before performing the upgrade as a base comparison. Note
|
# Take a dump before performing the upgrade as a base comparison. Note
|
||||||
# that we need to use pg_dumpall from the new node here.
|
# that we need to use pg_dumpall from the new node here.
|
||||||
my @dump_command = (
|
my @dump_command = (
|
||||||
|
@ -294,6 +294,11 @@ sub adjust_old_dumpfile
|
|||||||
# Version comments will certainly not match.
|
# Version comments will certainly not match.
|
||||||
$dump =~ s/^-- Dumped from database version.*\n//mg;
|
$dump =~ s/^-- Dumped from database version.*\n//mg;
|
||||||
|
|
||||||
|
# Same with version argument to pg_restore_relation_stats() or
|
||||||
|
# pg_restore_attribute_stats().
|
||||||
|
$dump =~ s ['version', '${old_version}\d{4}'::integer,]
|
||||||
|
['version', '000000'::integer,]mg;
|
||||||
|
|
||||||
if ($old_version < 16)
|
if ($old_version < 16)
|
||||||
{
|
{
|
||||||
# Fix up some view queries that no longer require table-qualification.
|
# Fix up some view queries that no longer require table-qualification.
|
||||||
@ -626,6 +631,11 @@ sub adjust_new_dumpfile
|
|||||||
# Version comments will certainly not match.
|
# Version comments will certainly not match.
|
||||||
$dump =~ s/^-- Dumped from database version.*\n//mg;
|
$dump =~ s/^-- Dumped from database version.*\n//mg;
|
||||||
|
|
||||||
|
# Same with version argument to pg_restore_relation_stats() or
|
||||||
|
# pg_restore_attribute_stats().
|
||||||
|
$dump =~ s ['version', '\d{6}'::integer,]
|
||||||
|
['version', '000000'::integer,]mg;
|
||||||
|
|
||||||
if ($old_version < 14)
|
if ($old_version < 14)
|
||||||
{
|
{
|
||||||
# Suppress noise-word uses of IN in CREATE/ALTER PROCEDURE.
|
# Suppress noise-word uses of IN in CREATE/ALTER PROCEDURE.
|
||||||
|
@ -107,7 +107,7 @@ command_ok(
|
|||||||
[
|
[
|
||||||
'pg_dumpall',
|
'pg_dumpall',
|
||||||
'--file' => $outputdir . '/primary.dump',
|
'--file' => $outputdir . '/primary.dump',
|
||||||
'--no-sync',
|
'--no-sync', '--no-statistics',
|
||||||
'--port' => $node_primary->port,
|
'--port' => $node_primary->port,
|
||||||
'--no-unlogged-table-data', # if unlogged, standby has schema only
|
'--no-unlogged-table-data', # if unlogged, standby has schema only
|
||||||
],
|
],
|
||||||
@ -116,7 +116,7 @@ command_ok(
|
|||||||
[
|
[
|
||||||
'pg_dumpall',
|
'pg_dumpall',
|
||||||
'--file' => $outputdir . '/standby.dump',
|
'--file' => $outputdir . '/standby.dump',
|
||||||
'--no-sync',
|
'--no-sync', '--no-statistics',
|
||||||
'--port' => $node_standby_1->port,
|
'--port' => $node_standby_1->port,
|
||||||
],
|
],
|
||||||
'dump standby server');
|
'dump standby server');
|
||||||
|
@ -2403,6 +2403,7 @@ RelMapFile
|
|||||||
RelMapping
|
RelMapping
|
||||||
RelOptInfo
|
RelOptInfo
|
||||||
RelOptKind
|
RelOptKind
|
||||||
|
RelStatsInfo
|
||||||
RelToCheck
|
RelToCheck
|
||||||
RelToCluster
|
RelToCluster
|
||||||
RelabelType
|
RelabelType
|
||||||
|
Reference in New Issue
Block a user