1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

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
This commit is contained in:
Bruce Momjian
2002-11-10 00:35:58 +00:00
parent ceb4f5ea9c
commit cfd2728100
6 changed files with 259 additions and 145 deletions

View File

@@ -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;

View File

@@ -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)
{
Assert(stmt->varno >= 0);
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;
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;
/*
* 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);
/*
* If not already done create a plan for this expression
*/
if (expr->plan == NULL)
exec_prepare_plan(estate, expr);
exec_set_found(estate, (estate->eval_processed != 0));
rc = exec_run_select(estate, expr, 0, NULL);
if (rc != SPI_OK_SELECT)
elog(ERROR, "query \"%s\" didn't return data", expr->query);
exec_set_found(estate, (estate->eval_processed != 0));
exec_eval_cleanup(estate);
}
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()

View File

@@ -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 */