1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-18 13:44:19 +03:00

pg_dump: Fix query for gathering attribute stats on older versions.

Commit 9c02e3a986 taught pg_dump to retrieve attribute statistics
for 64 relations at a time.  pg_dump supports dumping from v9.2 and
newer versions, but our query for retrieving statistics for
multiple relations uses WITH ORDINALITY and multi-argument
UNNEST(), both of which were introduced in v9.4.  To fix, we resort
to gathering statistics for a single relation at a time on versions
older than v9.4.

Per buildfarm member crake.

Author: Corey Huinker <corey.huinker@gmail.com>
Discussion: https://postgr.es/m/Z_BcWVMvlUIJ_iuZ%40nathan
This commit is contained in:
Nathan Bossart 2025-04-04 21:05:30 -05:00
parent 43b8e6c4ab
commit f0d0083f52

View File

@ -10571,6 +10571,16 @@ fetchAttributeStats(Archive *fout)
PGresult *res = NULL; PGresult *res = NULL;
static TocEntry *te; static TocEntry *te;
static bool restarted; static bool restarted;
int max_rels = MAX_ATTR_STATS_RELS;
/*
* Our query for retrieving statistics for multiple relations uses WITH
* ORDINALITY and multi-argument UNNEST(), both of which were introduced
* in v9.4. For older versions, we resort to gathering statistics for a
* single relation at a time.
*/
if (fout->remoteVersion < 90400)
max_rels = 1;
/* If we're just starting, set our TOC pointer. */ /* If we're just starting, set our TOC pointer. */
if (!te) if (!te)
@ -10596,7 +10606,7 @@ fetchAttributeStats(Archive *fout)
* This is perhaps not the sturdiest assumption, so we verify it matches * This is perhaps not the sturdiest assumption, so we verify it matches
* reality in dumpRelationStats_dumper(). * reality in dumpRelationStats_dumper().
*/ */
for (; te != AH->toc && count < MAX_ATTR_STATS_RELS; te = te->next) for (; te != AH->toc && count < max_rels; te = te->next)
{ {
if ((te->reqs & REQ_STATS) != 0 && if ((te->reqs & REQ_STATS) != 0 &&
strcmp(te->desc, "STATISTICS DATA") == 0) strcmp(te->desc, "STATISTICS DATA") == 0)
@ -10709,14 +10719,26 @@ dumpRelationStats_dumper(Archive *fout, const void *userArg, const TocEntry *te)
* sufficient to convince the planner to use * sufficient to convince the planner to use
* pg_class_relname_nsp_index, which avoids a full scan of pg_stats. * pg_class_relname_nsp_index, which avoids a full scan of pg_stats.
* This may not work for all versions. * This may not work for all versions.
*
* Our query for retrieving statistics for multiple relations uses
* WITH ORDINALITY and multi-argument UNNEST(), both of which were
* introduced in v9.4. For older versions, we resort to gathering
* statistics for a single relation at a time.
*/ */
appendPQExpBufferStr(query, if (fout->remoteVersion >= 90400)
"FROM pg_catalog.pg_stats s " appendPQExpBufferStr(query,
"JOIN unnest($1, $2) WITH ORDINALITY AS u (schemaname, tablename, ord) " "FROM pg_catalog.pg_stats s "
"ON s.schemaname = u.schemaname " "JOIN unnest($1, $2) WITH ORDINALITY AS u (schemaname, tablename, ord) "
"AND s.tablename = u.tablename " "ON s.schemaname = u.schemaname "
"WHERE s.tablename = ANY($2) " "AND s.tablename = u.tablename "
"ORDER BY u.ord, s.attname, s.inherited"); "WHERE s.tablename = ANY($2) "
"ORDER BY u.ord, s.attname, s.inherited");
else
appendPQExpBufferStr(query,
"FROM pg_catalog.pg_stats s "
"WHERE s.schemaname = $1[1] "
"AND s.tablename = $2[1] "
"ORDER BY s.attname, s.inherited");
ExecuteSqlStatement(fout, query->data); ExecuteSqlStatement(fout, query->data);