summaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
authorNeil Conway2005-06-07 02:47:23 +0000
committerNeil Conway2005-06-07 02:47:23 +0000
commitc59887f91618b95f42a33d4c62dac35165a7910a (patch)
treec61d207d0329b53331d720651bd7a3728e3d3ccc /src/pl
parent0f011f6daae65963cc29a1208bf662a7c13056c3 (diff)
Add support for an optional INTO clause to PL/PgSQL's EXECUTE command.
This allows the result of executing a SELECT to be assigned to a row variable, record variable, or list of scalars. Docs and regression tests updated. Per Pavel Stehule, improvements and cleanup by Neil Conway.
Diffstat (limited to 'src/pl')
-rw-r--r--src/pl/plpgsql/src/gram.y49
-rw-r--r--src/pl/plpgsql/src/pl_exec.c29
-rw-r--r--src/pl/plpgsql/src/plpgsql.h4
3 files changed, 76 insertions, 6 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 028323192fa..d1823d7a091 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -4,7 +4,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.72 2005/05/26 04:08:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.73 2005/06/07 02:47:16 neilc Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -1250,19 +1250,62 @@ stmt_execsql : execsql_start lno
}
;
-stmt_dynexecute : K_EXECUTE lno expr_until_semi
+stmt_dynexecute : K_EXECUTE lno
{
PLpgSQL_stmt_dynexecute *new;
+ PLpgSQL_expr *expr;
+ int endtoken;
+
+ expr = read_sql_construct(K_INTO, ';', "INTO|;", "SELECT ",
+ true, true, &endtoken);
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
new->lineno = $2;
- new->query = $3;
+ new->query = expr;
+
+ new->rec = NULL;
+ new->row = NULL;
+
+ /*
+ * If we saw "INTO", look for an additional
+ * row or record var.
+ */
+ if (endtoken == K_INTO)
+ {
+ switch (yylex())
+ {
+ case T_ROW:
+ check_assignable((PLpgSQL_datum *) yylval.row);
+ new->row = yylval.row;
+ break;
+
+ case T_RECORD:
+ check_assignable((PLpgSQL_datum *) yylval.row);
+ new->rec = yylval.rec;
+ break;
+
+ case T_SCALAR:
+ new->row = read_into_scalar_list(yytext, yylval.scalar);
+ break;
+
+ default:
+ plpgsql_error_lineno = $2;
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("syntax error at \"%s\"",
+ yytext),
+ errdetail("Expected record or row variable.")));
+ }
+ if (yylex() != ';')
+ yyerror("syntax error");
+ }
$$ = (PLpgSQL_stmt *)new;
}
;
+
stmt_open : K_OPEN lno cursor_varptr
{
PLpgSQL_stmt_open *new;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 3c6216a3e56..1fe1ed4cbed 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.141 2005/05/26 04:08:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.142 2005/06/07 02:47:17 neilc Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -2202,6 +2202,13 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
Oid restype;
char *querystr;
int exec_res;
+ PLpgSQL_rec *rec = NULL;
+ PLpgSQL_row *row = NULL;
+
+ if (stmt->rec != NULL)
+ rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);
+ else if (stmt->row != NULL)
+ row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);
/*
* First we evaluate the string expression after the EXECUTE keyword.
@@ -2221,9 +2228,27 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
/*
* Call SPI_execute() without preparing a saved plan. The returncode can
* be any standard OK. Note that while a SELECT is allowed, its
- * results will be discarded.
+ * results will be discarded unless an INTO clause is specified.
*/
exec_res = SPI_execute(querystr, estate->readonly_func, 0);
+
+ /* Assign to INTO variable */
+ if (rec || row)
+ {
+ if (exec_res != SPI_OK_SELECT)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("EXECUTE ... INTO is only for SELECT")));
+ else
+ {
+ if (SPI_processed == 0)
+ exec_move_row(estate, rec, row, NULL, SPI_tuptable->tupdesc);
+ else
+ exec_move_row(estate, rec, row,
+ SPI_tuptable->vals[0], SPI_tuptable->tupdesc);
+ }
+ }
+
switch (exec_res)
{
case SPI_OK_SELECT:
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 17a466e01e8..a70553ac2c8 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.60 2005/05/26 04:08:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.61 2005/06/07 02:47:18 neilc Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -524,6 +524,8 @@ typedef struct
{ /* Dynamic SQL string to execute */
int cmd_type;
int lineno;
+ PLpgSQL_rec *rec; /* INTO record or row variable */
+ PLpgSQL_row *row;
PLpgSQL_expr *query;
} PLpgSQL_stmt_dynexecute;