Skip to content

Commit ea2e263

Browse files
committed
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.
1 parent 7a2fe85 commit ea2e263

File tree

7 files changed

+97
-56
lines changed

7 files changed

+97
-56
lines changed

doc/src/sgml/spi.sgml

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.46 2006/08/12 20:05:54 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/spi.sgml,v 1.47 2006/08/27 23:47:57 tgl Exp $ -->
22

33
<chapter id="spi">
44
<title>Server Programming Interface</title>
@@ -361,12 +361,16 @@ SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
361361

362362
<para>
363363
The actual number of rows for which the (last) command was executed
364-
is returned in the global variable <varname>SPI_processed</varname>
365-
(unless the return value of the function is
366-
<symbol>SPI_OK_UTILITY</symbol>). If the return value of the
367-
function is <symbol>SPI_OK_SELECT</symbol> then you may use the
364+
is returned in the global variable <varname>SPI_processed</varname>.
365+
If the return value of the function is <symbol>SPI_OK_SELECT</symbol>,
366+
<symbol>SPI_OK_INSERT_RETURNING</symbol>,
367+
<symbol>SPI_OK_DELETE_RETURNING</symbol>, or
368+
<symbol>SPI_OK_UPDATE_RETURNING</symbol>,
369+
then you may use the
368370
global pointer <literal>SPITupleTable *SPI_tuptable</literal> to
369-
access the result rows.
371+
access the result rows. Some utility commands (such as
372+
<command>EXPLAIN</>) also return rowsets, and <literal>SPI_tuptable</>
373+
will contain the result in these cases too.
370374
</para>
371375

372376
<para>
@@ -459,19 +463,19 @@ typedef struct
459463
</varlistentry>
460464

461465
<varlistentry>
462-
<term><symbol>SPI_OK_DELETE</symbol></term>
466+
<term><symbol>SPI_OK_INSERT</symbol></term>
463467
<listitem>
464468
<para>
465-
if a <command>DELETE</command> was executed
469+
if an <command>INSERT</command> was executed
466470
</para>
467471
</listitem>
468472
</varlistentry>
469473

470474
<varlistentry>
471-
<term><symbol>SPI_OK_INSERT</symbol></term>
475+
<term><symbol>SPI_OK_DELETE</symbol></term>
472476
<listitem>
473477
<para>
474-
if an <command>INSERT</command> was executed
478+
if a <command>DELETE</command> was executed
475479
</para>
476480
</listitem>
477481
</varlistentry>
@@ -485,6 +489,33 @@ typedef struct
485489
</listitem>
486490
</varlistentry>
487491

492+
<varlistentry>
493+
<term><symbol>SPI_OK_INSERT_RETURNING</symbol></term>
494+
<listitem>
495+
<para>
496+
if an <command>INSERT RETURNING</command> was executed
497+
</para>
498+
</listitem>
499+
</varlistentry>
500+
501+
<varlistentry>
502+
<term><symbol>SPI_OK_DELETE_RETURNING</symbol></term>
503+
<listitem>
504+
<para>
505+
if a <command>DELETE RETURNING</command> was executed
506+
</para>
507+
</listitem>
508+
</varlistentry>
509+
510+
<varlistentry>
511+
<term><symbol>SPI_OK_UPDATE_RETURNING</symbol></term>
512+
<listitem>
513+
<para>
514+
if an <command>UPDATE RETURNING</command> was executed
515+
</para>
516+
</listitem>
517+
</varlistentry>
518+
488519
<varlistentry>
489520
<term><symbol>SPI_OK_UTILITY</symbol></term>
490521
<listitem>
@@ -2987,10 +3018,9 @@ execq(text *sql, int cnt)
29873018

29883019
proc = SPI_processed;
29893020
/*
2990-
* If this is a SELECT and some rows were fetched,
2991-
* then the rows are printed via elog(INFO).
3021+
* If some rows were fetched, print them via elog(INFO).
29923022
*/
2993-
if (ret == SPI_OK_SELECT && SPI_processed &gt; 0)
3023+
if (ret &gt; 0 &amp;&amp; SPI_tuptable != NULL)
29943024
{
29953025
TupleDesc tupdesc = SPI_tuptable-&gt;tupdesc;
29963026
SPITupleTable *tuptable = SPI_tuptable;
@@ -3005,7 +3035,7 @@ execq(text *sql, int cnt)
30053035
snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s",
30063036
SPI_getvalue(tuple, tupdesc, i),
30073037
(i == tupdesc-&gt;natts) ? " " : " |");
3008-
elog (INFO, "EXECQ: %s", buf);
3038+
elog(INFO, "EXECQ: %s", buf);
30093039
}
30103040
}
30113041

src/backend/executor/spi.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.157 2006/08/14 22:57:15 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.158 2006/08/27 23:47:57 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1136,6 +1136,12 @@ SPI_result_code_string(int code)
11361136
return "SPI_OK_UPDATE";
11371137
case SPI_OK_CURSOR:
11381138
return "SPI_OK_CURSOR";
1139+
case SPI_OK_INSERT_RETURNING:
1140+
return "SPI_OK_INSERT_RETURNING";
1141+
case SPI_OK_DELETE_RETURNING:
1142+
return "SPI_OK_DELETE_RETURNING";
1143+
case SPI_OK_UPDATE_RETURNING:
1144+
return "SPI_OK_UPDATE_RETURNING";
11391145
}
11401146
/* Unrecognized code ... return something useful ... */
11411147
sprintf(buf, "Unrecognized SPI code %d", code);
@@ -1454,6 +1460,9 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
14541460
{
14551461
ProcessUtility(queryTree->utilityStmt, paramLI,
14561462
dest, NULL);
1463+
/* Update "processed" if stmt returned tuples */
1464+
if (_SPI_current->tuptable)
1465+
_SPI_current->processed = _SPI_current->tuptable->alloced - _SPI_current->tuptable->free;
14571466
res = SPI_OK_UTILITY;
14581467
}
14591468
else
@@ -1542,13 +1551,22 @@ _SPI_pquery(QueryDesc *queryDesc, long tcount)
15421551
res = SPI_OK_SELECT;
15431552
break;
15441553
case CMD_INSERT:
1545-
res = SPI_OK_INSERT;
1554+
if (queryDesc->parsetree->returningList)
1555+
res = SPI_OK_INSERT_RETURNING;
1556+
else
1557+
res = SPI_OK_INSERT;
15461558
break;
15471559
case CMD_DELETE:
1548-
res = SPI_OK_DELETE;
1560+
if (queryDesc->parsetree->returningList)
1561+
res = SPI_OK_DELETE_RETURNING;
1562+
else
1563+
res = SPI_OK_DELETE;
15491564
break;
15501565
case CMD_UPDATE:
1551-
res = SPI_OK_UPDATE;
1566+
if (queryDesc->parsetree->returningList)
1567+
res = SPI_OK_UPDATE_RETURNING;
1568+
else
1569+
res = SPI_OK_UPDATE;
15521570
break;
15531571
default:
15541572
return SPI_ERROR_OPUNKNOWN;
@@ -1568,7 +1586,8 @@ _SPI_pquery(QueryDesc *queryDesc, long tcount)
15681586
_SPI_current->processed = queryDesc->estate->es_processed;
15691587
_SPI_current->lastoid = queryDesc->estate->es_lastoid;
15701588

1571-
if (operation == CMD_SELECT && queryDesc->dest->mydest == DestSPI)
1589+
if ((res == SPI_OK_SELECT || queryDesc->parsetree->returningList) &&
1590+
queryDesc->dest->mydest == DestSPI)
15721591
{
15731592
if (_SPI_checktuples())
15741593
elog(ERROR, "consistency check on SPI tuple count failed");

src/include/executor/spi.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* spi.h
44
*
5-
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.54 2006/07/11 18:26:11 momjian Exp $
5+
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.55 2006/08/27 23:47:58 tgl Exp $
66
*
77
*-------------------------------------------------------------------------
88
*/
@@ -71,6 +71,9 @@ typedef struct
7171
#define SPI_OK_DELETE 8
7272
#define SPI_OK_UPDATE 9
7373
#define SPI_OK_CURSOR 10
74+
#define SPI_OK_INSERT_RETURNING 11
75+
#define SPI_OK_DELETE_RETURNING 12
76+
#define SPI_OK_UPDATE_RETURNING 13
7477

7578
extern DLLIMPORT uint32 SPI_processed;
7679
extern DLLIMPORT Oid SPI_lastoid;

src/pl/plperl/plperl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**********************************************************************
22
* plperl.c - perl as a procedural language for PostgreSQL
33
*
4-
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.117 2006/08/13 17:31:10 momjian Exp $
4+
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.118 2006/08/27 23:47:58 tgl Exp $
55
*
66
**********************************************************************/
77

@@ -1630,7 +1630,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
16301630
hv_store(result, "processed", strlen("processed"),
16311631
newSViv(processed), 0);
16321632

1633-
if (status == SPI_OK_SELECT)
1633+
if (status > 0 && tuptable)
16341634
{
16351635
AV *rows;
16361636
SV *row;

src/pl/plpgsql/src/pl_exec.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.176 2006/08/15 19:01:17 tgl Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.177 2006/08/27 23:47:58 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2370,23 +2370,16 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
23702370
case SPI_OK_INSERT:
23712371
case SPI_OK_UPDATE:
23722372
case SPI_OK_DELETE:
2373+
case SPI_OK_INSERT_RETURNING:
2374+
case SPI_OK_UPDATE_RETURNING:
2375+
case SPI_OK_DELETE_RETURNING:
23732376
Assert(stmt->mod_stmt);
23742377
exec_set_found(estate, (SPI_processed != 0));
23752378
break;
23762379

23772380
case SPI_OK_SELINTO:
2378-
Assert(!stmt->mod_stmt);
2379-
break;
2380-
23812381
case SPI_OK_UTILITY:
23822382
Assert(!stmt->mod_stmt);
2383-
/*
2384-
* spi.c currently does not update SPI_processed for utility
2385-
* commands. Not clear if this should be considered a bug;
2386-
* for the moment, work around it here.
2387-
*/
2388-
if (SPI_tuptable)
2389-
SPI_processed = (SPI_tuptable->alloced - SPI_tuptable->free);
23902383
break;
23912384

23922385
default:
@@ -2505,16 +2498,10 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
25052498
case SPI_OK_INSERT:
25062499
case SPI_OK_UPDATE:
25072500
case SPI_OK_DELETE:
2508-
break;
2509-
2501+
case SPI_OK_INSERT_RETURNING:
2502+
case SPI_OK_UPDATE_RETURNING:
2503+
case SPI_OK_DELETE_RETURNING:
25102504
case SPI_OK_UTILITY:
2511-
/*
2512-
* spi.c currently does not update SPI_processed for utility
2513-
* commands. Not clear if this should be considered a bug;
2514-
* for the moment, work around it here.
2515-
*/
2516-
if (SPI_tuptable)
2517-
SPI_processed = (SPI_tuptable->alloced - SPI_tuptable->free);
25182505
break;
25192506

25202507
case 0:

src/pl/plpython/plpython.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**********************************************************************
22
* plpython.c - python as a procedural language for PostgreSQL
33
*
4-
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.85 2006/08/08 19:15:09 tgl Exp $
4+
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.86 2006/08/27 23:47:58 tgl Exp $
55
*
66
*********************************************************************
77
*/
@@ -2193,24 +2193,19 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
21932193
Py_DECREF(result->status);
21942194
result->status = PyInt_FromLong(status);
21952195

2196-
if (status == SPI_OK_UTILITY)
2197-
{
2198-
Py_DECREF(result->nrows);
2199-
result->nrows = PyInt_FromLong(0);
2200-
}
2201-
else if (status != SPI_OK_SELECT)
2196+
if (status > 0 && tuptable == NULL)
22022197
{
22032198
Py_DECREF(result->nrows);
22042199
result->nrows = PyInt_FromLong(rows);
22052200
}
2206-
else
2201+
else if (status > 0 && tuptable != NULL)
22072202
{
22082203
PLyTypeInfo args;
22092204
int i;
22102205

2211-
PLy_typeinfo_init(&args);
22122206
Py_DECREF(result->nrows);
22132207
result->nrows = PyInt_FromLong(rows);
2208+
PLy_typeinfo_init(&args);
22142209

22152210
oldcontext = CurrentMemoryContext;
22162211
PG_TRY();

src/pl/tcl/pltcl.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* pltcl.c - PostgreSQL support for Tcl as
33
* procedural language (PL)
44
*
5-
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.106 2006/08/08 19:15:09 tgl Exp $
5+
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.107 2006/08/27 23:47:58 tgl Exp $
66
*
77
**********************************************************************/
88

@@ -1663,10 +1663,6 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
16631663

16641664
switch (spi_rc)
16651665
{
1666-
case SPI_OK_UTILITY:
1667-
Tcl_SetResult(interp, "0", TCL_VOLATILE);
1668-
break;
1669-
16701666
case SPI_OK_SELINTO:
16711667
case SPI_OK_INSERT:
16721668
case SPI_OK_DELETE:
@@ -1675,7 +1671,18 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
16751671
Tcl_SetResult(interp, buf, TCL_VOLATILE);
16761672
break;
16771673

1674+
case SPI_OK_UTILITY:
1675+
if (tuptable == NULL)
1676+
{
1677+
Tcl_SetResult(interp, "0", TCL_VOLATILE);
1678+
break;
1679+
}
1680+
/* FALL THRU for utility returning tuples */
1681+
16781682
case SPI_OK_SELECT:
1683+
case SPI_OK_INSERT_RETURNING:
1684+
case SPI_OK_DELETE_RETURNING:
1685+
case SPI_OK_UPDATE_RETURNING:
16791686

16801687
/*
16811688
* Process the tuples we got

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy