]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add checks to verify that a plpgsql function returning a rowtype is actually
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 3 Jan 2006 22:48:28 +0000 (22:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 3 Jan 2006 22:48:28 +0000 (22:48 +0000)
returning the rowtype it's supposed to return.  Per reports from David Niblett
and Michael Fuhr.

src/pl/plpgsql/src/pl_exec.c

index 0470a14f999f79270bd315b7662226ac77f0a436..9d17ead258fb32d6233dd370526b539e01ba6ccb 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.3 2005/06/20 22:51:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.4 2006/01/03 22:48:28 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -382,10 +382,37 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
        {
                if (estate.retistuple)
                {
-                       /* Copy tuple to upper executor memory, as a tuple Datum */
+                       /*
+                        * We have to check that the returned tuple actually matches
+                        * the expected result type.
+                        */
+                       ReturnSetInfo *rsi = estate.rsi;
+                       TupleDesc       tupdesc;
+
+                       if (rsi && IsA(rsi, ReturnSetInfo) &&
+                               rsi->expectedDesc != NULL)
+                               tupdesc = rsi->expectedDesc;
+                       else if (estate.fn_rettype == RECORDOID)
+                       {
+                               /* assume caller can handle any record type */
+                               tupdesc = estate.rettupdesc;
+                       }
+                       else
+                               tupdesc = lookup_rowtype_tupdesc(estate.fn_rettype, -1);
+                       /* got the expected result rowtype, now check it */
+                       if (estate.rettupdesc == NULL ||
+                               !compatible_tupdesc(estate.rettupdesc, tupdesc))
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_DATATYPE_MISMATCH),
+                                                errmsg("returned record type does not match expected record type")));
+
+                       /*
+                        * Copy tuple to upper executor memory, as a tuple Datum.
+                        * Make sure it is labeled with the caller-supplied tuple type.
+                        */
                        estate.retval =
                                PointerGetDatum(SPI_returntuple((HeapTuple) (estate.retval),
-                                                                                               estate.rettupdesc));
+                                                                                               tupdesc));
                }
                else
                {