Add SPI_push/SPI_pop calls so that datatype input and output functions called
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Jan 2007 18:02:22 +0000 (18:02 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Jan 2007 18:02:22 +0000 (18:02 +0000)
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

index 67bcbf0cc408398607f5e3856a47879cbe66baf1..8a9c0093c5b5c98d4ae6ad0f9cb3bc413fb30725 100644 (file)
@@ -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();
        }
    }