mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
pg_dump: Include column statistics for index-backed constraints
dumpIndex() emits ALTER INDEX .. SET STATISTICS for per-column
statistics targets, but dumpConstraint() never did. Targets set on the
expression columns of an exclusion constraint's index were silently
lost on dump/restore and pg_upgrade.
The same code can be used in the index and constraint dump code to
generate these ALTER INDEX commands. The logic has been refactored so
that both share a new subroutine in charge of generating all these
custom SET STATISTICS, if any.
Oversight in e4fca461ab.
Author: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Andrew Krylosov <krylosov.andrew@gmail.com>
Discussion: https://postgr.es/m/CAN4CZFMd9riOuV5LkM+uV=uF-HYp49C8Fh22xWyMxptGLBCZ3A@mail.gmail.com
Backpatch-through: 14
This commit is contained in:
@@ -17029,6 +17029,48 @@ getAttrName(int attrnum, const TableInfo *tblInfo)
|
||||
return NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
/*
|
||||
* appendIndexStatTargets
|
||||
* append ALTER INDEX ... SET STATISTICS commands for the per-column
|
||||
* statistics targets of an index (attstattarget), if any.
|
||||
*/
|
||||
static void
|
||||
appendIndexStatTargets(PQExpBuffer q, const IndxInfo *indxinfo)
|
||||
{
|
||||
char **indstatcolsarray = NULL;
|
||||
char **indstatvalsarray = NULL;
|
||||
int nstatcols = 0;
|
||||
int nstatvals = 0;
|
||||
|
||||
if (strlen(indxinfo->indstatcols) == 0 &&
|
||||
strlen(indxinfo->indstatvals) == 0)
|
||||
return;
|
||||
|
||||
if (!parsePGArray(indxinfo->indstatcols, &indstatcolsarray, &nstatcols))
|
||||
fatal("could not parse index statistic columns");
|
||||
if (!parsePGArray(indxinfo->indstatvals, &indstatvalsarray, &nstatvals))
|
||||
fatal("could not parse index statistic values");
|
||||
if (nstatcols != nstatvals)
|
||||
fatal("mismatched number of columns and values for index statistics");
|
||||
|
||||
for (int j = 0; j < nstatcols; j++)
|
||||
{
|
||||
appendPQExpBuffer(q, "ALTER INDEX %s ",
|
||||
fmtQualifiedDumpable(indxinfo));
|
||||
|
||||
/*
|
||||
* Note that this is a column number, so no quotes should be used.
|
||||
*/
|
||||
appendPQExpBuffer(q, "ALTER COLUMN %s ",
|
||||
indstatcolsarray[j]);
|
||||
appendPQExpBuffer(q, "SET STATISTICS %s;\n",
|
||||
indstatvalsarray[j]);
|
||||
}
|
||||
|
||||
free(indstatcolsarray);
|
||||
free(indstatvalsarray);
|
||||
}
|
||||
|
||||
/*
|
||||
* dumpIndex
|
||||
* write out to fout a user-defined index
|
||||
@@ -17062,13 +17104,6 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
|
||||
*/
|
||||
if (!is_constraint)
|
||||
{
|
||||
char *indstatcols = indxinfo->indstatcols;
|
||||
char *indstatvals = indxinfo->indstatvals;
|
||||
char **indstatcolsarray = NULL;
|
||||
char **indstatvalsarray = NULL;
|
||||
int nstatcols = 0;
|
||||
int nstatvals = 0;
|
||||
|
||||
if (dopt->binary_upgrade)
|
||||
binary_upgrade_set_pg_class_oids(fout, q,
|
||||
indxinfo->dobj.catId.oid, true);
|
||||
@@ -17092,35 +17127,8 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
|
||||
qindxname);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the index has any statistics on some of its columns, generate
|
||||
* the associated ALTER INDEX queries.
|
||||
*/
|
||||
if (strlen(indstatcols) != 0 || strlen(indstatvals) != 0)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (!parsePGArray(indstatcols, &indstatcolsarray, &nstatcols))
|
||||
fatal("could not parse index statistic columns");
|
||||
if (!parsePGArray(indstatvals, &indstatvalsarray, &nstatvals))
|
||||
fatal("could not parse index statistic values");
|
||||
if (nstatcols != nstatvals)
|
||||
fatal("mismatched number of columns and values for index statistics");
|
||||
|
||||
for (j = 0; j < nstatcols; j++)
|
||||
{
|
||||
appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname);
|
||||
|
||||
/*
|
||||
* Note that this is a column number, so no quotes should be
|
||||
* used.
|
||||
*/
|
||||
appendPQExpBuffer(q, "ALTER COLUMN %s ",
|
||||
indstatcolsarray[j]);
|
||||
appendPQExpBuffer(q, "SET STATISTICS %s;\n",
|
||||
indstatvalsarray[j]);
|
||||
}
|
||||
}
|
||||
/* Per-column statistics targets, if any */
|
||||
appendIndexStatTargets(q, indxinfo);
|
||||
|
||||
/* Indexes can depend on extensions */
|
||||
append_depends_on_extension(fout, q, &indxinfo->dobj,
|
||||
@@ -17159,11 +17167,6 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo)
|
||||
.section = SECTION_POST_DATA,
|
||||
.createStmt = q->data,
|
||||
.dropStmt = delq->data));
|
||||
|
||||
if (indstatcolsarray)
|
||||
free(indstatcolsarray);
|
||||
if (indstatvalsarray)
|
||||
free(indstatvalsarray);
|
||||
}
|
||||
|
||||
/* Dump Index Comments */
|
||||
@@ -17423,6 +17426,9 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
|
||||
fmtId(indxinfo->dobj.name));
|
||||
}
|
||||
|
||||
/* Per-column statistics targets, if any */
|
||||
appendIndexStatTargets(q, indxinfo);
|
||||
|
||||
/* If the index defines identity, we need to record that. */
|
||||
if (indxinfo->indisreplident)
|
||||
{
|
||||
|
||||
@@ -2876,6 +2876,31 @@ my %tests = (
|
||||
unlike => { exclude_dump_test_schema => 1, },
|
||||
},
|
||||
|
||||
'CREATE TABLE table_with_constraint_stats' => {
|
||||
create_order => 98,
|
||||
create_sql => 'CREATE TABLE dump_test.table_constraint_stats (
|
||||
col1 int,
|
||||
col2 int);
|
||||
ALTER TABLE dump_test.table_constraint_stats
|
||||
ADD CONSTRAINT ex_with_stats
|
||||
EXCLUDE USING btree ((col1 + 1) WITH =,
|
||||
col1 WITH =, (col2 + 1) WITH =);
|
||||
ALTER INDEX dump_test.ex_with_stats
|
||||
ALTER COLUMN 1 SET STATISTICS 100;
|
||||
ALTER INDEX dump_test.ex_with_stats
|
||||
ALTER COLUMN 3 SET STATISTICS 200;',
|
||||
regexp => qr/^
|
||||
\QALTER INDEX dump_test.ex_with_stats ALTER COLUMN 1 SET STATISTICS 100;\E\n
|
||||
\QALTER INDEX dump_test.ex_with_stats ALTER COLUMN 3 SET STATISTICS 200;\E\n
|
||||
/xms,
|
||||
like =>
|
||||
{ %full_runs, %dump_test_schema_runs, section_post_data => 1, },
|
||||
unlike => {
|
||||
exclude_dump_test_schema => 1,
|
||||
only_dump_measurement => 1,
|
||||
},
|
||||
},
|
||||
|
||||
'CREATE TABLE test_inheritance_parent' => {
|
||||
create_order => 90,
|
||||
create_sql => 'CREATE TABLE dump_test.test_inheritance_parent (
|
||||
|
||||
Reference in New Issue
Block a user