aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpgsql/src/gram.y11
-rw-r--r--src/pl/plpgsql/src/pl_exec.c74
-rw-r--r--src/pl/plpgsql/src/plpgsql.h11
-rw-r--r--src/test/regress/expected/plpgsql.out51
-rw-r--r--src/test/regress/sql/plpgsql.sql45
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