From e01f9183fa4302d1240910accb33d2704f176d29 Mon Sep 17 00:00:00 2001 From: Artem Gavrilov Date: Wed, 21 Oct 2026 17:20:55 +0200 Subject: [PATCH] pg_dump: Fix inherited flag of extended stats from pre-v15 servers Since c32fb29e979, pg_dump --statistics dumps extended statistics data. For servers older than v15, where pg_stats_ext has no inherited column, the query hard-coded the flag to false. However, these versions build inherited extended stats on partitioned tables since 20b9fa308eb, back-patched down to 10.20, 11.15, 12.10, 13.6 and 14.2. The planner always searches for inherited extended statistics on partitioned tables, so after restore the data dumped as non-inherited was never used. pg_upgrade from v10-v14 was affected the same way, as it transfers statistics by default. For pre-v15 servers, the flag is now deduced from the relkind of the table, the same way 20b9fa308eb chooses which data to build: true for partitioned tables, false for all other relations. --- src/bin/pg_dump/pg_dump.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index dc04c12142b..e843b756b1c 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -18724,7 +18724,8 @@ dumpStatisticsExtStats(Archive *fout, const StatsExtInfo *statsextinfo) * catalogs. * - In v18 and older versions, ndistinct and dependencies have a * different format that needs translation. - * - In v14 and older versions, inherited does not exist. + * - In v14 and older versions, there is no inherited flag, hence + * it is deduced from the relkind of the table when dumping the data. * - In v11 and older versions, there is no pg_stats_ext, hence * the logic joins pg_statistic_ext and pg_namespace. *--------- @@ -18738,7 +18739,8 @@ dumpStatisticsExtStats(Archive *fout, const StatsExtInfo *statsextinfo) * Versions 15 and newer have inherited stats. * * Create this column in all versions because we need to order by it - * later. + * later. For older versions, the value is resolved from the table's + * relkind, see below. */ if (fout->remoteVersion >= 150000) appendPQExpBufferStr(pq, "e.inherited, "); @@ -18912,10 +18914,21 @@ dumpStatisticsExtStats(Archive *fout, const StatsExtInfo *statsextinfo) for (int i = 0; i < nstats; i++) { TableInfo *tbinfo = statsextinfo->stattable; + const char *inherited; if (PQgetisnull(res, i, i_inherited)) pg_fatal("inherited cannot be NULL"); + /* + * v14 and older have no inherited flag, but for partitioned + * tables they store inherited extended statistics. + */ + if (fout->remoteVersion >= 150000) + inherited = PQgetvalue(res, i, i_inherited); + else + inherited = + (tbinfo->relkind == RELKIND_PARTITIONED_TABLE) ? "t" : "f"; + appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_extended_stats(\n"); appendPQExpBuffer(out, "\t'version', '%d'::integer,\n", @@ -18932,8 +18945,7 @@ dumpStatisticsExtStats(Archive *fout, const StatsExtInfo *statsextinfo) appendStringLiteralAH(out, statsextinfo->dobj.namespace->dobj.name, fout); appendPQExpBufferStr(out, ",\n\t'statistics_name', "); appendStringLiteralAH(out, statsextinfo->dobj.name, fout); - appendNamedArgument(out, fout, "inherited", "boolean", - PQgetvalue(res, i, i_inherited)); + appendNamedArgument(out, fout, "inherited", "boolean", inherited); if (!PQgetisnull(res, i, i_ndistinct)) appendNamedArgument(out, fout, "n_distinct", "pg_ndistinct", -- 2.56.0