Merge bk-internal.mysql.com:/home/bk/mysql-5.1-new-rpl
into bodhi.local:/opt/local/work/mysql-5.1-runtime-merge mysql-test/t/disabled.def: Auto merged sql/handler.cc: Auto merged sql/item_func.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sp_head.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.h: Auto merged mysql-test/r/show_check.result: Manual merge. mysql-test/t/show_check.test: Manual merge.
This commit is contained in:
commit
c155c66da6
@ -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 */
|
||||
|
@ -67,6 +67,19 @@ create table if not exists t2 select * from t1;
|
||||
create temporary table tt1 (a int);
|
||||
create table if not exists t3 like tt1;
|
||||
|
||||
# BUG#25091 (A DELETE statement to mysql database is not logged with
|
||||
# ROW mode format): Checking that some basic operations on tables in
|
||||
# the mysql database is replicated even when the current database is
|
||||
# 'mysql'.
|
||||
|
||||
--disable_warnings
|
||||
USE mysql;
|
||||
INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test');
|
||||
UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@';
|
||||
DELETE FROM user WHERE host='localhost' AND user='@#@';
|
||||
--enable_warnings
|
||||
|
||||
use test;
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
@ -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
|
||||
|
@ -249,6 +249,11 @@ create table t1 (a int);
|
||||
create table if not exists t2 select * from t1;
|
||||
create temporary table tt1 (a int);
|
||||
create table if not exists t3 like tt1;
|
||||
USE mysql;
|
||||
INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test');
|
||||
UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@';
|
||||
DELETE FROM user WHERE host='localhost' AND user='@#@';
|
||||
use test;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
||||
@ -262,6 +267,12 @@ master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t2` (
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||
master-bin.000001 # Update_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||
master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
|
||||
drop table t1,t2,t3,tt1;
|
||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||
@ -281,6 +292,12 @@ master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t2` (
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||
master-bin.000001 # Update_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||
master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1`,`t2`,`t3` /* generated by server */
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.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;
|
||||
|
@ -159,6 +159,11 @@ create table t1 (a int);
|
||||
create table if not exists t2 select * from t1;
|
||||
create temporary table tt1 (a int);
|
||||
create table if not exists t3 like tt1;
|
||||
USE mysql;
|
||||
INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test');
|
||||
UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@';
|
||||
DELETE FROM user WHERE host='localhost' AND user='@#@';
|
||||
use test;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
||||
@ -169,6 +174,9 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int)
|
||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int)
|
||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1
|
||||
master-bin.000001 # Query 1 # use `mysql`; INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test')
|
||||
master-bin.000001 # Query 1 # use `mysql`; UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'
|
||||
master-bin.000001 # Query 1 # use `mysql`; DELETE FROM user WHERE host='localhost' AND user='@#@'
|
||||
drop table t1,t2,t3,tt1;
|
||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||
@ -185,6 +193,9 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int)
|
||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int)
|
||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1
|
||||
master-bin.000001 # Query 1 # use `mysql`; INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test')
|
||||
master-bin.000001 # Query 1 # use `mysql`; UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'
|
||||
master-bin.000001 # Query 1 # use `mysql`; DELETE FROM user WHERE host='localhost' AND user='@#@'
|
||||
master-bin.000001 # Query 1 # use `test`; drop table t1,t2,t3,tt1
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.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;
|
||||
|
@ -30,17 +30,17 @@ HEX(s1) HEX(s2) d
|
||||
466F6F2773206120426172 ED40ED41ED42 47.93
|
||||
DROP PROCEDURE bug18293|
|
||||
DROP TABLE t4|
|
||||
SHOW BINLOG EVENTS FROM 397|
|
||||
SHOW BINLOG EVENTS FROM 406|
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 397 Query 1 560 use `test`; CREATE TABLE t4 (s1 CHAR(50) CHARACTER SET latin1,
|
||||
master-bin.000001 406 Query 1 572 use `test`; CREATE TABLE t4 (s1 CHAR(50) CHARACTER SET latin1,
|
||||
s2 CHAR(50) CHARACTER SET cp932,
|
||||
d DECIMAL(10,2))
|
||||
master-bin.000001 560 Query 1 805 use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE bug18293 (IN ins1 CHAR(50),
|
||||
master-bin.000001 572 Query 1 820 use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE bug18293 (IN ins1 CHAR(50),
|
||||
IN ins2 CHAR(50) CHARACTER SET cp932,
|
||||
IN ind DECIMAL(10,2))
|
||||
BEGIN
|
||||
INSERT INTO t4 VALUES (ins1, ins2, ind);
|
||||
END
|
||||
master-bin.000001 805 Query 1 1021 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93))
|
||||
master-bin.000001 1021 Query 1 1107 use `test`; DROP PROCEDURE bug18293
|
||||
master-bin.000001 1107 Query 1 1183 use `test`; DROP TABLE t4
|
||||
master-bin.000001 820 Query 1 1039 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93))
|
||||
master-bin.000001 1039 Query 1 1128 use `test`; DROP PROCEDURE bug18293
|
||||
master-bin.000001 1128 Query 1 1207 use `test`; DROP TABLE t4
|
||||
|
@ -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
|
||||
|
@ -274,3 +274,61 @@ call p1();
|
||||
1
|
||||
drop procedure p1;
|
||||
flush logs;
|
||||
create table t1 (a varchar(64) character set utf8);
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=latin1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=latin1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1 character set koi8r;
|
||||
select hex(a) from t1;
|
||||
hex(a)
|
||||
C3BF
|
||||
D0AA
|
||||
C3BF
|
||||
C3BF
|
||||
D0AA
|
||||
C3BF
|
||||
D0AA
|
||||
drop table t1;
|
||||
flush logs;
|
||||
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
|
||||
DELIMITER /*!*/;
|
||||
use test/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1/*!*/;
|
||||
SET @@session.sql_mode=0/*!*/;
|
||||
/*!\C latin1 *//*!*/;
|
||||
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
|
||||
create table t1 (a varchar(64) character set utf8)/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-6-0' INTO table t1/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
SET @@session.collation_database=7/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-7-0' INTO table t1/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
SET @@session.collation_database=DEFAULT/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-8-0' INTO table t1/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-9-0' INTO table t1/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
SET @@session.collation_database=7/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-a-0' INTO table t1/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
SET @@session.collation_database=DEFAULT/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-b-0' INTO table t1/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
load data LOCAL INFILE 'MYSQL_TMP_DIR/SQL_LOAD_MB-c-0' INTO table t1 character set koi8r/*!*/;
|
||||
SET TIMESTAMP=1000000000/*!*/;
|
||||
drop table t1/*!*/;
|
||||
DELIMITER ;
|
||||
# End of log file
|
||||
ROLLBACK /* added by mysqlbinlog */;
|
||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||
flush logs;
|
||||
|
@ -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;
|
37
mysql-test/r/rpl_loaddata_charset.result
Normal file
37
mysql-test/r/rpl_loaddata_charset.result
Normal file
@ -0,0 +1,37 @@
|
||||
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 varchar(10) character set utf8);
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=DEFAULT;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=DEFAULT;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1 character set koi8r;
|
||||
select hex(a) from t1;
|
||||
hex(a)
|
||||
C3BF
|
||||
D0AA
|
||||
C3BF
|
||||
C3BF
|
||||
C3BF
|
||||
D0AA
|
||||
D0AA
|
||||
select hex(a) from t1;
|
||||
hex(a)
|
||||
C3BF
|
||||
D0AA
|
||||
C3BF
|
||||
C3BF
|
||||
C3BF
|
||||
D0AA
|
||||
D0AA
|
||||
drop table t1;
|
@ -41,3 +41,37 @@ select * from t1;
|
||||
ts
|
||||
2005-08-12 00:00:00
|
||||
drop table t1;
|
||||
*** master ***
|
||||
create table t1 (a int, b int);
|
||||
create trigger trg1 before insert on t1 for each row set new.b=2;
|
||||
create table t2 (a int, b int);
|
||||
create trigger trg2 before insert on t2 for each row set new.b=2;
|
||||
show tables;
|
||||
Tables_in_test
|
||||
t1
|
||||
t2
|
||||
show triggers;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
trg1 INSERT t1 set new.b=2 BEFORE NULL root@localhost
|
||||
trg2 INSERT t2 set new.b=2 BEFORE NULL root@localhost
|
||||
*** slave ***
|
||||
show tables;
|
||||
Tables_in_test
|
||||
t1
|
||||
show triggers;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
trg1 INSERT t1 set new.b=2 BEFORE NULL root@localhost
|
||||
*** master ***
|
||||
drop trigger trg1;
|
||||
drop trigger trg2;
|
||||
show triggers;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
*** slave ***
|
||||
show tables;
|
||||
Tables_in_test
|
||||
t1
|
||||
show triggers;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
*** master ***
|
||||
drop table t1;
|
||||
drop table 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
|
||||
|
@ -80,4 +80,178 @@ abc\def
|
||||
This is a test
|
||||
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
|
||||
drop table t1;
|
||||
End of 4.1 tests.
|
||||
DROP TABLE IF EXISTS t20;
|
||||
DROP TABLE IF EXISTS t21;
|
||||
DROP PROCEDURE IF EXISTS test.insert;
|
||||
CREATE TABLE t20 (a VARCHAR(20));
|
||||
CREATE TABLE t21 (a VARCHAR(20));
|
||||
CREATE PROCEDURE test.insert()
|
||||
BEGIN
|
||||
IF (@VAR)
|
||||
THEN
|
||||
INSERT INTO test.t20 VALUES ('SP_TRUE');
|
||||
ELSE
|
||||
INSERT INTO test.t20 VALUES ('SP_FALSE');
|
||||
END IF;
|
||||
END|
|
||||
CREATE TRIGGER test.insert_bi BEFORE INSERT
|
||||
ON test.t20 FOR EACH ROW
|
||||
BEGIN
|
||||
IF (@VAR)
|
||||
THEN
|
||||
INSERT INTO test.t21 VALUES ('TRIG_TRUE');
|
||||
ELSE
|
||||
INSERT INTO test.t21 VALUES ('TRIG_FALSE');
|
||||
END IF;
|
||||
END|
|
||||
SET @VAR=0;
|
||||
CALL test.insert();
|
||||
SET @VAR=1;
|
||||
CALL test.insert();
|
||||
On master: Check the tables for correct data
|
||||
SELECT * FROM t20;
|
||||
a
|
||||
SP_FALSE
|
||||
SP_TRUE
|
||||
SELECT * FROM t21;
|
||||
a
|
||||
TRIG_FALSE
|
||||
TRIG_TRUE
|
||||
On slave: Check the tables for correct data and it matches master
|
||||
SELECT * FROM t20;
|
||||
a
|
||||
SP_FALSE
|
||||
SP_TRUE
|
||||
SELECT * FROM t21;
|
||||
a
|
||||
TRIG_FALSE
|
||||
TRIG_TRUE
|
||||
DROP TABLE t20;
|
||||
DROP TABLE t21;
|
||||
DROP PROCEDURE test.insert;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP FUNCTION IF EXISTS test.square;
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE FUNCTION test.square() RETURNS INTEGER DETERMINISTIC RETURN
|
||||
(@var * @var);
|
||||
SET @var = 1;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 2;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 3;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 4;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 5;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
On master: Retrieve the values from the table
|
||||
SELECT * FROM t1;
|
||||
i
|
||||
1
|
||||
4
|
||||
9
|
||||
16
|
||||
25
|
||||
On slave: Retrieve the values from the table and verify they are the same as on master
|
||||
SELECT * FROM t1;
|
||||
i
|
||||
1
|
||||
4
|
||||
9
|
||||
16
|
||||
25
|
||||
DROP TABLE t1;
|
||||
DROP FUNCTION test.square;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP FUNCTION IF EXISTS f2;
|
||||
CREATE TABLE t1(a int);
|
||||
CREATE FUNCTION f1() returns int deterministic BEGIN
|
||||
return @a;
|
||||
END |
|
||||
CREATE FUNCTION f2() returns int deterministic BEGIN
|
||||
IF (@b > 0) then
|
||||
SET @c = (@a + @b);
|
||||
else
|
||||
SET @c = (@a - 1);
|
||||
END if;
|
||||
return @c;
|
||||
END |
|
||||
SET @a=500;
|
||||
INSERT INTO t1 values(f1());
|
||||
SET @b = 125;
|
||||
SET @c = 1;
|
||||
INSERT INTO t1 values(f2());
|
||||
On master: Retrieve the values from the table
|
||||
SELECT * from t1;
|
||||
a
|
||||
500
|
||||
625
|
||||
On slave: Check the tables for correct data and it matches master
|
||||
SELECT * from t1;
|
||||
a
|
||||
500
|
||||
625
|
||||
DROP TABLE t1;
|
||||
DROP FUNCTION f1;
|
||||
DROP FUNCTION f2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1 (i int);
|
||||
CREATE TABLE t2 (k int);
|
||||
CREATE trigger t1_bi before INSERT on t1 for each row BEGIN
|
||||
INSERT INTO t2 values (@a);
|
||||
SET @a:=42;
|
||||
INSERT INTO t2 values (@a);
|
||||
END |
|
||||
SET @a:=100;
|
||||
INSERT INTO t1 values (5);
|
||||
On master: Check to see that data was inserted correctly in both tables
|
||||
SELECT * from t1;
|
||||
i
|
||||
5
|
||||
SELECT * from t2;
|
||||
k
|
||||
100
|
||||
42
|
||||
On slave: Check the tables for correct data and it matches master
|
||||
SELECT * from t1;
|
||||
i
|
||||
5
|
||||
SELECT * from t2;
|
||||
k
|
||||
100
|
||||
42
|
||||
End of 5.0 tests.
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP FUNCTION IF EXISTS f2;
|
||||
CREATE TABLE t1 (i INT);
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN @a;
|
||||
CREATE
|
||||
FUNCTION f2() RETURNS INT BEGIN
|
||||
INSERT INTO t1 VALUES (10 + @a);
|
||||
RETURN 0;
|
||||
END|
|
||||
SET @a:=123;
|
||||
SELECT f1(), f2();
|
||||
f1() f2()
|
||||
123 0
|
||||
On master: Check to see that data was inserted correctly
|
||||
INSERT INTO t1 VALUES(f1());
|
||||
SELECT * FROM t1;
|
||||
i
|
||||
133
|
||||
123
|
||||
On slave: Check the table for correct data and it matches master
|
||||
SELECT * FROM t1;
|
||||
i
|
||||
133
|
||||
123
|
||||
DROP FUNCTION f1;
|
||||
DROP FUNCTION f2;
|
||||
DROP TABLE t1;
|
||||
stop slave;
|
||||
|
@ -744,4 +744,12 @@ show engine csv logs;
|
||||
Type Name Status
|
||||
show engine csv mutex;
|
||||
Type Name Status
|
||||
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
|
||||
|
1
mysql-test/std_data/loaddata6.dat
Normal file
1
mysql-test/std_data/loaddata6.dat
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
@ -22,7 +22,7 @@ CALL bug18293("Foo's a Bar", _cp932 0xED40ED41ED42, 47.93)|
|
||||
SELECT HEX(s1),HEX(s2),d FROM t4|
|
||||
DROP PROCEDURE bug18293|
|
||||
DROP TABLE t4|
|
||||
SHOW BINLOG EVENTS FROM 397|
|
||||
SHOW BINLOG EVENTS FROM 406|
|
||||
delimiter ;|
|
||||
|
||||
# End of 5.0 tests
|
||||
|
@ -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;
|
||||
|
||||
|
@ -193,6 +193,30 @@ drop procedure p1;
|
||||
--exec $MYSQL_BINLOG --help 2>&1 > /dev/null
|
||||
--enable_query_log
|
||||
|
||||
#
|
||||
# Bug#15126 character_set_database is not replicated
|
||||
# (LOAD DATA INFILE need it)
|
||||
#
|
||||
|
||||
flush logs;
|
||||
create table t1 (a varchar(64) character set utf8);
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=latin1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set character_set_database=latin1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1 character set koi8r;
|
||||
select hex(a) from t1;
|
||||
drop table t1;
|
||||
flush logs;
|
||||
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||
--exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000012
|
||||
|
||||
# End of 5.0 tests
|
||||
|
||||
#
|
||||
@ -200,7 +224,7 @@ drop procedure p1;
|
||||
#
|
||||
flush logs;
|
||||
--error 1
|
||||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000012 >/dev/null 2>/dev/null
|
||||
--exec $MYSQL_BINLOG --force-if-open $MYSQLTEST_VARDIR/log/master-bin.000012 >/dev/null 2>/dev/null
|
||||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000014 >/dev/null 2>/dev/null
|
||||
--exec $MYSQL_BINLOG --force-if-open $MYSQLTEST_VARDIR/log/master-bin.000014 >/dev/null 2>/dev/null
|
||||
|
||||
# End of 5.1 tests
|
||||
|
@ -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
|
33
mysql-test/t/rpl_loaddata_charset.test
Normal file
33
mysql-test/t/rpl_loaddata_charset.test
Normal file
@ -0,0 +1,33 @@
|
||||
#
|
||||
# Check LOAD DATA + character sets + replication
|
||||
#
|
||||
source include/master-slave.inc;
|
||||
|
||||
#
|
||||
# Bug#15126 character_set_database is not replicated
|
||||
# (LOAD DATA INFILE need it)
|
||||
#
|
||||
connection master;
|
||||
create table t1 (a varchar(10) character set utf8);
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=DEFAULT;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=koi8r;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1;
|
||||
set @@character_set_database=DEFAULT;
|
||||
load data infile '../std_data_ln/loaddata6.dat' into table t1 character set koi8r;
|
||||
|
||||
select hex(a) from t1;
|
||||
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
sync_with_master;
|
||||
|
||||
select hex(a) from t1;
|
||||
connection master;
|
||||
drop table t1;
|
||||
sync_slave_with_master;
|
@ -58,3 +58,35 @@ drop table t1;
|
||||
sync_slave_with_master;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
# Bug#24478 DROP TRIGGER is not caught by replicate-*-table filters
|
||||
#
|
||||
--echo *** master ***
|
||||
connection master;
|
||||
create table t1 (a int, b int);
|
||||
create trigger trg1 before insert on t1 for each row set new.b=2;
|
||||
create table t2 (a int, b int);
|
||||
create trigger trg2 before insert on t2 for each row set new.b=2;
|
||||
show tables;
|
||||
show triggers;
|
||||
sync_slave_with_master;
|
||||
--echo *** slave ***
|
||||
connection slave;
|
||||
show tables;
|
||||
show triggers;
|
||||
--echo *** master ***
|
||||
connection master;
|
||||
drop trigger trg1;
|
||||
drop trigger trg2;
|
||||
show triggers;
|
||||
sync_slave_with_master;
|
||||
--echo *** slave ***
|
||||
connection slave;
|
||||
show tables;
|
||||
show triggers;
|
||||
--echo *** master ***
|
||||
connection master;
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
sync_slave_with_master;
|
||||
|
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_";
|
||||
|
@ -53,5 +53,302 @@ SELECT * FROM t1 ORDER BY n;
|
||||
connection master;
|
||||
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
|
||||
drop table t1;
|
||||
--echo End of 4.1 tests.
|
||||
|
||||
# BUG#20141
|
||||
# The following tests ensure that if user-defined variables are used in SF/Triggers
|
||||
# that they are replicated correctly. These tests should be run in both SBR and RBR
|
||||
# modes.
|
||||
|
||||
# This test uses a procedure that inserts data values based on the value of a
|
||||
# user-defined variable. It also has a trigger that inserts data based on the
|
||||
# same variable. Successful test runs show that the @var is replicated
|
||||
# properly and that the procedure and trigger insert the correct data on the
|
||||
# slave.
|
||||
#
|
||||
# The test of stored procedure was included for completeness. Replication of stored
|
||||
# procedures was not directly affected by BUG#20141.
|
||||
#
|
||||
# This test was constructed for BUG#20141
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t20;
|
||||
DROP TABLE IF EXISTS t21;
|
||||
DROP PROCEDURE IF EXISTS test.insert;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t20 (a VARCHAR(20));
|
||||
CREATE TABLE t21 (a VARCHAR(20));
|
||||
DELIMITER |;
|
||||
|
||||
# Create a procedure that uses the @var for flow control
|
||||
|
||||
CREATE PROCEDURE test.insert()
|
||||
BEGIN
|
||||
IF (@VAR)
|
||||
THEN
|
||||
INSERT INTO test.t20 VALUES ('SP_TRUE');
|
||||
ELSE
|
||||
INSERT INTO test.t20 VALUES ('SP_FALSE');
|
||||
END IF;
|
||||
END|
|
||||
|
||||
# Create a trigger that uses the @var for flow control
|
||||
|
||||
CREATE TRIGGER test.insert_bi BEFORE INSERT
|
||||
ON test.t20 FOR EACH ROW
|
||||
BEGIN
|
||||
IF (@VAR)
|
||||
THEN
|
||||
INSERT INTO test.t21 VALUES ('TRIG_TRUE');
|
||||
ELSE
|
||||
INSERT INTO test.t21 VALUES ('TRIG_FALSE');
|
||||
END IF;
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
# Set @var and call the procedure, repeat with different values
|
||||
|
||||
SET @VAR=0;
|
||||
CALL test.insert();
|
||||
SET @VAR=1;
|
||||
CALL test.insert();
|
||||
|
||||
--echo On master: Check the tables for correct data
|
||||
|
||||
SELECT * FROM t20;
|
||||
SELECT * FROM t21;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo On slave: Check the tables for correct data and it matches master
|
||||
|
||||
SELECT * FROM t20;
|
||||
SELECT * FROM t21;
|
||||
connection master;
|
||||
|
||||
# Cleanup
|
||||
|
||||
DROP TABLE t20;
|
||||
DROP TABLE t21;
|
||||
DROP PROCEDURE test.insert;
|
||||
|
||||
# This test uses a stored function that uses user-defined variables to return data
|
||||
# This test was constructed for BUG#20141
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP FUNCTION IF EXISTS test.square;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (i INT);
|
||||
|
||||
# Create function that returns a value from @var. In this case, the square function
|
||||
|
||||
CREATE FUNCTION test.square() RETURNS INTEGER DETERMINISTIC RETURN
|
||||
(@var * @var);
|
||||
|
||||
# Set the @var to different values and insert them into a table
|
||||
|
||||
SET @var = 1;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 2;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 3;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 4;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
SET @var = 5;
|
||||
INSERT INTO t1 VALUES (square());
|
||||
|
||||
--echo On master: Retrieve the values from the table
|
||||
|
||||
SELECT * FROM t1;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo On slave: Retrieve the values from the table and verify they are the same as on master
|
||||
|
||||
SELECT * FROM t1;
|
||||
|
||||
connection master;
|
||||
|
||||
# Cleanup
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP FUNCTION test.square;
|
||||
|
||||
# This test uses stored functions that uses user-defined variables to return data
|
||||
# based on the use of @vars inside a function body.
|
||||
# This test was constructed for BUG#14914
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP FUNCTION IF EXISTS f2;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1(a int);
|
||||
DELIMITER |;
|
||||
|
||||
# Create a function that simply returns the value of an @var.
|
||||
# Create a function that uses an @var for flow control, creates and uses another
|
||||
# @var and sets its value to a value based on another @var.
|
||||
|
||||
CREATE FUNCTION f1() returns int deterministic BEGIN
|
||||
return @a;
|
||||
END |
|
||||
|
||||
CREATE FUNCTION f2() returns int deterministic BEGIN
|
||||
IF (@b > 0) then
|
||||
SET @c = (@a + @b);
|
||||
else
|
||||
SET @c = (@a - 1);
|
||||
END if;
|
||||
return @c;
|
||||
END |
|
||||
DELIMITER ;|
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
# Set an @var to a value and insert data into a table using the first function.
|
||||
# Set two more @vars to some values and insert data into a table using the second function.
|
||||
|
||||
SET @a=500;
|
||||
INSERT INTO t1 values(f1());
|
||||
SET @b = 125;
|
||||
SET @c = 1;
|
||||
INSERT INTO t1 values(f2());
|
||||
|
||||
--echo On master: Retrieve the values from the table
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
SELECT * from t1;
|
||||
|
||||
connection slave;
|
||||
|
||||
--echo On slave: Check the tables for correct data and it matches master
|
||||
|
||||
SELECT * from t1;
|
||||
|
||||
connection master;
|
||||
|
||||
# Cleanup
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP FUNCTION f1;
|
||||
DROP FUNCTION f2;
|
||||
|
||||
# This test uses a function that changes a user-defined variable in its body. This test
|
||||
# will ensure the @vars are replicated when needed and not interrupt the normal execution
|
||||
# of the function on the slave. This also applies to procedures and triggers.
|
||||
|
||||
# This test was constructed for BUG#25167
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
--enable_warnings
|
||||
CREATE TABLE t1 (i int);
|
||||
CREATE TABLE t2 (k int);
|
||||
DELIMITER |;
|
||||
|
||||
# Create a trigger that inserts data into another table, changes the @var then inserts
|
||||
# another row with the modified value.
|
||||
|
||||
CREATE trigger t1_bi before INSERT on t1 for each row BEGIN
|
||||
INSERT INTO t2 values (@a);
|
||||
SET @a:=42;
|
||||
INSERT INTO t2 values (@a);
|
||||
END |
|
||||
DELIMITER ;|
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
# Set the @var to a value then insert data into first table.
|
||||
|
||||
SET @a:=100;
|
||||
INSERT INTO t1 values (5);
|
||||
|
||||
--echo On master: Check to see that data was inserted correctly in both tables
|
||||
|
||||
SELECT * from t1;
|
||||
SELECT * from t2;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo On slave: Check the tables for correct data and it matches master
|
||||
|
||||
SELECT * from t1;
|
||||
SELECT * from t2;
|
||||
|
||||
connection master;
|
||||
|
||||
--echo End of 5.0 tests.
|
||||
|
||||
# Cleanup
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
|
||||
# This test uses a stored function that uses user-defined variables to return data
|
||||
# The test ensures the value of the user-defined variable is replicated correctly
|
||||
# and in the correct order of assignment.
|
||||
|
||||
# This test was constructed for BUG#20141
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP FUNCTION IF EXISTS f2;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (i INT);
|
||||
|
||||
# Create two functions. One simply returns the user-defined variable. The other
|
||||
# returns a value based on the user-defined variable.
|
||||
|
||||
CREATE FUNCTION f1() RETURNS INT RETURN @a; DELIMITER |; CREATE
|
||||
FUNCTION f2() RETURNS INT BEGIN
|
||||
INSERT INTO t1 VALUES (10 + @a);
|
||||
RETURN 0;
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
|
||||
# Set the variable and execute the functions.
|
||||
|
||||
SET @a:=123;
|
||||
SELECT f1(), f2();
|
||||
|
||||
--echo On master: Check to see that data was inserted correctly
|
||||
|
||||
INSERT INTO t1 VALUES(f1());
|
||||
SELECT * FROM t1;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo On slave: Check the table for correct data and it matches master
|
||||
|
||||
SELECT * FROM t1;
|
||||
|
||||
connection master;
|
||||
|
||||
# Cleanup
|
||||
|
||||
DROP FUNCTION f1;
|
||||
DROP FUNCTION f2;
|
||||
DROP TABLE t1;
|
||||
|
||||
sync_slave_with_master;
|
||||
stop slave;
|
||||
|
||||
|
@ -580,5 +580,16 @@ show engine mutex status;
|
||||
show engine csv status;
|
||||
show engine csv logs;
|
||||
show engine csv mutex;
|
||||
#
|
||||
# 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;
|
||||
|
@ -3451,7 +3451,7 @@ namespace {
|
||||
{
|
||||
int const check(table->s->tmp_table == NO_TMP_TABLE &&
|
||||
binlog_filter->db_ok(table->s->db.str) &&
|
||||
strcmp("mysql", table->s->db.str) != 0);
|
||||
!table->no_replicate);
|
||||
table->s->cached_row_logging_check= check;
|
||||
}
|
||||
|
||||
|
@ -4224,7 +4224,14 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
||||
user_var_entry *var_entry;
|
||||
var_entry= get_variable(&thd->user_vars, name, 0);
|
||||
|
||||
if (!(opt_bin_log && is_update_query(sql_command)))
|
||||
/*
|
||||
Any reference to user-defined variable which is done from stored
|
||||
function or trigger affects their execution and the execution of the
|
||||
calling statement. We must log all such variables even if they are
|
||||
not involved in table-updating statements.
|
||||
*/
|
||||
if (!(opt_bin_log &&
|
||||
(is_update_query(sql_command) || thd->in_sub_stmt)))
|
||||
{
|
||||
*out_entry= var_entry;
|
||||
return 0;
|
||||
|
@ -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 },
|
||||
|
||||
{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}
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
lex->term= MY_XPATH_LEX_FUNC;
|
||||
return;
|
||||
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;
|
||||
|
21
sql/log.cc
21
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
|
||||
@ -148,6 +139,7 @@ public:
|
||||
void truncate(my_off_t pos)
|
||||
{
|
||||
DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
|
||||
DBUG_PRINT("info", ("before_stmt_pos=%lu", (ulong) pos));
|
||||
delete pending();
|
||||
set_pending(0);
|
||||
reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
|
||||
@ -311,6 +303,7 @@ bool Log_to_csv_event_handler::open_log_table(uint log_table_type)
|
||||
{
|
||||
table->table->use_all_columns();
|
||||
table->table->locked_by_logger= TRUE;
|
||||
table->table->no_replicate= TRUE;
|
||||
}
|
||||
/* restore thread settings */
|
||||
if (curr)
|
||||
@ -3352,13 +3345,13 @@ bool MYSQL_BIN_LOG::flush_and_sync()
|
||||
return err;
|
||||
}
|
||||
|
||||
void MYSQL_BIN_LOG::start_union_events(THD *thd)
|
||||
void MYSQL_BIN_LOG::start_union_events(THD *thd, query_id_t query_id_param)
|
||||
{
|
||||
DBUG_ASSERT(!thd->binlog_evt_union.do_union);
|
||||
thd->binlog_evt_union.do_union= TRUE;
|
||||
thd->binlog_evt_union.unioned_events= FALSE;
|
||||
thd->binlog_evt_union.unioned_events_trans= FALSE;
|
||||
thd->binlog_evt_union.first_query_id= thd->query_id;
|
||||
thd->binlog_evt_union.first_query_id= query_id_param;
|
||||
}
|
||||
|
||||
void MYSQL_BIN_LOG::stop_union_events(THD *thd)
|
||||
@ -3473,9 +3466,9 @@ 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", (ulong) trx_data));
|
||||
if (trx_data)
|
||||
DBUG_PRINT("enter", ("trx_data->before_stmt_pos: %lu",
|
||||
DBUG_PRINT("enter", ("trx_data->before_stmt_pos=%lu",
|
||||
(ulong) trx_data->before_stmt_pos));
|
||||
|
||||
/*
|
||||
@ -4525,7 +4518,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;
|
||||
|
@ -341,7 +341,7 @@ public:
|
||||
|
||||
int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
|
||||
|
||||
void start_union_events(THD *thd);
|
||||
void start_union_events(THD *thd, query_id_t query_id_param);
|
||||
void stop_union_events(THD *thd);
|
||||
bool is_query_in_union(THD *thd, query_id_t query_id_param);
|
||||
|
||||
|
189
sql/log_event.cc
189
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;
|
||||
}
|
||||
@ -1276,7 +1281,8 @@ bool Query_log_event::write(IO_CACHE* file)
|
||||
1+4+ // code of autoinc and the 2 autoinc variables
|
||||
1+6+ // code of charset and charset
|
||||
1+1+MAX_TIME_ZONE_NAME_LENGTH+ // code of tz and tz length and tz name
|
||||
1+2 // code of lc_time_names and lc_time_names_number
|
||||
1+2+ // code of lc_time_names and lc_time_names_number
|
||||
1+2 // code of charset_database and charset_database_number
|
||||
], *start, *start_of_status;
|
||||
ulong event_length;
|
||||
|
||||
@ -1395,6 +1401,13 @@ bool Query_log_event::write(IO_CACHE* file)
|
||||
int2store(start, lc_time_names_number);
|
||||
start+= 2;
|
||||
}
|
||||
if (charset_database_number)
|
||||
{
|
||||
DBUG_ASSERT(charset_database_number <= 0xFFFF);
|
||||
*start++= Q_CHARSET_DATABASE_CODE;
|
||||
int2store(start, charset_database_number);
|
||||
start+= 2;
|
||||
}
|
||||
/*
|
||||
Here there could be code like
|
||||
if (command-line-option-which-says-"log_this_variable" && inited)
|
||||
@ -1460,7 +1473,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
|
||||
sql_mode(thd_arg->variables.sql_mode),
|
||||
auto_increment_increment(thd_arg->variables.auto_increment_increment),
|
||||
auto_increment_offset(thd_arg->variables.auto_increment_offset),
|
||||
lc_time_names_number(thd_arg->variables.lc_time_names->number)
|
||||
lc_time_names_number(thd_arg->variables.lc_time_names->number),
|
||||
charset_database_number(0)
|
||||
{
|
||||
time_t end_time;
|
||||
time(&end_time);
|
||||
@ -1468,6 +1482,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
|
||||
catalog_len = (catalog) ? (uint32) strlen(catalog) : 0;
|
||||
/* status_vars_len is set just before writing the event */
|
||||
db_len = (db) ? (uint32) strlen(db) : 0;
|
||||
if (thd_arg->variables.collation_database != thd_arg->db_charset)
|
||||
charset_database_number= thd_arg->variables.collation_database->number;
|
||||
|
||||
/*
|
||||
If we don't use flags2 for anything else than options contained in
|
||||
thd->options, it would be more efficient to flags2=thd_arg->options
|
||||
@ -1538,7 +1555,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
|
||||
db(NullS), catalog_len(0), status_vars_len(0),
|
||||
flags2_inited(0), sql_mode_inited(0), charset_inited(0),
|
||||
auto_increment_increment(1), auto_increment_offset(1),
|
||||
time_zone_len(0), lc_time_names_number(0)
|
||||
time_zone_len(0), lc_time_names_number(0), charset_database_number(0)
|
||||
{
|
||||
ulong data_len;
|
||||
uint32 tmp;
|
||||
@ -1643,6 +1660,10 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
|
||||
lc_time_names_number= uint2korr(pos);
|
||||
pos+= 2;
|
||||
break;
|
||||
case Q_CHARSET_DATABASE_CODE:
|
||||
charset_database_number= uint2korr(pos);
|
||||
pos+= 2;
|
||||
break;
|
||||
default:
|
||||
/* That's why you must write status vars in growing order of code */
|
||||
DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
|
||||
@ -1841,6 +1862,16 @@ void Query_log_event::print_query_header(IO_CACHE* file,
|
||||
lc_time_names_number, print_event_info->delimiter);
|
||||
print_event_info->lc_time_names_number= lc_time_names_number;
|
||||
}
|
||||
if (charset_database_number != print_event_info->charset_database_number)
|
||||
{
|
||||
if (charset_database_number)
|
||||
my_b_printf(file, "SET @@session.collation_database=%d%s\n",
|
||||
charset_database_number, print_event_info->delimiter);
|
||||
else
|
||||
my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
|
||||
print_event_info->delimiter);
|
||||
print_event_info->charset_database_number= charset_database_number;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1996,7 +2027,21 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli,
|
||||
}
|
||||
else
|
||||
thd->variables.lc_time_names= &my_locale_en_US;
|
||||
|
||||
if (charset_database_number)
|
||||
{
|
||||
CHARSET_INFO *cs;
|
||||
if (!(cs= get_charset(charset_database_number, MYF(0))))
|
||||
{
|
||||
char buf[20];
|
||||
int10_to_str((int) charset_database_number, buf, -10);
|
||||
my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
|
||||
goto compare_errors;
|
||||
}
|
||||
thd->variables.collation_database= cs;
|
||||
}
|
||||
else
|
||||
thd->variables.collation_database= thd->db_charset;
|
||||
|
||||
/* Execute the query (note that we bypass dispatch_command()) */
|
||||
mysql_parse(thd, thd->query, thd->query_length);
|
||||
|
||||
@ -2241,6 +2286,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 +2411,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 +2503,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 +2543,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 +2644,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 +5547,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 +5573,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++;
|
||||
@ -5741,10 +5823,10 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
|
||||
need to add code to assert that is the case.
|
||||
*/
|
||||
thd->binlog_flush_pending_rows_event(false);
|
||||
close_tables_for_reopen(thd, &rli->tables_to_lock);
|
||||
TABLE_LIST *tables= rli->tables_to_lock;
|
||||
close_tables_for_reopen(thd, &tables);
|
||||
|
||||
if ((error= open_tables(thd, &rli->tables_to_lock,
|
||||
&rli->tables_to_lock_count, 0)))
|
||||
if ((error= open_tables(thd, &tables, &rli->tables_to_lock_count, 0)))
|
||||
{
|
||||
if (thd->query_error || thd->is_fatal_error)
|
||||
{
|
||||
@ -5763,15 +5845,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= 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 +6154,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 +6336,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 +6386,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 +6433,17 @@ 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.
|
||||
|
||||
The memory allocated by the table_def structure (i.e., not the
|
||||
memory allocated *for* the table_def structure) is released
|
||||
inside st_relay_log_info::clear_tables_to_lock() by calling the
|
||||
table_def destructor explicitly.
|
||||
*/
|
||||
new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt);
|
||||
table_list->m_tabledef_valid= TRUE;
|
||||
|
||||
/*
|
||||
We record in the slave's information that the table should be
|
||||
|
@ -272,6 +272,7 @@ struct sql_ex_info
|
||||
|
||||
#define Q_LC_TIME_NAMES_CODE 7
|
||||
|
||||
#define Q_CHARSET_DATABASE_CODE 8
|
||||
/* Intvar event post-header */
|
||||
|
||||
#define I_TYPE_OFFSET 0
|
||||
@ -533,10 +534,11 @@ typedef struct st_print_event_info
|
||||
char charset[6]; // 3 variables, each of them storable in 2 bytes
|
||||
char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
|
||||
uint lc_time_names_number;
|
||||
uint charset_database_number;
|
||||
st_print_event_info()
|
||||
:flags2_inited(0), sql_mode_inited(0),
|
||||
auto_increment_increment(1),auto_increment_offset(1), charset_inited(0),
|
||||
lc_time_names_number(0)
|
||||
lc_time_names_number(0), charset_database_number(0)
|
||||
{
|
||||
/*
|
||||
Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
|
||||
@ -546,16 +548,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 */
|
||||
@ -846,6 +851,7 @@ public:
|
||||
uint time_zone_len; /* 0 means uninited */
|
||||
const char *time_zone_str;
|
||||
uint lc_time_names_number; /* 0 means en_US */
|
||||
uint charset_database_number;
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
|
||||
@ -1153,6 +1159,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 +1191,7 @@ public:
|
||||
*/
|
||||
return FORMAT_DESCRIPTION_HEADER_LEN;
|
||||
}
|
||||
void calc_server_version_split();
|
||||
};
|
||||
|
||||
|
||||
@ -1727,14 +1735,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 +1825,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 +1839,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 +1859,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 */
|
||||
|
@ -96,15 +96,18 @@ void net_set_read_timeout(NET *net, uint timeout);
|
||||
#define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
|
||||
#define all_bits_set(A,B) ((A) & (B) != (B))
|
||||
|
||||
#define WARN_DEPRECATED(Thd,Ver,Old,New) \
|
||||
do { \
|
||||
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) >= 0); \
|
||||
push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \
|
||||
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
|
||||
(Old), (Ver), (New)); \
|
||||
#define WARN_DEPRECATED(Thd,Ver,Old,New) \
|
||||
do { \
|
||||
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0); \
|
||||
if (((gptr)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).
|
||||
@ -454,9 +455,10 @@ my_bool sp_automatic_privileges= 1;
|
||||
ulong opt_binlog_rows_event_max_size;
|
||||
const char *binlog_format_names[]= {"STATEMENT", "ROW", "MIXED", NullS};
|
||||
TYPELIB binlog_format_typelib=
|
||||
{ array_elements(binlog_format_names)-1,"",
|
||||
{ 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,17 +3257,24 @@ with --log-bin instead.");
|
||||
"--log-slave-updates work.");
|
||||
unireg_abort(1);
|
||||
}
|
||||
|
||||
if (!opt_bin_log && (global_system_variables.binlog_format != 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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 */
|
||||
DBUG_ASSERT((uint)global_system_variables.binlog_format <=
|
||||
@ -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(NULL, "5.2", "for replication startup options",
|
||||
"'CHANGE MASTER'");
|
||||
}
|
||||
break;
|
||||
case OPT_CONSOLE:
|
||||
if (opt_console)
|
||||
opt_error_log= 0; // Force logs to stdout
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "rpl_rli.h"
|
||||
#include <my_dir.h> // For MY_STAT
|
||||
#include "sql_repl.h" // For check_binlog_magic
|
||||
#include "rpl_utility.h"
|
||||
|
||||
static int count_relay_log_space(RELAY_LOG_INFO* rli);
|
||||
|
||||
@ -1108,4 +1109,23 @@ void st_relay_log_info::cleanup_context(THD *thd, bool error)
|
||||
unsafe_to_stop_at= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void st_relay_log_info::clear_tables_to_lock()
|
||||
{
|
||||
while (tables_to_lock)
|
||||
{
|
||||
gptr to_free= reinterpret_cast<gptr>(tables_to_lock);
|
||||
if (tables_to_lock->m_tabledef_valid)
|
||||
{
|
||||
tables_to_lock->m_tabledef.table_def::~table_def();
|
||||
tables_to_lock->m_tabledef_valid= FALSE;
|
||||
}
|
||||
tables_to_lock=
|
||||
static_cast<RPL_TABLE_LIST*>(tables_to_lock->next_global);
|
||||
tables_to_lock_count--;
|
||||
my_free(to_free, MYF(MY_WME));
|
||||
}
|
||||
DBUG_ASSERT(tables_to_lock == NULL && tables_to_lock_count == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "rpl_tblmap.h"
|
||||
|
||||
struct RPL_TABLE_LIST;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@ -279,7 +281,7 @@ typedef struct st_relay_log_info
|
||||
group_relay_log_pos);
|
||||
}
|
||||
|
||||
TABLE_LIST *tables_to_lock; /* RBR: Tables to lock */
|
||||
RPL_TABLE_LIST *tables_to_lock; /* RBR: Tables to lock */
|
||||
uint tables_to_lock_count; /* RBR: Count of tables to lock */
|
||||
table_mapping m_table_map; /* RBR: Mapping table-id to table */
|
||||
|
||||
@ -295,16 +297,7 @@ typedef struct st_relay_log_info
|
||||
void transaction_end(THD*);
|
||||
|
||||
void cleanup_context(THD *, bool);
|
||||
void clear_tables_to_lock() {
|
||||
while (tables_to_lock)
|
||||
{
|
||||
char *to_free= reinterpret_cast<gptr>(tables_to_lock);
|
||||
tables_to_lock= tables_to_lock->next_global;
|
||||
tables_to_lock_count--;
|
||||
my_free(to_free, MYF(MY_WME));
|
||||
}
|
||||
DBUG_ASSERT(tables_to_lock == NULL && tables_to_lock_count == 0);
|
||||
}
|
||||
void clear_tables_to_lock();
|
||||
|
||||
time_t unsafe_to_stop_at;
|
||||
} RELAY_LOG_INFO;
|
||||
|
@ -22,98 +22,100 @@
|
||||
|
||||
#include "mysql_priv.h"
|
||||
|
||||
uint32
|
||||
field_length_from_packed(enum_field_types const field_type,
|
||||
byte const *const data);
|
||||
struct st_relay_log_info;
|
||||
typedef st_relay_log_info RELAY_LOG_INFO;
|
||||
|
||||
/*
|
||||
uint32
|
||||
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.
|
||||
|
||||
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
|
||||
difference between, e.g., BIT(5) and BIT(10).
|
||||
@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:
|
||||
Compare the definition with a table to see if it is compatible
|
||||
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 +124,15 @@ 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
|
||||
{
|
||||
bool m_tabledef_valid;
|
||||
table_def m_tabledef;
|
||||
};
|
||||
|
||||
#endif /* RPL_UTILITY_H */
|
||||
|
87
sql/slave.cc
87
sql/slave.cc
@ -53,6 +53,7 @@ ulonglong relay_log_space_limit = 0;
|
||||
*/
|
||||
|
||||
int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
|
||||
int events_till_abort = -1;
|
||||
|
||||
typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
|
||||
|
||||
@ -2205,11 +2206,16 @@ err:
|
||||
THD_CHECK_SENTRY(thd);
|
||||
delete thd;
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
mi->abort_slave = 0;
|
||||
mi->slave_running = 0;
|
||||
mi->io_thd = 0;
|
||||
pthread_mutex_unlock(&mi->run_lock);
|
||||
mi->abort_slave= 0;
|
||||
mi->slave_running= 0;
|
||||
mi->io_thd= 0;
|
||||
/*
|
||||
Note: the order of the two following calls (first broadcast, then unlock)
|
||||
is important. Otherwise a killer_thread can execute between the calls and
|
||||
delete the mi structure leading to a crash! (see BUG#25306 for details)
|
||||
*/
|
||||
pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done
|
||||
pthread_mutex_unlock(&mi->run_lock);
|
||||
my_thread_end();
|
||||
pthread_exit(0);
|
||||
DBUG_RETURN(0); // Can't return anything here
|
||||
@ -2455,9 +2461,14 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
|
||||
THD_CHECK_SENTRY(thd);
|
||||
delete thd;
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
/*
|
||||
Note: the order of the broadcast and unlock calls below (first broadcast, then unlock)
|
||||
is important. Otherwise a killer_thread can execute between the calls and
|
||||
delete the mi structure leading to a crash! (see BUG#25306 for details)
|
||||
*/
|
||||
pthread_cond_broadcast(&rli->stop_cond);
|
||||
// tell the world we are done
|
||||
pthread_mutex_unlock(&rli->run_lock);
|
||||
pthread_mutex_unlock(&rli->run_lock); // tell the world we are done
|
||||
|
||||
my_thread_end();
|
||||
pthread_exit(0);
|
||||
DBUG_RETURN(0); // Can't return anything here
|
||||
@ -3653,6 +3664,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);
|
||||
|
21
sql/sp.cc
21
sql/sp.cc
@ -498,6 +498,13 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
||||
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
|
||||
sp->m_name.str));
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
if (!(table= open_proc_table_for_update(thd)))
|
||||
ret= SP_OPEN_TABLE_FAILED;
|
||||
else
|
||||
@ -634,6 +641,13 @@ db_drop_routine(THD *thd, int type, sp_name *name)
|
||||
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
||||
type, name->m_name.length, name->m_name.str));
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
if (!(table= open_proc_table_for_update(thd)))
|
||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
||||
@ -666,6 +680,13 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
|
||||
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
||||
type, name->m_name.length, name->m_name.str));
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
if (!(table= open_proc_table_for_update(thd)))
|
||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
||||
|
@ -1484,8 +1484,24 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
|
||||
|
||||
if (need_binlog_call)
|
||||
{
|
||||
query_id_t q;
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
mysql_bin_log.start_union_events(thd);
|
||||
/*
|
||||
In case of artificially constructed events for function calls
|
||||
we have separate union for each such event and hence can't use
|
||||
query_id of real calling statement as the start of all these
|
||||
unions (this will break logic of replication of user-defined
|
||||
variables). So we use artifical value which is guaranteed to
|
||||
be greater than all query_id's of all statements belonging
|
||||
to previous events/unions.
|
||||
Possible alternative to this is logging of all function invocations
|
||||
as one select and not resetting THD::user_var_events before
|
||||
each invocation.
|
||||
*/
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
q= global_query_id;
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
mysql_bin_log.start_union_events(thd, q + 1);
|
||||
binlog_save_options= thd->options;
|
||||
thd->options&= ~OPTION_BIN_LOG;
|
||||
}
|
||||
|
@ -3001,6 +3001,13 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
||||
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
|
||||
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
/*
|
||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||
@ -3218,6 +3225,13 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
|
||||
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
|
||||
tables[0].db=tables[1].db=(char*) "mysql";
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
/*
|
||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||
@ -3357,6 +3371,13 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
||||
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
|
||||
tables[0].db=tables[1].db=(char*) "mysql";
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
/*
|
||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||
@ -5401,6 +5422,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
|
||||
TABLE_LIST tables[GRANT_TABLES];
|
||||
DBUG_ENTER("mysql_create_user");
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
/* CREATE USER may be skipped on replication client. */
|
||||
if ((result= open_grant_tables(thd, tables)))
|
||||
DBUG_RETURN(result != 1);
|
||||
@ -5473,6 +5501,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
|
||||
TABLE_LIST tables[GRANT_TABLES];
|
||||
DBUG_ENTER("mysql_drop_user");
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
/* DROP USER may be skipped on replication client. */
|
||||
if ((result= open_grant_tables(thd, tables)))
|
||||
DBUG_RETURN(result != 1);
|
||||
@ -5537,6 +5572,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
|
||||
TABLE_LIST tables[GRANT_TABLES];
|
||||
DBUG_ENTER("mysql_rename_user");
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
/* RENAME USER may be skipped on replication client. */
|
||||
if ((result= open_grant_tables(thd, tables)))
|
||||
DBUG_RETURN(result != 1);
|
||||
@ -5612,6 +5654,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
|
||||
TABLE_LIST tables[GRANT_TABLES];
|
||||
DBUG_ENTER("mysql_revoke_all");
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
if ((result= open_grant_tables(thd, tables)))
|
||||
DBUG_RETURN(result != 1);
|
||||
|
||||
@ -5802,6 +5851,13 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
|
||||
rw_wrlock(&LOCK_grant);
|
||||
VOID(pthread_mutex_lock(&acl_cache->lock));
|
||||
|
||||
/*
|
||||
This statement will be replicated as a statement, even when using
|
||||
row-based replication. The flag will be reset at the end of the
|
||||
statement.
|
||||
*/
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
|
||||
/* Remove procedure access */
|
||||
do
|
||||
{
|
||||
|
@ -997,6 +997,7 @@ sql_exchange::sql_exchange(char *name,bool flag)
|
||||
enclosed= line_start= &my_empty_string;
|
||||
line_term= &default_line_term;
|
||||
escaped= &default_escaped;
|
||||
cs= NULL;
|
||||
}
|
||||
|
||||
bool select_send::send_fields(List<Item> &list, uint flags)
|
||||
@ -2158,7 +2159,12 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||
!current_stmt_binlog_row_based)
|
||||
{
|
||||
options&= ~OPTION_BIN_LOG;
|
||||
}
|
||||
}
|
||||
|
||||
if ((backup->options & OPTION_BIN_LOG) && is_update_query(lex->sql_command)&&
|
||||
!current_stmt_binlog_row_based)
|
||||
mysql_bin_log.start_union_events(this, this->query_id);
|
||||
|
||||
/* Disable result sets */
|
||||
client_capabilities &= ~CLIENT_MULTI_RESULTS;
|
||||
in_sub_stmt|= new_state;
|
||||
@ -2202,6 +2208,10 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
||||
sent_row_count= backup->sent_row_count;
|
||||
client_capabilities= backup->client_capabilities;
|
||||
|
||||
if ((options & OPTION_BIN_LOG) && is_update_query(lex->sql_command) &&
|
||||
!current_stmt_binlog_row_based)
|
||||
mysql_bin_log.stop_union_events(this);
|
||||
|
||||
/*
|
||||
The following is added to the old values as we are interested in the
|
||||
total complexity of the query
|
||||
|
@ -1656,6 +1656,7 @@ public:
|
||||
bool opt_enclosed;
|
||||
bool dumpfile;
|
||||
ulong skip_lines;
|
||||
CHARSET_INFO *cs;
|
||||
sql_exchange(char *name,bool dumpfile_flag);
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
@ -363,6 +364,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
Name_resolution_context_state ctx_state;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
char *query= thd->query;
|
||||
#endif
|
||||
/*
|
||||
log_on is about delayed inserts only.
|
||||
By default, both logs are enabled (this won't cause problems if the server
|
||||
@ -370,7 +372,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 +392,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 +536,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)
|
||||
@ -1195,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;
|
||||
@ -2559,6 +2597,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);
|
||||
@ -3162,8 +3209,7 @@ 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",
|
||||
("Current table (at 0x%lu) %s a temporary (or non-existant) table",
|
||||
(ulong) table,
|
||||
table && !table->s->tmp_table ? "is NOT" : "is"));
|
||||
DBUG_PRINT("info",
|
||||
|
@ -316,7 +316,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
info.handle_duplicates=handle_duplicates;
|
||||
info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
|
||||
|
||||
READ_INFO read_info(file,tot_length,thd->variables.collation_database,
|
||||
READ_INFO read_info(file,tot_length,
|
||||
ex->cs ? ex->cs : thd->variables.collation_database,
|
||||
*field_term,*ex->line_start, *ex->line_term, *enclosed,
|
||||
info.escape_char, read_file_from_client, is_fifo);
|
||||
if (read_info.error)
|
||||
@ -458,7 +459,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
}
|
||||
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
|
||||
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
||||
send_ok(thd,info.copied+info.deleted,0L,name);
|
||||
|
||||
if (!transactional_table)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
@ -494,6 +494,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
if (transactional_table)
|
||||
error=ha_autocommit_or_rollback(thd,error);
|
||||
|
||||
/* ok to client sent only after binlog write and engine commit */
|
||||
send_ok(thd, info.copied + info.deleted, 0L, name);
|
||||
err:
|
||||
table->file->ha_release_auto_increment();
|
||||
if (thd->lock)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "sp_cache.h"
|
||||
#include "events.h"
|
||||
#include "event_data_objects.h"
|
||||
#include "sql_trigger.h"
|
||||
|
||||
/* Used in error handling only */
|
||||
#define SP_TYPE_STRING(LP) \
|
||||
@ -1682,6 +1683,30 @@ mysql_execute_command(THD *thd)
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (unlikely(thd->slave_thread))
|
||||
{
|
||||
if (lex->sql_command == SQLCOM_DROP_TRIGGER)
|
||||
{
|
||||
/*
|
||||
When dropping a trigger, we need to load its table name
|
||||
before checking slave filter rules.
|
||||
*/
|
||||
add_table_for_trigger(thd, thd->lex->spname, 1, &all_tables);
|
||||
|
||||
if (!all_tables)
|
||||
{
|
||||
/*
|
||||
If table name cannot be loaded,
|
||||
it means the trigger does not exists possibly because
|
||||
CREATE TRIGGER was previously skipped for this trigger
|
||||
according to slave filtering rules.
|
||||
Returning success without producing any errors in this case.
|
||||
*/
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
// force searching in slave.cc:tables_ok()
|
||||
all_tables->updating= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if statment should be skipped because of slave filtering
|
||||
rules
|
||||
|
@ -886,12 +886,14 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
|
||||
|
||||
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
|
||||
{
|
||||
DBUG_ENTER("stop_slave");
|
||||
|
||||
int slave_errno;
|
||||
if (!thd)
|
||||
thd = current_thd;
|
||||
|
||||
if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
|
||||
return 1;
|
||||
DBUG_RETURN(1);
|
||||
thd->proc_info = "Killing slave";
|
||||
int thread_mask;
|
||||
lock_slave_threads(mi);
|
||||
@ -925,12 +927,12 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
|
||||
{
|
||||
if (net_report)
|
||||
my_message(slave_errno, ER(slave_errno), MYF(0));
|
||||
return 1;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
else if (net_report)
|
||||
send_ok(thd);
|
||||
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -106,10 +106,6 @@ const LEX_STRING trg_event_type_names[]=
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
||||
TABLE_LIST ** table);
|
||||
|
||||
class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
|
||||
{
|
||||
private:
|
||||
@ -1180,7 +1176,7 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
||||
1 Error
|
||||
*/
|
||||
|
||||
static int
|
||||
int
|
||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
||||
TABLE_LIST **table)
|
||||
{
|
||||
|
@ -137,3 +137,7 @@ private:
|
||||
|
||||
extern const LEX_STRING trg_action_time_type_names[];
|
||||
extern const LEX_STRING trg_event_type_names[];
|
||||
|
||||
int
|
||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
||||
TABLE_LIST **table);
|
||||
|
@ -1129,6 +1129,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
old_or_new_charset_name_or_default
|
||||
collation_name
|
||||
collation_name_or_default
|
||||
opt_load_data_charset
|
||||
|
||||
%type <variable> internal_variable_name
|
||||
|
||||
@ -4736,6 +4737,10 @@ charset_name_or_default:
|
||||
charset_name { $$=$1; }
|
||||
| DEFAULT { $$=NULL; } ;
|
||||
|
||||
opt_load_data_charset:
|
||||
/* Empty */ { $$= NULL; }
|
||||
| charset charset_name_or_default { $$= $2; }
|
||||
;
|
||||
|
||||
old_or_new_charset_name:
|
||||
ident_or_text
|
||||
@ -9048,6 +9053,8 @@ load_data:
|
||||
lex->update_list.empty();
|
||||
lex->value_list.empty();
|
||||
}
|
||||
opt_load_data_charset
|
||||
{ Lex->exchange->cs= $12; }
|
||||
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
|
||||
opt_load_data_set_spec
|
||||
{}
|
||||
|
@ -408,6 +408,10 @@ struct st_table {
|
||||
/*
|
||||
If true, the current table row is considered to have all columns set to
|
||||
NULL, including columns declared as "not null" (see maybe_null).
|
||||
|
||||
TODO: Each of these flags take up 8 bits. They can just as easily
|
||||
be put into one single unsigned long and instead of taking up 18
|
||||
bytes, it would take up 4.
|
||||
*/
|
||||
my_bool null_row;
|
||||
my_bool force_index;
|
||||
@ -415,6 +419,7 @@ struct st_table {
|
||||
my_bool key_read, no_keyread;
|
||||
my_bool locked_by_flush;
|
||||
my_bool locked_by_logger;
|
||||
my_bool no_replicate;
|
||||
my_bool locked_by_name;
|
||||
my_bool fulltext_searched;
|
||||
my_bool no_cache;
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user