From 476ea078bdfdbc8ee2ba03ba3f0f451701b418aa Mon Sep 17 00:00:00 2001
From: Jeff Davis <jdavis@postgresql.org>
Date: Sat, 29 Oct 2022 13:30:15 -0700
Subject: [PATCH 2/4] Enable pg_collation_actual_version() to work on the
 default collation.

Previously, it would simply return NULL, which was less useful.
---
 src/backend/commands/collationcmds.c | 67 ++++++++++++++++++++--------
 1 file changed, 48 insertions(+), 19 deletions(-)

diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index fcfc02d2ae..23468cf79d 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -22,6 +22,7 @@
 #include "catalog/namespace.h"
 #include "catalog/objectaccess.h"
 #include "catalog/pg_collation.h"
+#include "catalog/pg_database.h"
 #include "commands/alter.h"
 #include "commands/collationcmds.h"
 #include "commands/comment.h"
@@ -425,33 +426,61 @@ AlterCollation(AlterCollationStmt *stmt)
 Datum
 pg_collation_actual_version(PG_FUNCTION_ARGS)
 {
-	Oid			collid = PG_GETARG_OID(0);
-	HeapTuple	tp;
-	char		collprovider;
-	Datum		datum;
-	bool		isnull;
-	char	   *version;
+	Oid		 collid = PG_GETARG_OID(0);
+	char	 provider;
+	char	*locale;
+	char	*version;
+	Datum	 datum;
+	bool	 isnull;
+
+	if (collid == DEFAULT_COLLATION_OID)
+	{
+		/* retrieve from pg_database */
 
-	tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
-	if (!HeapTupleIsValid(tp))
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("collation with OID %u does not exist", collid)));
+		HeapTuple	dbtup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
+		if (!HeapTupleIsValid(dbtup))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("database with OID %u does not exist", MyDatabaseId)));
 
-	collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
+		provider = ((Form_pg_database) GETSTRUCT(dbtup))->datlocprovider;
 
-	if (collprovider != COLLPROVIDER_DEFAULT)
-	{
-		datum = SysCacheGetAttr(COLLOID, tp, collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate, &isnull);
+		datum = SysCacheGetAttr(DATABASEOID, dbtup,
+								provider == COLLPROVIDER_ICU ?
+								Anum_pg_database_daticulocale : Anum_pg_database_datcollate,
+								&isnull);
 		if (isnull)
-			elog(ERROR, "unexpected null in pg_collation");
-		version = get_collation_actual_version(collprovider, TextDatumGetCString(datum));
+			elog(ERROR, "unexpected null in pg_database");
+
+		locale = TextDatumGetCString(datum);
+
+		ReleaseSysCache(dbtup);
 	}
 	else
-		version = NULL;
+	{
+		/* retrieve from pg_collation */
+
+		HeapTuple	colltp		= SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
+		if (!HeapTupleIsValid(colltp))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("collation with OID %u does not exist", collid)));
+
+		provider = ((Form_pg_collation) GETSTRUCT(colltp))->collprovider;
+		Assert(provider != COLLPROVIDER_DEFAULT);
+		datum = SysCacheGetAttr(COLLOID, colltp,
+								provider == COLLPROVIDER_ICU ?
+								Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate,
+								&isnull);
+		if (isnull)
+			elog(ERROR, "unexpected null in pg_collation");
 
-	ReleaseSysCache(tp);
+		locale = TextDatumGetCString(datum);
+
+		ReleaseSysCache(colltp);
+	}
 
+	version = get_collation_actual_version(provider, locale);
 	if (version)
 		PG_RETURN_TEXT_P(cstring_to_text(version));
 	else
-- 
2.34.1

