diff options
author | unknown <monty@mysql.com> | 2005-08-15 18:15:12 +0300 |
---|---|---|
committer | unknown <monty@mysql.com> | 2005-08-15 18:15:12 +0300 |
commit | 262075d108fa2c3f12f9ffcf27910d3a41cb9348 (patch) | |
tree | 74f6de82390f01182f650d8d8e22291fd18df1e6 /sql/sql_class.cc | |
parent | ae8f5845b317d0ce2a31c755369ff40038bbbd2f (diff) | |
download | mariadb-git-262075d108fa2c3f12f9ffcf27910d3a41cb9348.tar.gz |
Save and clear run context before executing a stored function or trigger and restore it afterwards.
This allows us to use statement replication with functions and triggers
The following things are fixed with this patch:
- NOW() and automatic timestamps takes the value from the main event for functions and triggers (which allows these to replicate with statement level logging)
- No side effects for triggers or functions with auto-increment values(), last_insert_id(), rand() or found_rows()
- Triggers can't return result sets
Fixes bugs:
#12480: NOW() is not constant in a trigger
#12481: Using NOW() in a stored function breaks statement based replication
#12482: Triggers has side effects with auto_increment values
#11587: trigger causes lost connection error
mysql-test/r/trigger.result:
Added test fpr big
mysql-test/t/sp-error.test:
Changed error message numbers
mysql-test/t/trigger.test:
Added test for trigger returning result (#11587)
sql/item_func.cc:
Store the first used seed value for RAND() value.
(This makes rand() replicatable in functions and triggers)
Save and clear run context before executing a stored function and restore it afterwards.
This removes side effects of stored functions for RAND(), auto-increment values and NOW() and makes most stored function replicatable
sql/share/errmsg.txt:
Reuse error message also for triggers
sql/sp_head.cc:
If in function or trigger, don't change value of NOW()
(This allows us to use statement replication with functions that directly or indirectly uses timestamps)
sql/sql_class.cc:
Added framework for storing and retrieving run context while exceuting triggers or stored functions.
sql/sql_class.h:
Added framework for storing and retrieving run context while exceuting triggers or stored functions.
sql/sql_parse.cc:
If in function or trigger, don't change value of NOW()
(This allows us to use statement replication with functions that directly or indirectly uses timestamps)
sql/sql_trigger.cc:
Moved process_triggers function from sql_trigger.h
Use reset/restore sub_statement_state while executing triggers to avoid side effects and make them replicatable
sql/sql_trigger.h:
Moved process_triggers function from sql_trigger.h
Use reset/restore sub_statement_state while executing triggers to avoid side effects and make them replicatable
sql/sql_yacc.yy:
Give error message if trigger can return a result set (Bug #11587)
tests/fork_big2.pl:
Removed return from end of lines
mysql-test/r/rpl_trigger.result:
New BitKeeper file ``mysql-test/r/rpl_trigger.result''
mysql-test/t/rpl_trigger.test:
New BitKeeper file ``mysql-test/t/rpl_trigger.test''
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 21df4640f3f..566d4e9d2a2 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -174,7 +174,7 @@ THD::THD() :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0), Open_tables_state(refresh_version), lock_id(&main_lock_id), - user_time(0), in_sub_stmt(FALSE), global_read_lock(0), is_fatal_error(0), + user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0), rand_used(0), time_zone_used(0), last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0), in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), @@ -1836,3 +1836,85 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup) set_open_tables_state(backup); DBUG_VOID_RETURN; } + + +/**************************************************************************** + Handling of statement states in functions and triggers. + + This is used to ensure that the function/trigger gets a clean state + to work with and does not cause any side effects of the calling statement. + + It also allows most stored functions and triggers to replicate even + if they are used items that would normally be stored in the binary + replication (like last_insert_id() etc...) + + The following things is done + - Disable binary logging for the duration of the statement + - Disable multi-result-sets for the duration of the statement + - Value of last_insert_id() is reset and restored + - Value set by 'SET INSERT_ID=#' is reset and restored + - Value for found_rows() is reset and restored + - examined_row_count is added to the total + - cuted_fields is added to the total + + NOTES: + Seed for random() is saved for the first! usage of RAND() + We reset examined_row_count and cuted_fields and add these to the + result to ensure that if we have a bug that would reset these within + a function, we are not loosing any rows from the main statement. +****************************************************************************/ + +void THD::reset_sub_statement_state(Sub_statement_state *backup, + uint new_state) +{ + backup->options= options; + backup->in_sub_stmt= in_sub_stmt; + backup->no_send_ok= net.no_send_ok; + backup->enable_slow_log= enable_slow_log; + backup->last_insert_id= last_insert_id; + backup->next_insert_id= next_insert_id; + backup->insert_id_used= insert_id_used; + backup->limit_found_rows= limit_found_rows; + backup->examined_row_count= examined_row_count; + backup->sent_row_count= sent_row_count; + backup->cuted_fields= cuted_fields; + backup->client_capabilities= client_capabilities; + + options&= ~OPTION_BIN_LOG; + /* Disable result sets */ + client_capabilities &= ~CLIENT_MULTI_RESULTS; + in_sub_stmt|= new_state; + last_insert_id= 0; + next_insert_id= 0; + insert_id_used= 0; + examined_row_count= 0; + sent_row_count= 0; + cuted_fields= 0; + +#ifndef EMBEDDED_LIBRARY + /* Surpress OK packets in case if we will execute statements */ + net.no_send_ok= TRUE; +#endif +} + + +void THD::restore_sub_statement_state(Sub_statement_state *backup) +{ + options= backup->options; + in_sub_stmt= backup->in_sub_stmt; + net.no_send_ok= backup->no_send_ok; + enable_slow_log= backup->enable_slow_log; + last_insert_id= backup->last_insert_id; + next_insert_id= backup->next_insert_id; + insert_id_used= backup->insert_id_used; + limit_found_rows= backup->limit_found_rows; + sent_row_count= backup->sent_row_count; + client_capabilities= backup->client_capabilities; + + /* + The following is added to the old values as we are interested in the + total complexity of the query + */ + examined_row_count+= backup->examined_row_count; + cuted_fields+= backup->cuted_fields; +} |