diff options
Diffstat (limited to 'src/backend/executor/spi.c')
-rw-r--r-- | src/backend/executor/spi.c | 57 |
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; |