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: