mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Fix for bug #13825 "Triggers: crash if release savepoint" and for general
handling of savepoints in stored routines. Fixed ha_rollback_to_savepoint()/ha_savepoint()/ha_release_savepoint() functions to properly handle savepoints inside of stored functions and triggers. Also now when we invoke stored function or trigger we create new savepoint level. We destroy it at the end of function/trigger execution and return back to old savepoint level. mysql-test/r/sp_trans.result: Added test for bug #13825 "Triggers: crash if release savepoint" and for general handling of savepoints in stored routines. mysql-test/t/sp_trans.test: Added test for bug #13825 "Triggers: crash if release savepoint" and for general handling of savepoints in stored routines. sql/ha_innodb.cc: innobase_savepoint(): Replaced check which always failed due to similar check in caller with assertion. sql/handler.cc: ha_rollback_to_savepoint()/ha_savepoint()/ha_release_savepoint(): Changed functions to properly support handling of savepoints inside of stored functions and triggers. sql/sql_class.cc: THD::reset_sub_statement_state()/restore_sub_statement_state(): When we invoke stored function or trigger we should create new savepoint level. We should destroy it at the end of function/trigger execution and return back to old savepoint level. To support this behavior we should save and reset list of current savepoints on entering function and restore old list when we leave it. sql/sql_class.h: Sub_statement_state: When we invoke stored function or trigger we should create new savepoint level. We should destroy it at the end of function/trigger execution and return back to old savepoint level. To support this behavior added "savepoint" member which is used to save/restore list of current savepoints on entering/leaving function. sql/sql_parse.cc: mysql_execute_command(): Changed processing of SQLCOM_SAVEPOINT so now it is not ignored when we are in autocommit mode and savepoint is set inside of stored function or trigger.
This commit is contained in:
@@ -1916,6 +1916,7 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
|
||||
- Value for found_rows() is reset and restored
|
||||
- examined_row_count is added to the total
|
||||
- cuted_fields is added to the total
|
||||
- new savepoint level is created and destroyed
|
||||
|
||||
NOTES:
|
||||
Seed for random() is saved for the first! usage of RAND()
|
||||
@@ -1939,6 +1940,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||
backup->sent_row_count= sent_row_count;
|
||||
backup->cuted_fields= cuted_fields;
|
||||
backup->client_capabilities= client_capabilities;
|
||||
backup->savepoints= transaction.savepoints;
|
||||
|
||||
if (!lex->requires_prelocking() || is_update_query(lex->sql_command))
|
||||
options&= ~OPTION_BIN_LOG;
|
||||
@@ -1951,6 +1953,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||
examined_row_count= 0;
|
||||
sent_row_count= 0;
|
||||
cuted_fields= 0;
|
||||
transaction.savepoints= 0;
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
/* Surpress OK packets in case if we will execute statements */
|
||||
@@ -1961,6 +1964,21 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||
|
||||
void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
||||
{
|
||||
/*
|
||||
To save resources we want to release savepoints which were created
|
||||
during execution of function or trigger before leaving their savepoint
|
||||
level. It is enough to release first savepoint set on this level since
|
||||
all later savepoints will be released automatically.
|
||||
*/
|
||||
if (transaction.savepoints)
|
||||
{
|
||||
SAVEPOINT *sv;
|
||||
for (sv= transaction.savepoints; sv->prev; sv= sv->prev)
|
||||
{}
|
||||
/* ha_release_savepoint() never returns error. */
|
||||
(void)ha_release_savepoint(this, sv);
|
||||
}
|
||||
transaction.savepoints= backup->savepoints;
|
||||
options= backup->options;
|
||||
in_sub_stmt= backup->in_sub_stmt;
|
||||
net.no_send_ok= backup->no_send_ok;
|
||||
|
||||
Reference in New Issue
Block a user