From ff9906d78c5c59c296b7a9ecfefd8715f29a0fe0 Mon Sep 17 00:00:00 2001 From: Amit Khandekar Date: Sat, 23 May 2020 21:44:28 +0800 Subject: [PATCH 2/3] Get rid of exec_stmt() function call Reduce exec_stmt() callers and move its code into exec_stmts(). All other callers of exec_stmt() were toplevel block executors. These don't need to exec_stmt(); they can directly call exec_stmt_block(). This reduces funtion call overhead because exec_stmt() is called frequently. This is shown to obtain as much as 7% performance benefit on some systems. --- src/pl/plpgsql/src/pl_exec.c | 236 +++++++++++++++++------------------ 1 file changed, 114 insertions(+), 122 deletions(-) diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 0a70ceddbb..d5377a6dad 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -274,8 +274,6 @@ 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, @@ -1566,7 +1564,15 @@ exec_toplevel_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block, estate->err_text = NULL; estate->err_stmt = (PLpgSQL_stmt *)block; - rc = exec_stmt(estate, (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); + + 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); if (rc != PLPGSQL_RC_RETURN) { @@ -1930,162 +1936,148 @@ exec_stmts(PLpgSQL_execstate *estate, List *stmts) foreach(s, stmts) { PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s); - int rc = exec_stmt(estate, stmt); + PLpgSQL_stmt *save_estmt; + int rc = -1; - if (rc != PLPGSQL_RC_OK) - return rc; - } - - return PLPGSQL_RC_OK; -} + save_estmt = estate->err_stmt; + 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; + CHECK_FOR_INTERRUPTS(); - save_estmt = estate->err_stmt; - estate->err_stmt = stmt; + switch (stmt->cmd_type) + { + case PLPGSQL_STMT_BLOCK: + rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt); + break; - /* 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); + case PLPGSQL_STMT_ASSIGN: + rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt); + break; - CHECK_FOR_INTERRUPTS(); + case PLPGSQL_STMT_PERFORM: + rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt); + break; - switch (stmt->cmd_type) - { - case PLPGSQL_STMT_BLOCK: - rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt); - break; + case PLPGSQL_STMT_CALL: + rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) stmt); + break; - case PLPGSQL_STMT_ASSIGN: - rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt); - break; + case PLPGSQL_STMT_GETDIAG: + rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt); + break; - case PLPGSQL_STMT_PERFORM: - rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt); - break; + case PLPGSQL_STMT_IF: + rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt); + break; - case PLPGSQL_STMT_CALL: - rc = exec_stmt_call(estate, (PLpgSQL_stmt_call *) stmt); - break; + case PLPGSQL_STMT_CASE: + rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt); + break; - case PLPGSQL_STMT_GETDIAG: - rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt); - break; + case PLPGSQL_STMT_LOOP: + rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt); + break; - case PLPGSQL_STMT_IF: - rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt); - break; + case PLPGSQL_STMT_WHILE: + rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt); + break; - case PLPGSQL_STMT_CASE: - rc = exec_stmt_case(estate, (PLpgSQL_stmt_case *) stmt); - break; + case PLPGSQL_STMT_FORI: + rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt); + break; - case PLPGSQL_STMT_LOOP: - rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt); - break; + case PLPGSQL_STMT_FORS: + rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt); + break; - case PLPGSQL_STMT_WHILE: - rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt); - break; + case PLPGSQL_STMT_FORC: + rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt); + break; - case PLPGSQL_STMT_FORI: - rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt); - break; + case PLPGSQL_STMT_FOREACH_A: + rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt); + break; - case PLPGSQL_STMT_FORS: - rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt); - break; + case PLPGSQL_STMT_EXIT: + rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt); + break; - case PLPGSQL_STMT_FORC: - rc = exec_stmt_forc(estate, (PLpgSQL_stmt_forc *) stmt); - break; + case PLPGSQL_STMT_RETURN: + rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt); + break; - case PLPGSQL_STMT_FOREACH_A: - rc = exec_stmt_foreach_a(estate, (PLpgSQL_stmt_foreach_a *) stmt); - break; + case PLPGSQL_STMT_RETURN_NEXT: + rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt); + break; - case PLPGSQL_STMT_EXIT: - rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt); - break; + case PLPGSQL_STMT_RETURN_QUERY: + rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt); + break; - case PLPGSQL_STMT_RETURN: - rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt); - break; + case PLPGSQL_STMT_RAISE: + rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt); + break; - case PLPGSQL_STMT_RETURN_NEXT: - rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt); - break; + case PLPGSQL_STMT_ASSERT: + rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt); + break; - case PLPGSQL_STMT_RETURN_QUERY: - rc = exec_stmt_return_query(estate, (PLpgSQL_stmt_return_query *) stmt); - break; + case PLPGSQL_STMT_EXECSQL: + rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt); + break; - case PLPGSQL_STMT_RAISE: - rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt); - break; + case PLPGSQL_STMT_DYNEXECUTE: + rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt); + break; - case PLPGSQL_STMT_ASSERT: - rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt); - break; + case PLPGSQL_STMT_DYNFORS: + rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt); + break; - case PLPGSQL_STMT_EXECSQL: - rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt); - break; + case PLPGSQL_STMT_OPEN: + rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt); + break; - case PLPGSQL_STMT_DYNEXECUTE: - rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt); - break; + case PLPGSQL_STMT_FETCH: + rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt); + break; - case PLPGSQL_STMT_DYNFORS: - rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt); - break; + case PLPGSQL_STMT_CLOSE: + rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt); + break; - case PLPGSQL_STMT_OPEN: - rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt); - break; + case PLPGSQL_STMT_COMMIT: + rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt); + break; - case PLPGSQL_STMT_FETCH: - rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt); - break; + case PLPGSQL_STMT_ROLLBACK: + rc = exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback *) stmt); + break; - case PLPGSQL_STMT_CLOSE: - rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt); - break; + case PLPGSQL_STMT_SET: + rc = exec_stmt_set(estate, (PLpgSQL_stmt_set *) stmt); + break; - case PLPGSQL_STMT_COMMIT: - rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit *) stmt); - break; + default: + estate->err_stmt = save_estmt; + elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); + } - case PLPGSQL_STMT_ROLLBACK: - rc = exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback *) 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); - case PLPGSQL_STMT_SET: - rc = exec_stmt_set(estate, (PLpgSQL_stmt_set *) stmt); - break; + estate->err_stmt = save_estmt; - default: - estate->err_stmt = save_estmt; - elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); + if (rc != PLPGSQL_RC_OK) + return rc; } - /* 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); - - estate->err_stmt = save_estmt; - - return rc; + return PLPGSQL_RC_OK; } -- 2.17.1