static void push_stmt_mcontext(PLpgSQL_execstate *estate);
static void pop_stmt_mcontext(PLpgSQL_execstate *estate);
+static int exec_toplevel_block(PLpgSQL_execstate *estate,
+ PLpgSQL_stmt_block *block);
static int exec_stmt_block(PLpgSQL_execstate *estate,
PLpgSQL_stmt_block *block);
static int exec_stmts(PLpgSQL_execstate *estate,
List *stmts);
-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,
* Now call the toplevel block of statements
*/
estate.err_text = NULL;
- estate.err_stmt = (PLpgSQL_stmt *) (func->action);
- rc = exec_stmt(&estate, (PLpgSQL_stmt *) func->action);
+ rc = exec_toplevel_block(&estate, func->action);
if (rc != PLPGSQL_RC_RETURN)
{
- estate.err_stmt = NULL;
estate.err_text = NULL;
ereport(ERROR,
(errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
/*
* We got a return value - process it
*/
- estate.err_stmt = NULL;
estate.err_text = gettext_noop("while casting return value to function's return type");
fcinfo->isnull = estate.retisnull;
* Now call the toplevel block of statements
*/
estate.err_text = NULL;
- estate.err_stmt = (PLpgSQL_stmt *) (func->action);
- rc = exec_stmt(&estate, (PLpgSQL_stmt *) func->action);
+ rc = exec_toplevel_block(&estate, func->action);
if (rc != PLPGSQL_RC_RETURN)
{
- estate.err_stmt = NULL;
estate.err_text = NULL;
ereport(ERROR,
(errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
errmsg("control reached end of trigger procedure without RETURN")));
}
- estate.err_stmt = NULL;
estate.err_text = gettext_noop("during function exit");
if (estate.retisset)
* Now call the toplevel block of statements
*/
estate.err_text = NULL;
- estate.err_stmt = (PLpgSQL_stmt *) (func->action);
- rc = exec_stmt(&estate, (PLpgSQL_stmt *) func->action);
+ rc = exec_toplevel_block(&estate, func->action);
if (rc != PLPGSQL_RC_RETURN)
{
- estate.err_stmt = NULL;
estate.err_text = NULL;
ereport(ERROR,
(errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
errmsg("control reached end of trigger procedure without RETURN")));
}
- estate.err_stmt = NULL;
estate.err_text = gettext_noop("during function exit");
/*
}
+/* ----------
+ * exec_toplevel_block Execute the toplevel block
+ *
+ * This is intentionally equivalent to executing exec_stmts() with a
+ * list consisting of the one statement. One tiny difference is that
+ * we do not bother to save the entry value of estate->err_stmt;
+ * that's assumed to be NULL.
+ * ----------
+ */
+static int
+exec_toplevel_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
+{
+ int rc;
+
+ estate->err_stmt = (PLpgSQL_stmt *) block;
+
+ /* Let the plugin know that we are about to execute this statement */
+ if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
+ ((*plpgsql_plugin_ptr)->stmt_beg) (estate, (PLpgSQL_stmt *) block);
+
+ CHECK_FOR_INTERRUPTS();
+
+ rc = exec_stmt_block(estate, block);
+
+ /* Let the plugin know that we have finished executing this statement */
+ if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
+ ((*plpgsql_plugin_ptr)->stmt_end) (estate, (PLpgSQL_stmt *) block);
+
+ estate->err_stmt = NULL;
+
+ return rc;
+}
+
+
/* ----------
* exec_stmt_block Execute a block of statements
* ----------
static int
exec_stmts(PLpgSQL_execstate *estate, List *stmts)
{
+ PLpgSQL_stmt *save_estmt = estate->err_stmt;
ListCell *s;
if (stmts == NIL)
foreach(s, stmts)
{
PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s);
- int rc = exec_stmt(estate, stmt);
-
- if (rc != PLPGSQL_RC_OK)
- return rc;
- }
+ int rc;
- return PLPGSQL_RC_OK;
-}
+ estate->err_stmt = stmt;
+ /* Let the plugin know that we are about to execute this statement */
+ if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
+ ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
-/* ----------
- * exec_stmt Distribute one statement to the statements
- * type specific execution function.
- * ----------
- */
-static int
-exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
-{
- PLpgSQL_stmt *save_estmt;
- int rc = -1;
-
- save_estmt = estate->err_stmt;
- estate->err_stmt = stmt;
+ CHECK_FOR_INTERRUPTS();
- /* Let the plugin know that we are about to execute this statement */
- if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_beg)
- ((*plpgsql_plugin_ptr)->stmt_beg) (estate, stmt);
+ switch (stmt->cmd_type)
+ {
+ case PLPGSQL_STMT_BLOCK:
+ rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
+ break;
- CHECK_FOR_INTERRUPTS();
+ case PLPGSQL_STMT_ASSIGN:
+ rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
+ break;
- switch (stmt->cmd_type)
- {
- case PLPGSQL_STMT_BLOCK:
- rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
- break;
+ case PLPGSQL_STMT_PERFORM:
+ rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);
+ break;
- case PLPGSQL_STMT_ASSIGN:
- rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
- break;
+ case PLPGSQL_STMT_CALL:
+ rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) 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;
- case PLPGSQL_STMT_CALL:
- rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) stmt);
- break;
+ case PLPGSQL_STMT_IF:
+ rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
+ break;
- case PLPGSQL_STMT_GETDIAG:
- rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
- break;
+ case PLPGSQL_STMT_CASE:
+ rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
+ break;
- case PLPGSQL_STMT_IF:
- rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
- break;
+ case PLPGSQL_STMT_LOOP:
+ rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
+ break;
- case PLPGSQL_STMT_CASE:
- rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt);
- break;
+ case PLPGSQL_STMT_WHILE:
+ rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
+ break;
- case PLPGSQL_STMT_LOOP:
- rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
- break;
+ case PLPGSQL_STMT_FORI:
+ rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
+ break;
- case PLPGSQL_STMT_WHILE:
- rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
- break;
+ case PLPGSQL_STMT_FORS:
+ rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
+ break;
- case PLPGSQL_STMT_FORI:
- rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
- break;
+ case PLPGSQL_STMT_FORC:
+ rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
+ break;
- case PLPGSQL_STMT_FORS:
- rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
- break;
+ case PLPGSQL_STMT_FOREACH_A:
+ rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
+ break;
- case PLPGSQL_STMT_FORC:
- rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt);
- break;
+ case PLPGSQL_STMT_EXIT:
+ rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
+ break;
- case PLPGSQL_STMT_FOREACH_A:
- rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt);
- break;
+ case PLPGSQL_STMT_RETURN:
+ rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
+ break;
- case PLPGSQL_STMT_EXIT:
- rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
- break;
+ case PLPGSQL_STMT_RETURN_NEXT:
+ rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
+ break;
- case PLPGSQL_STMT_RETURN:
- rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
- break;
+ case PLPGSQL_STMT_RETURN_QUERY:
+ rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
+ break;
- case PLPGSQL_STMT_RETURN_NEXT:
- rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);
- break;
+ case PLPGSQL_STMT_RAISE:
+ rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
+ break;
- case PLPGSQL_STMT_RETURN_QUERY:
- rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt);
- break;
+ case PLPGSQL_STMT_ASSERT:
+ rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
+ break;
- case PLPGSQL_STMT_RAISE:
- rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
- break;
+ case PLPGSQL_STMT_EXECSQL:
+ rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
+ break;
- case PLPGSQL_STMT_ASSERT:
- rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
- break;
+ case PLPGSQL_STMT_DYNEXECUTE:
+ rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
+ break;
- case PLPGSQL_STMT_EXECSQL:
- rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
- break;
+ case PLPGSQL_STMT_DYNFORS:
+ rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
+ break;
- case PLPGSQL_STMT_DYNEXECUTE:
- rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);
- break;
+ case PLPGSQL_STMT_OPEN:
+ rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
+ break;
- case PLPGSQL_STMT_DYNFORS:
- rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);
- break;
+ case PLPGSQL_STMT_FETCH:
+ rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
+ break;
- case PLPGSQL_STMT_OPEN:
- rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);
- break;
+ case PLPGSQL_STMT_CLOSE:
+ rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
+ break;
- case PLPGSQL_STMT_FETCH:
- rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);
- break;
+ case PLPGSQL_STMT_COMMIT:
+ rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt);
+ break;
- case PLPGSQL_STMT_CLOSE:
- rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);
- break;
+ case PLPGSQL_STMT_ROLLBACK:
+ rc = exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback *) stmt);
+ break;
- case PLPGSQL_STMT_COMMIT:
- rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt);
- break;
+ case PLPGSQL_STMT_SET:
+ rc = exec_stmt_set(estate, (PLpgSQL_stmt_set *) stmt);
+ break;
- case PLPGSQL_STMT_ROLLBACK:
- rc = exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback *) stmt);
- break;
+ default:
+ /* point err_stmt to parent, since this one seems corrupt */
+ estate->err_stmt = save_estmt;
+ elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
+ rc = -1; /* keep compiler quiet */
+ }
- case PLPGSQL_STMT_SET:
- rc = exec_stmt_set(estate, (PLpgSQL_stmt_set *) stmt);
- break;
+ /* Let the plugin know that we have finished executing this statement */
+ if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
+ ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
- default:
+ if (rc != PLPGSQL_RC_OK)
+ {
estate->err_stmt = save_estmt;
- elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
- }
-
- /* Let the plugin know that we have finished executing this statement */
- if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->stmt_end)
- ((*plpgsql_plugin_ptr)->stmt_end) (estate, stmt);
+ return rc;
+ }
+ } /* end of loop over statements */
estate->err_stmt = save_estmt;
-
- return rc;
+ return PLPGSQL_RC_OK;
}