From 6ea8dfac788be4f02e8c6162b6e2d9cd6bd0b4aa Mon Sep 17 00:00:00 2001
From: Davinder Singh <davindersingh2692@gmail.com>
Date: Mon, 6 Apr 2020 16:31:54 +0530
Subject: [PATCH] PG compilation error with VS 2015/2017/2019

This fix is to resolve undefined struct/union error while accessing
locale_name.
---
 src/backend/utils/adt/pg_locale.c | 66 ++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 24 deletions(-)

diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 2562eb5416..c00a3c9181 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -990,6 +990,7 @@ IsoLocaleName(const char *winlocname)
 #ifdef _MSC_VER
 	static char iso_lc_messages[32];
 	_locale_t	loct = NULL;
+	size_t		rc;
 
 	if (pg_strcasecmp("c", winlocname) == 0 ||
 		pg_strcasecmp("posix", winlocname) == 0)
@@ -997,38 +998,55 @@ IsoLocaleName(const char *winlocname)
 		strcpy(iso_lc_messages, "C");
 		return iso_lc_messages;
 	}
-
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
 	loct = _create_locale(LC_CTYPE, winlocname);
 	if (loct != NULL)
 	{
-		size_t		rc;
-		char	   *hyphen;
-
 		/* Locale names use only ASCII, any conversion locale suffices. */
 		rc = wchar2char(iso_lc_messages, loct->locinfo->locale_name[LC_CTYPE],
-						sizeof(iso_lc_messages), NULL);
+			sizeof(iso_lc_messages), NULL);
 		_free_locale(loct);
-		if (rc == -1 || rc == sizeof(iso_lc_messages))
-			return NULL;
+	}
+	else
+		return NULL;
+#endif		/*_MSC_VER && _MSC_VER < 1900*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+	WCHAR		wc_locale_name[LOCALE_NAME_MAX_LENGTH];
+	WCHAR		buffer[LOCALE_NAME_MAX_LENGTH];
 
-		/*
-		 * Since the message catalogs sit on a case-insensitive filesystem, we
-		 * need not standardize letter case here.  So long as we do not ship
-		 * message catalogs for which it would matter, we also need not
-		 * translate the script/variant portion, e.g. uz-Cyrl-UZ to
-		 * uz_UZ@cyrillic.  Simply replace the hyphen with an underscore.
-		 *
-		 * Note that the locale name can be less-specific than the value we
-		 * would derive under earlier Visual Studio releases.  For example,
-		 * French_France.1252 yields just "fr".  This does not affect any of
-		 * the country-specific message catalogs available as of this writing
-		 * (pt_BR, zh_CN, zh_TW).
-		 */
-		hyphen = strchr(iso_lc_messages, '-');
-		if (hyphen)
-			*hyphen = '_';
-		return iso_lc_messages;
+	memset(wc_locale_name, 0, sizeof(wc_locale_name));
+	memset(buffer, 0, sizeof(buffer));
+
+	MultiByteToWideChar(CP_ACP, 0, winlocname, -1, wc_locale_name, LOCALE_NAME_MAX_LENGTH);
+
+	if ((GetLocaleInfoEx(wc_locale_name, LOCALE_SNAME,
+		(LPWSTR)&buffer, LOCALE_NAME_MAX_LENGTH)) > 0) {
+		rc = wchar2char(iso_lc_messages, buffer, sizeof(iso_lc_messages), NULL);
 	}
+	else
+		return NULL;
+#endif		/* _MSC_VER && _MSC_VER >= 1900 */
+	char* hyphen;
+	if (rc == -1 || rc == sizeof(iso_lc_messages))
+		return NULL;
+
+	/*
+	 * Since the message catalogs sit on a case-insensitive filesystem, we
+	 * need not standardize letter case here.  So long as we do not ship
+	 * message catalogs for which it would matter, we also need not
+	 * translate the script/variant portion, e.g. uz-Cyrl-UZ to
+	 * uz_UZ@cyrillic.  Simply replace the hyphen with an underscore.
+	 *
+	 * Note that the locale name can be less-specific than the value we
+	 * would derive under earlier Visual Studio releases.  For example,
+	 * French_France.1252 yields just "fr".  This does not affect any of
+	 * the country-specific message catalogs available as of this writing
+	 * (pt_BR, zh_CN, zh_TW).
+	 */
+	hyphen = strchr(iso_lc_messages, '-');
+	if (hyphen)
+		*hyphen = '_';
+	return iso_lc_messages;
 #endif							/* _MSC_VER */
 	return NULL;				/* Not supported on this version of msvc/mingw */
 }
-- 
2.24.0.windows.2

