summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas2009-01-21 11:02:40 +0000
committerHeikki Linnakangas2009-01-21 11:02:40 +0000
commitaddd1fc7eda459ba4430d4e6a603f667e3238856 (patch)
treef0921cf20d342c29e7ae6727bb5a307872c00db2
parent1158983bb029084659ab87eab860af0bf10fe8a7 (diff)
Add new SPI_OK_REWRITTEN return code to SPI_execute and friends, for the
case that the command is rewritten into another type of command. The old behavior to return the command tag of the last executed command was pretty surprising. In PL/pgSQL, for example, it meant that if a command was rewritten to a utility statement, FOUND wasn't set at all.
-rw-r--r--doc/src/sgml/spi.sgml10
-rw-r--r--src/backend/executor/spi.c9
-rw-r--r--src/include/executor/spi.h1
-rw-r--r--src/pl/plpgsql/src/pl_exec.c24
4 files changed, 32 insertions, 12 deletions
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index 248564f92b..0db9c32904 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -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 a49f14f12d..a4d08e5595 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -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 1c422cfa13..25b92229ac 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -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 4421521ca9..68e7941d18 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -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: