1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add new return codes SPI_OK_INSERT_RETURNING etc to the SPI API.

Fix all the standard PLs to be able to return tuples from FOO_RETURNING
statements as well as utility statements that return tuples.  Also,
fix oversight that SPI_processed wasn't set for a utility statement
returning tuples.  Per recent discussion.
This commit is contained in:
Tom Lane
2006-08-27 23:47:58 +00:00
parent 7a2fe85b03
commit ea2e263539
7 changed files with 102 additions and 61 deletions

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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();

View File

@ -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