aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/spi.c10
-rw-r--r--src/pl/plpgsql/src/expected/plpgsql_array.out5
-rw-r--r--src/pl/plpgsql/src/pl_exec.c53
3 files changed, 51 insertions, 17 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index bf619d3a65a..a8d7fe6dabf 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1489,16 +1489,22 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
if (!SPI_is_cursor_plan(plan))
{
/* try to give a good error message */
+ const char *cmdtag;
+
if (list_length(plan->plancache_list) != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
errmsg("cannot open multi-query plan as cursor")));
plansource = (CachedPlanSource *) linitial(plan->plancache_list);
+ /* A SELECT that fails SPI_is_cursor_plan() must be SELECT INTO */
+ if (plansource->commandTag == CMDTAG_SELECT)
+ cmdtag = "SELECT INTO";
+ else
+ cmdtag = GetCommandTagName(plansource->commandTag);
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
/* translator: %s is name of a SQL command, eg INSERT */
- errmsg("cannot open %s query as cursor",
- GetCommandTagName(plansource->commandTag))));
+ errmsg("cannot open %s query as cursor", cmdtag)));
}
Assert(list_length(plan->plancache_list) == 1);
diff --git a/src/pl/plpgsql/src/expected/plpgsql_array.out b/src/pl/plpgsql/src/expected/plpgsql_array.out
index 5f28b4f685b..9e22e56f001 100644
--- a/src/pl/plpgsql/src/expected/plpgsql_array.out
+++ b/src/pl/plpgsql/src/expected/plpgsql_array.out
@@ -73,8 +73,9 @@ PL/pgSQL function inline_code_block line 2 at assignment
insert into onecol values(array[11]);
do $$ declare a int[];
begin a := f1 from onecol; raise notice 'a = %', a; end$$;
-ERROR: query "a := f1 from onecol" returned more than one row
-CONTEXT: PL/pgSQL function inline_code_block line 2 at assignment
+ERROR: query returned more than one row
+CONTEXT: query: a := f1 from onecol
+PL/pgSQL function inline_code_block line 2 at assignment
do $$ declare a int[];
begin a := f1 from onecol limit 1; raise notice 'a = %', a; end$$;
NOTICE: a = {1,2}
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 14bbe12da5b..7c5bc63778e 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3557,9 +3557,22 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
rc = SPI_execute_plan_extended(expr->plan, &options);
if (rc != SPI_OK_SELECT)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("query \"%s\" is not a SELECT", expr->query)));
+ {
+ /*
+ * SELECT INTO deserves a special error message, because "query is
+ * not a SELECT" is not very helpful in that case.
+ */
+ if (rc == SPI_OK_SELINTO)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("query is SELECT INTO, but it should be plain SELECT"),
+ errcontext("query: %s", expr->query)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("query is not a SELECT"),
+ errcontext("query: %s", expr->query)));
+ }
}
else
{
@@ -5644,7 +5657,8 @@ exec_eval_expr(PLpgSQL_execstate *estate,
if (rc != SPI_OK_SELECT)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("query \"%s\" did not return data", expr->query)));
+ errmsg("query did not return data"),
+ errcontext("query: %s", expr->query)));
/*
* Check that the expression returns exactly one column...
@@ -5652,11 +5666,11 @@ exec_eval_expr(PLpgSQL_execstate *estate,
if (estate->eval_tuptable->tupdesc->natts != 1)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg_plural("query \"%s\" returned %d column",
- "query \"%s\" returned %d columns",
+ errmsg_plural("query returned %d column",
+ "query returned %d columns",
estate->eval_tuptable->tupdesc->natts,
- expr->query,
- estate->eval_tuptable->tupdesc->natts)));
+ estate->eval_tuptable->tupdesc->natts),
+ errcontext("query: %s", expr->query)));
/*
* ... and get the column's datatype.
@@ -5680,8 +5694,8 @@ exec_eval_expr(PLpgSQL_execstate *estate,
if (estate->eval_processed != 1)
ereport(ERROR,
(errcode(ERRCODE_CARDINALITY_VIOLATION),
- errmsg("query \"%s\" returned more than one row",
- expr->query)));
+ errmsg("query returned more than one row"),
+ errcontext("query: %s", expr->query)));
/*
* Return the single result Datum.
@@ -5748,9 +5762,22 @@ exec_run_select(PLpgSQL_execstate *estate,
rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
estate->readonly_func, maxtuples);
if (rc != SPI_OK_SELECT)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("query \"%s\" is not a SELECT", expr->query)));
+ {
+ /*
+ * SELECT INTO deserves a special error message, because "query is not
+ * a SELECT" is not very helpful in that case.
+ */
+ if (rc == SPI_OK_SELINTO)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("query is SELECT INTO, but it should be plain SELECT"),
+ errcontext("query: %s", expr->query)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("query is not a SELECT"),
+ errcontext("query: %s", expr->query)));
+ }
/* Save query results for eventual cleanup */
Assert(estate->eval_tuptable == NULL);