diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index 9df76db0457427c21dff7aed3147f3b765c608f5..32cc6149f987c0a40c732f8ca6f64adcb41b0ede 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.63 2009/01/07 13:44:36 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.64 2009/01/21 11:02:40 heikki Exp $ -->
 
 <chapter id="spi">
  <title>Server Programming Interface</title>
@@ -527,6 +527,16 @@ typedef struct
       </para>
      </listitem>
     </varlistentry>
+
+    <varlistentry>
+     <term><symbol>SPI_OK_REWRITTEN</symbol></term>
+     <listitem>
+      <para>
+       if the command was rewritten into another kind of command (e.g.,
+       <command>UPDATE</command> became an <command>INSERT</command>) by a <link linkend="rules">rule</link>.
+      </para>
+     </listitem>
+    </varlistentry>
    </variablelist>
   </para>
 
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index aa562c2ea9a2e6a36ded2d295c540ba05f2304eb..f750560c6f44b7391a8a6ae6a8d144babd6cea26 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.206 2009/01/07 20:38:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.207 2009/01/21 11:02:40 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1490,6 +1490,8 @@ SPI_result_code_string(int code)
 			return "SPI_OK_DELETE_RETURNING";
 		case SPI_OK_UPDATE_RETURNING:
 			return "SPI_OK_UPDATE_RETURNING";
+		case SPI_OK_REWRITTEN:
+			return "SPI_OK_REWRITTEN";
 	}
 	/* Unrecognized code ... return something useful ... */
 	sprintf(buf, "Unrecognized SPI code %d", code);
@@ -1910,11 +1912,12 @@ fail:
 	_SPI_current->tuptable = NULL;
 
 	/*
-	 * If none of the queries had canSetTag, we return the last query's result
-	 * code, but not its auxiliary results (for backwards compatibility).
+	 * If none of the queries had canSetTag, return SPI_OK_REWRITTEN. Prior
+	 * to 8.4, we used return the last query's result code, but not its
+	 * auxiliary results, but that's confusing.
 	 */
 	if (my_res == 0)
-		my_res = res;
+		my_res = SPI_OK_REWRITTEN;
 
 	return my_res;
 }
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index 66a77ce47789dbdb1b3fce1ab2a22a91d18d34a1..8b9fe32d7ba629e68ed840e1ee7e66d94177131b 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.70 2009/01/07 20:38:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.71 2009/01/21 11:02:40 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,6 +56,7 @@ typedef struct _SPI_plan *SPIPlanPtr;
 #define SPI_OK_INSERT_RETURNING 11
 #define SPI_OK_DELETE_RETURNING 12
 #define SPI_OK_UPDATE_RETURNING 13
+#define SPI_OK_REWRITTEN		14
 
 extern PGDLLIMPORT uint32 SPI_processed;
 extern PGDLLIMPORT Oid SPI_lastoid;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index fd7cce3aeddbcc3169fa053e3323eb839523eb4b..7443c62feefbc88d677f02dc071865df785835e1 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.229 2009/01/14 09:53:51 heikki Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.230 2009/01/21 11:02:40 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2782,19 +2782,13 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
 
 	/*
 	 * Check for error, and set FOUND if appropriate (for historical reasons
-	 * we set FOUND only for certain query types).
-	 *
-	 * Note: the command type indicated by return code might not match
-	 * mod_stmt, if there is an INSTEAD OF rule rewriting an UPDATE into an
-	 * INSERT, for example. In that case, the INSERT doesn't have canSetTag
-	 * set, mod_stmt is false, and SPI_execute_plan sets SPI_processed to
-	 * zero. We'll set FOUND to false here in that case. If the statement is
-	 * rewritten into a utility statement, however, FOUND is left unchanged.
-	 * Arguably that's a bug, but changing it now could break applications.
+	 * we set FOUND only for certain query types).	Also Assert that we
+	 * identified the statement type the same as SPI did.
 	 */
 	switch (rc)
 	{
 		case SPI_OK_SELECT:
+			Assert(!stmt->mod_stmt);
 			exec_set_found(estate, (SPI_processed != 0));
 			break;
 
@@ -2804,11 +2798,23 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
 		case SPI_OK_INSERT_RETURNING:
 		case SPI_OK_UPDATE_RETURNING:
 		case SPI_OK_DELETE_RETURNING:
+			Assert(stmt->mod_stmt);
 			exec_set_found(estate, (SPI_processed != 0));
 			break;
 
 		case SPI_OK_SELINTO:
 		case SPI_OK_UTILITY:
+			Assert(!stmt->mod_stmt);
+			break;
+
+		case SPI_OK_REWRITTEN:
+			Assert(!stmt->mod_stmt);
+			/*
+			 * The command was rewritten into another kind of command. It's
+			 * not clear what FOUND would mean in that case (and SPI doesn't
+			 * return the row count either), so just set it to false.
+			 */
+			exec_set_found(estate, false);
 			break;
 
 		default: