diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index e39f99fbb32..9e37fc3a14e 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -323,19 +323,23 @@ typedef struct SPITupleTable
/* Public members */
TupleDesc tupdesc; /* tuple descriptor */
HeapTuple *vals; /* array of tuples */
+ uint64 numvals; /* number of valid tuples */
/* Private members, not intended for external callers */
+ uint64 alloced; /* allocated length of vals array */
MemoryContext tuptabcxt; /* memory context of result table */
- uint64 alloced; /* # of alloced vals */
- uint64 free; /* # of free vals */
slist_node next; /* link for internal bookkeeping */
SubTransactionId subid; /* subxact in which tuptable was created */
} SPITupleTable;
- vals and tupdesc can
- be used by SPI callers, the remaining fields are internal.
- vals is an array of pointers to rows. (The number
- of valid entries is given by SPI_processed.)
+ tupdesc,
+ vals, and
+ numvals
+ can be used by SPI callers; the remaining fields are internal.
+ vals is an array of pointers to rows.
+ The number of rows is given by numvals
+ (for somewhat historical reasons, this count is also returned
+ in SPI_processed).
tupdesc is a row descriptor which you can pass to
SPI functions dealing with rows.
@@ -4631,12 +4635,12 @@ execq(PG_FUNCTION_ARGS)
*/
if (ret > 0 && SPI_tuptable != NULL)
{
- TupleDesc tupdesc = SPI_tuptable->tupdesc;
SPITupleTable *tuptable = SPI_tuptable;
+ TupleDesc tupdesc = tuptable->tupdesc;
char buf[8192];
uint64 j;
- for (j = 0; j < proc; j++)
+ for (j = 0; j < tuptable->numvals; j++)
{
HeapTuple tuple = tuptable->vals[j];
int i;
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 8eedb613a18..74f8d89bcb1 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1872,8 +1872,9 @@ spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
slist_push_head(&_SPI_current->tuptables, &tuptable->next);
/* set up initial allocations */
- tuptable->alloced = tuptable->free = 128;
+ tuptable->alloced = 128;
tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
+ tuptable->numvals = 0;
tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
MemoryContextSwitchTo(oldcxt);
@@ -1899,18 +1900,18 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self)
oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
- if (tuptable->free == 0)
+ if (tuptable->numvals >= tuptable->alloced)
{
/* Double the size of the pointer array */
- tuptable->free = tuptable->alloced;
- tuptable->alloced += tuptable->free;
+ uint64 newalloced = tuptable->alloced * 2;
+
tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals,
- tuptable->alloced * sizeof(HeapTuple));
+ newalloced * sizeof(HeapTuple));
+ tuptable->alloced = newalloced;
}
- tuptable->vals[tuptable->alloced - tuptable->free] =
- ExecCopySlotHeapTuple(slot);
- (tuptable->free)--;
+ tuptable->vals[tuptable->numvals] = ExecCopySlotHeapTuple(slot);
+ (tuptable->numvals)++;
MemoryContextSwitchTo(oldcxt);
@@ -2324,8 +2325,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
/* Update "processed" if stmt returned tuples */
if (_SPI_current->tuptable)
- _SPI_current->processed = _SPI_current->tuptable->alloced -
- _SPI_current->tuptable->free;
+ _SPI_current->processed = _SPI_current->tuptable->numvals;
res = SPI_OK_UTILITY;
@@ -2694,7 +2694,7 @@ _SPI_checktuples(void)
if (tuptable == NULL) /* spi_dest_startup was not called */
failed = true;
- else if (processed != (tuptable->alloced - tuptable->free))
+ else if (processed != tuptable->numvals)
failed = true;
return failed;
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index af4f8c875c7..ad69a5ce433 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -24,11 +24,11 @@ typedef struct SPITupleTable
/* Public members */
TupleDesc tupdesc; /* tuple descriptor */
HeapTuple *vals; /* array of tuples */
+ uint64 numvals; /* number of valid tuples */
/* Private members, not intended for external callers */
+ uint64 alloced; /* allocated length of vals array */
MemoryContext tuptabcxt; /* memory context of result table */
- uint64 alloced; /* # of alloced vals */
- uint64 free; /* # of free vals */
slist_node next; /* link for internal bookkeeping */
SubTransactionId subid; /* subxact in which tuptable was created */
} SPITupleTable;