diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_create.cc | 4 | ||||
-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 | 19 | ||||
-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 |
11 files changed, 79 insertions, 18 deletions
diff --git a/sql/item_create.cc b/sql/item_create.cc index 8ff78ef1b48..67ffbaba1ad 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)); @@ -4527,7 +4527,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/share/errmsg.txt b/sql/share/errmsg.txt index 03990bbad0e..2e1240ab616 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 a2ce5111a25..6bd6360e642 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1873,7 +1873,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 551707fa7bd..61407440a11 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -379,7 +379,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 0f428da1fdb..0ec6ababab0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3591,7 +3591,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()) @@ -3632,7 +3632,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 4ee36f5864c..3e8b43f638e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -201,7 +201,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), global_read_lock(0), is_fatal_error(0), rand_used(0), time_zone_used(0), arg_of_last_insert_id_function(FALSE), @@ -2888,6 +2888,23 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, to how you treat this. */ case THD::STMT_QUERY_TYPE: + if (lex->is_stmt_unsafe()) + { + 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; + } + } + /* The MYSQL_LOG::write() function will set the STMT_END_F flag and flush the pending rows event if necessary. diff --git a/sql/sql_class.h b/sql/sql_class.h index 3d53c19633e..7f933c331c3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1048,6 +1048,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; @@ -1599,6 +1610,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 f6ae2df3750..b50568df9f6 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1533,6 +1533,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 4a162478388..685b915a8b9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1719,7 +1719,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 850586c6098..7097c2de4fd 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -910,14 +910,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. */ @@ -964,6 +956,41 @@ 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); + } + +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; }; @@ -1299,6 +1326,7 @@ typedef struct st_lex : public Query_tables_list void restore_backup_query_tables_list(Query_tables_list *backup); bool table_or_sp_used(); + } LEX; struct st_lex_local: public st_lex diff --git a/sql/sql_view.cc b/sql/sql_view.cc index c02fb7bcdc0..306c759359c 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1114,8 +1114,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); |