From ce89d0570702c5581100ba16742cc0b6914db61b Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@enterprisedb.com>
Date: Tue, 4 Sep 2018 04:54:56 +1200
Subject: [PATCH 1/2] Add libc_collation_version_command GUC.

---
 src/backend/utils/adt/pg_locale.c | 50 +++++++++++++++++++++++++++++++
 src/backend/utils/misc/guc.c      | 13 ++++++++
 src/include/utils/guc.h           |  1 +
 3 files changed, 64 insertions(+)

diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index a3dc3be5a87..bb65c075676 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -56,7 +56,9 @@
 #include "access/htup_details.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_control.h"
+#include "lib/stringinfo.h"
 #include "mb/pg_wchar.h"
+#include "storage/fd.h"
 #include "utils/builtins.h"
 #include "utils/hsearch.h"
 #include "utils/lsyscache.h"
@@ -1475,6 +1477,54 @@ get_collation_actual_version(char collprovider, const char *collcollate)
 	}
 	else
 #endif
+	if (libc_collation_version_command[0] != '\0')
+	{
+		char		buffer[1024];
+		StringInfoData output;
+		FILE	   *file;
+		size_t		len;
+		const char *p;
+
+#define LC_COLLATE_TOKEN "@LC_COLLATE@"
+#define LC_COLLATE_TOKEN_LEN (sizeof(LC_COLLATE_TOKEN) - 1)
+
+		/* Build the complete command. */
+		initStringInfo(&output);
+		p = libc_collation_version_command;
+		while (*p)
+		{
+			if (strncmp(p, LC_COLLATE_TOKEN, LC_COLLATE_TOKEN_LEN) == 0)
+			{
+				appendStringInfoString(&output, collcollate);
+				p += LC_COLLATE_TOKEN_LEN;
+			}
+			else
+				appendStringInfoChar(&output, *p++);
+		}
+
+		/* Execute it and read one line. */
+		file = OpenPipeStream(output.data, "r");
+		if (!file)
+			ereport(ERROR,
+					(errmsg("could not run command \"%s\": %m",
+							output.data)));
+		if (!fgets(buffer, sizeof(buffer), file))
+		{
+			ClosePipeStream(file);
+			ereport(ERROR,
+					(errmsg("could not read output from command \"%s\": %m",
+							output.data)));
+		}
+		ClosePipeStream(file);
+		pfree(output.data);
+
+		/* Trim off newline. */
+		len = strlen(buffer);
+		if (len > 0 && buffer[len - 1] == '\n')
+			buffer[len - 1] = '\0';
+		collversion = pstrdup(buffer);
+	}
+	else
 		collversion = NULL;
 
 	return collversion;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0625eff2191..ed19a71f319 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -474,6 +474,7 @@ char	   *ConfigFileName;
 char	   *HbaFileName;
 char	   *IdentFileName;
 char	   *external_pid_file;
+char	   *libc_collation_version_command;
 
 char	   *pgstat_temp_directory;
 
@@ -3883,6 +3884,18 @@ static struct config_string ConfigureNamesString[] =
 		check_cluster_name, NULL, NULL
 	},
 
+	{
+		{"libc_collation_version_command", PGC_POSTMASTER, PROCESS_TITLE,
+			gettext_noop("Command to obtain version strings for libc collations."),
+			NULL,
+			GUC_IS_NAME
+		},
+		&libc_collation_version_command,
+		"",
+		NULL, NULL, NULL
+	},
+
+
 	{
 		{"wal_consistency_checking", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Sets the WAL resource managers for which WAL consistency checks are done."),
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f462eabe594..7efbe033d22 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -262,6 +262,7 @@ extern PGDLLIMPORT char *ConfigFileName;
 extern char *HbaFileName;
 extern char *IdentFileName;
 extern char *external_pid_file;
+extern char *libc_collation_version_command;
 
 extern PGDLLIMPORT char *application_name;
 
-- 
2.17.0

