On Fri, Apr 4, 2025 at 6:25 PM Nathan Bossart <nathandboss...@gmail.com>
wrote:

> On Fri, Apr 04, 2025 at 03:58:53PM -0500, Nathan Bossart wrote:
> > I pushed commit 8ec0aae to fix this.
>
> And now I'm seeing cross-version test failures due to our use of WITH
> ORDINALITY, which wasn't added until v9.4.  Looking into it...
>
>
>
This patch shrinks the array size to 1 for versions < 9.4, which keeps the
modern code fairly elegant.
From fe551ab55622f95d84ac4c4d79fba898c6b60057 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huin...@gmail.com>
Date: Fri, 4 Apr 2025 19:30:00 -0400
Subject: [PATCH v1] Fall back to single attribute stat fetching for versions <
 9.4

Existing attribute statistics batch fetching query relies on the
existence of WITH ORDINALTIY, as well as multi-parameter unnest() calls.
Without those, we have no choice but to fall back to single relation
fetching.

Preserve the existing array building infrastructure, and drop the array
size to 1 for older versions.
---
 src/bin/pg_dump/pg_dump.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 0e915432e77..b88188448b0 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -10571,6 +10571,14 @@ fetchAttributeStats(Archive *fout)
 	PGresult   *res = NULL;
 	static TocEntry *te;
 	static bool restarted;
+	int			max_rels = MAX_ATTR_STATS_RELS;
+
+	/*
+	 * Versions prior to 9.4 lack the unnest() WITH ORDINALITY feature
+	 * that we need to keep the relation batches in order.
+	 */
+	if (fout->remoteVersion < 90400)
+		max_rels = 1;
 
 	/* If we're just starting, set our TOC pointer. */
 	if (!te)
@@ -10596,7 +10604,7 @@ fetchAttributeStats(Archive *fout)
 	 * This is perhaps not the sturdiest assumption, so we verify it matches
 	 * 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 &&
 			strcmp(te->desc, "STATISTICS DATA") == 0)
@@ -10709,14 +10717,25 @@ dumpRelationStats_dumper(Archive *fout, const void *userArg, const TocEntry *te)
 		 * sufficient to convince the planner to use
 		 * pg_class_relname_nsp_index, which avoids a full scan of pg_stats.
 		 * This may not work for all versions.
+		 *
+		 * WITH ORDINALITY was introduced in 9.4, and multi-argument unnest()
+		 * was introduced in 9.3. Rather than create a bunch of corner-cases,
+		 * we simply fall back to fetching a single relation per call.
 		 */
-		appendPQExpBufferStr(query,
-							 "FROM pg_catalog.pg_stats s "
-							 "JOIN unnest($1, $2) WITH ORDINALITY AS u (schemaname, tablename, ord) "
-							 "ON s.schemaname = u.schemaname "
-							 "AND s.tablename = u.tablename "
-							 "WHERE s.tablename = ANY($2) "
-							 "ORDER BY u.ord, s.attname, s.inherited");
+		if (fout->remoteVersion >= 90400)
+			appendPQExpBufferStr(query,
+								 "FROM pg_catalog.pg_stats s "
+								 "JOIN unnest($1, $2) WITH ORDINALITY AS u (schemaname, tablename, ord) "
+								 "ON s.schemaname = u.schemaname "
+								 "AND s.tablename = u.tablename "
+								 "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::text[])[1] "
+								 "AND s.tablename = ($2::text[])[1] "
+								 "ORDER BY s.attname, s.inherited");
 
 		ExecuteSqlStatement(fout, query->data);
 

base-commit: 0f43083d16f4be7c01efa80d05d0eef5e5ff69d3
-- 
2.49.0

Reply via email to