SPI_cursor_open failed to enforce that only read-only queries could be
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 17 Mar 2007 03:15:38 +0000 (03:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 17 Mar 2007 03:15:38 +0000 (03:15 +0000)
executed in read_only mode.  This could lead to various relatively-subtle
failures, such as an allegedly stable function returning non-stable results.
Bug goes all the way back to the introduction of read-only mode in 8.0.
Per report from Gaetano Mendola.

src/backend/executor/spi.c

index 7a34add7105b27e69dfe08511434ad01971f1a86..e0856a3d8f2bcc93fb029da301db2b8ceb275890 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.172 2007/03/15 23:12:06 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.173 2007/03/17 03:15:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -964,6 +964,30 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
    else
        portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
 
+   /*
+    * If told to be read-only, we'd better check for read-only queries.
+    * This can't be done earlier because we need to look at the finished,
+    * planned queries.  (In particular, we don't want to do it between
+    * RevalidateCachedPlan and PortalDefineQuery, because throwing an error
+    * between those steps would result in leaking our plancache refcount.)
+    */
+   if (read_only)
+   {
+       ListCell   *lc;
+
+       foreach(lc, stmt_list)
+       {
+           Node   *pstmt = (Node *) lfirst(lc);
+
+           if (!CommandIsReadOnly(pstmt))
+               ereport(ERROR,
+                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                        /* translator: %s is a SQL statement name */
+                        errmsg("%s is not allowed in a non-volatile function",
+                               CreateCommandTag(pstmt))));
+       }
+   }
+
    /*
     * Set up the snapshot to use.  (PortalStart will do CopySnapshot, so we
     * skip that here.)