diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 4 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 20 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 57 |
3 files changed, 40 insertions, 41 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 05c4a542b84..4b8a166ffae 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.278 2006/08/12 02:52:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.279 2006/08/12 20:05:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -497,7 +497,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) /* * if there is a result relation, initialize result relation stuff */ - if (parseTree->resultRelation != 0 && operation != CMD_SELECT) + if (parseTree->resultRelation) { List *resultRelations = parseTree->resultRelations; int numResultRelations; diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 0da2abba77c..28462ba8b8b 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.104 2006/07/14 14:52:19 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.105 2006/08/12 20:05:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -361,7 +361,9 @@ postquel_getnext(execution_state *es) * run it to completion. (If we run to completion then * ExecutorRun is guaranteed to return NULL.) */ - if (LAST_POSTQUEL_COMMAND(es) && es->qd->operation == CMD_SELECT) + if (LAST_POSTQUEL_COMMAND(es) && + es->qd->operation == CMD_SELECT && + es->qd->parsetree->into == NULL) count = 1L; else count = 0L; @@ -868,7 +870,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, JunkFilter **junkFilter) { Query *parse; - int cmd; + bool isSelect; List *tlist; ListCell *tlistitem; int tlistlen; @@ -893,15 +895,18 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, /* find the final query */ parse = (Query *) lfirst(list_tail(queryTreeList)); - cmd = parse->commandType; - tlist = parse->targetList; + /* + * Note: eventually replace this with QueryReturnsTuples? We'd need + * a more general method of determining the output type, though. + */ + isSelect = (parse->commandType == CMD_SELECT && parse->into == NULL); /* * The last query must be a SELECT if and only if return type isn't VOID. */ if (rettype == VOIDOID) { - if (cmd == CMD_SELECT) + if (isSelect) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("return type mismatch in function declared to return %s", @@ -911,7 +916,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, } /* by here, the function is declared to return some type */ - if (cmd != CMD_SELECT) + if (!isSelect) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("return type mismatch in function declared to return %s", @@ -921,6 +926,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, /* * Count the non-junk entries in the result targetlist. */ + tlist = parse->targetList; tlistlen = ExecCleanTargetListLength(tlist); fn_typtype = get_typtype(rettype); 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; |