From 33d78c9e48d8d096f606c169413ca3d56b9c9b2c Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 30 Jan 2007 18:02:22 +0000
Subject: [PATCH] Add SPI_push/SPI_pop calls so that datatype input and output
 functions called by plpgsql can themselves use SPI --- possibly indirectly,
 as in the case of domain_in() invoking plpgsql functions in a domain check
 constraint. Per bug #2945 from Sergiy Vyshnevetskiy.

Somewhat arbitrarily, I've chosen to back-patch this as far as 8.0.  Given
the lack of prior complaints, it doesn't seem critical for 7.x.
---
 src/pl/plpgsql/src/pl_exec.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 67bcbf0cc40..8a9c0093c5b 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.185 2007/01/28 17:58:13 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.186 2007/01/30 18:02:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4282,12 +4282,27 @@ make_tuple_from_row(PLpgSQL_execstate *estate,
 static char *
 convert_value_to_string(Datum value, Oid valtype)
 {
+	char	   *str;
 	Oid			typoutput;
 	bool		typIsVarlena;
 
 	getTypeOutputInfo(valtype, &typoutput, &typIsVarlena);
 
-	return OidOutputFunctionCall(typoutput, value);
+	/*
+	 * We do SPI_push to allow the datatype output function to use SPI.
+	 * However we do not mess around with CommandCounterIncrement or advancing
+	 * the snapshot, which means that a stable output function would not see
+	 * updates made so far by our own function.  The use-case for such
+	 * scenarios seems too narrow to justify the cycles that would be
+	 * expended.
+	 */
+	SPI_push();
+
+	str = OidOutputFunctionCall(typoutput, value);
+
+	SPI_pop();
+
+	return str;
 }
 
 /* ----------
@@ -4313,14 +4328,25 @@ exec_cast_value(Datum value, Oid valtype,
 			char	   *extval;
 
 			extval = convert_value_to_string(value, valtype);
+
+			/* Allow input function to use SPI ... see notes above */
+			SPI_push();
+
 			value = InputFunctionCall(reqinput, extval,
 									  reqtypioparam, reqtypmod);
+
+			SPI_pop();
+
 			pfree(extval);
 		}
 		else
 		{
+			SPI_push();
+
 			value = InputFunctionCall(reqinput, NULL,
 									  reqtypioparam, reqtypmod);
+
+			SPI_pop();
 		}
 	}
 
-- 
GitLab