Commit e485f8e1 authored by guilhem@mysql.com's avatar guilhem@mysql.com

Fixes to the replication mixed mode (patch approved by Monty):

- detect the need for row-based binlogging not at execution stage but earlier at parsing stage; needed for example for CREATE TABLE SELECT UUID().
- more tests of this mixed mode.
parent 91574a1d
...@@ -110,6 +110,11 @@ execute stmt1 using @string; ...@@ -110,6 +110,11 @@ execute stmt1 using @string;
deallocate prepare stmt1; deallocate prepare stmt1;
insert into t1 values(concat("for",UUID())); insert into t1 values(concat("for",UUID()));
insert into t1 select "yesterday"; insert into t1 select "yesterday";
create table t2 select UUID();
create table t3 select 1 union select UUID();
create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3);
create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
create procedure foo() create procedure foo()
begin begin
insert into t1 values("work"); insert into t1 values("work");
...@@ -137,6 +142,21 @@ select foo3(); ...@@ -137,6 +142,21 @@ select foo3();
ERROR HY000: Cannot change the binary logging format inside a stored function or trigger ERROR HY000: Cannot change the binary logging format inside a stored function or trigger
select * from t1 where a="alarm"; select * from t1 where a="alarm";
a a
select count(*) from t1;
count(*)
36
select count(*) from t2;
count(*)
1
select count(*) from t3;
count(*)
2
select count(*) from t4;
count(*)
29
select count(*) from t5;
count(*)
58
show binlog events from 102; show binlog events from 102;
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # drop database if exists mysqltest1 master-bin.000001 # Query 1 # drop database if exists mysqltest1
...@@ -179,17 +199,44 @@ master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' ...@@ -179,17 +199,44 @@ master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for") master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for")
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t2` (
`UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t3` (
`1` varbinary(108) NOT NULL DEFAULT ''
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t4` (
`a` varchar(100) DEFAULT NULL
)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t4)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT
master-bin.000001 # Query 1 # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3)
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t5)
master-bin.000001 # Write_rows 1 # table_id: #
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo() master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
begin begin
insert into t1 values("work"); insert into t1 values("work");
...@@ -212,10 +259,13 @@ insert into t1 values("alarm"); ...@@ -212,10 +259,13 @@ insert into t1 values("alarm");
return 100; return 100;
end end
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday" master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
......
...@@ -111,6 +111,15 @@ deallocate prepare stmt1; ...@@ -111,6 +111,15 @@ deallocate prepare stmt1;
insert into t1 values(concat("for",UUID())); insert into t1 values(concat("for",UUID()));
insert into t1 select "yesterday"; insert into t1 select "yesterday";
# Test of CREATE TABLE SELECT
create table t2 select UUID();
create table t3 select 1 union select UUID();
create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3);
create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
# what if UUID() is first:
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
# inside a stored procedure (inside a function or trigger won't # inside a stored procedure (inside a function or trigger won't
# work) # work)
...@@ -140,20 +149,60 @@ delimiter ;| ...@@ -140,20 +149,60 @@ delimiter ;|
call foo(); call foo();
call foo2(); call foo2();
# test that can't SET in a stored function if not in row-based mode # test that can't SET in a stored function
--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT --error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
select foo3(); select foo3();
select * from t1 where a="alarm"; select * from t1 where a="alarm";
# If you want to do manual testing of the mixed mode regarding UDFs (not
# testable automatically as quite platform- and compiler-dependent),
# you just need to set the variable below to 1, and to
# "make udf_example.so" in sql/, and to copy sql/udf_example.so to
# MYSQL_TEST_DIR/lib/mysql.
let $you_want_to_test_UDF=0;
if ($you_want_to_test_UDF)
{
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
prepare stmt1 from 'insert into t1 select metaphon(?)';
set @string="emergency";
insert into t1 values("work");
execute stmt1 using @string;
deallocate prepare stmt1;
prepare stmt1 from 'insert into t1 select ?';
insert into t1 values(metaphon("work"));
execute stmt1 using @string;
deallocate prepare stmt1;
insert into t1 values(metaphon("for"));
insert into t1 select "yesterday";
create table t6 select metaphon("for");
create table t7 select 1 union select metaphon("for");
create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for") union select 3);
create table t9 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
}
# and now compare: # and now compare:
# first check that data on master is sensible
select count(*) from t1;
select count(*) from t2;
select count(*) from t3;
select count(*) from t4;
select count(*) from t5;
if ($you_want_to_test_UDF)
{
select count(*) from t6;
select count(*) from t7;
select count(*) from t8;
select count(*) from t9;
}
--replace_column 2 # 5 # --replace_column 2 # 5 #
--replace_regex /table_id: [0-9]+/table_id: #/ --replace_regex /table_id: [0-9]+/table_id: #/
show binlog events from 102; show binlog events from 102;
sync_slave_with_master; sync_slave_with_master;
# as we're using UUID we don't SELECT but use "diff" like in rpl_row_UUID # as we're using UUID we don't SELECT but use "diff" like in rpl_row_UUID
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_row_UDF_master.sql --exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_row_UDF_slave.sql --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql
connection master; connection master;
drop database mysqltest1; drop database mysqltest1;
...@@ -164,4 +213,4 @@ sync_slave_with_master; ...@@ -164,4 +213,4 @@ sync_slave_with_master;
# will be created. You will need to go to the mysql-test dir and diff # will be created. You will need to go to the mysql-test dir and diff
# the files your self to see what is not matching # the files your self to see what is not matching
#--exec diff $MYSQLTEST_VARDIR/tmp/rpl_row_UDF_master.sql $MYSQLTEST_VARDIR/tmp/rpl_row_UDF_slave.sql; --exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
...@@ -431,7 +431,9 @@ Item *create_func_unhex(Item* a) ...@@ -431,7 +431,9 @@ Item *create_func_unhex(Item* a)
Item *create_func_uuid(void) Item *create_func_uuid(void)
{ {
return new Item_func_uuid(); THD *thd= current_thd;
thd->lex->binlog_row_based_if_mixed= 1;
return new(thd->mem_root) Item_func_uuid();
} }
Item *create_func_version(void) Item *create_func_version(void)
......
...@@ -2657,7 +2657,6 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, ...@@ -2657,7 +2657,6 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
u_d->name.str, ER(ER_UNKNOWN_ERROR)); u_d->name.str, ER(ER_UNKNOWN_ERROR));
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
thd->set_current_stmt_binlog_row_based_if_mixed();
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
......
...@@ -3002,7 +3002,6 @@ String *Item_func_uuid::val_str(String *str) ...@@ -3002,7 +3002,6 @@ String *Item_func_uuid::val_str(String *str)
char *s; char *s;
THD *thd= current_thd; THD *thd= current_thd;
thd->set_current_stmt_binlog_row_based_if_mixed();
pthread_mutex_lock(&LOCK_uuid_generator); pthread_mutex_lock(&LOCK_uuid_generator);
if (! uuid_time) /* first UUID() call. initializing data */ if (! uuid_time) /* first UUID() call. initializing data */
{ {
......
...@@ -1271,7 +1271,6 @@ bool sys_var_thd_binlog_format::is_readonly() const ...@@ -1271,7 +1271,6 @@ bool sys_var_thd_binlog_format::is_readonly() const
*/ */
if (thd->spcont && thd->prelocked_mode) if (thd->spcont && thd->prelocked_mode)
{ {
DBUG_ASSERT(thd->variables.binlog_format != BINLOG_FORMAT_ROW);
my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
return 1; return 1;
} }
......
...@@ -191,6 +191,7 @@ void lex_start(THD *thd, const uchar *buf, uint length) ...@@ -191,6 +191,7 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->nest_level=0 ; lex->nest_level=0 ;
lex->allow_sum_func= 0; lex->allow_sum_func= 0;
lex->in_sum_func= NULL; lex->in_sum_func= NULL;
lex->binlog_row_based_if_mixed= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -880,7 +880,11 @@ typedef struct st_lex ...@@ -880,7 +880,11 @@ typedef struct st_lex
uint8 create_view_check; uint8 create_view_check;
bool drop_if_exists, drop_temporary, local_file, one_shot_set; bool drop_if_exists, drop_temporary, local_file, one_shot_set;
bool in_comment, ignore_space, verbose, no_write_to_binlog; bool in_comment, ignore_space, verbose, no_write_to_binlog;
bool tx_chain, tx_release; /*
binlog_row_based_if_mixed tells if the parsing stage detected that some
items require row-based binlogging to give a reliable binlog/replication.
*/
bool tx_chain, tx_release, binlog_row_based_if_mixed;
/* /*
Special JOIN::prepare mode: changing of query is prohibited. Special JOIN::prepare mode: changing of query is prohibited.
When creating a view, we need to just check its syntax omitting When creating a view, we need to just check its syntax omitting
......
...@@ -2446,6 +2446,9 @@ mysql_execute_command(THD *thd) ...@@ -2446,6 +2446,9 @@ mysql_execute_command(THD *thd)
statistic_increment(thd->status_var.com_stat[lex->sql_command], statistic_increment(thd->status_var.com_stat[lex->sql_command],
&LOCK_status); &LOCK_status);
if (lex->binlog_row_based_if_mixed)
thd->set_current_stmt_binlog_row_based_if_mixed();
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_SELECT: case SQLCOM_SELECT:
{ {
...@@ -5065,6 +5068,8 @@ end_with_restore_list: ...@@ -5065,6 +5068,8 @@ end_with_restore_list:
send_ok(thd); send_ok(thd);
break; break;
} }
end:
thd->proc_info="query end"; thd->proc_info="query end";
/* /*
...@@ -5095,7 +5100,8 @@ end_with_restore_list: ...@@ -5095,7 +5100,8 @@ end_with_restore_list:
DBUG_RETURN(res || thd->net.report_error); DBUG_RETURN(res || thd->net.report_error);
error: error:
DBUG_RETURN(1); res= 1; // would be better to set res=1 before "goto error"
goto end;
} }
......
...@@ -6415,6 +6415,8 @@ simple_expr: ...@@ -6415,6 +6415,8 @@ simple_expr:
if (udf->type == UDFTYPE_AGGREGATE) if (udf->type == UDFTYPE_AGGREGATE)
Select->in_sum_expr--; Select->in_sum_expr--;
Lex->binlog_row_based_if_mixed= 1;
switch (udf->returns) { switch (udf->returns) {
case STRING_RESULT: case STRING_RESULT:
if (udf->type == UDFTYPE_FUNCTION) if (udf->type == UDFTYPE_FUNCTION)
......
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