Commit cfd27281 authored by Bruce Momjian's avatar Bruce Momjian

This patch makes a minor cleanup to the implementation of PERFORM in

PL/PgSQL. Previously, it had been bundled together with the assign
statement implementation, for some reason that wasn't clear to me
(they certainly don't share any code with one another). So I separated
them and made PERFORM a statement like any other. No changes in
functionality.

Along the way, I added some regression tests for PERFORM, added a
bunch more SGML tags to the PL/PgSQL docs, and removed an obsolete
comment relating to the implementation of RETURN NEXT.

Neil Conway
parent ceb4f5ea
This diff is collapsed.
......@@ -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;
......
......@@ -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,27 +979,28 @@ 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.
exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
return PLPGSQL_RC_OK;
}
/* ----------
* 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;
/*
......@@ -1009,7 +1016,6 @@ exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt)
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()
......
......@@ -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 */
......
......@@ -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;
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment