summaryrefslogtreecommitdiff
path: root/src/backend/executor/spi.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-05-06 20:26:28 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-05-06 20:26:28 +0000
commit79913910d4b518a42c893b6dd459656798ffa591 (patch)
treef0cd5c25dff8d026b9d8d4736717a4d38c278134 /src/backend/executor/spi.c
parent299fbb4b379003557f79d2732a85ece168d04ec4 (diff)
Restructure command destination handling so that we pass around
DestReceiver pointers instead of just CommandDest values. The DestReceiver is made at the point where the destination is selected, rather than deep inside the executor. This cleans up the original kluge implementation of tstoreReceiver.c, and makes it easy to support retrieving results from utility statements inside portals. Thus, you can now do fun things like Bind and Execute a FETCH or EXPLAIN command, and it'll all work as expected (e.g., you can Describe the portal, or use Execute's count parameter to suspend the output partway through). Implementation involves stuffing the utility command's output into a Tuplestore, which would be kind of annoying for huge output sets, but should be quite acceptable for typical uses of utility commands.
Diffstat (limited to 'src/backend/executor/spi.c')
-rw-r--r--src/backend/executor/spi.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 74299ddf3ea..c3b3ec3530a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.95 2003/05/06 00:20:31 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.96 2003/05/06 20:26:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,7 +38,7 @@ static int _SPI_execute_plan(_SPI_plan *plan,
Datum *Values, const char *Nulls, int tcount);
static void _SPI_cursor_operation(Portal portal, bool forward, int count,
- CommandDest dest);
+ DestReceiver *dest);
static _SPI_plan *_SPI_copy_plan(_SPI_plan *plan, int location);
@@ -841,7 +841,8 @@ SPI_cursor_find(const char *name)
void
SPI_cursor_fetch(Portal portal, bool forward, int count)
{
- _SPI_cursor_operation(portal, forward, count, SPI);
+ _SPI_cursor_operation(portal, forward, count, CreateDestReceiver(SPI));
+ /* we know that the SPI receiver doesn't need a destroy call */
}
@@ -853,7 +854,7 @@ SPI_cursor_fetch(Portal portal, bool forward, int count)
void
SPI_cursor_move(Portal portal, bool forward, int count)
{
- _SPI_cursor_operation(portal, forward, count, None);
+ _SPI_cursor_operation(portal, forward, count, None_Receiver);
}
@@ -874,13 +875,13 @@ SPI_cursor_close(Portal portal)
/* =================== private functions =================== */
/*
- * spi_dest_setup
+ * spi_dest_startup
* Initialize to receive tuples from Executor into SPITupleTable
* of current SPI procedure
*/
void
-spi_dest_setup(DestReceiver *self, int operation,
- const char *portalName, TupleDesc typeinfo, List *targetlist)
+spi_dest_startup(DestReceiver *self, int operation,
+ const char *portalName, TupleDesc typeinfo, List *targetlist)
{
SPITupleTable *tuptable;
MemoryContext oldcxt;
@@ -891,12 +892,12 @@ spi_dest_setup(DestReceiver *self, int operation,
* _SPI_connected
*/
if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
- elog(FATAL, "SPI: improper call to spi_dest_setup");
+ elog(FATAL, "SPI: improper call to spi_dest_startup");
if (_SPI_current != &(_SPI_stack[_SPI_curid]))
- elog(FATAL, "SPI: stack corrupted in spi_dest_setup");
+ elog(FATAL, "SPI: stack corrupted in spi_dest_startup");
if (_SPI_current->tuptable != NULL)
- elog(FATAL, "SPI: improper call to spi_dest_setup");
+ elog(FATAL, "SPI: improper call to spi_dest_startup");
oldcxt = _SPI_procmem(); /* switch to procedure memory context */
@@ -1029,10 +1030,12 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
Query *queryTree = (Query *) lfirst(query_list_item);
Plan *planTree;
QueryDesc *qdesc;
+ DestReceiver *dest;
planTree = pg_plan_query(queryTree);
plan_list = lappend(plan_list, planTree);
+ dest = CreateDestReceiver(queryTree->canSetTag ? SPI : None);
if (queryTree->commandType == CMD_UTILITY)
{
if (IsA(queryTree->utilityStmt, CopyStmt))
@@ -1051,14 +1054,13 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
res = SPI_OK_UTILITY;
if (plan == NULL)
{
- ProcessUtility(queryTree->utilityStmt, None, NULL);
+ ProcessUtility(queryTree->utilityStmt, dest, NULL);
CommandCounterIncrement();
}
}
else if (plan == NULL)
{
- qdesc = CreateQueryDesc(queryTree, planTree,
- queryTree->canSetTag ? SPI : None,
+ qdesc = CreateQueryDesc(queryTree, planTree, dest,
NULL, NULL, false);
res = _SPI_pquery(qdesc, true,
queryTree->canSetTag ? tcount : 0);
@@ -1068,8 +1070,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
}
else
{
- qdesc = CreateQueryDesc(queryTree, planTree,
- queryTree->canSetTag ? SPI : None,
+ qdesc = CreateQueryDesc(queryTree, planTree, dest,
NULL, NULL, false);
res = _SPI_pquery(qdesc, false, 0);
if (res < 0)
@@ -1144,20 +1145,21 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
Query *queryTree = (Query *) lfirst(query_list_item);
Plan *planTree;
QueryDesc *qdesc;
+ DestReceiver *dest;
planTree = lfirst(plan_list);
plan_list = lnext(plan_list);
+ dest = CreateDestReceiver(queryTree->canSetTag ? SPI : None);
if (queryTree->commandType == CMD_UTILITY)
{
- ProcessUtility(queryTree->utilityStmt, None, NULL);
+ ProcessUtility(queryTree->utilityStmt, dest, NULL);
res = SPI_OK_UTILITY;
CommandCounterIncrement();
}
else
{
- qdesc = CreateQueryDesc(queryTree, planTree,
- queryTree->canSetTag ? SPI : None,
+ qdesc = CreateQueryDesc(queryTree, planTree, dest,
NULL, paramLI, false);
res = _SPI_pquery(qdesc, true,
queryTree->canSetTag ? tcount : 0);
@@ -1185,7 +1187,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
if (queryDesc->parsetree->into != NULL) /* select into table */
{
res = SPI_OK_SELINTO;
- queryDesc->dest = None; /* don't output results anywhere */
+ queryDesc->dest = None_Receiver; /* don't output results */
}
break;
case CMD_INSERT:
@@ -1216,13 +1218,13 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
_SPI_current->processed = queryDesc->estate->es_processed;
save_lastoid = queryDesc->estate->es_lastoid;
- if (operation == CMD_SELECT && queryDesc->dest == SPI)
+ if (operation == CMD_SELECT && queryDesc->dest->mydest == SPI)
{
if (_SPI_checktuples())
elog(FATAL, "SPI_select: # of processed tuples check failed");
}
- if (queryDesc->dest == SPI)
+ if (queryDesc->dest->mydest == SPI)
{
SPI_processed = _SPI_current->processed;
SPI_lastoid = save_lastoid;
@@ -1253,7 +1255,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
*/
static void
_SPI_cursor_operation(Portal portal, bool forward, int count,
- CommandDest dest)
+ DestReceiver *dest)
{
/* Check that the portal is valid */
if (!PortalIsValid(portal))
@@ -1275,7 +1277,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
(long) count,
dest);
- if (dest == SPI && _SPI_checktuples())
+ if (dest->mydest == SPI && _SPI_checktuples())
elog(FATAL, "SPI_fetch: # of processed tuples check failed");
/* Put the result into place for access by caller */
@@ -1343,7 +1345,7 @@ _SPI_checktuples(void)
SPITupleTable *tuptable = _SPI_current->tuptable;
bool failed = false;
- if (tuptable == NULL) /* spi_dest_setup was not called */
+ if (tuptable == NULL) /* spi_dest_startup was not called */
failed = true;
else if (processed != (tuptable->alloced - tuptable->free))
failed = true;