From e2609323eb58ee273ac03a66343447e6a56154d5 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 2 Mar 2016 12:24:30 -0500
Subject: [PATCH] Make PL/Tcl require Tcl 8.4 or later.

As of commit 287822068246a6ae30bb2c7191de727672ae6328, PL/Tcl will not
compile against pre-8.0 Tcl, whereas it used to work (more or less anyway)
with quite prehistoric versions.  As long as we're moving these goalposts,
let's reinstall them at someplace that has some thought behind it.  This
commit sets the minimum allowed Tcl version at 8.4, and rips out some bits
of compatibility cruft that are in consequence no longer needed.  Reasons
for requiring 8.4 include:

* 8.4 was released in 2002; there seems little reason to believe that
anyone would want to use older versions with Postgres 9.6+.

* We have no buildfarm members testing anything older than 8.4, and
thus no way to know if it's broken.

* We need at least 8.1 to allow enforcement of database encoding
security (8.1 standardized Tcl on using UTF8 internally, before that
it was pretty unpredictable).

* Some versions between 8.1 and 8.4 allowed the backend to become
multithreaded, which is disastrous.  We need at least 8.4 to be able
to disable the Tcl notifier subsystem to prevent that.

A small side benefit is that we can make the code more readable by
doing s/CONST84/const/g.
---
 src/pl/tcl/pltcl.c | 95 +++++++++++++++++++---------------------------
 1 file changed, 40 insertions(+), 55 deletions(-)

diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 6b2004d34c6..9df63b103c4 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -13,16 +13,6 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-/* Hack to deal with Tcl 8.4 const-ification without losing compatibility */
-#ifndef CONST84
-#define CONST84
-#endif
-
-/* ... and for Tcl 8.6. */
-#ifndef CONST86
-#define CONST86
-#endif
-
 #include "access/htup_details.h"
 #include "access/xact.h"
 #include "catalog/pg_proc.h"
@@ -47,16 +37,21 @@
 	((TCL_MAJOR_VERSION > maj) || \
 	 (TCL_MAJOR_VERSION == maj && TCL_MINOR_VERSION >= min))
 
-/* Insist on Tcl >= 8.0 */
-#if !HAVE_TCL_VERSION(8,0)
-#error PostgreSQL only supports Tcl 8.0 or later.
+/* Insist on Tcl >= 8.4 */
+#if !HAVE_TCL_VERSION(8,4)
+#error PostgreSQL only supports Tcl 8.4 or later.
+#endif
+
+/* Hack to deal with Tcl 8.6 const-ification without losing compatibility */
+#ifndef CONST86
+#define CONST86
 #endif
 
 /* define our text domain for translations */
 #undef TEXTDOMAIN
 #define TEXTDOMAIN PG_TEXTDOMAIN("pltcl")
 
-#if defined(UNICODE_CONVERSION) && HAVE_TCL_VERSION(8,1)
+#if defined(UNICODE_CONVERSION)
 
 #include "mb/pg_wchar.h"
 
@@ -223,7 +218,7 @@ static int pltcl_returnnull(ClientData cdata, Tcl_Interp *interp,
 static int pltcl_SPI_execute(ClientData cdata, Tcl_Interp *interp,
 				  int objc, Tcl_Obj *const objv[]);
 static int pltcl_process_SPI_result(Tcl_Interp *interp,
-						 CONST84 char *arrayname,
+						 const char *arrayname,
 						 Tcl_Obj *loop_body,
 						 int spi_rc,
 						 SPITupleTable *tuptable,
@@ -235,7 +230,7 @@ static int pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp,
 static int pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp,
 				  int objc, Tcl_Obj *const objv[]);
 
-static void pltcl_set_tuple_values(Tcl_Interp *interp, CONST84 char *arrayname,
+static void pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname,
 					   int tupno, HeapTuple tuple, TupleDesc tupdesc);
 static Tcl_Obj *pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc);
 
@@ -250,10 +245,7 @@ static Tcl_Obj *pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc);
  * from Postgres, so the notifier capabilities are initialized, but never
  * used.  Only InitNotifier and DeleteFileHandler ever seem to get called
  * within Postgres, but we implement all the functions for completeness.
- * We can only fix this with Tcl >= 8.4, when Tcl_SetNotifier() appeared.
  */
-#if HAVE_TCL_VERSION(8,4)
-
 static ClientData
 pltcl_InitNotifier(void)
 {
@@ -298,7 +290,6 @@ pltcl_WaitForEvent(CONST86 Tcl_Time *timePtr)
 {
 	return 0;
 }
-#endif   /* HAVE_TCL_VERSION(8,4) */
 
 
 /*
@@ -329,6 +320,7 @@ perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
 void
 _PG_init(void)
 {
+	Tcl_NotifierProcs notifier;
 	HASHCTL		hash_ctl;
 
 	/* Be sure we do initialization only once (should be redundant now) */
@@ -342,25 +334,18 @@ _PG_init(void)
 	Tcl_FindExecutable("");
 #endif
 
-#if HAVE_TCL_VERSION(8,4)
-
 	/*
 	 * Override the functions in the Notifier subsystem.  See comments above.
 	 */
-	{
-		Tcl_NotifierProcs notifier;
-
-		notifier.setTimerProc = pltcl_SetTimer;
-		notifier.waitForEventProc = pltcl_WaitForEvent;
-		notifier.createFileHandlerProc = pltcl_CreateFileHandler;
-		notifier.deleteFileHandlerProc = pltcl_DeleteFileHandler;
-		notifier.initNotifierProc = pltcl_InitNotifier;
-		notifier.finalizeNotifierProc = pltcl_FinalizeNotifier;
-		notifier.alertNotifierProc = pltcl_AlertNotifier;
-		notifier.serviceModeHookProc = pltcl_ServiceModeHook;
-		Tcl_SetNotifier(&notifier);
-	}
-#endif
+	notifier.setTimerProc = pltcl_SetTimer;
+	notifier.waitForEventProc = pltcl_WaitForEvent;
+	notifier.createFileHandlerProc = pltcl_CreateFileHandler;
+	notifier.deleteFileHandlerProc = pltcl_DeleteFileHandler;
+	notifier.initNotifierProc = pltcl_InitNotifier;
+	notifier.finalizeNotifierProc = pltcl_FinalizeNotifier;
+	notifier.alertNotifierProc = pltcl_AlertNotifier;
+	notifier.serviceModeHookProc = pltcl_ServiceModeHook;
+	Tcl_SetNotifier(&notifier);
 
 	/************************************************************
 	 * Create the dummy hold interpreter to prevent close of
@@ -853,8 +838,8 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
 	Datum	   *modvalues;
 	char	   *modnulls;
 	int			ret_numvals;
-	CONST84 char *result;
-	CONST84 char **ret_values;
+	const char *result;
+	const char **ret_values;
 
 	/* Connect to SPI manager */
 	if (SPI_connect() != SPI_OK_CONNECT)
@@ -1093,8 +1078,8 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
 
 		for (i = 0; i < ret_numvals; i += 2)
 		{
-			CONST84 char *ret_name = ret_values[i];
-			CONST84 char *ret_value = ret_values[i + 1];
+			const char *ret_name = ret_values[i];
+			const char *ret_value = ret_values[i + 1];
 			int			attnum;
 			Oid			typinput;
 			Oid			typioparam;
@@ -1620,12 +1605,12 @@ pltcl_elog(ClientData cdata, Tcl_Interp *interp,
 	MemoryContext oldcontext;
 	int			priIndex;
 
-	static CONST84 char *logpriorities[] = {
+	static const char *logpriorities[] = {
 		"DEBUG", "LOG", "INFO", "NOTICE",
-		"WARNING", "ERROR", "FATAL", (char *) NULL
+		"WARNING", "ERROR", "FATAL", (const char *) NULL
 	};
 
-	static CONST84 int loglevels[] = {
+	static const int loglevels[] = {
 		DEBUG2, LOG, INFO, NOTICE,
 		WARNING, ERROR, FATAL
 	};
@@ -1934,7 +1919,7 @@ pltcl_SPI_execute(ClientData cdata, Tcl_Interp *interp,
 	int			i;
 	int			optIndex;
 	int			count = 0;
-	CONST84 char *volatile arrayname = NULL;
+	const char *volatile arrayname = NULL;
 	Tcl_Obj    *volatile loop_body = NULL;
 	MemoryContext oldcontext = CurrentMemoryContext;
 	ResourceOwner oldowner = CurrentResourceOwner;
@@ -1944,8 +1929,8 @@ pltcl_SPI_execute(ClientData cdata, Tcl_Interp *interp,
 		OPT_ARRAY, OPT_COUNT
 	};
 
-	static CONST84 char *options[] = {
-		"-array", "-count", (char *) NULL
+	static const char *options[] = {
+		"-array", "-count", (const char *) NULL
 	};
 
 	/************************************************************
@@ -2035,7 +2020,7 @@ pltcl_SPI_execute(ClientData cdata, Tcl_Interp *interp,
  */
 static int
 pltcl_process_SPI_result(Tcl_Interp *interp,
-						 CONST84 char *arrayname,
+						 const char *arrayname,
 						 Tcl_Obj *loop_body,
 						 int spi_rc,
 						 SPITupleTable *tuptable,
@@ -2282,7 +2267,7 @@ pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp,
 	Tcl_HashEntry *hashent;
 	pltcl_query_desc *qdesc;
 	const char *nulls = NULL;
-	CONST84 char *arrayname = NULL;
+	const char *arrayname = NULL;
 	Tcl_Obj    *loop_body = NULL;
 	int			count = 0;
 	int			callObjc;
@@ -2297,8 +2282,8 @@ pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp,
 		OPT_ARRAY, OPT_COUNT, OPT_NULLS
 	};
 
-	static CONST84 char *options[] = {
-		"-array", "-count", "-nulls", (char *) NULL
+	static const char *options[] = {
+		"-array", "-count", "-nulls", (const char *) NULL
 	};
 
 	/************************************************************
@@ -2500,19 +2485,19 @@ pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp,
  *				  of a given tuple
  **********************************************************************/
 static void
-pltcl_set_tuple_values(Tcl_Interp *interp, CONST84 char *arrayname,
+pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname,
 					   int tupno, HeapTuple tuple, TupleDesc tupdesc)
 {
 	int			i;
 	char	   *outputstr;
 	Datum		attr;
 	bool		isnull;
-	CONST84 char *attname;
+	const char *attname;
 	Oid			typoutput;
 	bool		typisvarlena;
-	CONST84 char **arrptr;
-	CONST84 char **nameptr;
-	CONST84 char *nullname = NULL;
+	const char **arrptr;
+	const char **nameptr;
+	const char *nullname = NULL;
 
 	/************************************************************
 	 * Prepare pointers for Tcl_SetVar2() below and in array
-- 
GitLab