diff options
-rw-r--r-- | doc/src/sgml/spi.sgml | 58 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 29 | ||||
-rw-r--r-- | src/include/executor/spi.h | 5 | ||||
-rw-r--r-- | src/pl/plperl/plperl.c | 4 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 27 | ||||
-rw-r--r-- | src/pl/plpython/plpython.c | 13 | ||||
-rw-r--r-- | src/pl/tcl/pltcl.c | 17 |
7 files changed, 97 insertions, 56 deletions
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index 016874dce70..b19189632e6 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.46 2006/08/12 20:05:54 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.47 2006/08/27 23:47:57 tgl Exp $ --> <chapter id="spi"> <title>Server Programming Interface</title> @@ -361,12 +361,16 @@ SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5); <para> The actual number of rows for which the (last) command was executed - is returned in the global variable <varname>SPI_processed</varname> - (unless the return value of the function is - <symbol>SPI_OK_UTILITY</symbol>). If the return value of the - function is <symbol>SPI_OK_SELECT</symbol> then you may use the + is returned in the global variable <varname>SPI_processed</varname>. + If the return value of the function is <symbol>SPI_OK_SELECT</symbol>, + <symbol>SPI_OK_INSERT_RETURNING</symbol>, + <symbol>SPI_OK_DELETE_RETURNING</symbol>, or + <symbol>SPI_OK_UPDATE_RETURNING</symbol>, + then you may use the global pointer <literal>SPITupleTable *SPI_tuptable</literal> to - access the result rows. + access the result rows. Some utility commands (such as + <command>EXPLAIN</>) also return rowsets, and <literal>SPI_tuptable</> + will contain the result in these cases too. </para> <para> @@ -459,19 +463,19 @@ typedef struct </varlistentry> <varlistentry> - <term><symbol>SPI_OK_DELETE</symbol></term> + <term><symbol>SPI_OK_INSERT</symbol></term> <listitem> <para> - if a <command>DELETE</command> was executed + if an <command>INSERT</command> was executed </para> </listitem> </varlistentry> <varlistentry> - <term><symbol>SPI_OK_INSERT</symbol></term> + <term><symbol>SPI_OK_DELETE</symbol></term> <listitem> <para> - if an <command>INSERT</command> was executed + if a <command>DELETE</command> was executed </para> </listitem> </varlistentry> @@ -486,6 +490,33 @@ typedef struct </varlistentry> <varlistentry> + <term><symbol>SPI_OK_INSERT_RETURNING</symbol></term> + <listitem> + <para> + if an <command>INSERT RETURNING</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_DELETE_RETURNING</symbol></term> + <listitem> + <para> + if a <command>DELETE RETURNING</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><symbol>SPI_OK_UPDATE_RETURNING</symbol></term> + <listitem> + <para> + if an <command>UPDATE RETURNING</command> was executed + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><symbol>SPI_OK_UTILITY</symbol></term> <listitem> <para> @@ -2987,10 +3018,9 @@ execq(text *sql, int cnt) proc = SPI_processed; /* - * If this is a SELECT and some rows were fetched, - * then the rows are printed via elog(INFO). + * If some rows were fetched, print them via elog(INFO). */ - if (ret == SPI_OK_SELECT && SPI_processed > 0) + if (ret > 0 && SPI_tuptable != NULL) { TupleDesc tupdesc = SPI_tuptable->tupdesc; SPITupleTable *tuptable = SPI_tuptable; @@ -3005,7 +3035,7 @@ execq(text *sql, int cnt) snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s", SPI_getvalue(tuple, tupdesc, i), (i == tupdesc->natts) ? " " : " |"); - elog (INFO, "EXECQ: %s", buf); + elog(INFO, "EXECQ: %s", buf); } } diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 183969f1b85..dd22a2dd5f2 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.157 2006/08/14 22:57:15 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.158 2006/08/27 23:47:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1136,6 +1136,12 @@ SPI_result_code_string(int code) return "SPI_OK_UPDATE"; case SPI_OK_CURSOR: return "SPI_OK_CURSOR"; + case SPI_OK_INSERT_RETURNING: + return "SPI_OK_INSERT_RETURNING"; + case SPI_OK_DELETE_RETURNING: + return "SPI_OK_DELETE_RETURNING"; + case SPI_OK_UPDATE_RETURNING: + return "SPI_OK_UPDATE_RETURNING"; } /* Unrecognized code ... return something useful ... */ sprintf(buf, "Unrecognized SPI code %d", code); @@ -1454,6 +1460,9 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls, { ProcessUtility(queryTree->utilityStmt, paramLI, dest, NULL); + /* Update "processed" if stmt returned tuples */ + if (_SPI_current->tuptable) + _SPI_current->processed = _SPI_current->tuptable->alloced - _SPI_current->tuptable->free; res = SPI_OK_UTILITY; } else @@ -1542,13 +1551,22 @@ _SPI_pquery(QueryDesc *queryDesc, long tcount) res = SPI_OK_SELECT; break; case CMD_INSERT: - res = SPI_OK_INSERT; + if (queryDesc->parsetree->returningList) + res = SPI_OK_INSERT_RETURNING; + else + res = SPI_OK_INSERT; break; case CMD_DELETE: - res = SPI_OK_DELETE; + if (queryDesc->parsetree->returningList) + res = SPI_OK_DELETE_RETURNING; + else + res = SPI_OK_DELETE; break; case CMD_UPDATE: - res = SPI_OK_UPDATE; + if (queryDesc->parsetree->returningList) + res = SPI_OK_UPDATE_RETURNING; + else + res = SPI_OK_UPDATE; break; default: return SPI_ERROR_OPUNKNOWN; @@ -1568,7 +1586,8 @@ _SPI_pquery(QueryDesc *queryDesc, long tcount) _SPI_current->processed = queryDesc->estate->es_processed; _SPI_current->lastoid = queryDesc->estate->es_lastoid; - if (operation == CMD_SELECT && queryDesc->dest->mydest == DestSPI) + if ((res == SPI_OK_SELECT || queryDesc->parsetree->returningList) && + queryDesc->dest->mydest == DestSPI) { if (_SPI_checktuples()) elog(ERROR, "consistency check on SPI tuple count failed"); diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index b68f5932e39..0d91290968d 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -2,7 +2,7 @@ * * spi.h * - * $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.54 2006/07/11 18:26:11 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.55 2006/08/27 23:47:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -71,6 +71,9 @@ typedef struct #define SPI_OK_DELETE 8 #define SPI_OK_UPDATE 9 #define SPI_OK_CURSOR 10 +#define SPI_OK_INSERT_RETURNING 11 +#define SPI_OK_DELETE_RETURNING 12 +#define SPI_OK_UPDATE_RETURNING 13 extern DLLIMPORT uint32 SPI_processed; extern DLLIMPORT Oid SPI_lastoid; diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index c63e9d7b62e..0906d3186ac 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1,7 +1,7 @@ /********************************************************************** * plperl.c - perl as a procedural language for PostgreSQL * - * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.117 2006/08/13 17:31:10 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.118 2006/08/27 23:47:58 tgl Exp $ * **********************************************************************/ @@ -1630,7 +1630,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, hv_store(result, "processed", strlen("processed"), newSViv(processed), 0); - if (status == SPI_OK_SELECT) + if (status > 0 && tuptable) { AV *rows; SV *row; diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index f8213d4a50f..dedba151178 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.176 2006/08/15 19:01:17 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.177 2006/08/27 23:47:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2370,23 +2370,16 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, case SPI_OK_INSERT: case SPI_OK_UPDATE: case SPI_OK_DELETE: + 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: - Assert(!stmt->mod_stmt); - break; - case SPI_OK_UTILITY: Assert(!stmt->mod_stmt); - /* - * spi.c currently does not update SPI_processed for utility - * commands. Not clear if this should be considered a bug; - * for the moment, work around it here. - */ - if (SPI_tuptable) - SPI_processed = (SPI_tuptable->alloced - SPI_tuptable->free); break; default: @@ -2505,16 +2498,10 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, case SPI_OK_INSERT: case SPI_OK_UPDATE: case SPI_OK_DELETE: - break; - + case SPI_OK_INSERT_RETURNING: + case SPI_OK_UPDATE_RETURNING: + case SPI_OK_DELETE_RETURNING: case SPI_OK_UTILITY: - /* - * spi.c currently does not update SPI_processed for utility - * commands. Not clear if this should be considered a bug; - * for the moment, work around it here. - */ - if (SPI_tuptable) - SPI_processed = (SPI_tuptable->alloced - SPI_tuptable->free); break; case 0: diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 289ab2e7b73..f45ecd72222 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -1,7 +1,7 @@ /********************************************************************** * plpython.c - python as a procedural language for PostgreSQL * - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.85 2006/08/08 19:15:09 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.86 2006/08/27 23:47:58 tgl Exp $ * ********************************************************************* */ @@ -2193,24 +2193,19 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status) Py_DECREF(result->status); result->status = PyInt_FromLong(status); - if (status == SPI_OK_UTILITY) - { - Py_DECREF(result->nrows); - result->nrows = PyInt_FromLong(0); - } - else if (status != SPI_OK_SELECT) + if (status > 0 && tuptable == NULL) { Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); } - else + else if (status > 0 && tuptable != NULL) { PLyTypeInfo args; int i; - PLy_typeinfo_init(&args); Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); + PLy_typeinfo_init(&args); oldcontext = CurrentMemoryContext; PG_TRY(); diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 54abd096722..44b2e405f32 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -2,7 +2,7 @@ * pltcl.c - PostgreSQL support for Tcl as * procedural language (PL) * - * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.106 2006/08/08 19:15:09 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.107 2006/08/27 23:47:58 tgl Exp $ * **********************************************************************/ @@ -1663,10 +1663,6 @@ pltcl_process_SPI_result(Tcl_Interp *interp, switch (spi_rc) { - case SPI_OK_UTILITY: - Tcl_SetResult(interp, "0", TCL_VOLATILE); - break; - case SPI_OK_SELINTO: case SPI_OK_INSERT: case SPI_OK_DELETE: @@ -1675,7 +1671,18 @@ pltcl_process_SPI_result(Tcl_Interp *interp, Tcl_SetResult(interp, buf, TCL_VOLATILE); break; + case SPI_OK_UTILITY: + if (tuptable == NULL) + { + Tcl_SetResult(interp, "0", TCL_VOLATILE); + break; + } + /* FALL THRU for utility returning tuples */ + case SPI_OK_SELECT: + case SPI_OK_INSERT_RETURNING: + case SPI_OK_DELETE_RETURNING: + case SPI_OK_UPDATE_RETURNING: /* * Process the tuples we got |