diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pl/plpgsql/src/gram.y | 11 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 74 | ||||
-rw-r--r-- | src/pl/plpgsql/src/plpgsql.h | 11 | ||||
-rw-r--r-- | src/test/regress/expected/plpgsql.out | 51 | ||||
-rw-r--r-- | src/test/regress/sql/plpgsql.sql | 45 |
5 files changed, 149 insertions, 43 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index d22e4aa0e44..f8adc55dcee 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -4,7 +4,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.39 2002/11/01 22:52:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.40 2002/11/10 00:35:58 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -728,14 +728,13 @@ proc_stmt : pl_block ';' stmt_perform : K_PERFORM lno expr_until_semi { - PLpgSQL_stmt_assign *new; + PLpgSQL_stmt_perform *new; - new = malloc(sizeof(PLpgSQL_stmt_assign)); - memset(new, 0, sizeof(PLpgSQL_stmt_assign)); + new = malloc(sizeof(PLpgSQL_stmt_perform)); + memset(new, 0, sizeof(PLpgSQL_stmt_perform)); - new->cmd_type = PLPGSQL_STMT_ASSIGN; + new->cmd_type = PLPGSQL_STMT_PERFORM; new->lineno = $2; - new->varno = -1; new->expr = $3; $$ = (PLpgSQL_stmt *)new; diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 9adf2d7a2e9..bbf59f2ae8d 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.65 2002/10/19 22:10:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.66 2002/11/10 00:35:58 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -73,6 +73,8 @@ static int exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt); static int exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt); +static int exec_stmt_perform(PLpgSQL_execstate * estate, + PLpgSQL_stmt_perform * stmt); static int exec_stmt_getdiag(PLpgSQL_execstate * estate, PLpgSQL_stmt_getdiag * stmt); static int exec_stmt_if(PLpgSQL_execstate * estate, @@ -890,6 +892,10 @@ exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt) rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt); break; + case PLPGSQL_STMT_PERFORM: + rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt); + break; + case PLPGSQL_STMT_GETDIAG: rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt); break; @@ -973,43 +979,43 @@ exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt) /* ---------- * exec_stmt_assign Evaluate an expression and * put the result into a variable. - * - * For no very good reason, this is also used for PERFORM statements. * ---------- */ static int exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt) { - PLpgSQL_expr *expr = stmt->expr; + Assert(stmt->varno >= 0); - if (stmt->varno >= 0) - exec_assign_expr(estate, estate->datums[stmt->varno], expr); - else - { - /* - * PERFORM: evaluate query and discard result (but set FOUND - * depending on whether at least one row was returned). - * - * This cannot share code with the assignment case since we do not - * wish to constrain the discarded result to be only one - * row/column. - */ - int rc; + exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr); - /* - * If not already done create a plan for this expression - */ - if (expr->plan == NULL) - exec_prepare_plan(estate, expr); + return PLPGSQL_RC_OK; +} - rc = exec_run_select(estate, expr, 0, NULL); - if (rc != SPI_OK_SELECT) - elog(ERROR, "query \"%s\" didn't return data", expr->query); +/* ---------- + * exec_stmt_perform Evaluate query and discard result (but set + * FOUND depending on whether at least one row + * was returned). + * ---------- + */ +static int +exec_stmt_perform(PLpgSQL_execstate * estate, PLpgSQL_stmt_perform * stmt) +{ + PLpgSQL_expr *expr = stmt->expr; + int rc; - exec_set_found(estate, (estate->eval_processed != 0)); + /* + * If not already done create a plan for this expression + */ + if (expr->plan == NULL) + exec_prepare_plan(estate, expr); + + rc = exec_run_select(estate, expr, 0, NULL); + if (rc != SPI_OK_SELECT) + elog(ERROR, "query \"%s\" didn't return data", expr->query); - exec_eval_cleanup(estate); - } + exec_set_found(estate, (estate->eval_processed != 0)); + + exec_eval_cleanup(estate); return PLPGSQL_RC_OK; } @@ -1579,12 +1585,11 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt) return PLPGSQL_RC_RETURN; } -/* - * Notes: - * - the tuple store must be created in a sufficiently long-lived - * memory context, as the same store must be used within the executor - * after the PL/PgSQL call returns. At present, the code uses - * TopTransactionContext. +/* ---------- + * exec_stmt_return_next Evaluate an expression and add it to the + * list of tuples returned by the current + * SRF. + * ---------- */ static int exec_stmt_return_next(PLpgSQL_execstate * estate, @@ -1732,7 +1737,6 @@ exec_init_tuple_store(PLpgSQL_execstate * estate) estate->rettupdesc = rsi->expectedDesc; } - /* ---------- * exec_stmt_raise Build a message and throw it with * elog() diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index cf3e1942d8a..2f4c10e0356 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.28 2002/09/12 00:24:09 momjian Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.29 2002/11/10 00:35:58 momjian Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -100,7 +100,8 @@ enum PLPGSQL_STMT_GETDIAG, PLPGSQL_STMT_OPEN, PLPGSQL_STMT_FETCH, - PLPGSQL_STMT_CLOSE + PLPGSQL_STMT_CLOSE, + PLPGSQL_STMT_PERFORM }; @@ -288,6 +289,12 @@ typedef struct PLpgSQL_expr *expr; } PLpgSQL_stmt_assign; +typedef struct +{ /* PERFORM statement */ + int cmd_type; + int lineno; + PLpgSQL_expr *expr; +} PLpgSQL_stmt_perform; typedef struct { /* Get Diagnostics item */ diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index e18a1d556a6..b300b695d91 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -1733,3 +1733,54 @@ SELECT * FROM test_ret_rec_dyn(5) AS (a int, b numeric, c text); 50 | 5 | xxx (1 row) +-- +-- test PERFORM +-- +create table perform_test ( + a INT, + b INT +); +create function simple_func(int) returns boolean as ' +BEGIN + IF $1 < 20 THEN + INSERT INTO perform_test VALUES ($1, $1 + 10); + RETURN TRUE; + ELSE + RETURN FALSE; + END IF; +END;' language 'plpgsql'; +create function perform_test_func() returns void as ' +BEGIN + IF FOUND then + INSERT INTO perform_test VALUES (100, 100); + END IF; + + PERFORM simple_func(5); + + IF FOUND then + INSERT INTO perform_test VALUES (100, 100); + END IF; + + PERFORM simple_func(50); + + IF FOUND then + INSERT INTO perform_test VALUES (100, 100); + END IF; + + RETURN; +END;' language 'plpgsql'; +SELECT perform_test_func(); + perform_test_func +------------------- + +(1 row) + +SELECT * FROM perform_test; + a | b +-----+----- + 5 | 15 + 100 | 100 + 100 | 100 +(3 rows) + +drop table perform_test; diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index b6607442d72..b4d0186458d 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -1559,3 +1559,48 @@ END;' language 'plpgsql'; SELECT * FROM test_ret_rec_dyn(1500) AS (a int, b int, c int); SELECT * FROM test_ret_rec_dyn(5) AS (a int, b numeric, c text); + +-- +-- test PERFORM +-- + +create table perform_test ( + a INT, + b INT +); + +create function simple_func(int) returns boolean as ' +BEGIN + IF $1 < 20 THEN + INSERT INTO perform_test VALUES ($1, $1 + 10); + RETURN TRUE; + ELSE + RETURN FALSE; + END IF; +END;' language 'plpgsql'; + +create function perform_test_func() returns void as ' +BEGIN + IF FOUND then + INSERT INTO perform_test VALUES (100, 100); + END IF; + + PERFORM simple_func(5); + + IF FOUND then + INSERT INTO perform_test VALUES (100, 100); + END IF; + + PERFORM simple_func(50); + + IF FOUND then + INSERT INTO perform_test VALUES (100, 100); + END IF; + + RETURN; +END;' language 'plpgsql'; + +SELECT perform_test_func(); +SELECT * FROM perform_test; + +drop table perform_test;
\ No newline at end of file |