From 5174d658dc7ab05964518bcfc82b82e408fb6a17 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 8 Nov 2019 12:01:05 +1300
Subject: [PATCH 1/2] Add collation versions for Windows.

Work in progress.
---
 src/backend/utils/adt/pg_locale.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index fcdbaae37b..36f70279e5 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -1532,6 +1532,29 @@ get_collation_actual_version(char collprovider, const char *collcollate)
 #if defined(__GLIBC__)
 		/* Use the glibc version because we don't have anything better. */
 		collversion = pstrdup(gnu_get_libc_version());
+#elif defined(WIN32) && _WIN32_WINNT >= 0x0600
+		/*
+		 * If we are targeting Windows Vista and above, we can ask for a
+		 * name given a collation name (earlier versions required a
+		 * location code that we don't have).
+		 */
+		NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)};
+		WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
+
+		/* These would be invalid arguments, but have no version. */
+		if (pg_strcasecmp("c", collcollate) == 0 ||
+			pg_strcasecmp("posix", collcollate) == 0)
+			return pstrdup("");
+
+		/* For all other names, ask the OS. */
+		MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
+							LOCALE_NAME_MAX_LENGTH);
+		if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
+			ereport(ERROR,
+					(errmsg("could not get collation version for locale \"%s\": error code %lu",
+							collcollate,
+							GetLastError())));
+		collversion = psprintf("%x,%x", version.dwNLSVersion, version.dwDefinedVersion);
 #endif
 	}
 
-- 
2.23.0

