mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge mysql.com:/nfsdisk1/lars/bkroot/mysql-5.1-new-rpl
into mysql.com:/nfsdisk1/lars/MERGE/mysql-5.1-merge client/mysqlbinlog.cc: Auto merged include/my_global.h: Auto merged mysql-test/t/disabled.def: Auto merged sql/field.cc: Auto merged sql/item_func.cc: Auto merged sql/log.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/slave.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_show.cc: Auto merged
This commit is contained in:
@ -486,18 +486,15 @@ write_event_header_and_base64(Log_event *ev, FILE *result_file,
|
||||
DBUG_ENTER("write_event_header_and_base64");
|
||||
/* Write header and base64 output to cache */
|
||||
IO_CACHE result_cache;
|
||||
if (init_io_cache(&result_cache, -1, 0, WRITE_CACHE, 0L, FALSE,
|
||||
MYF(MY_WME | MY_NABP)))
|
||||
{
|
||||
if (open_cached_file(&result_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
ev->print_header(&result_cache, print_event_info, FALSE);
|
||||
ev->print_base64(&result_cache, print_event_info, FALSE);
|
||||
|
||||
/* Read data from cache and write to result file */
|
||||
my_b_copy_to_file(&result_cache, result_file);
|
||||
end_io_cache(&result_cache);
|
||||
close_cached_file(&result_cache);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -1016,6 +1013,9 @@ static int dump_log_entries(const char* logname)
|
||||
{
|
||||
int rc;
|
||||
PRINT_EVENT_INFO print_event_info;
|
||||
|
||||
if (!print_event_info.init_ok())
|
||||
return 1;
|
||||
/*
|
||||
Set safe delimiter, to dump things
|
||||
like CREATE PROCEDURE safely
|
||||
|
@ -1479,4 +1479,11 @@ do { doubleget_union _tmp; \
|
||||
#define dlerror() ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
Include standard definitions of operator new and delete.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
#endif /* my_global_h */
|
||||
|
@ -413,3 +413,14 @@ select * from t1;
|
||||
insert into t1 values ('abc');
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#25815 Data truncated for column TEXT
|
||||
#
|
||||
set names utf8;
|
||||
create table t1 (a text) default character set cp932;
|
||||
insert into t1 values (_utf8 0xE38182);
|
||||
show warnings;
|
||||
select * from t1;
|
||||
select hex(a) from t1;
|
||||
drop table t1;
|
||||
|
86
mysql-test/extra/rpl_tests/rpl_insert_delayed.test
Normal file
86
mysql-test/extra/rpl_tests/rpl_insert_delayed.test
Normal file
@ -0,0 +1,86 @@
|
||||
# The two bugs below (BUG#25507 and BUG#26116) existed only in
|
||||
# statement-based binlogging; we test that now they are fixed;
|
||||
# we also test that mixed and row-based binlogging work too,
|
||||
# for completeness.
|
||||
|
||||
connection master;
|
||||
--disable_warnings
|
||||
CREATE SCHEMA IF NOT EXISTS mysqlslap;
|
||||
USE mysqlslap;
|
||||
--enable_warnings
|
||||
|
||||
select @@global.binlog_format;
|
||||
|
||||
#
|
||||
# BUG#25507 "multi-row insert delayed + auto increment causes
|
||||
# duplicate key entries on slave";
|
||||
# happened only in statement-based binlogging.
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (id INT primary key auto_increment, name VARCHAR(64));
|
||||
let $query = "INSERT DELAYED INTO t1 VALUES (null, 'Dr. No'), (null, 'From Russia With Love'), (null, 'Goldfinger'), (null, 'Thunderball'), (null, 'You Only Live Twice')";
|
||||
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=200 --query=$query --delimiter=";"
|
||||
|
||||
FLUSH TABLE t1; # another way to be sure INSERT DELAYED has inserted
|
||||
SELECT COUNT(*) FROM t1;
|
||||
# when bug existed slave failed below ("duplicate key" error at random INSERT)
|
||||
sync_slave_with_master;
|
||||
use mysqlslap;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
|
||||
#
|
||||
# BUG#26116 "If multi-row INSERT DELAYED has errors,
|
||||
# statement-based binlogging breaks";
|
||||
# happened only in statement-based binlogging.
|
||||
#
|
||||
|
||||
connection master;
|
||||
truncate table t1;
|
||||
# first scenario: duplicate on first row
|
||||
insert delayed into t1 values(10, "my name");
|
||||
if ($binlog_format_statement)
|
||||
{
|
||||
# statement below will be converted to non-delayed INSERT and so
|
||||
# will stop at first error, guaranteeing replication.
|
||||
--error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
|
||||
}
|
||||
if (!$binlog_format_statement)
|
||||
{
|
||||
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
|
||||
}
|
||||
flush table t1; # to wait for INSERT DELAYED to be done
|
||||
select * from t1;
|
||||
sync_slave_with_master;
|
||||
# when bug existed in statement-based binlogging, t1 on slave had
|
||||
# different content from on master
|
||||
select * from t1;
|
||||
|
||||
# second scenario: duplicate on second row
|
||||
connection master;
|
||||
delete from t1 where id!=10;
|
||||
if ($binlog_format_statement)
|
||||
{
|
||||
# statement below will be converted to non-delayed INSERT and so
|
||||
# will be binlogged with its ER_DUP_ENTRY error code, guaranteeing
|
||||
# replication (slave will hit the same error code and so be fine).
|
||||
--error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
|
||||
}
|
||||
if (!$binlog_format_statement)
|
||||
{
|
||||
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
|
||||
}
|
||||
flush table t1; # to wait for INSERT DELAYED to be done
|
||||
select * from t1;
|
||||
sync_slave_with_master;
|
||||
# when bug existed in statement-based binlogging, query was binlogged
|
||||
# with error_code=0 so slave stopped
|
||||
select * from t1;
|
||||
|
||||
# clean up
|
||||
connection master;
|
||||
USE test;
|
||||
DROP SCHEMA mysqlslap;
|
||||
sync_slave_with_master;
|
||||
connection master;
|
@ -209,7 +209,7 @@ connection master;
|
||||
|
||||
drop function bug15728;
|
||||
drop function bug15728_insert;
|
||||
drop table t1;
|
||||
drop table t1,t2;
|
||||
drop procedure foo;
|
||||
|
||||
# test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in
|
||||
@ -276,6 +276,59 @@ connection master;
|
||||
drop table t1;
|
||||
sync_slave_with_master;
|
||||
|
||||
#
|
||||
# BUG#24432 "INSERT... ON DUPLICATE KEY UPDATE skips auto_increment values"
|
||||
#
|
||||
|
||||
connection master;
|
||||
# testcase with INSERT VALUES
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
|
||||
UNIQUE(b));
|
||||
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
|
||||
SELECT * FROM t1;
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1;
|
||||
connection master;
|
||||
drop table t1;
|
||||
|
||||
# tescase with INSERT SELECT
|
||||
CREATE TABLE t1 (
|
||||
id bigint(20) unsigned NOT NULL auto_increment,
|
||||
field_1 int(10) unsigned NOT NULL,
|
||||
field_2 varchar(255) NOT NULL,
|
||||
field_3 varchar(255) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY field_1 (field_1, field_2)
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
field_a int(10) unsigned NOT NULL,
|
||||
field_b varchar(255) NOT NULL,
|
||||
field_c varchar(255) NOT NULL
|
||||
);
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e');
|
||||
# Updating table t1 based on values from table t2
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
# Inserting new record into t2
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f');
|
||||
# Updating t1 again
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
SELECT * FROM t1;
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1;
|
||||
connection master;
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# BUG#20339: stored procedure using LAST_INSERT_ID() does not
|
||||
|
@ -11353,3 +11353,15 @@ a
|
||||
a
|
||||
a
|
||||
drop table t1;
|
||||
set names utf8;
|
||||
create table t1 (a text) default character set cp932;
|
||||
insert into t1 values (_utf8 0xE38182);
|
||||
show warnings;
|
||||
Level Code Message
|
||||
select * from t1;
|
||||
a
|
||||
あ
|
||||
select hex(a) from t1;
|
||||
hex(a)
|
||||
82A0
|
||||
drop table t1;
|
||||
|
@ -11353,3 +11353,15 @@ a
|
||||
a
|
||||
a
|
||||
drop table t1;
|
||||
set names utf8;
|
||||
create table t1 (a text) default character set cp932;
|
||||
insert into t1 values (_utf8 0xE38182);
|
||||
show warnings;
|
||||
Level Code Message
|
||||
select * from t1;
|
||||
a
|
||||
あ
|
||||
select hex(a) from t1;
|
||||
hex(a)
|
||||
82A0
|
||||
drop table t1;
|
||||
|
@ -2,11 +2,11 @@ drop table if exists t1;
|
||||
create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
|
||||
select * from t1;
|
||||
c1 c2 stamp
|
||||
replace delayed into t1 (c1, c2) values ( "text1","11"),( "text2","12");
|
||||
replace delayed into t1 (c1, c2) values ( "text1","11");
|
||||
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||
select * from t1;
|
||||
c1 c2 stamp
|
||||
replace delayed into t1 (c1, c2) values ( "text1","12"),( "text2","13"),( "text3","14", "a" ),( "text4","15", "b" );
|
||||
replace delayed into t1 (c1, c2) values ( "text1","12");
|
||||
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||
select * from t1;
|
||||
c1 c2 stamp
|
||||
|
@ -86,5 +86,25 @@ Aberdeen
|
||||
Abernathy
|
||||
aberrant
|
||||
aberration
|
||||
flush logs;
|
||||
drop table t2;
|
||||
create table t2 (word varchar(20));
|
||||
load data infile '../std_data_ln/words.dat' into table t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
select count(*) from t2;
|
||||
count(*)
|
||||
35840
|
||||
flush logs;
|
||||
select count(*) from t2;
|
||||
count(*)
|
||||
35840
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
@ -196,7 +196,7 @@ id last_id
|
||||
3 5
|
||||
drop function bug15728;
|
||||
drop function bug15728_insert;
|
||||
drop table t1;
|
||||
drop table t1,t2;
|
||||
drop procedure foo;
|
||||
create table t1 (n int primary key auto_increment not null,
|
||||
b int, unique(b));
|
||||
@ -263,6 +263,64 @@ n b
|
||||
2 100
|
||||
3 350
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
|
||||
UNIQUE(b));
|
||||
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 10
|
||||
2 2
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 10
|
||||
2 2
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (
|
||||
id bigint(20) unsigned NOT NULL auto_increment,
|
||||
field_1 int(10) unsigned NOT NULL,
|
||||
field_2 varchar(255) NOT NULL,
|
||||
field_3 varchar(255) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY field_1 (field_1, field_2)
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
field_a int(10) unsigned NOT NULL,
|
||||
field_b varchar(255) NOT NULL,
|
||||
field_c varchar(255) NOT NULL
|
||||
);
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e');
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f');
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
SELECT * FROM t1;
|
||||
id field_1 field_2 field_3
|
||||
1 1 a 1a
|
||||
2 2 b 2b
|
||||
3 3 c 3c
|
||||
4 4 d 4d
|
||||
5 5 e 5e
|
||||
6 6 f 6f
|
||||
SELECT * FROM t1;
|
||||
id field_1 field_2 field_3
|
||||
1 1 a 1a
|
||||
2 2 b 2b
|
||||
3 3 c 3c
|
||||
4 4 d 4d
|
||||
5 5 e 5e
|
||||
6 6 f 6f
|
||||
drop table t1, t2;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
SELECT LAST_INSERT_ID(0);
|
||||
|
133
mysql-test/r/rpl_known_bugs_detection.result
Normal file
133
mysql-test/r/rpl_known_bugs_detection.result
Normal file
@ -0,0 +1,133 @@
|
||||
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;
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
|
||||
UNIQUE(b));
|
||||
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 10
|
||||
2 2
|
||||
show slave status;;
|
||||
Slave_IO_State #
|
||||
Master_Host 127.0.0.1
|
||||
Master_User root
|
||||
Master_Port #
|
||||
Connect_Retry 1
|
||||
Master_Log_File master-bin.000001
|
||||
Read_Master_Log_Pos #
|
||||
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 1105
|
||||
Last_Error Error 'master may suffer from http://bugs.mysql.com/bug.php?id=24432 so slave stops; check error log on slave for more info' on query. Default database: 'test'. Query: 'INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10'
|
||||
Skip_Counter 0
|
||||
Exec_Master_Log_Pos 242
|
||||
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 #
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
stop slave;
|
||||
reset slave;
|
||||
reset master;
|
||||
drop table t1;
|
||||
start slave;
|
||||
CREATE TABLE t1 (
|
||||
id bigint(20) unsigned NOT NULL auto_increment,
|
||||
field_1 int(10) unsigned NOT NULL,
|
||||
field_2 varchar(255) NOT NULL,
|
||||
field_3 varchar(255) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY field_1 (field_1, field_2)
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
field_a int(10) unsigned NOT NULL,
|
||||
field_b varchar(255) NOT NULL,
|
||||
field_c varchar(255) NOT NULL
|
||||
);
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e');
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f');
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
SELECT * FROM t1;
|
||||
id field_1 field_2 field_3
|
||||
1 1 a 1a
|
||||
2 2 b 2b
|
||||
3 3 c 3c
|
||||
4 4 d 4d
|
||||
5 5 e 5e
|
||||
6 6 f 6f
|
||||
show slave status;;
|
||||
Slave_IO_State #
|
||||
Master_Host 127.0.0.1
|
||||
Master_User root
|
||||
Master_Port #
|
||||
Connect_Retry 1
|
||||
Master_Log_File master-bin.000001
|
||||
Read_Master_Log_Pos #
|
||||
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 1105
|
||||
Last_Error Error 'master may suffer from http://bugs.mysql.com/bug.php?id=24432 so slave stops; check error log on slave for more info' on query. Default database: 'test'. Query: 'INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c'
|
||||
Skip_Counter 0
|
||||
Exec_Master_Log_Pos 1274
|
||||
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 #
|
||||
SELECT * FROM t1;
|
||||
id field_1 field_2 field_3
|
||||
drop table t1, t2;
|
||||
drop table t1, t2;
|
48
mysql-test/r/rpl_row_insert_delayed.result
Normal file
48
mysql-test/r/rpl_row_insert_delayed.result
Normal file
@ -0,0 +1,48 @@
|
||||
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;
|
||||
set @old_global_binlog_format = @@global.binlog_format;
|
||||
set @@global.binlog_format = row;
|
||||
CREATE SCHEMA IF NOT EXISTS mysqlslap;
|
||||
USE mysqlslap;
|
||||
select @@global.binlog_format;
|
||||
@@global.binlog_format
|
||||
ROW
|
||||
CREATE TABLE t1 (id INT primary key auto_increment, name VARCHAR(64));
|
||||
FLUSH TABLE t1;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
use mysqlslap;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
truncate table t1;
|
||||
insert delayed into t1 values(10, "my name");
|
||||
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 James Bond
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 James Bond
|
||||
delete from t1 where id!=10;
|
||||
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 is Bond
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 is Bond
|
||||
USE test;
|
||||
DROP SCHEMA mysqlslap;
|
||||
set @@global.binlog_format = @old_global_binlog_format;
|
88
mysql-test/r/rpl_stm_insert_delayed.result
Normal file
88
mysql-test/r/rpl_stm_insert_delayed.result
Normal file
@ -0,0 +1,88 @@
|
||||
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;
|
||||
set @old_global_binlog_format = @@global.binlog_format;
|
||||
set @@global.binlog_format = statement;
|
||||
CREATE SCHEMA IF NOT EXISTS mysqlslap;
|
||||
USE mysqlslap;
|
||||
select @@global.binlog_format;
|
||||
@@global.binlog_format
|
||||
STATEMENT
|
||||
CREATE TABLE t1 (id INT primary key auto_increment, name VARCHAR(64));
|
||||
FLUSH TABLE t1;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
use mysqlslap;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
truncate table t1;
|
||||
insert delayed into t1 values(10, "my name");
|
||||
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
|
||||
ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
delete from t1 where id!=10;
|
||||
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
|
||||
ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 is Bond
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 is Bond
|
||||
USE test;
|
||||
DROP SCHEMA mysqlslap;
|
||||
set @@global.binlog_format = mixed;
|
||||
CREATE SCHEMA IF NOT EXISTS mysqlslap;
|
||||
USE mysqlslap;
|
||||
select @@global.binlog_format;
|
||||
@@global.binlog_format
|
||||
MIXED
|
||||
CREATE TABLE t1 (id INT primary key auto_increment, name VARCHAR(64));
|
||||
FLUSH TABLE t1;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
use mysqlslap;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
truncate table t1;
|
||||
insert delayed into t1 values(10, "my name");
|
||||
insert delayed into t1 values(10, "is Bond"), (20, "James Bond");
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 James Bond
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 James Bond
|
||||
delete from t1 where id!=10;
|
||||
insert delayed into t1 values(20, "is Bond"), (10, "James Bond");
|
||||
flush table t1;
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 is Bond
|
||||
select * from t1;
|
||||
id name
|
||||
10 my name
|
||||
20 is Bond
|
||||
USE test;
|
||||
DROP SCHEMA mysqlslap;
|
||||
set @@global.binlog_format = @old_global_binlog_format;
|
@ -7,8 +7,31 @@ start slave;
|
||||
drop database if exists mysqltest1;
|
||||
create database mysqltest1;
|
||||
use mysqltest1;
|
||||
set session binlog_format=mixed;
|
||||
show session variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format MIXED
|
||||
set session binlog_format=statement;
|
||||
show session variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format STATEMENT
|
||||
set session binlog_format=row;
|
||||
set global binlog_format=row;
|
||||
show session variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format ROW
|
||||
set global binlog_format=DEFAULT;
|
||||
show global variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format MIXED
|
||||
set global binlog_format=MIXED;
|
||||
show global variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format MIXED
|
||||
set global binlog_format=STATEMENT;
|
||||
show global variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format STATEMENT
|
||||
set global binlog_format=ROW;
|
||||
show global variables like "binlog_format%";
|
||||
Variable_name Value
|
||||
binlog_format ROW
|
||||
@ -67,12 +90,11 @@ execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values("for_10_");
|
||||
insert into t1 select "yesterday_11_";
|
||||
set binlog_format=default;
|
||||
set binlog_format=statement;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@@global.binlog_format @@session.binlog_format
|
||||
STATEMENT STATEMENT
|
||||
set global binlog_format=default;
|
||||
ERROR 42000: Variable 'binlog_format' doesn't have a default value
|
||||
set global binlog_format=statement;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@@global.binlog_format @@session.binlog_format
|
||||
STATEMENT STATEMENT
|
||||
@ -87,11 +109,11 @@ execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values("for_15_");
|
||||
insert into t1 select "yesterday_16_";
|
||||
set binlog_format=mixed;
|
||||
set global binlog_format=mixed;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@@global.binlog_format @@session.binlog_format
|
||||
STATEMENT MIXED
|
||||
set global binlog_format=mixed;
|
||||
MIXED STATEMENT
|
||||
set binlog_format=default;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@@global.binlog_format @@session.binlog_format
|
||||
MIXED MIXED
|
||||
|
@ -730,4 +730,12 @@ show keys from `mysqlttest\1`.`a\b`;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
drop table `mysqlttest\1`.`a\b`;
|
||||
drop database `mysqlttest\1`;
|
||||
set names utf8;
|
||||
drop table if exists `été`;
|
||||
create table `été` (field1 int);
|
||||
show full tables;
|
||||
Tables_in_test Table_type
|
||||
été BASE TABLE
|
||||
drop table `été`;
|
||||
set names latin1;
|
||||
End of 5.1 tests
|
||||
|
@ -809,3 +809,78 @@ ExtractValue(@xml, "/entry[(50<pt)]/id")
|
||||
select ExtractValue(@xml, "/entry[(50<=pt)]/id");
|
||||
ExtractValue(@xml, "/entry[(50<=pt)]/id")
|
||||
pt50
|
||||
select ExtractValue('<a><b><Text>test</Text></b></a>','/a/b/Text');
|
||||
ExtractValue('<a><b><Text>test</Text></b></a>','/a/b/Text')
|
||||
test
|
||||
select ExtractValue('<a><b><comment>test</comment></b></a>','/a/b/comment');
|
||||
ExtractValue('<a><b><comment>test</comment></b></a>','/a/b/comment')
|
||||
test
|
||||
select ExtractValue('<a><b><node>test</node></b></a>','/a/b/node');
|
||||
ExtractValue('<a><b><node>test</node></b></a>','/a/b/node')
|
||||
test
|
||||
select ExtractValue('<a><b><processing-instruction>test</processing-instruction></b></a>','/a/b/processing-instruction');
|
||||
ExtractValue('<a><b><processing-instruction>test</processing-instruction></b></a>','/a/b/processing-instruction')
|
||||
test
|
||||
select ExtractValue('<a><and>test</and></a>', '/a/and');
|
||||
ExtractValue('<a><and>test</and></a>', '/a/and')
|
||||
test
|
||||
select ExtractValue('<a><or>test</or></a>', '/a/or');
|
||||
ExtractValue('<a><or>test</or></a>', '/a/or')
|
||||
test
|
||||
select ExtractValue('<a><mod>test</mod></a>', '/a/mod');
|
||||
ExtractValue('<a><mod>test</mod></a>', '/a/mod')
|
||||
test
|
||||
select ExtractValue('<a><div>test</div></a>', '/a/div');
|
||||
ExtractValue('<a><div>test</div></a>', '/a/div')
|
||||
test
|
||||
select ExtractValue('<a><and:and>test</and:and></a>', '/a/and:and');
|
||||
ExtractValue('<a><and:and>test</and:and></a>', '/a/and:and')
|
||||
test
|
||||
select ExtractValue('<a><or:or>test</or:or></a>', '/a/or:or');
|
||||
ExtractValue('<a><or:or>test</or:or></a>', '/a/or:or')
|
||||
test
|
||||
select ExtractValue('<a><mod:mod>test</mod:mod></a>', '/a/mod:mod');
|
||||
ExtractValue('<a><mod:mod>test</mod:mod></a>', '/a/mod:mod')
|
||||
test
|
||||
select ExtractValue('<a><div:div>test</div:div></a>', '/a/div:div');
|
||||
ExtractValue('<a><div:div>test</div:div></a>', '/a/div:div')
|
||||
test
|
||||
select ExtractValue('<a><ancestor>test</ancestor></a>', '/a/ancestor');
|
||||
ExtractValue('<a><ancestor>test</ancestor></a>', '/a/ancestor')
|
||||
test
|
||||
select ExtractValue('<a><ancestor-or-self>test</ancestor-or-self></a>', '/a/ancestor-or-self');
|
||||
ExtractValue('<a><ancestor-or-self>test</ancestor-or-self></a>', '/a/ancestor-or-self')
|
||||
test
|
||||
select ExtractValue('<a><attribute>test</attribute></a>', '/a/attribute');
|
||||
ExtractValue('<a><attribute>test</attribute></a>', '/a/attribute')
|
||||
test
|
||||
select ExtractValue('<a><child>test</child></a>', '/a/child');
|
||||
ExtractValue('<a><child>test</child></a>', '/a/child')
|
||||
test
|
||||
select ExtractValue('<a><descendant>test</descendant></a>', '/a/descendant');
|
||||
ExtractValue('<a><descendant>test</descendant></a>', '/a/descendant')
|
||||
test
|
||||
select ExtractValue('<a><descendant-or-self>test</descendant-or-self></a>', '/a/descendant-or-self');
|
||||
ExtractValue('<a><descendant-or-self>test</descendant-or-self></a>', '/a/descendant-or-self')
|
||||
test
|
||||
select ExtractValue('<a><following>test</following></a>', '/a/following');
|
||||
ExtractValue('<a><following>test</following></a>', '/a/following')
|
||||
test
|
||||
select ExtractValue('<a><following-sibling>test</following-sibling></a>', '/a/following-sibling');
|
||||
ExtractValue('<a><following-sibling>test</following-sibling></a>', '/a/following-sibling')
|
||||
test
|
||||
select ExtractValue('<a><namespace>test</namespace></a>', '/a/namespace');
|
||||
ExtractValue('<a><namespace>test</namespace></a>', '/a/namespace')
|
||||
test
|
||||
select ExtractValue('<a><parent>test</parent></a>', '/a/parent');
|
||||
ExtractValue('<a><parent>test</parent></a>', '/a/parent')
|
||||
test
|
||||
select ExtractValue('<a><preceding>test</preceding></a>', '/a/preceding');
|
||||
ExtractValue('<a><preceding>test</preceding></a>', '/a/preceding')
|
||||
test
|
||||
select ExtractValue('<a><preceding-sibling>test</preceding-sibling></a>', '/a/preceding-sibling');
|
||||
ExtractValue('<a><preceding-sibling>test</preceding-sibling></a>', '/a/preceding-sibling')
|
||||
test
|
||||
select ExtractValue('<a><self>test</self></a>', '/a/self');
|
||||
ExtractValue('<a><self>test</self></a>', '/a/self')
|
||||
test
|
||||
|
@ -12,10 +12,10 @@ drop table if exists t1;
|
||||
create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
|
||||
select * from t1;
|
||||
--error 1031
|
||||
replace delayed into t1 (c1, c2) values ( "text1","11"),( "text2","12");
|
||||
replace delayed into t1 (c1, c2) values ( "text1","11");
|
||||
select * from t1;
|
||||
--error 1031
|
||||
replace delayed into t1 (c1, c2) values ( "text1","12"),( "text2","13"),( "text3","14", "a" ),( "text4","15", "b" );
|
||||
replace delayed into t1 (c1, c2) values ( "text1","12");
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
|
@ -31,6 +31,34 @@ drop table t2;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
|
||||
#
|
||||
# Verify that events larger than the default IO_CACHE buffer
|
||||
# are handled correctly (BUG#25628).
|
||||
#
|
||||
flush logs;
|
||||
drop table t2;
|
||||
create table t2 (word varchar(20));
|
||||
load data infile '../std_data_ln/words.dat' into table t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
insert into t2 select * from t2;
|
||||
select count(*) from t2;
|
||||
|
||||
flush logs;
|
||||
--exec $MYSQL_BINLOG --hexdump $MYSQLTEST_VARDIR/log/master-bin.000003 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
|
||||
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
|
||||
|
||||
#
|
||||
# Verify that all binlog events have been executed
|
||||
#
|
||||
select count(*) from t2;
|
||||
|
||||
#
|
||||
# Test cleanup
|
||||
#
|
||||
|
1
mysql-test/t/rpl_known_bugs_detection-master.opt
Normal file
1
mysql-test/t/rpl_known_bugs_detection-master.opt
Normal file
@ -0,0 +1 @@
|
||||
--loose-debug=d,pretend_version_50034_in_binlog
|
93
mysql-test/t/rpl_known_bugs_detection.test
Normal file
93
mysql-test/t/rpl_known_bugs_detection.test
Normal file
@ -0,0 +1,93 @@
|
||||
# Test to see if slave can detect certain known bugs present
|
||||
# on the master, and appropriately decides to stop
|
||||
# (assuming the bug is fixed in the slave, slave cannot of course
|
||||
# imitate the bug, so it has to stop).
|
||||
|
||||
source include/have_debug.inc;
|
||||
source include/master-slave.inc;
|
||||
|
||||
# Currently only statement-based-specific bugs are here
|
||||
-- source include/have_binlog_format_mixed_or_statement.inc
|
||||
|
||||
#
|
||||
# This is to test that slave properly detects if
|
||||
# master may suffer from:
|
||||
# BUG#24432 "INSERT... ON DUPLICATE KEY UPDATE skips auto_increment values"
|
||||
# (i.e. on master, INSERT ON DUPLICATE KEY UPDATE is used and manipulates
|
||||
# an auto_increment column, and is binlogged statement-based).
|
||||
#
|
||||
|
||||
# testcase with INSERT VALUES
|
||||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
|
||||
UNIQUE(b));
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
|
||||
SELECT * FROM t1;
|
||||
connection slave;
|
||||
wait_for_slave_to_stop;
|
||||
# show the error message
|
||||
--replace_column 1 # 4 # 7 # 8 # 9 # 23 # 33 #
|
||||
--query_vertical show slave status;
|
||||
# show that it was not replicated
|
||||
SELECT * FROM t1;
|
||||
|
||||
# restart replication for the next testcase
|
||||
stop slave;
|
||||
reset slave;
|
||||
connection master;
|
||||
reset master;
|
||||
drop table t1;
|
||||
connection slave;
|
||||
start slave;
|
||||
|
||||
# testcase with INSERT SELECT
|
||||
connection master;
|
||||
CREATE TABLE t1 (
|
||||
id bigint(20) unsigned NOT NULL auto_increment,
|
||||
field_1 int(10) unsigned NOT NULL,
|
||||
field_2 varchar(255) NOT NULL,
|
||||
field_3 varchar(255) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY field_1 (field_1, field_2)
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
field_a int(10) unsigned NOT NULL,
|
||||
field_b varchar(255) NOT NULL,
|
||||
field_c varchar(255) NOT NULL
|
||||
);
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d');
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e');
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
# Updating table t1 based on values from table t2
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
# Inserting new record into t2
|
||||
INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f');
|
||||
# Updating t1 again
|
||||
INSERT INTO t1 (field_1, field_2, field_3)
|
||||
SELECT t2.field_a, t2.field_b, t2.field_c
|
||||
FROM t2
|
||||
ON DUPLICATE KEY UPDATE
|
||||
t1.field_3 = t2.field_c;
|
||||
SELECT * FROM t1;
|
||||
connection slave;
|
||||
wait_for_slave_to_stop;
|
||||
# show the error message
|
||||
--replace_column 1 # 4 # 7 # 8 # 9 # 23 # 33 #
|
||||
--query_vertical show slave status;
|
||||
# show that it was not replicated
|
||||
SELECT * FROM t1;
|
||||
connection master;
|
||||
drop table t1, t2;
|
||||
connection slave;
|
||||
drop table t1, t2;
|
||||
|
||||
# End of 5.0 tests
|
14
mysql-test/t/rpl_row_insert_delayed.test
Normal file
14
mysql-test/t/rpl_row_insert_delayed.test
Normal file
@ -0,0 +1,14 @@
|
||||
--source include/have_binlog_format_row.inc
|
||||
--source include/master-slave.inc
|
||||
--source include/not_embedded.inc
|
||||
--source include/not_windows.inc
|
||||
|
||||
connection master;
|
||||
set @old_global_binlog_format = @@global.binlog_format;
|
||||
|
||||
let $binlog_format_statement=0;
|
||||
set @@global.binlog_format = row;
|
||||
--source extra/rpl_tests/rpl_insert_delayed.test
|
||||
|
||||
connection master;
|
||||
set @@global.binlog_format = @old_global_binlog_format;
|
20
mysql-test/t/rpl_stm_insert_delayed.test
Normal file
20
mysql-test/t/rpl_stm_insert_delayed.test
Normal file
@ -0,0 +1,20 @@
|
||||
# we run first in statement-based then in mixed binlogging
|
||||
|
||||
--source include/have_binlog_format_mixed_or_statement.inc
|
||||
--source include/master-slave.inc
|
||||
--source include/not_embedded.inc
|
||||
--source include/not_windows.inc
|
||||
|
||||
connection master;
|
||||
set @old_global_binlog_format = @@global.binlog_format;
|
||||
|
||||
let $binlog_format_statement=1;
|
||||
set @@global.binlog_format = statement;
|
||||
--source extra/rpl_tests/rpl_insert_delayed.test
|
||||
|
||||
let $binlog_format_statement=0;
|
||||
set @@global.binlog_format = mixed;
|
||||
--source extra/rpl_tests/rpl_insert_delayed.test
|
||||
|
||||
connection master;
|
||||
set @@global.binlog_format = @old_global_binlog_format;
|
@ -1,3 +1,14 @@
|
||||
#
|
||||
# rpl_switch_stm_row_mixed tests covers
|
||||
#
|
||||
# - switching explicitly between STATEMENT, ROW, and MIXED binlog format
|
||||
# showing when it is possible and when not.
|
||||
# - switching from MIXED to RBR implicitly listing all use cases,
|
||||
# e.g a query invokes UUID(), thereafter to serve as the definition
|
||||
# of MIXED binlog format
|
||||
# - correctness of execution
|
||||
|
||||
|
||||
-- source include/not_ndb_default.inc
|
||||
-- source include/master-slave.inc
|
||||
|
||||
@ -8,9 +19,22 @@ create database mysqltest1;
|
||||
--enable_warnings
|
||||
use mysqltest1;
|
||||
|
||||
set session binlog_format=row;
|
||||
set global binlog_format=row;
|
||||
|
||||
# play with switching
|
||||
set session binlog_format=mixed;
|
||||
show session variables like "binlog_format%";
|
||||
set session binlog_format=statement;
|
||||
show session variables like "binlog_format%";
|
||||
set session binlog_format=row;
|
||||
show session variables like "binlog_format%";
|
||||
|
||||
set global binlog_format=DEFAULT;
|
||||
show global variables like "binlog_format%";
|
||||
set global binlog_format=MIXED;
|
||||
show global variables like "binlog_format%";
|
||||
set global binlog_format=STATEMENT;
|
||||
show global variables like "binlog_format%";
|
||||
set global binlog_format=ROW;
|
||||
show global variables like "binlog_format%";
|
||||
show session variables like "binlog_format%";
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@ -63,12 +87,10 @@ deallocate prepare stmt1;
|
||||
insert into t1 values("for_10_");
|
||||
insert into t1 select "yesterday_11_";
|
||||
|
||||
# test SET DEFAULT (=statement at this point of test)
|
||||
set binlog_format=default;
|
||||
# test statement (is not default after wl#3368)
|
||||
set binlog_format=statement;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
# due to cluster it's hard to set back to default
|
||||
--error ER_NO_DEFAULT
|
||||
set global binlog_format=default;
|
||||
set global binlog_format=statement;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
@ -87,10 +109,10 @@ insert into t1 select "yesterday_16_";
|
||||
|
||||
# and now the mixed mode
|
||||
|
||||
set binlog_format=mixed;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
set global binlog_format=mixed;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
set binlog_format=default;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
|
||||
set @string="emergency_17_";
|
||||
|
@ -563,4 +563,16 @@ show keys from `mysqlttest\1`.`a\b`;
|
||||
drop table `mysqlttest\1`.`a\b`;
|
||||
drop database `mysqlttest\1`;
|
||||
|
||||
#
|
||||
# Bug#25081 SHOW FULL TABLES on table with latin chars in name fails
|
||||
#
|
||||
set names utf8;
|
||||
--disable_warnings
|
||||
drop table if exists `été`;
|
||||
--enable_warnings
|
||||
create table `été` (field1 int);
|
||||
show full tables;
|
||||
drop table `été`;
|
||||
set names latin1;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
@ -406,3 +406,41 @@ select ExtractValue(@xml, "/entry[(50>pt)]/id");
|
||||
select ExtractValue(@xml, "/entry[(50>=pt)]/id");
|
||||
select ExtractValue(@xml, "/entry[(50<pt)]/id");
|
||||
select ExtractValue(@xml, "/entry[(50<=pt)]/id");
|
||||
|
||||
#
|
||||
# Bug#24747 XPath error with the node name "Text"
|
||||
#
|
||||
#
|
||||
# Test nodetypes in node name context
|
||||
#
|
||||
select ExtractValue('<a><b><Text>test</Text></b></a>','/a/b/Text');
|
||||
select ExtractValue('<a><b><comment>test</comment></b></a>','/a/b/comment');
|
||||
select ExtractValue('<a><b><node>test</node></b></a>','/a/b/node');
|
||||
select ExtractValue('<a><b><processing-instruction>test</processing-instruction></b></a>','/a/b/processing-instruction');
|
||||
#
|
||||
# Test keywords in node name contexts
|
||||
#
|
||||
select ExtractValue('<a><and>test</and></a>', '/a/and');
|
||||
select ExtractValue('<a><or>test</or></a>', '/a/or');
|
||||
select ExtractValue('<a><mod>test</mod></a>', '/a/mod');
|
||||
select ExtractValue('<a><div>test</div></a>', '/a/div');
|
||||
select ExtractValue('<a><and:and>test</and:and></a>', '/a/and:and');
|
||||
select ExtractValue('<a><or:or>test</or:or></a>', '/a/or:or');
|
||||
select ExtractValue('<a><mod:mod>test</mod:mod></a>', '/a/mod:mod');
|
||||
select ExtractValue('<a><div:div>test</div:div></a>', '/a/div:div');
|
||||
#
|
||||
# Test axis names in node name context
|
||||
#
|
||||
select ExtractValue('<a><ancestor>test</ancestor></a>', '/a/ancestor');
|
||||
select ExtractValue('<a><ancestor-or-self>test</ancestor-or-self></a>', '/a/ancestor-or-self');
|
||||
select ExtractValue('<a><attribute>test</attribute></a>', '/a/attribute');
|
||||
select ExtractValue('<a><child>test</child></a>', '/a/child');
|
||||
select ExtractValue('<a><descendant>test</descendant></a>', '/a/descendant');
|
||||
select ExtractValue('<a><descendant-or-self>test</descendant-or-self></a>', '/a/descendant-or-self');
|
||||
select ExtractValue('<a><following>test</following></a>', '/a/following');
|
||||
select ExtractValue('<a><following-sibling>test</following-sibling></a>', '/a/following-sibling');
|
||||
select ExtractValue('<a><namespace>test</namespace></a>', '/a/namespace');
|
||||
select ExtractValue('<a><parent>test</parent></a>', '/a/parent');
|
||||
select ExtractValue('<a><preceding>test</preceding></a>', '/a/preceding');
|
||||
select ExtractValue('<a><preceding-sibling>test</preceding-sibling></a>', '/a/preceding-sibling');
|
||||
select ExtractValue('<a><self>test</self></a>', '/a/self');
|
||||
|
@ -50,7 +50,6 @@
|
||||
int
|
||||
my_b_copy_to_file(IO_CACHE *cache, FILE *file)
|
||||
{
|
||||
byte buf[IO_SIZE];
|
||||
uint bytes_in_cache;
|
||||
DBUG_ENTER("my_b_copy_to_file");
|
||||
|
||||
@ -58,19 +57,17 @@ my_b_copy_to_file(IO_CACHE *cache, FILE *file)
|
||||
if (reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE))
|
||||
DBUG_RETURN(1);
|
||||
bytes_in_cache= my_b_bytes_in_cache(cache);
|
||||
while (bytes_in_cache > 0) {
|
||||
uint const read_bytes= min(bytes_in_cache, sizeof(buf));
|
||||
DBUG_PRINT("debug", ("Remaining %u bytes - Reading %u bytes",
|
||||
bytes_in_cache, read_bytes));
|
||||
if (my_b_read(cache, buf, read_bytes))
|
||||
do
|
||||
{
|
||||
if (my_fwrite(file, cache->read_pos, bytes_in_cache,
|
||||
MYF(MY_WME | MY_NABP)) == (uint) -1)
|
||||
DBUG_RETURN(1);
|
||||
if (my_fwrite(file, buf, read_bytes, MYF(MY_WME | MY_NABP)) == (uint) -1)
|
||||
DBUG_RETURN(1);
|
||||
bytes_in_cache -= read_bytes;
|
||||
}
|
||||
cache->read_pos= cache->read_end;
|
||||
} while ((bytes_in_cache= my_b_fill(cache)));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
my_off_t my_b_append_tell(IO_CACHE* info)
|
||||
{
|
||||
/*
|
||||
|
@ -7203,7 +7203,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
cannot_convert_error_pos, from + length))
|
||||
return 2;
|
||||
|
||||
if (copy_length < length)
|
||||
if (from_end_pos < from + length)
|
||||
{
|
||||
report_data_too_long(this);
|
||||
return 2;
|
||||
|
@ -1044,12 +1044,12 @@ static struct my_xpath_keyword_names_st my_keyword_names[] =
|
||||
{MY_XPATH_LEX_OR , "or" , 2, 0 },
|
||||
{MY_XPATH_LEX_DIV , "div" , 3, 0 },
|
||||
{MY_XPATH_LEX_MOD , "mod" , 3, 0 },
|
||||
{0,NULL,0,0}
|
||||
};
|
||||
|
||||
{MY_XPATH_LEX_NODETYPE, "comment" , 7, 0 },
|
||||
{MY_XPATH_LEX_NODETYPE, "text" , 4, 0 },
|
||||
{MY_XPATH_LEX_NODETYPE, "processing-instruction" , 22,0 },
|
||||
{MY_XPATH_LEX_NODETYPE, "node" , 4, 0 },
|
||||
|
||||
static struct my_xpath_keyword_names_st my_axis_names[]=
|
||||
{
|
||||
{MY_XPATH_LEX_AXIS,"ancestor" , 8,MY_XPATH_AXIS_ANCESTOR },
|
||||
{MY_XPATH_LEX_AXIS,"ancestor-or-self" ,16,MY_XPATH_AXIS_ANCESTOR_OR_SELF },
|
||||
{MY_XPATH_LEX_AXIS,"attribute" , 9,MY_XPATH_AXIS_ATTRIBUTE },
|
||||
@ -1063,7 +1063,16 @@ static struct my_xpath_keyword_names_st my_keyword_names[] =
|
||||
{MY_XPATH_LEX_AXIS,"preceding" , 9,MY_XPATH_AXIS_PRECEDING },
|
||||
{MY_XPATH_LEX_AXIS,"preceding-sibling" ,17,MY_XPATH_AXIS_PRECEDING_SIBLING },
|
||||
{MY_XPATH_LEX_AXIS,"self" , 4,MY_XPATH_AXIS_SELF },
|
||||
{0,NULL,0,0}
|
||||
};
|
||||
|
||||
|
||||
static struct my_xpath_keyword_names_st my_nodetype_names[]=
|
||||
{
|
||||
{MY_XPATH_LEX_NODETYPE, "comment" , 7, 0 },
|
||||
{MY_XPATH_LEX_NODETYPE, "text" , 4, 0 },
|
||||
{MY_XPATH_LEX_NODETYPE, "processing-instruction" , 22,0 },
|
||||
{MY_XPATH_LEX_NODETYPE, "node" , 4, 0 },
|
||||
{0,NULL,0,0}
|
||||
};
|
||||
|
||||
@ -1078,11 +1087,14 @@ static struct my_xpath_keyword_names_st my_keyword_names[] =
|
||||
- Token type, on lookup success.
|
||||
- MY_XPATH_LEX_IDENT, on lookup failure.
|
||||
*/
|
||||
static int my_xpath_keyword(MY_XPATH *x, const char *beg, const char *end)
|
||||
static int
|
||||
my_xpath_keyword(MY_XPATH *x,
|
||||
struct my_xpath_keyword_names_st *keyword_names,
|
||||
const char *beg, const char *end)
|
||||
{
|
||||
struct my_xpath_keyword_names_st *k;
|
||||
size_t length= end-beg;
|
||||
for (k= my_keyword_names; k->name; k++)
|
||||
for (k= keyword_names; k->name; k++)
|
||||
{
|
||||
if (length == k->length && !strncasecmp(beg, k->name, length))
|
||||
{
|
||||
@ -1368,15 +1380,32 @@ my_xpath_lex_scan(MY_XPATH *xpath,
|
||||
beg+= length) /* no op */;
|
||||
lex->end= beg;
|
||||
|
||||
// check if a function call
|
||||
if (*beg == '(' && (xpath->func= my_xpath_function(lex->beg, beg)))
|
||||
if (beg < end)
|
||||
{
|
||||
if (*beg == '(')
|
||||
{
|
||||
/*
|
||||
check if a function call, e.g.: count(/a/b)
|
||||
or a nodetype test, e.g.: /a/b/text()
|
||||
*/
|
||||
if ((xpath->func= my_xpath_function(lex->beg, beg)))
|
||||
lex->term= MY_XPATH_LEX_FUNC;
|
||||
else
|
||||
lex->term= my_xpath_keyword(xpath, my_nodetype_names,
|
||||
lex->beg, beg);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if an axis specifier, e.g.: /a/b/child::*
|
||||
else if (*beg == ':' && beg + 1 < end && beg[1] == ':')
|
||||
{
|
||||
lex->term= my_xpath_keyword(xpath, my_axis_names,
|
||||
lex->beg, beg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// check if a keyword
|
||||
lex->term= my_xpath_keyword(xpath, lex->beg, beg);
|
||||
lex->term= my_xpath_keyword(xpath, my_keyword_names,
|
||||
lex->beg, beg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2328,6 +2357,36 @@ static int my_xpath_parse_Number(MY_XPATH *xpath)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Scan NCName.
|
||||
|
||||
SYNOPSYS
|
||||
|
||||
The keywords AND, OR, MOD, DIV are valid identitiers
|
||||
when they are in identifier context:
|
||||
|
||||
SELECT
|
||||
ExtractValue('<and><or><mod><div>VALUE</div></mod></or></and>',
|
||||
'/and/or/mod/div')
|
||||
-> VALUE
|
||||
|
||||
RETURN
|
||||
1 - success
|
||||
0 - failure
|
||||
*/
|
||||
|
||||
static int
|
||||
my_xpath_parse_NCName(MY_XPATH *xpath)
|
||||
{
|
||||
return
|
||||
my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT) ||
|
||||
my_xpath_parse_term(xpath, MY_XPATH_LEX_AND) ||
|
||||
my_xpath_parse_term(xpath, MY_XPATH_LEX_OR) ||
|
||||
my_xpath_parse_term(xpath, MY_XPATH_LEX_MOD) ||
|
||||
my_xpath_parse_term(xpath, MY_XPATH_LEX_DIV) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
QName grammar can be found in a separate document
|
||||
http://www.w3.org/TR/REC-xml-names/#NT-QName
|
||||
@ -2336,16 +2395,17 @@ static int my_xpath_parse_Number(MY_XPATH *xpath)
|
||||
[7] Prefix ::= NCName
|
||||
[8] LocalPart ::= NCName
|
||||
*/
|
||||
|
||||
static int
|
||||
my_xpath_parse_QName(MY_XPATH *xpath)
|
||||
{
|
||||
const char *beg;
|
||||
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
|
||||
if (!my_xpath_parse_NCName(xpath))
|
||||
return 0;
|
||||
beg= xpath->prevtok.beg;
|
||||
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
|
||||
return 1; /* Non qualified name */
|
||||
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
|
||||
if (!my_xpath_parse_NCName(xpath))
|
||||
return 0;
|
||||
xpath->prevtok.beg= beg;
|
||||
return 1;
|
||||
|
20
sql/log.cc
20
sql/log.cc
@ -31,15 +31,6 @@
|
||||
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
/*
|
||||
Define placement versions of operator new and operator delete since
|
||||
we cannot be sure that the <new> include exists.
|
||||
*/
|
||||
inline void *operator new(size_t, void *ptr) { return ptr; }
|
||||
inline void *operator new[](size_t, void *ptr) { return ptr; }
|
||||
inline void operator delete(void*, void*) { /* Do nothing */ }
|
||||
inline void operator delete[](void*, void*) { /* Do nothing */ }
|
||||
|
||||
/* max size of the log message */
|
||||
#define MAX_LOG_BUFFER_SIZE 1024
|
||||
#define MAX_USER_HOST_SIZE 512
|
||||
@ -147,7 +138,8 @@ public:
|
||||
*/
|
||||
void truncate(my_off_t pos)
|
||||
{
|
||||
DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
|
||||
DBUG_PRINT("info", ("truncating to position %ld", pos));
|
||||
DBUG_PRINT("info", ("before_stmt_pos=%lu", (void*) pos));
|
||||
delete pending();
|
||||
set_pending(0);
|
||||
reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
|
||||
@ -3473,10 +3465,10 @@ int THD::binlog_flush_transaction_cache()
|
||||
{
|
||||
DBUG_ENTER("binlog_flush_transaction_cache");
|
||||
binlog_trx_data *trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot];
|
||||
DBUG_PRINT("enter", ("trx_data: 0x%lx", (ulong) trx_data));
|
||||
DBUG_PRINT("enter", ("trx_data=0x%lu", (void*) trx_data));
|
||||
if (trx_data)
|
||||
DBUG_PRINT("enter", ("trx_data->before_stmt_pos: %lu",
|
||||
(ulong) trx_data->before_stmt_pos));
|
||||
DBUG_PRINT("enter", ("trx_data->before_stmt_pos=%d",
|
||||
trx_data->before_stmt_pos));
|
||||
|
||||
/*
|
||||
Write the transaction cache to the binary log. We don't flush and
|
||||
@ -4525,7 +4517,7 @@ int TC_LOG_MMAP::open(const char *opt_name)
|
||||
goto err;
|
||||
if (using_heuristic_recover())
|
||||
return 1;
|
||||
if ((fd= my_create(logname, O_RDWR, 0, MYF(MY_WME))) < 0)
|
||||
if ((fd= my_create(logname, CREATE_MODE, O_RDWR, MYF(MY_WME))) < 0)
|
||||
goto err;
|
||||
inited=1;
|
||||
file_length= opt_tc_log_size;
|
||||
|
130
sql/log_event.cc
130
sql/log_event.cc
@ -1130,13 +1130,18 @@ void Log_event::print_header(IO_CACHE* file,
|
||||
char emit_buf[256];
|
||||
int const bytes_written=
|
||||
my_snprintf(emit_buf, sizeof(emit_buf),
|
||||
"# %8.8lx %-48.48s |%s|\n# ",
|
||||
"# %8.8lx %-48.48s |%s|\n",
|
||||
(unsigned long) (hexdump_from + (i & 0xfffffff0)),
|
||||
hex_string, char_string);
|
||||
DBUG_ASSERT(bytes_written >= 0);
|
||||
DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf));
|
||||
my_b_write(file, (byte*) emit_buf, bytes_written);
|
||||
}
|
||||
/*
|
||||
need a # to prefix the rest of printouts for example those of
|
||||
Rows_log_event::print_helper().
|
||||
*/
|
||||
my_b_write(file, reinterpret_cast<const byte*>("# "), 2);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -2241,6 +2246,8 @@ Start_log_event_v3::Start_log_event_v3(const char* buf,
|
||||
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
|
||||
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
|
||||
ST_SERVER_VER_LEN);
|
||||
// prevent overrun if log is corrupted on disk
|
||||
server_version[ST_SERVER_VER_LEN-1]= 0;
|
||||
created= uint4korr(buf+ST_CREATED_OFFSET);
|
||||
/* We use log_pos to mark if this was an artificial event or not */
|
||||
artificial_event= (log_pos == 0);
|
||||
@ -2364,6 +2371,8 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
|
||||
switch (binlog_ver) {
|
||||
case 4: /* MySQL 5.0 */
|
||||
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
|
||||
DBUG_EXECUTE_IF("pretend_version_50034_in_binlog",
|
||||
strmov(server_version, "5.0.34"););
|
||||
common_header_len= LOG_EVENT_HEADER_LEN;
|
||||
number_of_event_types= LOG_EVENT_TYPES;
|
||||
/* we'll catch my_malloc() error in is_valid() */
|
||||
@ -2454,6 +2463,7 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
|
||||
post_header_len= 0; /* will make is_valid() fail */
|
||||
break;
|
||||
}
|
||||
calc_server_version_split();
|
||||
}
|
||||
|
||||
|
||||
@ -2493,6 +2503,7 @@ Format_description_log_event(const char* buf,
|
||||
post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
|
||||
number_of_event_types*
|
||||
sizeof(*post_header_len), MYF(0));
|
||||
calc_server_version_split();
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -2593,6 +2604,37 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Splits the event's 'server_version' string into three numeric pieces stored
|
||||
into 'server_version_split':
|
||||
X.Y.Zabc (X,Y,Z numbers, a not a digit) -> {X,Y,Z}
|
||||
X.Yabc -> {X,Y,0}
|
||||
Xabc -> {X,0,0}
|
||||
'server_version_split' is then used for lookups to find if the server which
|
||||
created this event has some known bug.
|
||||
*/
|
||||
void Format_description_log_event::calc_server_version_split()
|
||||
{
|
||||
char *p= server_version, *r;
|
||||
ulong number;
|
||||
for (uint i= 0; i<=2; i++)
|
||||
{
|
||||
number= strtoul(p, &r, 10);
|
||||
server_version_split[i]= (uchar)number;
|
||||
DBUG_ASSERT(number < 256); // fit in uchar
|
||||
p= r;
|
||||
DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice
|
||||
if (*r == '.')
|
||||
p++; // skip the dot
|
||||
}
|
||||
DBUG_PRINT("info",("Format_description_log_event::server_version_split:"
|
||||
" '%s' %d %d %d", server_version,
|
||||
server_version_split[0],
|
||||
server_version_split[1], server_version_split[2]));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Load_log_event methods
|
||||
General note about Load_log_event: the binlogging of LOAD DATA INFILE is
|
||||
@ -5465,12 +5507,12 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
|
||||
DBUG_ASSERT(m_rows_cur <= m_rows_end);
|
||||
|
||||
/* The cast will always work since m_rows_cur <= m_rows_end */
|
||||
if (static_cast<my_size_t>(m_rows_end - m_rows_cur) < length)
|
||||
if (static_cast<my_size_t>(m_rows_end - m_rows_cur) <= length)
|
||||
{
|
||||
my_size_t const block_size= 1024;
|
||||
my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf;
|
||||
my_ptrdiff_t const new_alloc=
|
||||
block_size * ((cur_size + length) / block_size + block_size - 1);
|
||||
block_size * ((cur_size + length + block_size - 1) / block_size);
|
||||
|
||||
byte* const new_buf= (byte*)my_realloc((gptr)m_rows_buf, (uint) new_alloc,
|
||||
MYF(MY_ALLOW_ZERO_PTR|MY_WME));
|
||||
@ -5491,7 +5533,7 @@ int Rows_log_event::do_add_row_data(byte *const row_data,
|
||||
m_rows_end= m_rows_buf + new_alloc;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(m_rows_cur + length < m_rows_end);
|
||||
DBUG_ASSERT(m_rows_cur + length <= m_rows_end);
|
||||
memcpy(m_rows_cur, row_data, length);
|
||||
m_rows_cur+= length;
|
||||
m_row_count++;
|
||||
@ -5763,15 +5805,45 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
When the open and locking succeeded, we add all the tables to
|
||||
the table map and remove them from tables to lock.
|
||||
When the open and locking succeeded, we check all tables to
|
||||
ensure that they still have the correct type.
|
||||
|
||||
We can use a down cast here since we know that every table added
|
||||
to the tables_to_lock is a RPL_TABLE_LIST.
|
||||
*/
|
||||
|
||||
{
|
||||
RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(rli->tables_to_lock);
|
||||
for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global))
|
||||
{
|
||||
if (ptr->m_tabledef.compatible_with(rli, ptr->table))
|
||||
{
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock= 0;
|
||||
thd->query_error= 1;
|
||||
rli->clear_tables_to_lock();
|
||||
DBUG_RETURN(ERR_BAD_TABLE_DEF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
... and then we add all the tables to the table map and remove
|
||||
them from tables to lock.
|
||||
|
||||
We also invalidate the query cache for all the tables, since
|
||||
they will now be changed.
|
||||
|
||||
TODO [/Matz]: Maybe the query cache should not be invalidated
|
||||
here? It might be that a table is not changed, even though it
|
||||
was locked for the statement. We do know that each
|
||||
Rows_log_event contain at least one row, so after processing one
|
||||
Rows_log_event, we can invalidate the query cache for the
|
||||
associated table.
|
||||
*/
|
||||
TABLE_LIST *ptr;
|
||||
for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
|
||||
for (TABLE_LIST *ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
|
||||
{
|
||||
rli->m_table_map.set_table(ptr->table_id, ptr->table);
|
||||
}
|
||||
@ -6042,7 +6114,7 @@ void Rows_log_event::print_helper(FILE *file,
|
||||
{
|
||||
bool const last_stmt_event= get_flags(STMT_END_F);
|
||||
print_header(head, print_event_info, !last_stmt_event);
|
||||
my_b_printf(head, "\t%s: table id %lu", name, m_table_id);
|
||||
my_b_printf(head, "\t%s: table id %lu\n", name, m_table_id);
|
||||
print_base64(body, print_event_info, !last_stmt_event);
|
||||
}
|
||||
|
||||
@ -6224,11 +6296,11 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
|
||||
thd->query_id= next_query_id();
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
|
||||
TABLE_LIST *table_list;
|
||||
RPL_TABLE_LIST *table_list;
|
||||
char *db_mem, *tname_mem;
|
||||
void *const memory=
|
||||
my_multi_malloc(MYF(MY_WME),
|
||||
&table_list, sizeof(TABLE_LIST),
|
||||
&table_list, sizeof(RPL_TABLE_LIST),
|
||||
&db_mem, NAME_LEN + 1,
|
||||
&tname_mem, NAME_LEN + 1,
|
||||
NULL);
|
||||
@ -6274,11 +6346,27 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
|
||||
}
|
||||
|
||||
/*
|
||||
Open the table if it is not already open and add the table to table map.
|
||||
Note that for any table that should not be replicated, a filter is needed.
|
||||
Open the table if it is not already open and add the table to
|
||||
table map. Note that for any table that should not be
|
||||
replicated, a filter is needed.
|
||||
|
||||
The creation of a new TABLE_LIST is used to up-cast the
|
||||
table_list consisting of RPL_TABLE_LIST items. This will work
|
||||
since the only case where the argument to open_tables() is
|
||||
changed, is when thd->lex->query_tables == table_list, i.e.,
|
||||
when the statement requires prelocking. Since this is not
|
||||
executed when a statement is executed, this case will not occur.
|
||||
As a precaution, an assertion is added to ensure that the bad
|
||||
case is not a fact.
|
||||
|
||||
Either way, the memory in the list is *never* released
|
||||
internally in the open_tables() function, hence we take a copy
|
||||
of the pointer to make sure that it's not lost.
|
||||
*/
|
||||
uint count;
|
||||
if ((error= open_tables(thd, &table_list, &count, 0)))
|
||||
DBUG_ASSERT(thd->lex->query_tables != table_list);
|
||||
TABLE_LIST *tmp_table_list= table_list;
|
||||
if ((error= open_tables(thd, &tmp_table_list, &count, 0)))
|
||||
{
|
||||
if (thd->query_error || thd->is_fatal_error)
|
||||
{
|
||||
@ -6305,14 +6393,12 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
|
||||
*/
|
||||
DBUG_ASSERT(m_table->in_use);
|
||||
|
||||
table_def const def(m_coltype, m_colcnt);
|
||||
if (def.compatible_with(rli, m_table))
|
||||
{
|
||||
thd->query_error= 1;
|
||||
error= ERR_BAD_TABLE_DEF;
|
||||
goto err;
|
||||
/* purecov: end */
|
||||
}
|
||||
/*
|
||||
Use placement new to construct the table_def instance in the
|
||||
memory allocated for it inside table_list.
|
||||
*/
|
||||
const table_def *const def=
|
||||
new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt);
|
||||
|
||||
/*
|
||||
We record in the slave's information that the table should be
|
||||
|
@ -546,16 +546,19 @@ typedef struct st_print_event_info
|
||||
bzero(db, sizeof(db));
|
||||
bzero(charset, sizeof(charset));
|
||||
bzero(time_zone_str, sizeof(time_zone_str));
|
||||
strcpy(delimiter, ";");
|
||||
uint const flags = MYF(MY_WME | MY_NABP);
|
||||
init_io_cache(&head_cache, -1, 0, WRITE_CACHE, 0L, FALSE, flags);
|
||||
init_io_cache(&body_cache, -1, 0, WRITE_CACHE, 0L, FALSE, flags);
|
||||
delimiter[0]= ';';
|
||||
delimiter[1]= 0;
|
||||
myf const flags = MYF(MY_WME | MY_NABP);
|
||||
open_cached_file(&head_cache, NULL, NULL, 0, flags);
|
||||
open_cached_file(&body_cache, NULL, NULL, 0, flags);
|
||||
}
|
||||
|
||||
~st_print_event_info() {
|
||||
end_io_cache(&head_cache);
|
||||
end_io_cache(&body_cache);
|
||||
close_cached_file(&head_cache);
|
||||
close_cached_file(&body_cache);
|
||||
}
|
||||
bool init_ok() /* tells if construction was successful */
|
||||
{ return my_b_inited(&head_cache) && my_b_inited(&body_cache); }
|
||||
|
||||
|
||||
/* Settings on how to print the events */
|
||||
@ -1153,6 +1156,7 @@ public:
|
||||
uint8 number_of_event_types;
|
||||
/* The list of post-headers' lengthes */
|
||||
uint8 *post_header_len;
|
||||
uchar server_version_split[3];
|
||||
|
||||
Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
|
||||
|
||||
@ -1184,6 +1188,7 @@ public:
|
||||
*/
|
||||
return FORMAT_DESCRIPTION_HEADER_LEN;
|
||||
}
|
||||
void calc_server_version_split();
|
||||
};
|
||||
|
||||
|
||||
@ -1727,14 +1732,17 @@ public:
|
||||
TYPE_CODE = TABLE_MAP_EVENT
|
||||
};
|
||||
|
||||
/**
|
||||
Enumeration of the errors that can be returned.
|
||||
*/
|
||||
enum enum_error
|
||||
{
|
||||
ERR_OPEN_FAILURE = -1, /* Failure to open table */
|
||||
ERR_OK = 0, /* No error */
|
||||
ERR_TABLE_LIMIT_EXCEEDED = 1, /* No more room for tables */
|
||||
ERR_OUT_OF_MEM = 2, /* Out of memory */
|
||||
ERR_BAD_TABLE_DEF = 3, /* Table definition does not match */
|
||||
ERR_RBR_TO_SBR = 4 /* daisy-chanining RBR to SBR not allowed */
|
||||
ERR_OPEN_FAILURE = -1, /**< Failure to open table */
|
||||
ERR_OK = 0, /**< No error */
|
||||
ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */
|
||||
ERR_OUT_OF_MEM = 2, /**< Out of memory */
|
||||
ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */
|
||||
ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */
|
||||
};
|
||||
|
||||
enum enum_flag
|
||||
@ -1814,7 +1822,7 @@ private:
|
||||
|
||||
Row level log event class.
|
||||
|
||||
Common base class for all row-level log events.
|
||||
Common base class for all row-containing log events.
|
||||
|
||||
RESPONSIBILITIES
|
||||
|
||||
@ -1828,6 +1836,19 @@ private:
|
||||
class Rows_log_event : public Log_event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Enumeration of the errors that can be returned.
|
||||
*/
|
||||
enum enum_error
|
||||
{
|
||||
ERR_OPEN_FAILURE = -1, /**< Failure to open table */
|
||||
ERR_OK = 0, /**< No error */
|
||||
ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */
|
||||
ERR_OUT_OF_MEM = 2, /**< Out of memory */
|
||||
ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */
|
||||
ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */
|
||||
};
|
||||
|
||||
/*
|
||||
These definitions allow you to combine the flags into an
|
||||
appropriate flag set using the normal bitwise operators. The
|
||||
@ -1835,7 +1856,6 @@ public:
|
||||
accepted by the compiler, which is then used to set the real set
|
||||
of flags.
|
||||
*/
|
||||
|
||||
enum enum_flag
|
||||
{
|
||||
/* Last event of a statement */
|
||||
|
@ -98,13 +98,16 @@ void net_set_read_timeout(NET *net, uint timeout);
|
||||
|
||||
#define WARN_DEPRECATED(Thd,Ver,Old,New) \
|
||||
do { \
|
||||
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) >= 0); \
|
||||
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0); \
|
||||
if (Thd != NULL) \
|
||||
push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \
|
||||
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
|
||||
(Old), (Ver), (New)); \
|
||||
else \
|
||||
sql_print_warning("The syntax %s is deprecated and will be removed " \
|
||||
"in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
|
||||
} while(0)
|
||||
|
||||
|
||||
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
|
||||
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
||||
|
||||
|
@ -367,6 +367,7 @@ my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
|
||||
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
|
||||
my_bool opt_log_slave_updates= 0;
|
||||
my_bool opt_innodb;
|
||||
bool slave_warning_issued = false;
|
||||
|
||||
/*
|
||||
Legacy global handlerton. These will be removed (please do not add more).
|
||||
@ -456,7 +457,8 @@ const char *binlog_format_names[]= {"STATEMENT", "ROW", "MIXED", NullS};
|
||||
TYPELIB binlog_format_typelib=
|
||||
{ array_elements(binlog_format_names) - 1, "",
|
||||
binlog_format_names, NULL };
|
||||
|
||||
ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC;
|
||||
const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id];
|
||||
#ifdef HAVE_INITGROUPS
|
||||
static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
|
||||
#endif
|
||||
@ -3255,16 +3257,23 @@ with --log-bin instead.");
|
||||
"--log-slave-updates work.");
|
||||
unireg_abort(1);
|
||||
}
|
||||
|
||||
if (!opt_bin_log && (global_system_variables.binlog_format != BINLOG_FORMAT_UNSPEC))
|
||||
if (!opt_bin_log)
|
||||
if (opt_binlog_format_id != BINLOG_FORMAT_UNSPEC)
|
||||
{
|
||||
sql_print_error("You need to use --log-bin to make "
|
||||
"--binlog-format work.");
|
||||
unireg_abort(1);
|
||||
}
|
||||
if (global_system_variables.binlog_format == BINLOG_FORMAT_UNSPEC)
|
||||
else
|
||||
{
|
||||
global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC;
|
||||
}
|
||||
else
|
||||
if (opt_binlog_format_id == BINLOG_FORMAT_UNSPEC)
|
||||
global_system_variables.binlog_format= BINLOG_FORMAT_MIXED;
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(global_system_variables.binlog_format != BINLOG_FORMAT_UNSPEC);
|
||||
}
|
||||
|
||||
/* Check that we have not let the format to unspecified at this point */
|
||||
@ -3401,7 +3410,7 @@ server.");
|
||||
(TC_LOG *) &tc_log_mmap) :
|
||||
(TC_LOG *) &tc_log_dummy);
|
||||
|
||||
if (tc_log->open(opt_bin_logname))
|
||||
if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
|
||||
{
|
||||
sql_print_error("Can't init tc log");
|
||||
unireg_abort(1);
|
||||
@ -5028,6 +5037,7 @@ struct my_option my_long_options[] =
|
||||
(gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"binlog_format", OPT_BINLOG_FORMAT,
|
||||
"Does not have any effect without '--log-bin'. "
|
||||
"Tell the master the form of binary logging to use: either 'row' for "
|
||||
"row-based binary logging, or 'statement' for statement-based binary "
|
||||
"logging, or 'mixed'. 'mixed' is statement-based binary logging except "
|
||||
@ -5035,11 +5045,12 @@ struct my_option my_long_options[] =
|
||||
"involve user-defined functions (i.e. UDFs) or the UUID() function; for "
|
||||
"those, row-based binary logging is automatically used. "
|
||||
#ifdef HAVE_NDB_BINLOG
|
||||
"If ndbcluster is enabled, the default is 'row'."
|
||||
"If ndbcluster is enabled and binlog_format is `mixed', the format switches"
|
||||
" to 'row' and back implicitly per each query accessing a NDB table."
|
||||
#endif
|
||||
, 0, 0, 0, GET_STR, REQUIRED_ARG,
|
||||
BINLOG_FORMAT_MIXED
|
||||
, 0, 0, 0, 0, 0 },
|
||||
,(gptr*) &opt_binlog_format, (gptr*) &opt_binlog_format,
|
||||
0, GET_STR, REQUIRED_ARG, BINLOG_FORMAT_MIXED, BINLOG_FORMAT_STMT,
|
||||
BINLOG_FORMAT_MIXED, 0, 0, 0},
|
||||
{"binlog-do-db", OPT_BINLOG_DO_DB,
|
||||
"Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
|
||||
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
@ -7423,7 +7434,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
binlog_format_names[BINLOG_FORMAT_MIXED]);
|
||||
exit(1);
|
||||
}
|
||||
global_system_variables.binlog_format= id-1;
|
||||
global_system_variables.binlog_format= opt_binlog_format_id= id - 1;
|
||||
break;
|
||||
}
|
||||
case (int)OPT_BINLOG_DO_DB:
|
||||
@ -7602,6 +7613,29 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
case (int) OPT_STANDALONE: /* Dummy option for NT */
|
||||
break;
|
||||
#endif
|
||||
/*
|
||||
The following change issues a deprecation warning if the slave
|
||||
configuration is specified either in the my.cnf file or on
|
||||
the command-line. See BUG#21490.
|
||||
*/
|
||||
case OPT_MASTER_HOST:
|
||||
case OPT_MASTER_USER:
|
||||
case OPT_MASTER_PASSWORD:
|
||||
case OPT_MASTER_PORT:
|
||||
case OPT_MASTER_CONNECT_RETRY:
|
||||
case OPT_MASTER_SSL:
|
||||
case OPT_MASTER_SSL_KEY:
|
||||
case OPT_MASTER_SSL_CERT:
|
||||
case OPT_MASTER_SSL_CAPATH:
|
||||
case OPT_MASTER_SSL_CIPHER:
|
||||
case OPT_MASTER_SSL_CA:
|
||||
if (!slave_warning_issued) //only show the warning once
|
||||
{
|
||||
slave_warning_issued = true;
|
||||
WARN_DEPRECATED(0, "5.2", "for replication startup options",
|
||||
"'CHANGE MASTER'");
|
||||
}
|
||||
break;
|
||||
case OPT_CONSOLE:
|
||||
if (opt_console)
|
||||
opt_error_log= 0; // Force logs to stdout
|
||||
|
@ -23,97 +23,96 @@
|
||||
#include "mysql_priv.h"
|
||||
|
||||
uint32
|
||||
field_length_from_packed(enum_field_types const field_type,
|
||||
byte const *const data);
|
||||
field_length_from_packed(enum_field_types field_type, byte const *data);
|
||||
|
||||
/*
|
||||
/**
|
||||
A table definition from the master.
|
||||
|
||||
RESPONSIBILITIES
|
||||
|
||||
The responsibilities of this class is:
|
||||
- Extract and decode table definition data from the table map event
|
||||
- Check if table definition in table map is compatible with table
|
||||
definition on slave
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Currently, the only field type data available is an array of the
|
||||
type operators that are present in the table map event.
|
||||
|
||||
TODO
|
||||
|
||||
Add type operands to this structure to allow detection of
|
||||
@todo Add type operands to this structure to allow detection of
|
||||
difference between, e.g., BIT(5) and BIT(10).
|
||||
*/
|
||||
|
||||
class table_def
|
||||
{
|
||||
public:
|
||||
/*
|
||||
/**
|
||||
Convenience declaration of the type of the field type data in a
|
||||
table map event.
|
||||
*/
|
||||
typedef unsigned char field_type;
|
||||
|
||||
/*
|
||||
/**
|
||||
Constructor.
|
||||
|
||||
SYNOPSIS
|
||||
table_def()
|
||||
types Array of types
|
||||
size Number of elements in array 'types'
|
||||
@param types Array of types
|
||||
@param size Number of elements in array 'types'
|
||||
*/
|
||||
table_def(field_type *types, my_size_t size)
|
||||
: m_type(types), m_size(size)
|
||||
: m_type(new unsigned char [size]), m_size(size)
|
||||
{
|
||||
if (m_type)
|
||||
memcpy(m_type, types, size);
|
||||
else
|
||||
m_size= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
~table_def() {
|
||||
if (m_type)
|
||||
delete [] m_type;
|
||||
#ifndef DBUG_OFF
|
||||
m_type= 0;
|
||||
m_size= 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Return the number of fields there is type data for.
|
||||
|
||||
SYNOPSIS
|
||||
size()
|
||||
|
||||
RETURN VALUE
|
||||
The number of fields that there is type data for.
|
||||
@return The number of fields that there is type data for.
|
||||
*/
|
||||
my_size_t size() const { return m_size; }
|
||||
|
||||
|
||||
/*
|
||||
Return a representation of the type data for one field.
|
||||
|
||||
SYNOPSIS
|
||||
type()
|
||||
i Field index to return data for
|
||||
@param index Field index to return data for
|
||||
|
||||
RETURN VALUE
|
||||
|
||||
Will return a representation of the type data for field
|
||||
'i'. Currently, only the type identifier is returned.
|
||||
@return Will return a representation of the type data for field
|
||||
<code>index</code>. Currently, only the type identifier is
|
||||
returned.
|
||||
*/
|
||||
field_type type(my_ptrdiff_t i) const { return m_type[i]; }
|
||||
field_type type(my_ptrdiff_t index) const
|
||||
{
|
||||
DBUG_ASSERT(0 <= index);
|
||||
DBUG_ASSERT(static_cast<my_size_t>(index) < m_size);
|
||||
return m_type[index];
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
Decide if the table definition is compatible with a table.
|
||||
|
||||
SYNOPSIS
|
||||
compatible_with()
|
||||
rli Pointer to relay log info
|
||||
table Pointer to table to compare with.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Compare the definition with a table to see if it is compatible
|
||||
with it. A table definition is compatible with a table if:
|
||||
with it.
|
||||
|
||||
A table definition is compatible with a table if:
|
||||
- the columns types of the table definition is a (not
|
||||
necessarily proper) prefix of the column type of the table, or
|
||||
|
||||
- the other way around
|
||||
|
||||
RETURN VALUE
|
||||
1 if the table definition is not compatible with 'table'
|
||||
0 if the table definition is compatible with 'table'
|
||||
@param rli Pointer to relay log info
|
||||
@param table Pointer to table to compare with.
|
||||
|
||||
@retval 1 if the table definition is not compatible with @c table
|
||||
@retval 0 if the table definition is compatible with @c table
|
||||
*/
|
||||
int compatible_with(RELAY_LOG_INFO *rli, TABLE *table) const;
|
||||
|
||||
@ -122,4 +121,14 @@ private:
|
||||
field_type *m_type; // Array of type descriptors
|
||||
};
|
||||
|
||||
/**
|
||||
Extend the normal table list with a few new fields needed by the
|
||||
slave thread, but nowhere else.
|
||||
*/
|
||||
struct RPL_TABLE_LIST
|
||||
: public st_table_list
|
||||
{
|
||||
table_def m_tabledef;
|
||||
};
|
||||
|
||||
#endif /* RPL_UTILITY_H */
|
||||
|
64
sql/slave.cc
64
sql/slave.cc
@ -3653,6 +3653,70 @@ end:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Detects, based on master's version (as found in the relay log), if master
|
||||
has a certain bug.
|
||||
@param rli RELAY_LOG_INFO which tells the master's version
|
||||
@param bug_id Number of the bug as found in bugs.mysql.com
|
||||
@return TRUE if master has the bug, FALSE if it does not.
|
||||
*/
|
||||
bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id)
|
||||
{
|
||||
struct st_version_range_for_one_bug {
|
||||
uint bug_id;
|
||||
const uchar introduced_in[3]; // first version with bug
|
||||
const uchar fixed_in[3]; // first version with fix
|
||||
};
|
||||
static struct st_version_range_for_one_bug versions_for_all_bugs[]=
|
||||
{
|
||||
{24432, { 5, 0, 24 }, { 5, 0, 38 } },
|
||||
{24432, { 5, 1, 12 }, { 5, 1, 17 } }
|
||||
};
|
||||
const uchar *master_ver=
|
||||
rli->relay_log.description_event_for_exec->server_version_split;
|
||||
|
||||
DBUG_ASSERT(sizeof(rli->relay_log.description_event_for_exec->server_version_split) == 3);
|
||||
|
||||
for (uint i= 0;
|
||||
i < sizeof(versions_for_all_bugs)/sizeof(*versions_for_all_bugs);i++)
|
||||
{
|
||||
const uchar *introduced_in= versions_for_all_bugs[i].introduced_in,
|
||||
*fixed_in= versions_for_all_bugs[i].fixed_in;
|
||||
if ((versions_for_all_bugs[i].bug_id == bug_id) &&
|
||||
(memcmp(introduced_in, master_ver, 3) <= 0) &&
|
||||
(memcmp(fixed_in, master_ver, 3) > 0))
|
||||
{
|
||||
// a short message for SHOW SLAVE STATUS (message length constraints)
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "master may suffer from"
|
||||
" http://bugs.mysql.com/bug.php?id=%u"
|
||||
" so slave stops; check error log on slave"
|
||||
" for more info", MYF(0), bug_id);
|
||||
// a verbose message for the error log
|
||||
slave_print_msg(ERROR_LEVEL, rli, ER_UNKNOWN_ERROR,
|
||||
"According to the master's version ('%s'),"
|
||||
" it is probable that master suffers from this bug:"
|
||||
" http://bugs.mysql.com/bug.php?id=%u"
|
||||
" and thus replicating the current binary log event"
|
||||
" may make the slave's data become different from the"
|
||||
" master's data."
|
||||
" To take no risk, slave refuses to replicate"
|
||||
" this event and stops."
|
||||
" We recommend that all updates be stopped on the"
|
||||
" master and slave, that the data of both be"
|
||||
" manually synchronized,"
|
||||
" that master's binary logs be deleted,"
|
||||
" that master be upgraded to a version at least"
|
||||
" equal to '%d.%d.%d'. Then replication can be"
|
||||
" restarted.",
|
||||
rli->relay_log.description_event_for_exec->server_version,
|
||||
bug_id,
|
||||
fixed_in[0], fixed_in[1], fixed_in[2]);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||
template class I_List_iterator<i_string>;
|
||||
template class I_List_iterator<i_string_pair>;
|
||||
|
@ -159,6 +159,7 @@ int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
||||
|
||||
bool show_master_info(THD* thd, MASTER_INFO* mi);
|
||||
bool show_binlog_info(THD* thd);
|
||||
bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id);
|
||||
|
||||
const char *print_slave_db_safe(const char *db);
|
||||
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "sql_trigger.h"
|
||||
#include "sql_select.h"
|
||||
#include "sql_show.h"
|
||||
#include "slave.h"
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
|
||||
@ -361,7 +362,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
List_item *values;
|
||||
Name_resolution_context *context;
|
||||
Name_resolution_context_state ctx_state;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
char *query= thd->query;
|
||||
/*
|
||||
log_on is about delayed inserts only.
|
||||
@ -370,7 +370,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
*/
|
||||
bool log_on= ((thd->options & OPTION_BIN_LOG) ||
|
||||
(!(thd->security_ctx->master_access & SUPER_ACL)));
|
||||
#endif
|
||||
thr_lock_type lock_type = table_list->lock_type;
|
||||
Item *unused_conds= 0;
|
||||
DBUG_ENTER("mysql_insert");
|
||||
@ -391,6 +390,36 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
(duplic == DUP_UPDATE))
|
||||
lock_type=TL_WRITE;
|
||||
#endif
|
||||
if ((lock_type == TL_WRITE_DELAYED) &&
|
||||
(global_system_variables.binlog_format == BINLOG_FORMAT_STMT) &&
|
||||
log_on && mysql_bin_log.is_open() &&
|
||||
(values_list.elements > 1))
|
||||
{
|
||||
/*
|
||||
Statement-based binary logging does not work in this case, because:
|
||||
a) two concurrent statements may have their rows intermixed in the
|
||||
queue, leading to autoincrement replication problems on slave (because
|
||||
the values generated used for one statement don't depend only on the
|
||||
value generated for the first row of this statement, so are not
|
||||
replicable)
|
||||
b) if first row of the statement has an error the full statement is
|
||||
not binlogged, while next rows of the statement may be inserted.
|
||||
c) if first row succeeds, statement is binlogged immediately with a
|
||||
zero error code (i.e. "no error"), if then second row fails, query
|
||||
will fail on slave too and slave will stop (wrongly believing that the
|
||||
master got no error).
|
||||
So we fallback to non-delayed INSERT.
|
||||
Note that to be fully correct, we should test the "binlog format which
|
||||
the delayed thread is going to use for this row". But in the common case
|
||||
where the global binlog format is not changed and the session binlog
|
||||
format may be changed, that is equal to the global binlog format.
|
||||
We test it without mutex for speed reasons (condition rarely true), and
|
||||
in the common case (global not changed) it is as good as without mutex;
|
||||
if global value is changed, anyway there is uncertainty as the delayed
|
||||
thread may be old and use the before-the-change value.
|
||||
*/
|
||||
lock_type= TL_WRITE;
|
||||
}
|
||||
table_list->lock_type= lock_type;
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
@ -505,6 +534,14 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
thd->cuted_fields = 0L;
|
||||
table->next_number_field=table->found_next_number_field;
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (thd->slave_thread &&
|
||||
(info.handle_duplicates == DUP_UPDATE) &&
|
||||
(table->next_number_field != NULL) &&
|
||||
rpl_master_has_bug(&active_mi->rli, 24432))
|
||||
goto abort;
|
||||
#endif
|
||||
|
||||
error=0;
|
||||
thd->proc_info="update";
|
||||
if (duplic != DUP_ERROR || ignore)
|
||||
@ -1197,14 +1234,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
if (res == VIEW_CHECK_ERROR)
|
||||
goto before_trg_err;
|
||||
|
||||
table->file->restore_auto_increment(prev_insert_id);
|
||||
if ((error=table->file->ha_update_row(table->record[1],
|
||||
table->record[0])))
|
||||
{
|
||||
if (info->ignore &&
|
||||
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
||||
{
|
||||
table->file->restore_auto_increment(prev_insert_id);
|
||||
|
||||
goto ok_or_after_trg_err;
|
||||
}
|
||||
goto err;
|
||||
@ -2540,6 +2576,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
}
|
||||
restore_record(table,s->default_values); // Get empty record
|
||||
table->next_number_field=table->found_next_number_field;
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (thd->slave_thread &&
|
||||
(info.handle_duplicates == DUP_UPDATE) &&
|
||||
(table->next_number_field != NULL) &&
|
||||
rpl_master_has_bug(&active_mi->rli, 24432))
|
||||
DBUG_RETURN(1);
|
||||
#endif
|
||||
|
||||
thd->cuted_fields=0;
|
||||
if (info.ignore || info.handle_duplicates != DUP_ERROR)
|
||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
@ -3143,9 +3188,8 @@ void select_create::send_error(uint errcode,const char *err)
|
||||
("Current statement %s row-based",
|
||||
thd->current_stmt_binlog_row_based ? "is" : "is NOT"));
|
||||
DBUG_PRINT("info",
|
||||
("Current table (at 0x%lx) %s a temporary (or non-existing) "
|
||||
"table",
|
||||
(ulong) table,
|
||||
("Current table (at 0x%lu) %s a temporary (or non-existant) table",
|
||||
(void*) table,
|
||||
table && !table->s->tmp_table ? "is NOT" : "is"));
|
||||
DBUG_PRINT("info",
|
||||
("Table %s prior to executing this statement",
|
||||
|
@ -2532,7 +2532,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
|
||||
SELECT_LEX sel;
|
||||
INDEX_FIELD_VALUES idx_field_vals;
|
||||
char path[FN_REFLEN], *end, *base_name, *orig_base_name, *file_name;
|
||||
char path[FN_REFLEN], *base_name, *orig_base_name, *file_name;
|
||||
uint len;
|
||||
bool with_i_schema;
|
||||
enum enum_schema_tables schema_table_idx;
|
||||
@ -2550,7 +2550,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
#endif
|
||||
DBUG_ENTER("get_all_tables");
|
||||
|
||||
LINT_INIT(end);
|
||||
LINT_INIT(len);
|
||||
|
||||
lex->view_prepare_mode= TRUE;
|
||||
@ -2642,7 +2641,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
else
|
||||
{
|
||||
len= build_table_filename(path, sizeof(path), base_name, "", "", 0);
|
||||
end= path + len;
|
||||
len= FN_LEN - len;
|
||||
find_files_result res= find_files(thd, &files, base_name,
|
||||
path, idx_field_vals.table_value, 0);
|
||||
@ -2692,7 +2690,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
}
|
||||
else
|
||||
{
|
||||
my_snprintf(end, len, "/%s%s", file_name, reg_ext);
|
||||
build_table_filename(path, sizeof(path),
|
||||
base_name, file_name, reg_ext, 0);
|
||||
|
||||
switch (mysql_frm_type(thd, path, ¬_used)) {
|
||||
case FRMTYPE_ERROR:
|
||||
table->field[3]->store(STRING_WITH_LEN("ERROR"),
|
||||
|
@ -115,8 +115,6 @@ static const char table_name_separator = '/';
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline void* operator new(size_t, void* __p) { return __p; }
|
||||
inline void* operator new[](size_t, void* __p) { return __p; }
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user