As mentioned in [0], pg_upgrade currently does not preserve the version
of collation objects created by initdb. Here is an attempt to fix that.
The way I deal with this here is by having the binary-upgrade mode in
pg_dump delete all the collations created by initdb and then dump out
CREATE COLLATION commands with version information normally.
I had originally imagined doing some kind of ALTER COLLATION (or perhaps
a direct UPDATE pg_collation) to update the version information, but
that doesn't really work because we don't know whether the collation
object with a given name in the new cluster is the same as the one in
the old cluster. So it seems more robust to just delete all existing
collations and create them from scratch.
Thoughts?
[0]:
https://www.postgresql.org/message-id/ca+hukgkde98dfwkjos7e4z+oamzc-1szfpl3v3ppgi1unvq...@mail.gmail.com
--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From f4e804b3c1ccc7c36fe8d253ae74955ab1855448 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Mon, 28 Oct 2019 13:38:56 +0100
Subject: [PATCH v1] Preserve versions of initdb-created collations in
pg_upgrade
---
src/bin/pg_dump/pg_dump.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index bf69adc2f4..f54ea2e73e 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -1649,6 +1649,28 @@ selectDumpableCast(CastInfo *cast, Archive *fout)
DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
}
+/*
+ * selectDumpableCollation: policy-setting subroutine
+ * Mark a collation as to be dumped or not
+ */
+static void
+selectDumpableCollation(CollInfo *collinfo, Archive *fout)
+{
+ DumpOptions *dopt = fout->dopt;
+
+ if (checkExtensionMembership(&collinfo->dobj, fout))
+ return; /* extension membership
overrides all else */
+
+ collinfo->dobj.dump = collinfo->dobj.namespace->dobj.dump_contains;
+
+ /*
+ * Collations in pg_catalog created by initdb must be dumped in
+ * binary-upgrade mode to preserve the collation version.
+ */
+ if (dopt->binary_upgrade && collinfo->dobj.catId.oid >=
FirstBootstrapObjectId)
+ collinfo->dobj.dump = DUMP_COMPONENT_ALL;
+}
+
/*
* selectDumpableProcLang: policy-setting subroutine
* Mark a procedural language as to be dumped or not
@@ -2980,6 +3002,10 @@ dumpDatabase(Archive *fout)
frozenxid, minmxid);
appendStringLiteralAH(creaQry, datname, fout);
appendPQExpBufferStr(creaQry, ";\n");
+
+ appendPQExpBufferStr(creaQry, "\n-- Remove collations created
by initdb.\n");
+ appendPQExpBuffer(creaQry, "DELETE FROM pg_catalog.pg_collation
WHERE oid > %u;\n",
+ FirstBootstrapObjectId);
}
if (creaQry->len > 0)
@@ -5107,7 +5133,8 @@ getCollations(Archive *fout, int *numCollations)
appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
"collnamespace, "
"(%s collowner) AS rolname "
- "FROM pg_collation",
+ "FROM pg_collation "
+ "WHERE collencoding = (SELECT
encoding FROM pg_database WHERE datname = current_database()) OR collencoding =
-1",
username_subquery);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -5136,7 +5163,7 @@ getCollations(Archive *fout, int *numCollations)
collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
- selectDumpableObject(&(collinfo[i].dobj), fout);
+ selectDumpableCollation(&collinfo[i], fout);
/* Collations do not currently have ACLs. */
collinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
base-commit: 61ecea45e50bcd3b87d4e905719e63e41d6321ce
--
2.23.0