diff options
author | unknown <bar@bar.myoffice.izhnet.ru> | 2007-06-01 15:16:57 +0500 |
---|---|---|
committer | unknown <bar@bar.myoffice.izhnet.ru> | 2007-06-01 15:16:57 +0500 |
commit | 075346acc8e5b17a9612718d3eda320762350f3a (patch) | |
tree | 2e85d3308d352fd698b690a2eb4867e50c17bbbe | |
parent | 924eacee08f63732a92d20c36306e96ec4f0a69b (diff) | |
parent | e319a0493461000f9eeabceed7f2c5d57cfc44cd (diff) | |
download | mariadb-git-075346acc8e5b17a9612718d3eda320762350f3a.tar.gz |
Merge abarkov@bk-internal.mysql.com:/home/bk/mysql-5.1-rpl
into mysql.com:/home/bar/mysql-work/mysql-5.1.b28600
-rw-r--r-- | mysql-test/r/binlog_unsafe.result | 13 | ||||
-rw-r--r-- | mysql-test/r/check.result | 3 | ||||
-rw-r--r-- | mysql-test/r/rpl_slave_skip.result | 136 | ||||
-rw-r--r-- | mysql-test/r/rpl_udf.result | 8 | ||||
-rw-r--r-- | mysql-test/t/binlog_unsafe.test | 16 | ||||
-rw-r--r-- | mysql-test/t/check.test | 3 | ||||
-rw-r--r-- | mysql-test/t/func_misc.test | 2 | ||||
-rw-r--r-- | mysql-test/t/rpl_slave_skip.test | 71 | ||||
-rw-r--r-- | sql/item_create.cc | 4 | ||||
-rw-r--r-- | sql/log_event.cc | 27 | ||||
-rw-r--r-- | sql/log_event.h | 2 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 3 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.h | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.cc | 23 | ||||
-rw-r--r-- | sql/sql_class.h | 12 | ||||
-rw-r--r-- | sql/sql_insert.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 44 | ||||
-rw-r--r-- | sql/sql_view.cc | 4 |
21 files changed, 362 insertions, 20 deletions
diff --git a/mysql-test/r/binlog_unsafe.result b/mysql-test/r/binlog_unsafe.result new file mode 100644 index 00000000000..36213cbb2ae --- /dev/null +++ b/mysql-test/r/binlog_unsafe.result @@ -0,0 +1,13 @@ +SET BINLOG_FORMAT=STATEMENT; +CREATE TABLE t1 (a CHAR(40)); +CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY); +CREATE TABLE t3 (b INT AUTO_INCREMENT PRIMARY KEY); +CREATE VIEW v1(a,b) AS SELECT a,b FROM t2,t3; +INSERT INTO t1 SELECT UUID(); +Warnings: +Warning 1588 Statement is not safe to log in statement format. +SHOW WARNINGS; +Level Warning +Code 1588 +Message Statement is not safe to log in statement format. +DROP TABLE t1,t2,t3; diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result index 60806e7393e..739eab2ed76 100644 --- a/mysql-test/r/check.result +++ b/mysql-test/r/check.result @@ -1,4 +1,5 @@ -drop table if exists t1; +drop table if exists t1,t2; +drop view if exists v1; create table t1(n int not null, key(n), key(n), key(n), key(n)); check table t1 extended; insert into t1 values (200000); diff --git a/mysql-test/r/rpl_slave_skip.result b/mysql-test/r/rpl_slave_skip.result new file mode 100644 index 00000000000..e2bc34eeb41 --- /dev/null +++ b/mysql-test/r/rpl_slave_skip.result @@ -0,0 +1,136 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +**** On Slave **** +STOP SLAVE; +**** On Master **** +SET SESSION BINLOG_FORMAT=ROW; +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (c INT, d INT); +INSERT INTO t1 VALUES (1,1),(2,4),(3,9); +INSERT INTO t2 VALUES (1,1),(2,8),(3,27); +UPDATE t1,t2 SET b = d, d = b * 2 WHERE a = c; +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT) +master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (c INT, d INT) +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Update_rows # # table_id: # +master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F +SELECT * FROM t1; +a b +1 1 +2 8 +3 27 +SELECT * FROM t2; +c d +1 2 +2 16 +3 54 +**** On Slave **** +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=484; +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 714 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 484 +Relay_Log_Space # +Until_Condition Master +Until_Log_File master-bin.000001 +Until_Log_Pos 484 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +SELECT * FROM t1; +a b +1 1 +2 4 +3 9 +SELECT * FROM t2; +c d +1 1 +2 8 +3 27 +STOP SLAVE; +RESET SLAVE; +RESET MASTER; +SET SESSION BINLOG_FORMAT=STATEMENT; +SET @foo = 12; +INSERT INTO t1 VALUES(@foo, 2*@foo); +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # User var # # @`foo`=12 +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES(@foo, 2*@foo) +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=106; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 248 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 248 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +**** On Master **** +DROP TABLE t1, t2; diff --git a/mysql-test/r/rpl_udf.result b/mysql-test/r/rpl_udf.result index 6587632bca0..220358aab9c 100644 --- a/mysql-test/r/rpl_udf.result +++ b/mysql-test/r/rpl_udf.result @@ -181,12 +181,20 @@ affected rows: 2 CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM; affected rows: 0 INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00)); +Warnings: +Warning 1588 Statement is not safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00)); +Warnings: +Warning 1588 Statement is not safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00)); +Warnings: +Warning 1588 Statement is not safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00)); +Warnings: +Warning 1588 Statement is not safe to log in statement format. affected rows: 1 SELECT * FROM t1 ORDER BY sum; sum price diff --git a/mysql-test/t/binlog_unsafe.test b/mysql-test/t/binlog_unsafe.test new file mode 100644 index 00000000000..9e0716cf2b4 --- /dev/null +++ b/mysql-test/t/binlog_unsafe.test @@ -0,0 +1,16 @@ +# Test to check that a warning is generated for unsafe statements +# executed under statement mode logging. + +SET BINLOG_FORMAT=STATEMENT; + +CREATE TABLE t1 (a CHAR(40)); +CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY); +CREATE TABLE t3 (b INT AUTO_INCREMENT PRIMARY KEY); +CREATE VIEW v1(a,b) AS SELECT a,b FROM t2,t3; + +INSERT INTO t1 SELECT UUID(); +query_vertical SHOW WARNINGS; + +DROP TABLE t1,t2,t3; + + diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test index 8d9d70bd29a..eb72d75da3c 100644 --- a/mysql-test/t/check.test +++ b/mysql-test/t/check.test @@ -2,7 +2,8 @@ connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; +drop view if exists v1; --enable_warnings # Add a lot of keys to slow down check diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 8ff62f68e45..23b8db607b8 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -89,7 +89,9 @@ select export_set(3, _latin1'foo', _utf8'bar', ',', 4); # # Test for BUG#9535 # +--disable_warnings create table t1 as select uuid(), length(uuid()); +--enable_warnings show create table t1; drop table t1; diff --git a/mysql-test/t/rpl_slave_skip.test b/mysql-test/t/rpl_slave_skip.test new file mode 100644 index 00000000000..70a5b23c288 --- /dev/null +++ b/mysql-test/t/rpl_slave_skip.test @@ -0,0 +1,71 @@ +source include/master-slave.inc; + +--echo **** On Slave **** +connection slave; +STOP SLAVE; + +--echo **** On Master **** +connection master; +SET SESSION BINLOG_FORMAT=ROW; + +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (c INT, d INT); +INSERT INTO t1 VALUES (1,1),(2,4),(3,9); +INSERT INTO t2 VALUES (1,1),(2,8),(3,27); +UPDATE t1,t2 SET b = d, d = b * 2 WHERE a = c; +source include/show_binlog_events.inc; + +# These tables should be changed +SELECT * FROM t1; +SELECT * FROM t2; +save_master_pos; + +--echo **** On Slave **** +connection slave; + +# Stop when reaching the the first table map event. +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=484; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 8 # 9 # 23 # 33 # +query_vertical SHOW SLAVE STATUS; + +# Now we skip *one* table map event. If the execution starts right +# after that table map event, *one* of the involved tables will be +# changed. +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +sync_with_master; + +# These values should be what was inserted, not what was +# updated. Since we are skipping the first table map of the group +# representing the UPDATE statement above, we should skip the entire +# group and not start executing at the first table map. +SELECT * FROM t1; +SELECT * FROM t2; + +STOP SLAVE; +RESET SLAVE; +connection master; +RESET MASTER; + +SET SESSION BINLOG_FORMAT=STATEMENT; +SET @foo = 12; +INSERT INTO t1 VALUES(@foo, 2*@foo); +save_master_pos; +source include/show_binlog_events.inc; + +connection slave; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=106; +wait_for_slave_to_stop; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +sync_with_master; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 8 # 9 # 23 # 33 # +query_vertical SHOW SLAVE STATUS; + +--echo **** On Master **** +connection master; +DROP TABLE t1, t2; +sync_slave_with_master; diff --git a/sql/item_create.cc b/sql/item_create.cc index 62f44996f4b..5dd09bc7b2c 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2341,7 +2341,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list) if (item_list != NULL) arg_count= item_list->elements; - thd->lex->binlog_row_based_if_mixed= TRUE; + thd->lex->set_stmt_unsafe(); DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION) || (udf->type == UDFTYPE_AGGREGATE)); @@ -4528,7 +4528,7 @@ Create_func_uuid Create_func_uuid::s_singleton; Item* Create_func_uuid::create(THD *thd) { - thd->lex->binlog_row_based_if_mixed= TRUE; + thd->lex->set_stmt_unsafe(); return new (thd->mem_root) Item_func_uuid(); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 3cca8d53f07..d33c0382d7c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6149,6 +6149,20 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) DBUG_RETURN(0); } +Log_event::enum_skip_reason +Rows_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +{ + /* + If the slave skip counter is 1 and this event does not end a + statement, then we should not start executing on the next event. + Otherwise, we defer the decision to the normal skipping logic. + */ + if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F)) + return Log_event::EVENT_SKIP_IGNORE; + else + return Log_event::do_shall_skip(rli); +} + int Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli) { @@ -6622,6 +6636,19 @@ err: DBUG_RETURN(error); } +Log_event::enum_skip_reason +Table_map_log_event::do_shall_skip(RELAY_LOG_INFO *rli) +{ + /* + If the slave skip counter is 1, then we should not start executing + on the next event. + */ + if (rli->slave_skip_counter == 1) + return Log_event::EVENT_SKIP_IGNORE; + else + return Log_event::do_shall_skip(rli); +} + int Table_map_log_event::do_update_pos(RELAY_LOG_INFO *rli) { rli->inc_event_relay_log_pos(); diff --git a/sql/log_event.h b/sql/log_event.h index bb69043969d..092b349350e 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2067,6 +2067,7 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_apply_event(RELAY_LOG_INFO const *rli); virtual int do_update_pos(RELAY_LOG_INFO *rli); + virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); #endif #ifndef MYSQL_CLIENT @@ -2245,6 +2246,7 @@ private: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_apply_event(RELAY_LOG_INFO const *rli); virtual int do_update_pos(RELAY_LOG_INFO *rli); + virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli); /* Primitive to prepare for a sequence of row executions. diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index bb2d9c25a77..40744d0b07b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6059,3 +6059,6 @@ ER_SLAVE_INCIDENT eng "The incident %s occured on the master. Message: %-.64s" ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT eng "Table has no partition for some existing values" +ER_BINLOG_UNSAFE_STATEMENT + eng "Statement is not safe to log in statement format." + swe "Detta är inte säkert att logga i statement-format." diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 566aadcc864..8a09cede337 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1855,7 +1855,7 @@ sp_head::restore_lex(THD *thd) cannot switch from statement-based to row-based only for this substatement). */ - if (sublex->binlog_row_based_if_mixed) + if (sublex->is_stmt_unsafe()) m_flags|= BINLOG_ROW_BASED_IF_MIXED; /* diff --git a/sql/sp_head.h b/sql/sp_head.h index 4e3e11e468d..a6a41ec68f9 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -378,7 +378,7 @@ public: the substatements not). */ if (m_flags & BINLOG_ROW_BASED_IF_MIXED) - lex->binlog_row_based_if_mixed= TRUE; + lex->set_stmt_unsafe(); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a97d285810e..1986c09b2d2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3992,7 +3992,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) /* CREATE ... SELECT UUID() locks no tables, we have to test here. */ - if (thd->lex->binlog_row_based_if_mixed) + if (thd->lex->is_stmt_unsafe()) thd->set_current_stmt_binlog_row_based_if_mixed(); if (!tables && !thd->lex->requires_prelocking()) @@ -4033,7 +4033,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED && has_two_write_locked_tables_with_auto_increment(tables)) { - thd->lex->binlog_row_based_if_mixed= TRUE; + thd->lex->set_stmt_unsafe(); thd->set_current_stmt_binlog_row_based_if_mixed(); } } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 018425099bb..cc3b281f892 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -329,7 +329,7 @@ THD::THD() Open_tables_state(refresh_version), rli_fake(0), lock_id(&main_lock_id), user_time(0), in_sub_stmt(0), - binlog_table_maps(0), + binlog_table_maps(0), binlog_flags(0UL), arg_of_last_insert_id_function(FALSE), first_successful_insert_id_in_prev_stmt(0), first_successful_insert_id_in_prev_stmt_for_binlog(0), @@ -3103,6 +3103,27 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query, if (int error= binlog_flush_pending_rows_event(TRUE)) DBUG_RETURN(error); + /* + If we are in statement mode and trying to log an unsafe statement, + we should print a warning. + */ + if (lex->is_stmt_unsafe() && + variables.binlog_format == BINLOG_FORMAT_STMT) + { + DBUG_ASSERT(this->query != NULL); + push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_BINLOG_UNSAFE_STATEMENT, + ER(ER_BINLOG_UNSAFE_STATEMENT)); + if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) + { + char warn_buf[MYSQL_ERRMSG_SIZE]; + my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s", + ER(ER_BINLOG_UNSAFE_STATEMENT), this->query); + sql_print_warning(warn_buf); + binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; + } + } + switch (qtype) { case THD::ROW_QUERY_TYPE: if (current_stmt_binlog_row_based) diff --git a/sql/sql_class.h b/sql/sql_class.h index a0b1402d060..fb713d8a80b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1110,6 +1110,17 @@ public: private: uint binlog_table_maps; // Number of table maps currently in the binlog + + enum enum_binlog_flag { + BINLOG_FLAG_UNSAFE_STMT_PRINTED, + BINLOG_FLAG_COUNT + }; + + /** + Flags with per-thread information regarding the status of the + binary log. + */ + uint32 binlog_flags; public: uint get_binlog_table_maps() const { return binlog_table_maps; @@ -1680,6 +1691,7 @@ public: void restore_sub_statement_state(Sub_statement_state *backup); void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void restore_active_arena(Query_arena *set, Query_arena *backup); + inline void set_current_stmt_binlog_row_based_if_mixed() { /* diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5fd0ec669bd..6be2c95a661 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1664,6 +1664,7 @@ public: Statement-based replication of INSERT DELAYED has problems with RAND() and user vars, so in mixed mode we go to row-based. */ + thd.lex->set_stmt_unsafe(); thd.set_current_stmt_binlog_row_based_if_mixed(); bzero((char*) &thd.net, sizeof(thd.net)); // Safety diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c19c224f0a3..684db21c2c9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1782,7 +1782,7 @@ void Query_tables_list::reset_query_tables_list(bool init) sroutines_list.empty(); sroutines_list_own_last= sroutines_list.next; sroutines_list_own_elements= 0; - binlog_row_based_if_mixed= FALSE; + binlog_stmt_flags= 0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 68a3092cd77..a953f1a2684 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -951,14 +951,6 @@ public: uint sroutines_list_own_elements; /* - Tells if the parsing stage detected that some items require row-based - binlogging to give a reliable binlog/replication, or if we will use - stored functions or triggers which themselves need require row-based - binlogging. - */ - bool binlog_row_based_if_mixed; - - /* These constructor and destructor serve for creation/destruction of Query_tables_list instances which are used as backup storage. */ @@ -1005,12 +997,48 @@ public: query_tables_own_last= 0; } } + + /** + Has the parser/scanner detected that this statement is unsafe? + */ + inline bool is_stmt_unsafe() const { + return binlog_stmt_flags & (1U << BINLOG_STMT_FLAG_UNSAFE); + } + + /** + Flag the current (top-level) statement as unsafe. + + The flag will be reset after the statement has finished. + + */ + inline void set_stmt_unsafe() { + binlog_stmt_flags|= (1U << BINLOG_STMT_FLAG_UNSAFE); + } + + inline void clear_stmt_unsafe() { + binlog_stmt_flags&= ~(1U << BINLOG_STMT_FLAG_UNSAFE); + } + /** true if the parsed tree contains references to stored procedures or functions, false otherwise */ bool uses_stored_routines() const { return sroutines_list.elements != 0; } + +private: + enum enum_binlog_stmt_flag { + BINLOG_STMT_FLAG_UNSAFE, + BINLOG_STMT_FLAG_COUNT + }; + + /* + Tells if the parsing stage detected properties of the statement, + for example: that some items require row-based binlogging to give + a reliable binlog/replication, or if we will use stored functions + or triggers which themselves need require row-based binlogging. + */ + uint32 binlog_stmt_flags; }; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8645cc60d89..64f2f9d32b8 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1118,8 +1118,8 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, If the view's body needs row-based binlogging (e.g. the VIEW is created from SELECT UUID()), the top statement also needs it. */ - if (lex->binlog_row_based_if_mixed) - old_lex->binlog_row_based_if_mixed= TRUE; + if (lex->is_stmt_unsafe()) + old_lex->set_stmt_unsafe(); view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE && lex->can_be_merged()); LINT_INIT(view_main_select_tables); |