Commit 5c662d6d authored by mats@kindahl-laptop.dnsalias.net's avatar mats@kindahl-laptop.dnsalias.net

Merge mkindahl@bk-internal.mysql.com:/home/bk/mysql-5.1-new-rpl

into  kindahl-laptop.dnsalias.net:/home/bk/b28618-mysql-5.1-rpl
parents 685293b9 b1bd9a6c
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;
# 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;
...@@ -2341,7 +2341,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list) ...@@ -2341,7 +2341,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list)
if (item_list != NULL) if (item_list != NULL)
arg_count= item_list->elements; arg_count= item_list->elements;
thd->lex->binlog_row_based_if_mixed= TRUE; thd->lex->set_stmt_unsafe();
DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION) DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION)
|| (udf->type == UDFTYPE_AGGREGATE)); || (udf->type == UDFTYPE_AGGREGATE));
...@@ -4528,7 +4528,7 @@ Create_func_uuid Create_func_uuid::s_singleton; ...@@ -4528,7 +4528,7 @@ Create_func_uuid Create_func_uuid::s_singleton;
Item* Item*
Create_func_uuid::create(THD *thd) 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(); return new (thd->mem_root) Item_func_uuid();
} }
......
...@@ -6149,6 +6149,20 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli) ...@@ -6149,6 +6149,20 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
DBUG_RETURN(0); 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 int
Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli) Rows_log_event::do_update_pos(RELAY_LOG_INFO *rli)
{ {
...@@ -6622,6 +6636,19 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli) ...@@ -6622,6 +6636,19 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
DBUG_RETURN(error); 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) int Table_map_log_event::do_update_pos(RELAY_LOG_INFO *rli)
{ {
rli->inc_event_relay_log_pos(); rli->inc_event_relay_log_pos();
......
...@@ -2067,6 +2067,7 @@ class Table_map_log_event : public Log_event ...@@ -2067,6 +2067,7 @@ class Table_map_log_event : public Log_event
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
virtual int do_apply_event(RELAY_LOG_INFO const *rli); virtual int do_apply_event(RELAY_LOG_INFO const *rli);
virtual int do_update_pos(RELAY_LOG_INFO *rli); virtual int do_update_pos(RELAY_LOG_INFO *rli);
virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);
#endif #endif
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
...@@ -2245,6 +2246,7 @@ class Rows_log_event : public Log_event ...@@ -2245,6 +2246,7 @@ class Rows_log_event : public Log_event
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
virtual int do_apply_event(RELAY_LOG_INFO const *rli); virtual int do_apply_event(RELAY_LOG_INFO const *rli);
virtual int do_update_pos(RELAY_LOG_INFO *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. Primitive to prepare for a sequence of row executions.
......
...@@ -6059,3 +6059,6 @@ ER_SLAVE_INCIDENT ...@@ -6059,3 +6059,6 @@ ER_SLAVE_INCIDENT
eng "The incident %s occured on the master. Message: %-.64s" eng "The incident %s occured on the master. Message: %-.64s"
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
eng "Table has no partition for some existing values" 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 skert att logga i statement-format."
...@@ -1855,7 +1855,7 @@ sp_head::restore_lex(THD *thd) ...@@ -1855,7 +1855,7 @@ sp_head::restore_lex(THD *thd)
cannot switch from statement-based to row-based only for this cannot switch from statement-based to row-based only for this
substatement). substatement).
*/ */
if (sublex->binlog_row_based_if_mixed) if (sublex->is_stmt_unsafe())
m_flags|= BINLOG_ROW_BASED_IF_MIXED; m_flags|= BINLOG_ROW_BASED_IF_MIXED;
/* /*
......
...@@ -378,7 +378,7 @@ class sp_head :private Query_arena ...@@ -378,7 +378,7 @@ class sp_head :private Query_arena
the substatements not). the substatements not).
*/ */
if (m_flags & BINLOG_ROW_BASED_IF_MIXED) if (m_flags & BINLOG_ROW_BASED_IF_MIXED)
lex->binlog_row_based_if_mixed= TRUE; lex->set_stmt_unsafe();
} }
......
...@@ -3992,7 +3992,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) ...@@ -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. 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(); thd->set_current_stmt_binlog_row_based_if_mixed();
if (!tables && !thd->lex->requires_prelocking()) if (!tables && !thd->lex->requires_prelocking())
...@@ -4033,7 +4033,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) ...@@ -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 && if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
has_two_write_locked_tables_with_auto_increment(tables)) 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(); thd->set_current_stmt_binlog_row_based_if_mixed();
} }
} }
......
...@@ -329,7 +329,7 @@ THD::THD() ...@@ -329,7 +329,7 @@ THD::THD()
Open_tables_state(refresh_version), rli_fake(0), Open_tables_state(refresh_version), rli_fake(0),
lock_id(&main_lock_id), lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0), 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), arg_of_last_insert_id_function(FALSE),
first_successful_insert_id_in_prev_stmt(0), first_successful_insert_id_in_prev_stmt(0),
first_successful_insert_id_in_prev_stmt_for_binlog(0), first_successful_insert_id_in_prev_stmt_for_binlog(0),
...@@ -3118,6 +3118,23 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query, ...@@ -3118,6 +3118,23 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query,
to how you treat this. to how you treat this.
*/ */
case THD::STMT_QUERY_TYPE: 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 The MYSQL_LOG::write() function will set the STMT_END_F flag and
flush the pending rows event if necessary. flush the pending rows event if necessary.
......
...@@ -1110,6 +1110,17 @@ class THD :public Statement, ...@@ -1110,6 +1110,17 @@ class THD :public Statement,
private: private:
uint binlog_table_maps; // Number of table maps currently in the binlog 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: public:
uint get_binlog_table_maps() const { uint get_binlog_table_maps() const {
return binlog_table_maps; return binlog_table_maps;
...@@ -1680,6 +1691,7 @@ class THD :public Statement, ...@@ -1680,6 +1691,7 @@ class THD :public Statement,
void restore_sub_statement_state(Sub_statement_state *backup); void restore_sub_statement_state(Sub_statement_state *backup);
void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
void restore_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() inline void set_current_stmt_binlog_row_based_if_mixed()
{ {
/* /*
......
...@@ -1664,6 +1664,7 @@ class Delayed_insert :public ilink { ...@@ -1664,6 +1664,7 @@ class Delayed_insert :public ilink {
Statement-based replication of INSERT DELAYED has problems with RAND() Statement-based replication of INSERT DELAYED has problems with RAND()
and user vars, so in mixed mode we go to row-based. 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(); thd.set_current_stmt_binlog_row_based_if_mixed();
bzero((char*) &thd.net, sizeof(thd.net)); // Safety bzero((char*) &thd.net, sizeof(thd.net)); // Safety
......
...@@ -1782,7 +1782,7 @@ void Query_tables_list::reset_query_tables_list(bool init) ...@@ -1782,7 +1782,7 @@ void Query_tables_list::reset_query_tables_list(bool init)
sroutines_list.empty(); sroutines_list.empty();
sroutines_list_own_last= sroutines_list.next; sroutines_list_own_last= sroutines_list.next;
sroutines_list_own_elements= 0; sroutines_list_own_elements= 0;
binlog_row_based_if_mixed= FALSE; binlog_stmt_flags= 0;
} }
......
...@@ -950,14 +950,6 @@ class Query_tables_list ...@@ -950,14 +950,6 @@ class Query_tables_list
byte **sroutines_list_own_last; byte **sroutines_list_own_last;
uint sroutines_list_own_elements; 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 These constructor and destructor serve for creation/destruction
of Query_tables_list instances which are used as backup storage. of Query_tables_list instances which are used as backup storage.
...@@ -1005,12 +997,48 @@ class Query_tables_list ...@@ -1005,12 +997,48 @@ class Query_tables_list
query_tables_own_last= 0; 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 true if the parsed tree contains references to stored procedures
or functions, false otherwise or functions, false otherwise
*/ */
bool uses_stored_routines() const bool uses_stored_routines() const
{ return sroutines_list.elements != 0; } { 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;
}; };
......
...@@ -1118,8 +1118,8 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, ...@@ -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 If the view's body needs row-based binlogging (e.g. the VIEW is created
from SELECT UUID()), the top statement also needs it. from SELECT UUID()), the top statement also needs it.
*/ */
if (lex->binlog_row_based_if_mixed) if (lex->is_stmt_unsafe())
old_lex->binlog_row_based_if_mixed= TRUE; old_lex->set_stmt_unsafe();
view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE && view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
lex->can_be_merged()); lex->can_be_merged());
LINT_INIT(view_main_select_tables); LINT_INIT(view_main_select_tables);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment