mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Include ALTER INDEX SET STATISTICS in pg_dump
The new grammar pattern of ALTER INDEX SET STATISTICS able to use column
numbers on top of the existing column names introduced by commit 5b6d13e
forgot to add support for the feature in pg_dump, so defining statistics
on index columns was missing from the dumps, potentially causing silent
planning problems with a subsequent restore.
pg_dump ought to not use column names in what it generates as these are
automatically generated by the server and could conflict with real
relation attributes with matching patterns. "expr" and "exprN", N
incremented automatically after the creation of the first one, are used
as default attribute names for index expressions, and that could easily
match what is defined in other relations, causing the dumps to fail if
some of those attributes are renamed at some point. So to avoid any
problems, the new grammar with column numbers gets used.
Reported-by: Ronan Dunklau
Author: Michael Paquier
Reviewed-by: Tom Lane, Adrien Nayrat, Amul Sul
Discussion: https://postgr.es/m/CAARsnT3UQ4V=yDNW468w8RqHfYiY9mpn2r_c5UkBJ97NAApUEw@mail.gmail.com
Backpatch-through: 11, where the new syntax has been introduced.
This commit is contained in:
parent
cc92cca431
commit
e4fca461ab
@ -6712,7 +6712,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
i_conoid,
|
||||
i_condef,
|
||||
i_tablespace,
|
||||
i_indreloptions;
|
||||
i_indreloptions,
|
||||
i_indstatcols,
|
||||
i_indstatvals;
|
||||
int ntups;
|
||||
|
||||
for (i = 0; i < numTables; i++)
|
||||
@ -6766,7 +6768,15 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
"c.oid AS conoid, "
|
||||
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
|
||||
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
|
||||
"t.reloptions AS indreloptions "
|
||||
"t.reloptions AS indreloptions, "
|
||||
"(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
|
||||
" FROM pg_catalog.pg_attribute "
|
||||
" WHERE attrelid = i.indexrelid AND "
|
||||
" attstattarget >= 0) AS indstatcols,"
|
||||
"(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
|
||||
" FROM pg_catalog.pg_attribute "
|
||||
" WHERE attrelid = i.indexrelid AND "
|
||||
" attstattarget >= 0) AS indstatvals "
|
||||
"FROM pg_catalog.pg_index i "
|
||||
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
|
||||
"JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
|
||||
@ -6803,7 +6813,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
"c.oid AS conoid, "
|
||||
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
|
||||
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
|
||||
"t.reloptions AS indreloptions "
|
||||
"t.reloptions AS indreloptions, "
|
||||
"'' AS indstatcols, "
|
||||
"'' AS indstatvals "
|
||||
"FROM pg_catalog.pg_index i "
|
||||
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
|
||||
"LEFT JOIN pg_catalog.pg_constraint c "
|
||||
@ -6836,7 +6848,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
"c.oid AS conoid, "
|
||||
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
|
||||
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
|
||||
"t.reloptions AS indreloptions "
|
||||
"t.reloptions AS indreloptions, "
|
||||
"'' AS indstatcols, "
|
||||
"'' AS indstatvals "
|
||||
"FROM pg_catalog.pg_index i "
|
||||
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
|
||||
"LEFT JOIN pg_catalog.pg_constraint c "
|
||||
@ -6865,7 +6879,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
"c.oid AS conoid, "
|
||||
"null AS condef, "
|
||||
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
|
||||
"t.reloptions AS indreloptions "
|
||||
"t.reloptions AS indreloptions, "
|
||||
"'' AS indstatcols, "
|
||||
"'' AS indstatvals "
|
||||
"FROM pg_catalog.pg_index i "
|
||||
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
|
||||
"LEFT JOIN pg_catalog.pg_depend d "
|
||||
@ -6897,7 +6913,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
"c.oid AS conoid, "
|
||||
"null AS condef, "
|
||||
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
|
||||
"null AS indreloptions "
|
||||
"null AS indreloptions, "
|
||||
"'' AS indstatcols, "
|
||||
"'' AS indstatvals "
|
||||
"FROM pg_catalog.pg_index i "
|
||||
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
|
||||
"LEFT JOIN pg_catalog.pg_depend d "
|
||||
@ -6935,6 +6953,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
i_condef = PQfnumber(res, "condef");
|
||||
i_tablespace = PQfnumber(res, "tablespace");
|
||||
i_indreloptions = PQfnumber(res, "indreloptions");
|
||||
i_indstatcols = PQfnumber(res, "indstatcols");
|
||||
i_indstatvals = PQfnumber(res, "indstatvals");
|
||||
|
||||
tbinfo->indexes = indxinfo =
|
||||
(IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
|
||||
@ -6958,6 +6978,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
|
||||
indxinfo[j].indnattrs = atoi(PQgetvalue(res, j, i_indnatts));
|
||||
indxinfo[j].tablespace = pg_strdup(PQgetvalue(res, j, i_tablespace));
|
||||
indxinfo[j].indreloptions = pg_strdup(PQgetvalue(res, j, i_indreloptions));
|
||||
indxinfo[j].indstatcols = pg_strdup(PQgetvalue(res, j, i_indstatcols));
|
||||
indxinfo[j].indstatvals = pg_strdup(PQgetvalue(res, j, i_indstatvals));
|
||||
indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnattrs * sizeof(Oid));
|
||||
parseOidArray(PQgetvalue(res, j, i_indkey),
|
||||
indxinfo[j].indkeys, indxinfo[j].indnattrs);
|
||||
@ -16148,6 +16170,13 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
|
||||
*/
|
||||
if (!is_constraint)
|
||||
{
|
||||
char *indstatcols = indxinfo->indstatcols;
|
||||
char *indstatvals = indxinfo->indstatvals;
|
||||
char **indstatcolsarray = NULL;
|
||||
char **indstatvalsarray = NULL;
|
||||
int nstatcols;
|
||||
int nstatvals;
|
||||
|
||||
if (dopt->binary_upgrade)
|
||||
binary_upgrade_set_pg_class_oids(fout, q,
|
||||
indxinfo->dobj.catId.oid, true);
|
||||
@ -16171,6 +16200,32 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
|
||||
qindxname);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the index has any statistics on some of its columns, generate
|
||||
* the associated ALTER INDEX queries.
|
||||
*/
|
||||
if (parsePGArray(indstatcols, &indstatcolsarray, &nstatcols) &&
|
||||
parsePGArray(indstatvals, &indstatvalsarray, &nstatvals) &&
|
||||
nstatcols == nstatvals)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (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]);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the index defines identity, we need to record that. */
|
||||
if (indxinfo->indisreplident)
|
||||
{
|
||||
@ -16194,6 +16249,11 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
|
||||
q->data, delq->data, NULL,
|
||||
NULL, 0,
|
||||
NULL, NULL);
|
||||
|
||||
if (indstatcolsarray)
|
||||
free(indstatcolsarray);
|
||||
if (indstatvalsarray)
|
||||
free(indstatvalsarray);
|
||||
}
|
||||
|
||||
/* Dump Index Comments */
|
||||
|
@ -360,6 +360,8 @@ typedef struct _indxInfo
|
||||
char *indexdef;
|
||||
char *tablespace; /* tablespace in which index is stored */
|
||||
char *indreloptions; /* options specified by WITH (...) */
|
||||
char *indstatcols; /* column numbers with statistics */
|
||||
char *indstatvals; /* statistic values for columns */
|
||||
int indnkeyattrs; /* number of index key attributes */
|
||||
int indnattrs; /* total number of index attributes */
|
||||
Oid *indkeys; /* In spite of the name 'indkeys' this field
|
||||
|
@ -2343,6 +2343,28 @@ my %tests = (
|
||||
unlike => { exclude_dump_test_schema => 1, },
|
||||
},
|
||||
|
||||
'CREATE TABLE table_with_stats' => {
|
||||
create_order => 98,
|
||||
create_sql => 'CREATE TABLE dump_test.table_index_stats (
|
||||
col1 int,
|
||||
col2 int,
|
||||
col3 int);
|
||||
CREATE INDEX index_with_stats
|
||||
ON dump_test.table_index_stats
|
||||
((col1 + 1), col1, (col2 + 1), (col3 + 1));
|
||||
ALTER INDEX dump_test.index_with_stats
|
||||
ALTER COLUMN 1 SET STATISTICS 400;
|
||||
ALTER INDEX dump_test.index_with_stats
|
||||
ALTER COLUMN 3 SET STATISTICS 500;',
|
||||
regexp => qr/^
|
||||
\QALTER INDEX dump_test.index_with_stats ALTER COLUMN 1 SET STATISTICS 400;\E\n
|
||||
\QALTER INDEX dump_test.index_with_stats ALTER COLUMN 3 SET STATISTICS 500;\E\n
|
||||
/xms,
|
||||
like =>
|
||||
{ %full_runs, %dump_test_schema_runs, section_post_data => 1, },
|
||||
unlike => { exclude_dump_test_schema => 1, },
|
||||
},
|
||||
|
||||
'CREATE STATISTICS extended_stats_no_options' => {
|
||||
create_order => 97,
|
||||
create_sql => 'CREATE STATISTICS dump_test.test_ext_stats_no_options
|
||||
|
Loading…
Reference in New Issue
Block a user