summaryrefslogtreecommitdiff
path: root/src/backend/executor/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/spi.c')
-rw-r--r--src/backend/executor/spi.c57
1 files changed, 25 insertions, 32 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index c1f39f7c4f7..6c4cc585460 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.154 2006/08/12 02:52:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.155 2006/08/12 20:05:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -837,26 +837,12 @@ SPI_cursor_open(const char *name, void *plan,
planTree = (Plan *) linitial(ptlist);
/* Must be a query that returns tuples */
- switch (queryTree->commandType)
- {
- case CMD_SELECT:
- if (queryTree->into != NULL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
- errmsg("cannot open SELECT INTO query as cursor")));
- break;
- case CMD_UTILITY:
- if (!UtilityReturnsTuples(queryTree->utilityStmt))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
- errmsg("cannot open non-SELECT query as cursor")));
- break;
- default:
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
- errmsg("cannot open non-SELECT query as cursor")));
- break;
- }
+ if (!QueryReturnsTuples(queryTree))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
+ /* translator: %s is name of a SQL command, eg INSERT */
+ errmsg("cannot open %s query as cursor",
+ CreateQueryTag(queryTree))));
/* Reset SPI result (note we deliberately don't touch lastoid) */
SPI_processed = 0;
@@ -876,7 +862,7 @@ SPI_cursor_open(const char *name, void *plan,
portal = CreatePortal(name, false, false);
}
- /* Switch to portals memory and copy the parsetree and plan to there */
+ /* Switch to portal's memory and copy the parsetree and plan to there */
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
queryTree = copyObject(queryTree);
planTree = copyObject(planTree);
@@ -919,9 +905,9 @@ SPI_cursor_open(const char *name, void *plan,
* Set up the portal.
*/
PortalDefineQuery(portal,
- NULL,
+ NULL, /* no statement name */
spiplan->query,
- "SELECT", /* don't have the raw parse tree... */
+ CreateQueryTag(queryTree),
list_make1(queryTree),
list_make1(planTree),
PortalGetHeapMemory(portal));
@@ -954,9 +940,16 @@ SPI_cursor_open(const char *name, void *plan,
*/
PortalStart(portal, paramLI, snapshot);
- Assert(portal->strategy == PORTAL_ONE_SELECT ||
- portal->strategy == PORTAL_ONE_RETURNING ||
- portal->strategy == PORTAL_UTIL_SELECT);
+ /*
+ * If this test fails then we're out of sync with pquery.c about
+ * which queries can return tuples...
+ */
+ if (portal->strategy == PORTAL_MULTI_QUERY)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
+ /* translator: %s is name of a SQL command, eg INSERT */
+ errmsg("cannot open %s query as cursor",
+ CreateQueryTag(queryTree))));
/* Return the created portal */
return portal;
@@ -1046,12 +1039,12 @@ SPI_getargcount(void *plan)
/*
* Returns true if the plan contains exactly one command
- * and that command originates from normal SELECT (i.e.
- * *not* a SELECT ... INTO). In essence, the result indicates
- * if the command can be used with SPI_cursor_open
+ * and that command returns tuples to the caller (eg, SELECT or
+ * INSERT ... RETURNING, but not SELECT ... INTO). In essence,
+ * the result indicates if the command can be used with SPI_cursor_open
*
* Parameters
- * plan A plan previously prepared using SPI_prepare
+ * plan: A plan previously prepared using SPI_prepare
*/
bool
SPI_is_cursor_plan(void *plan)
@@ -1070,7 +1063,7 @@ SPI_is_cursor_plan(void *plan)
{
Query *queryTree = (Query *) linitial((List *) linitial(qtlist));
- if (queryTree->commandType == CMD_SELECT && queryTree->into == NULL)
+ if (QueryReturnsTuples(queryTree))
return true;
}
return false;