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");
|
DBUG_ENTER("write_event_header_and_base64");
|
||||||
/* Write header and base64 output to cache */
|
/* Write header and base64 output to cache */
|
||||||
IO_CACHE result_cache;
|
IO_CACHE result_cache;
|
||||||
if (init_io_cache(&result_cache, -1, 0, WRITE_CACHE, 0L, FALSE,
|
if (open_cached_file(&result_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)))
|
||||||
MYF(MY_WME | MY_NABP)))
|
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
ev->print_header(&result_cache, print_event_info, FALSE);
|
ev->print_header(&result_cache, print_event_info, FALSE);
|
||||||
ev->print_base64(&result_cache, print_event_info, FALSE);
|
ev->print_base64(&result_cache, print_event_info, FALSE);
|
||||||
|
|
||||||
/* Read data from cache and write to result file */
|
/* Read data from cache and write to result file */
|
||||||
my_b_copy_to_file(&result_cache, result_file);
|
my_b_copy_to_file(&result_cache, result_file);
|
||||||
end_io_cache(&result_cache);
|
close_cached_file(&result_cache);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,6 +1013,9 @@ static int dump_log_entries(const char* logname)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
PRINT_EVENT_INFO print_event_info;
|
PRINT_EVENT_INFO print_event_info;
|
||||||
|
|
||||||
|
if (!print_event_info.init_ok())
|
||||||
|
return 1;
|
||||||
/*
|
/*
|
||||||
Set safe delimiter, to dump things
|
Set safe delimiter, to dump things
|
||||||
like CREATE PROCEDURE safely
|
like CREATE PROCEDURE safely
|
||||||
|
@ -1479,4 +1479,11 @@ do { doubleget_union _tmp; \
|
|||||||
#define dlerror() ""
|
#define dlerror() ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Include standard definitions of operator new and delete.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <new>
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* my_global_h */
|
#endif /* my_global_h */
|
||||||
|
@ -67,6 +67,19 @@ create table if not exists t2 select * from t1;
|
|||||||
create temporary table tt1 (a int);
|
create temporary table tt1 (a int);
|
||||||
create table if not exists t3 like tt1;
|
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_column 2 # 5 #
|
||||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||||
show binlog events from 102;
|
show binlog events from 102;
|
||||||
|
@ -413,3 +413,14 @@ select * from t1;
|
|||||||
insert into t1 values ('abc');
|
insert into t1 values ('abc');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table 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;
|
||||||
drop function bug15728_insert;
|
drop function bug15728_insert;
|
||||||
drop table t1;
|
drop table t1,t2;
|
||||||
drop procedure foo;
|
drop procedure foo;
|
||||||
|
|
||||||
# test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in
|
# test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in
|
||||||
@ -276,6 +276,59 @@ connection master;
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
sync_slave_with_master;
|
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
|
# 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 table if not exists t2 select * from t1;
|
||||||
create temporary table tt1 (a int);
|
create temporary table tt1 (a int);
|
||||||
create table if not exists t3 like tt1;
|
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;
|
show binlog events from 102;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
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` (
|
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
||||||
`a` int(11) DEFAULT NULL
|
`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;
|
drop table t1,t2,t3,tt1;
|
||||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
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;
|
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` (
|
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
||||||
`a` int(11) DEFAULT NULL
|
`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`; 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 # 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)
|
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||||
|
@ -11353,3 +11353,15 @@ a
|
|||||||
a
|
a
|
||||||
a
|
a
|
||||||
drop table t1;
|
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 table if not exists t2 select * from t1;
|
||||||
create temporary table tt1 (a int);
|
create temporary table tt1 (a int);
|
||||||
create table if not exists t3 like tt1;
|
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;
|
show binlog events from 102;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
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 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 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 `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;
|
drop table t1,t2,t3,tt1;
|
||||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
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;
|
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 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 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 `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`; 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 # 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)
|
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||||
|
@ -11353,3 +11353,15 @@ a
|
|||||||
a
|
a
|
||||||
a
|
a
|
||||||
drop table t1;
|
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
|
466F6F2773206120426172 ED40ED41ED42 47.93
|
||||||
DROP PROCEDURE bug18293|
|
DROP PROCEDURE bug18293|
|
||||||
DROP TABLE t4|
|
DROP TABLE t4|
|
||||||
SHOW BINLOG EVENTS FROM 397|
|
SHOW BINLOG EVENTS FROM 406|
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000001 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,
|
s2 CHAR(50) CHARACTER SET cp932,
|
||||||
d DECIMAL(10,2))
|
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 ins2 CHAR(50) CHARACTER SET cp932,
|
||||||
IN ind DECIMAL(10,2))
|
IN ind DECIMAL(10,2))
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO t4 VALUES (ins1, ins2, ind);
|
INSERT INTO t4 VALUES (ins1, ins2, ind);
|
||||||
END
|
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 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 1021 Query 1 1107 use `test`; DROP PROCEDURE bug18293
|
master-bin.000001 1039 Query 1 1128 use `test`; DROP PROCEDURE bug18293
|
||||||
master-bin.000001 1107 Query 1 1183 use `test`; DROP TABLE t4
|
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;
|
create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
c1 c2 stamp
|
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
|
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||||
select * from t1;
|
select * from t1;
|
||||||
c1 c2 stamp
|
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
|
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
||||||
select * from t1;
|
select * from t1;
|
||||||
c1 c2 stamp
|
c1 c2 stamp
|
||||||
|
@ -274,3 +274,61 @@ call p1();
|
|||||||
1
|
1
|
||||||
drop procedure p1;
|
drop procedure p1;
|
||||||
flush logs;
|
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
|
Abernathy
|
||||||
aberrant
|
aberrant
|
||||||
aberration
|
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 t1;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
@ -196,7 +196,7 @@ id last_id
|
|||||||
3 5
|
3 5
|
||||||
drop function bug15728;
|
drop function bug15728;
|
||||||
drop function bug15728_insert;
|
drop function bug15728_insert;
|
||||||
drop table t1;
|
drop table t1,t2;
|
||||||
drop procedure foo;
|
drop procedure foo;
|
||||||
create table t1 (n int primary key auto_increment not null,
|
create table t1 (n int primary key auto_increment not null,
|
||||||
b int, unique(b));
|
b int, unique(b));
|
||||||
@ -263,6 +263,64 @@ n b
|
|||||||
2 100
|
2 100
|
||||||
3 350
|
3 350
|
||||||
drop table t1;
|
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 PROCEDURE IF EXISTS p1;
|
||||||
DROP TABLE IF EXISTS t1, t2;
|
DROP TABLE IF EXISTS t1, t2;
|
||||||
SELECT LAST_INSERT_ID(0);
|
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
|
ts
|
||||||
2005-08-12 00:00:00
|
2005-08-12 00:00:00
|
||||||
drop table t1;
|
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;
|
drop database if exists mysqltest1;
|
||||||
create database mysqltest1;
|
create database mysqltest1;
|
||||||
use 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 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%";
|
show global variables like "binlog_format%";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
binlog_format ROW
|
binlog_format ROW
|
||||||
@ -67,12 +90,11 @@ execute stmt1 using @string;
|
|||||||
deallocate prepare stmt1;
|
deallocate prepare stmt1;
|
||||||
insert into t1 values("for_10_");
|
insert into t1 values("for_10_");
|
||||||
insert into t1 select "yesterday_11_";
|
insert into t1 select "yesterday_11_";
|
||||||
set binlog_format=default;
|
set binlog_format=statement;
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
select @@global.binlog_format, @@session.binlog_format;
|
||||||
@@global.binlog_format @@session.binlog_format
|
@@global.binlog_format @@session.binlog_format
|
||||||
STATEMENT STATEMENT
|
STATEMENT STATEMENT
|
||||||
set global binlog_format=default;
|
set global binlog_format=statement;
|
||||||
ERROR 42000: Variable 'binlog_format' doesn't have a default value
|
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
select @@global.binlog_format, @@session.binlog_format;
|
||||||
@@global.binlog_format @@session.binlog_format
|
@@global.binlog_format @@session.binlog_format
|
||||||
STATEMENT STATEMENT
|
STATEMENT STATEMENT
|
||||||
@ -87,11 +109,11 @@ execute stmt1 using @string;
|
|||||||
deallocate prepare stmt1;
|
deallocate prepare stmt1;
|
||||||
insert into t1 values("for_15_");
|
insert into t1 values("for_15_");
|
||||||
insert into t1 select "yesterday_16_";
|
insert into t1 select "yesterday_16_";
|
||||||
set binlog_format=mixed;
|
set global binlog_format=mixed;
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
select @@global.binlog_format, @@session.binlog_format;
|
||||||
@@global.binlog_format @@session.binlog_format
|
@@global.binlog_format @@session.binlog_format
|
||||||
STATEMENT MIXED
|
MIXED STATEMENT
|
||||||
set global binlog_format=mixed;
|
set binlog_format=default;
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
select @@global.binlog_format, @@session.binlog_format;
|
||||||
@@global.binlog_format @@session.binlog_format
|
@@global.binlog_format @@session.binlog_format
|
||||||
MIXED MIXED
|
MIXED MIXED
|
||||||
|
@ -80,4 +80,178 @@ abc\def
|
|||||||
This is a test
|
This is a test
|
||||||
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
|
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
|
||||||
drop table t1;
|
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;
|
stop slave;
|
||||||
|
@ -744,4 +744,12 @@ show engine csv logs;
|
|||||||
Type Name Status
|
Type Name Status
|
||||||
show engine csv mutex;
|
show engine csv mutex;
|
||||||
Type Name Status
|
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
|
End of 5.1 tests
|
||||||
|
@ -809,3 +809,78 @@ ExtractValue(@xml, "/entry[(50<pt)]/id")
|
|||||||
select ExtractValue(@xml, "/entry[(50<=pt)]/id");
|
select ExtractValue(@xml, "/entry[(50<=pt)]/id");
|
||||||
ExtractValue(@xml, "/entry[(50<=pt)]/id")
|
ExtractValue(@xml, "/entry[(50<=pt)]/id")
|
||||||
pt50
|
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|
|
SELECT HEX(s1),HEX(s2),d FROM t4|
|
||||||
DROP PROCEDURE bug18293|
|
DROP PROCEDURE bug18293|
|
||||||
DROP TABLE t4|
|
DROP TABLE t4|
|
||||||
SHOW BINLOG EVENTS FROM 397|
|
SHOW BINLOG EVENTS FROM 406|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
|
||||||
# End of 5.0 tests
|
# 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;
|
create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
--error 1031
|
--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;
|
select * from t1;
|
||||||
--error 1031
|
--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;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
@ -193,6 +193,30 @@ drop procedure p1;
|
|||||||
--exec $MYSQL_BINLOG --help 2>&1 > /dev/null
|
--exec $MYSQL_BINLOG --help 2>&1 > /dev/null
|
||||||
--enable_query_log
|
--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
|
# End of 5.0 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -200,7 +224,7 @@ drop procedure p1;
|
|||||||
#
|
#
|
||||||
flush logs;
|
flush logs;
|
||||||
--error 1
|
--error 1
|
||||||
--exec $MYSQL_BINLOG $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.000012 >/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
|
# End of 5.1 tests
|
||||||
|
@ -31,6 +31,34 @@ drop table t2;
|
|||||||
select * from t1;
|
select * from t1;
|
||||||
select * from t2;
|
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
|
# 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;
|
sync_slave_with_master;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# 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/not_ndb_default.inc
|
||||||
-- source include/master-slave.inc
|
-- source include/master-slave.inc
|
||||||
|
|
||||||
@ -8,9 +19,22 @@ create database mysqltest1;
|
|||||||
--enable_warnings
|
--enable_warnings
|
||||||
use mysqltest1;
|
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 global variables like "binlog_format%";
|
||||||
show session variables like "binlog_format%";
|
show session variables like "binlog_format%";
|
||||||
select @@global.binlog_format, @@session.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 values("for_10_");
|
||||||
insert into t1 select "yesterday_11_";
|
insert into t1 select "yesterday_11_";
|
||||||
|
|
||||||
# test SET DEFAULT (=statement at this point of test)
|
# test statement (is not default after wl#3368)
|
||||||
set binlog_format=default;
|
set binlog_format=statement;
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
select @@global.binlog_format, @@session.binlog_format;
|
||||||
# due to cluster it's hard to set back to default
|
set global binlog_format=statement;
|
||||||
--error ER_NO_DEFAULT
|
|
||||||
set global binlog_format=default;
|
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
select @@global.binlog_format, @@session.binlog_format;
|
||||||
|
|
||||||
prepare stmt1 from 'insert into t1 select ?';
|
prepare stmt1 from 'insert into t1 select ?';
|
||||||
@ -87,10 +109,10 @@ insert into t1 select "yesterday_16_";
|
|||||||
|
|
||||||
# and now the mixed mode
|
# and now the mixed mode
|
||||||
|
|
||||||
set binlog_format=mixed;
|
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
|
||||||
set global binlog_format=mixed;
|
set global binlog_format=mixed;
|
||||||
select @@global.binlog_format, @@session.binlog_format;
|
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(),?)';
|
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
|
||||||
set @string="emergency_17_";
|
set @string="emergency_17_";
|
||||||
|
@ -53,5 +53,302 @@ SELECT * FROM t1 ORDER BY n;
|
|||||||
connection master;
|
connection master;
|
||||||
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
|
insert into t1 select * FROM (select @var1 union select @var2) AS t2;
|
||||||
drop table t1;
|
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;
|
sync_slave_with_master;
|
||||||
stop slave;
|
stop slave;
|
||||||
|
|
||||||
|
@ -580,5 +580,16 @@ show engine mutex status;
|
|||||||
show engine csv status;
|
show engine csv status;
|
||||||
show engine csv logs;
|
show engine csv logs;
|
||||||
show engine csv mutex;
|
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
|
--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");
|
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
|
int
|
||||||
my_b_copy_to_file(IO_CACHE *cache, FILE *file)
|
my_b_copy_to_file(IO_CACHE *cache, FILE *file)
|
||||||
{
|
{
|
||||||
byte buf[IO_SIZE];
|
|
||||||
uint bytes_in_cache;
|
uint bytes_in_cache;
|
||||||
DBUG_ENTER("my_b_copy_to_file");
|
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))
|
if (reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
bytes_in_cache= my_b_bytes_in_cache(cache);
|
bytes_in_cache= my_b_bytes_in_cache(cache);
|
||||||
while (bytes_in_cache > 0) {
|
do
|
||||||
uint const read_bytes= min(bytes_in_cache, sizeof(buf));
|
{
|
||||||
DBUG_PRINT("debug", ("Remaining %u bytes - Reading %u bytes",
|
if (my_fwrite(file, cache->read_pos, bytes_in_cache,
|
||||||
bytes_in_cache, read_bytes));
|
MYF(MY_WME | MY_NABP)) == (uint) -1)
|
||||||
if (my_b_read(cache, buf, read_bytes))
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
if (my_fwrite(file, buf, read_bytes, MYF(MY_WME | MY_NABP)) == (uint) -1)
|
cache->read_pos= cache->read_end;
|
||||||
DBUG_RETURN(1);
|
} while ((bytes_in_cache= my_b_fill(cache)));
|
||||||
bytes_in_cache -= read_bytes;
|
|
||||||
}
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_off_t my_b_append_tell(IO_CACHE* info)
|
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))
|
cannot_convert_error_pos, from + length))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (copy_length < length)
|
if (from_end_pos < from + length)
|
||||||
{
|
{
|
||||||
report_data_too_long(this);
|
report_data_too_long(this);
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -3451,7 +3451,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
int const check(table->s->tmp_table == NO_TMP_TABLE &&
|
int const check(table->s->tmp_table == NO_TMP_TABLE &&
|
||||||
binlog_filter->db_ok(table->s->db.str) &&
|
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;
|
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;
|
user_var_entry *var_entry;
|
||||||
var_entry= get_variable(&thd->user_vars, name, 0);
|
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;
|
*out_entry= var_entry;
|
||||||
return 0;
|
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_OR , "or" , 2, 0 },
|
||||||
{MY_XPATH_LEX_DIV , "div" , 3, 0 },
|
{MY_XPATH_LEX_DIV , "div" , 3, 0 },
|
||||||
{MY_XPATH_LEX_MOD , "mod" , 3, 0 },
|
{MY_XPATH_LEX_MOD , "mod" , 3, 0 },
|
||||||
|
{0,NULL,0,0}
|
||||||
{MY_XPATH_LEX_NODETYPE, "comment" , 7, 0 },
|
};
|
||||||
{MY_XPATH_LEX_NODETYPE, "text" , 4, 0 },
|
|
||||||
{MY_XPATH_LEX_NODETYPE, "processing-instruction" , 22,0 },
|
|
||||||
{MY_XPATH_LEX_NODETYPE, "node" , 4, 0 },
|
static struct my_xpath_keyword_names_st my_axis_names[]=
|
||||||
|
{
|
||||||
{MY_XPATH_LEX_AXIS,"ancestor" , 8,MY_XPATH_AXIS_ANCESTOR },
|
{MY_XPATH_LEX_AXIS,"ancestor" , 8,MY_XPATH_AXIS_ANCESTOR },
|
||||||
{MY_XPATH_LEX_AXIS,"ancestor-or-self" ,16,MY_XPATH_AXIS_ANCESTOR_OR_SELF },
|
{MY_XPATH_LEX_AXIS,"ancestor-or-self" ,16,MY_XPATH_AXIS_ANCESTOR_OR_SELF },
|
||||||
{MY_XPATH_LEX_AXIS,"attribute" , 9,MY_XPATH_AXIS_ATTRIBUTE },
|
{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" , 9,MY_XPATH_AXIS_PRECEDING },
|
||||||
{MY_XPATH_LEX_AXIS,"preceding-sibling" ,17,MY_XPATH_AXIS_PRECEDING_SIBLING },
|
{MY_XPATH_LEX_AXIS,"preceding-sibling" ,17,MY_XPATH_AXIS_PRECEDING_SIBLING },
|
||||||
{MY_XPATH_LEX_AXIS,"self" , 4,MY_XPATH_AXIS_SELF },
|
{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}
|
{0,NULL,0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1078,11 +1087,14 @@ static struct my_xpath_keyword_names_st my_keyword_names[] =
|
|||||||
- Token type, on lookup success.
|
- Token type, on lookup success.
|
||||||
- MY_XPATH_LEX_IDENT, on lookup failure.
|
- 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;
|
struct my_xpath_keyword_names_st *k;
|
||||||
size_t length= end-beg;
|
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))
|
if (length == k->length && !strncasecmp(beg, k->name, length))
|
||||||
{
|
{
|
||||||
@ -1368,15 +1380,32 @@ my_xpath_lex_scan(MY_XPATH *xpath,
|
|||||||
beg+= length) /* no op */;
|
beg+= length) /* no op */;
|
||||||
lex->end= beg;
|
lex->end= beg;
|
||||||
|
|
||||||
// check if a function call
|
if (beg < end)
|
||||||
if (*beg == '(' && (xpath->func= my_xpath_function(lex->beg, beg)))
|
|
||||||
{
|
{
|
||||||
lex->term= MY_XPATH_LEX_FUNC;
|
if (*beg == '(')
|
||||||
return;
|
{
|
||||||
|
/*
|
||||||
|
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
|
// 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;
|
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
|
QName grammar can be found in a separate document
|
||||||
http://www.w3.org/TR/REC-xml-names/#NT-QName
|
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
|
[7] Prefix ::= NCName
|
||||||
[8] LocalPart ::= NCName
|
[8] LocalPart ::= NCName
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
my_xpath_parse_QName(MY_XPATH *xpath)
|
my_xpath_parse_QName(MY_XPATH *xpath)
|
||||||
{
|
{
|
||||||
const char *beg;
|
const char *beg;
|
||||||
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
|
if (!my_xpath_parse_NCName(xpath))
|
||||||
return 0;
|
return 0;
|
||||||
beg= xpath->prevtok.beg;
|
beg= xpath->prevtok.beg;
|
||||||
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
|
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
|
||||||
return 1; /* Non qualified name */
|
return 1; /* Non qualified name */
|
||||||
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
|
if (!my_xpath_parse_NCName(xpath))
|
||||||
return 0;
|
return 0;
|
||||||
xpath->prevtok.beg= beg;
|
xpath->prevtok.beg= beg;
|
||||||
return 1;
|
return 1;
|
||||||
|
21
sql/log.cc
21
sql/log.cc
@ -31,15 +31,6 @@
|
|||||||
|
|
||||||
#include <mysql/plugin.h>
|
#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 */
|
/* max size of the log message */
|
||||||
#define MAX_LOG_BUFFER_SIZE 1024
|
#define MAX_LOG_BUFFER_SIZE 1024
|
||||||
#define MAX_USER_HOST_SIZE 512
|
#define MAX_USER_HOST_SIZE 512
|
||||||
@ -148,6 +139,7 @@ public:
|
|||||||
void truncate(my_off_t pos)
|
void truncate(my_off_t pos)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
|
DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
|
||||||
|
DBUG_PRINT("info", ("before_stmt_pos=%lu", (ulong) pos));
|
||||||
delete pending();
|
delete pending();
|
||||||
set_pending(0);
|
set_pending(0);
|
||||||
reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 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->use_all_columns();
|
||||||
table->table->locked_by_logger= TRUE;
|
table->table->locked_by_logger= TRUE;
|
||||||
|
table->table->no_replicate= TRUE;
|
||||||
}
|
}
|
||||||
/* restore thread settings */
|
/* restore thread settings */
|
||||||
if (curr)
|
if (curr)
|
||||||
@ -3352,13 +3345,13 @@ bool MYSQL_BIN_LOG::flush_and_sync()
|
|||||||
return err;
|
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);
|
DBUG_ASSERT(!thd->binlog_evt_union.do_union);
|
||||||
thd->binlog_evt_union.do_union= TRUE;
|
thd->binlog_evt_union.do_union= TRUE;
|
||||||
thd->binlog_evt_union.unioned_events= FALSE;
|
thd->binlog_evt_union.unioned_events= FALSE;
|
||||||
thd->binlog_evt_union.unioned_events_trans= 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)
|
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");
|
DBUG_ENTER("binlog_flush_transaction_cache");
|
||||||
binlog_trx_data *trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot];
|
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)
|
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));
|
(ulong) trx_data->before_stmt_pos));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4525,7 +4518,7 @@ int TC_LOG_MMAP::open(const char *opt_name)
|
|||||||
goto err;
|
goto err;
|
||||||
if (using_heuristic_recover())
|
if (using_heuristic_recover())
|
||||||
return 1;
|
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;
|
goto err;
|
||||||
inited=1;
|
inited=1;
|
||||||
file_length= opt_tc_log_size;
|
file_length= opt_tc_log_size;
|
||||||
|
@ -341,7 +341,7 @@ public:
|
|||||||
|
|
||||||
int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
|
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);
|
void stop_union_events(THD *thd);
|
||||||
bool is_query_in_union(THD *thd, query_id_t query_id_param);
|
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];
|
char emit_buf[256];
|
||||||
int const bytes_written=
|
int const bytes_written=
|
||||||
my_snprintf(emit_buf, sizeof(emit_buf),
|
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)),
|
(unsigned long) (hexdump_from + (i & 0xfffffff0)),
|
||||||
hex_string, char_string);
|
hex_string, char_string);
|
||||||
DBUG_ASSERT(bytes_written >= 0);
|
DBUG_ASSERT(bytes_written >= 0);
|
||||||
DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf));
|
DBUG_ASSERT(static_cast<my_size_t>(bytes_written) < sizeof(emit_buf));
|
||||||
my_b_write(file, (byte*) emit_buf, bytes_written);
|
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;
|
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+4+ // code of autoinc and the 2 autoinc variables
|
||||||
1+6+ // code of charset and charset
|
1+6+ // code of charset and charset
|
||||||
1+1+MAX_TIME_ZONE_NAME_LENGTH+ // code of tz and tz length and tz name
|
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;
|
], *start, *start_of_status;
|
||||||
ulong event_length;
|
ulong event_length;
|
||||||
|
|
||||||
@ -1395,6 +1401,13 @@ bool Query_log_event::write(IO_CACHE* file)
|
|||||||
int2store(start, lc_time_names_number);
|
int2store(start, lc_time_names_number);
|
||||||
start+= 2;
|
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
|
Here there could be code like
|
||||||
if (command-line-option-which-says-"log_this_variable" && inited)
|
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),
|
sql_mode(thd_arg->variables.sql_mode),
|
||||||
auto_increment_increment(thd_arg->variables.auto_increment_increment),
|
auto_increment_increment(thd_arg->variables.auto_increment_increment),
|
||||||
auto_increment_offset(thd_arg->variables.auto_increment_offset),
|
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_t end_time;
|
||||||
time(&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;
|
catalog_len = (catalog) ? (uint32) strlen(catalog) : 0;
|
||||||
/* status_vars_len is set just before writing the event */
|
/* status_vars_len is set just before writing the event */
|
||||||
db_len = (db) ? (uint32) strlen(db) : 0;
|
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
|
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
|
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),
|
db(NullS), catalog_len(0), status_vars_len(0),
|
||||||
flags2_inited(0), sql_mode_inited(0), charset_inited(0),
|
flags2_inited(0), sql_mode_inited(0), charset_inited(0),
|
||||||
auto_increment_increment(1), auto_increment_offset(1),
|
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;
|
ulong data_len;
|
||||||
uint32 tmp;
|
uint32 tmp;
|
||||||
@ -1643,6 +1660,10 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
|
|||||||
lc_time_names_number= uint2korr(pos);
|
lc_time_names_number= uint2korr(pos);
|
||||||
pos+= 2;
|
pos+= 2;
|
||||||
break;
|
break;
|
||||||
|
case Q_CHARSET_DATABASE_CODE:
|
||||||
|
charset_database_number= uint2korr(pos);
|
||||||
|
pos+= 2;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* That's why you must write status vars in growing order of code */
|
/* 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\
|
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);
|
lc_time_names_number, print_event_info->delimiter);
|
||||||
print_event_info->lc_time_names_number= lc_time_names_number;
|
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
|
else
|
||||||
thd->variables.lc_time_names= &my_locale_en_US;
|
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()) */
|
/* Execute the query (note that we bypass dispatch_command()) */
|
||||||
mysql_parse(thd, thd->query, thd->query_length);
|
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);
|
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
|
||||||
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
|
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
|
||||||
ST_SERVER_VER_LEN);
|
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);
|
created= uint4korr(buf+ST_CREATED_OFFSET);
|
||||||
/* We use log_pos to mark if this was an artificial event or not */
|
/* We use log_pos to mark if this was an artificial event or not */
|
||||||
artificial_event= (log_pos == 0);
|
artificial_event= (log_pos == 0);
|
||||||
@ -2364,6 +2411,8 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
|
|||||||
switch (binlog_ver) {
|
switch (binlog_ver) {
|
||||||
case 4: /* MySQL 5.0 */
|
case 4: /* MySQL 5.0 */
|
||||||
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
|
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;
|
common_header_len= LOG_EVENT_HEADER_LEN;
|
||||||
number_of_event_types= LOG_EVENT_TYPES;
|
number_of_event_types= LOG_EVENT_TYPES;
|
||||||
/* we'll catch my_malloc() error in is_valid() */
|
/* 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 */
|
post_header_len= 0; /* will make is_valid() fail */
|
||||||
break;
|
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,
|
post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
|
||||||
number_of_event_types*
|
number_of_event_types*
|
||||||
sizeof(*post_header_len), MYF(0));
|
sizeof(*post_header_len), MYF(0));
|
||||||
|
calc_server_version_split();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2593,6 +2644,37 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
Load_log_event methods
|
||||||
General note about Load_log_event: the binlogging of LOAD DATA INFILE is
|
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);
|
DBUG_ASSERT(m_rows_cur <= m_rows_end);
|
||||||
|
|
||||||
/* The cast will always work since 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_size_t const block_size= 1024;
|
||||||
my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf;
|
my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf;
|
||||||
my_ptrdiff_t const new_alloc=
|
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,
|
byte* const new_buf= (byte*)my_realloc((gptr)m_rows_buf, (uint) new_alloc,
|
||||||
MYF(MY_ALLOW_ZERO_PTR|MY_WME));
|
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;
|
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);
|
memcpy(m_rows_cur, row_data, length);
|
||||||
m_rows_cur+= length;
|
m_rows_cur+= length;
|
||||||
m_row_count++;
|
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.
|
need to add code to assert that is the case.
|
||||||
*/
|
*/
|
||||||
thd->binlog_flush_pending_rows_event(false);
|
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,
|
if ((error= open_tables(thd, &tables, &rli->tables_to_lock_count, 0)))
|
||||||
&rli->tables_to_lock_count, 0)))
|
|
||||||
{
|
{
|
||||||
if (thd->query_error || thd->is_fatal_error)
|
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);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When the open and locking succeeded, we add all the tables to
|
When the open and locking succeeded, we check all tables to
|
||||||
the table map and remove them from tables to lock.
|
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
|
We also invalidate the query cache for all the tables, since
|
||||||
they will now be changed.
|
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 (TABLE_LIST *ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
|
||||||
for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
|
|
||||||
{
|
{
|
||||||
rli->m_table_map.set_table(ptr->table_id, ptr->table);
|
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);
|
bool const last_stmt_event= get_flags(STMT_END_F);
|
||||||
print_header(head, print_event_info, !last_stmt_event);
|
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);
|
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();
|
thd->query_id= next_query_id();
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
TABLE_LIST *table_list;
|
RPL_TABLE_LIST *table_list;
|
||||||
char *db_mem, *tname_mem;
|
char *db_mem, *tname_mem;
|
||||||
void *const memory=
|
void *const memory=
|
||||||
my_multi_malloc(MYF(MY_WME),
|
my_multi_malloc(MYF(MY_WME),
|
||||||
&table_list, sizeof(TABLE_LIST),
|
&table_list, sizeof(RPL_TABLE_LIST),
|
||||||
&db_mem, NAME_LEN + 1,
|
&db_mem, NAME_LEN + 1,
|
||||||
&tname_mem, NAME_LEN + 1,
|
&tname_mem, NAME_LEN + 1,
|
||||||
NULL);
|
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.
|
Open the table if it is not already open and add the table to
|
||||||
Note that for any table that should not be replicated, a filter is needed.
|
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;
|
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)
|
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);
|
DBUG_ASSERT(m_table->in_use);
|
||||||
|
|
||||||
table_def const def(m_coltype, m_colcnt);
|
/*
|
||||||
if (def.compatible_with(rli, m_table))
|
Use placement new to construct the table_def instance in the
|
||||||
{
|
memory allocated for it inside table_list.
|
||||||
thd->query_error= 1;
|
|
||||||
error= ERR_BAD_TABLE_DEF;
|
The memory allocated by the table_def structure (i.e., not the
|
||||||
goto err;
|
memory allocated *for* the table_def structure) is released
|
||||||
/* purecov: end */
|
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
|
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_LC_TIME_NAMES_CODE 7
|
||||||
|
|
||||||
|
#define Q_CHARSET_DATABASE_CODE 8
|
||||||
/* Intvar event post-header */
|
/* Intvar event post-header */
|
||||||
|
|
||||||
#define I_TYPE_OFFSET 0
|
#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 charset[6]; // 3 variables, each of them storable in 2 bytes
|
||||||
char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
|
char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
|
||||||
uint lc_time_names_number;
|
uint lc_time_names_number;
|
||||||
|
uint charset_database_number;
|
||||||
st_print_event_info()
|
st_print_event_info()
|
||||||
:flags2_inited(0), sql_mode_inited(0),
|
:flags2_inited(0), sql_mode_inited(0),
|
||||||
auto_increment_increment(1),auto_increment_offset(1), charset_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
|
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(db, sizeof(db));
|
||||||
bzero(charset, sizeof(charset));
|
bzero(charset, sizeof(charset));
|
||||||
bzero(time_zone_str, sizeof(time_zone_str));
|
bzero(time_zone_str, sizeof(time_zone_str));
|
||||||
strcpy(delimiter, ";");
|
delimiter[0]= ';';
|
||||||
uint const flags = MYF(MY_WME | MY_NABP);
|
delimiter[1]= 0;
|
||||||
init_io_cache(&head_cache, -1, 0, WRITE_CACHE, 0L, FALSE, flags);
|
myf const flags = MYF(MY_WME | MY_NABP);
|
||||||
init_io_cache(&body_cache, -1, 0, WRITE_CACHE, 0L, FALSE, flags);
|
open_cached_file(&head_cache, NULL, NULL, 0, flags);
|
||||||
|
open_cached_file(&body_cache, NULL, NULL, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
~st_print_event_info() {
|
~st_print_event_info() {
|
||||||
end_io_cache(&head_cache);
|
close_cached_file(&head_cache);
|
||||||
end_io_cache(&body_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 */
|
/* Settings on how to print the events */
|
||||||
@ -846,6 +851,7 @@ public:
|
|||||||
uint time_zone_len; /* 0 means uninited */
|
uint time_zone_len; /* 0 means uninited */
|
||||||
const char *time_zone_str;
|
const char *time_zone_str;
|
||||||
uint lc_time_names_number; /* 0 means en_US */
|
uint lc_time_names_number; /* 0 means en_US */
|
||||||
|
uint charset_database_number;
|
||||||
|
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
|
|
||||||
@ -1153,6 +1159,7 @@ public:
|
|||||||
uint8 number_of_event_types;
|
uint8 number_of_event_types;
|
||||||
/* The list of post-headers' lengthes */
|
/* The list of post-headers' lengthes */
|
||||||
uint8 *post_header_len;
|
uint8 *post_header_len;
|
||||||
|
uchar server_version_split[3];
|
||||||
|
|
||||||
Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
|
Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
|
||||||
|
|
||||||
@ -1184,6 +1191,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
return FORMAT_DESCRIPTION_HEADER_LEN;
|
return FORMAT_DESCRIPTION_HEADER_LEN;
|
||||||
}
|
}
|
||||||
|
void calc_server_version_split();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1727,14 +1735,17 @@ public:
|
|||||||
TYPE_CODE = TABLE_MAP_EVENT
|
TYPE_CODE = TABLE_MAP_EVENT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enumeration of the errors that can be returned.
|
||||||
|
*/
|
||||||
enum enum_error
|
enum enum_error
|
||||||
{
|
{
|
||||||
ERR_OPEN_FAILURE = -1, /* Failure to open table */
|
ERR_OPEN_FAILURE = -1, /**< Failure to open table */
|
||||||
ERR_OK = 0, /* No error */
|
ERR_OK = 0, /**< No error */
|
||||||
ERR_TABLE_LIMIT_EXCEEDED = 1, /* No more room for tables */
|
ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */
|
||||||
ERR_OUT_OF_MEM = 2, /* Out of memory */
|
ERR_OUT_OF_MEM = 2, /**< Out of memory */
|
||||||
ERR_BAD_TABLE_DEF = 3, /* Table definition does not match */
|
ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */
|
||||||
ERR_RBR_TO_SBR = 4 /* daisy-chanining RBR to SBR not allowed */
|
ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum enum_flag
|
enum enum_flag
|
||||||
@ -1814,7 +1825,7 @@ private:
|
|||||||
|
|
||||||
Row level log event class.
|
Row level log event class.
|
||||||
|
|
||||||
Common base class for all row-level log events.
|
Common base class for all row-containing log events.
|
||||||
|
|
||||||
RESPONSIBILITIES
|
RESPONSIBILITIES
|
||||||
|
|
||||||
@ -1828,6 +1839,19 @@ private:
|
|||||||
class Rows_log_event : public Log_event
|
class Rows_log_event : public Log_event
|
||||||
{
|
{
|
||||||
public:
|
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
|
These definitions allow you to combine the flags into an
|
||||||
appropriate flag set using the normal bitwise operators. The
|
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
|
accepted by the compiler, which is then used to set the real set
|
||||||
of flags.
|
of flags.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum enum_flag
|
enum enum_flag
|
||||||
{
|
{
|
||||||
/* Last event of a statement */
|
/* 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 PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
|
||||||
#define all_bits_set(A,B) ((A) & (B) != (B))
|
#define all_bits_set(A,B) ((A) & (B) != (B))
|
||||||
|
|
||||||
#define WARN_DEPRECATED(Thd,Ver,Old,New) \
|
#define WARN_DEPRECATED(Thd,Ver,Old,New) \
|
||||||
do { \
|
do { \
|
||||||
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) >= 0); \
|
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0); \
|
||||||
push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \
|
if (((gptr)Thd) != NULL) \
|
||||||
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
|
push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \
|
||||||
(Old), (Ver), (New)); \
|
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)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
|
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
|
||||||
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
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_show_slave_auth_info, opt_sql_bin_update = 0;
|
||||||
my_bool opt_log_slave_updates= 0;
|
my_bool opt_log_slave_updates= 0;
|
||||||
my_bool opt_innodb;
|
my_bool opt_innodb;
|
||||||
|
bool slave_warning_issued = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Legacy global handlerton. These will be removed (please do not add more).
|
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;
|
ulong opt_binlog_rows_event_max_size;
|
||||||
const char *binlog_format_names[]= {"STATEMENT", "ROW", "MIXED", NullS};
|
const char *binlog_format_names[]= {"STATEMENT", "ROW", "MIXED", NullS};
|
||||||
TYPELIB binlog_format_typelib=
|
TYPELIB binlog_format_typelib=
|
||||||
{ array_elements(binlog_format_names)-1,"",
|
{ array_elements(binlog_format_names) - 1, "",
|
||||||
binlog_format_names, NULL };
|
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
|
#ifdef HAVE_INITGROUPS
|
||||||
static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
|
static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
|
||||||
#endif
|
#endif
|
||||||
@ -3255,17 +3257,24 @@ with --log-bin instead.");
|
|||||||
"--log-slave-updates work.");
|
"--log-slave-updates work.");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
|
if (!opt_bin_log)
|
||||||
if (!opt_bin_log && (global_system_variables.binlog_format != BINLOG_FORMAT_UNSPEC))
|
if (opt_binlog_format_id != BINLOG_FORMAT_UNSPEC)
|
||||||
{
|
{
|
||||||
sql_print_error("You need to use --log-bin to make "
|
sql_print_error("You need to use --log-bin to make "
|
||||||
"--binlog-format work.");
|
"--binlog-format work.");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
if (global_system_variables.binlog_format == BINLOG_FORMAT_UNSPEC)
|
else
|
||||||
{
|
{
|
||||||
|
global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (opt_binlog_format_id == BINLOG_FORMAT_UNSPEC)
|
||||||
global_system_variables.binlog_format= BINLOG_FORMAT_MIXED;
|
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 */
|
/* Check that we have not let the format to unspecified at this point */
|
||||||
DBUG_ASSERT((uint)global_system_variables.binlog_format <=
|
DBUG_ASSERT((uint)global_system_variables.binlog_format <=
|
||||||
@ -3401,7 +3410,7 @@ server.");
|
|||||||
(TC_LOG *) &tc_log_mmap) :
|
(TC_LOG *) &tc_log_mmap) :
|
||||||
(TC_LOG *) &tc_log_dummy);
|
(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");
|
sql_print_error("Can't init tc log");
|
||||||
unireg_abort(1);
|
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,
|
(gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR,
|
||||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"binlog_format", OPT_BINLOG_FORMAT,
|
{"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 "
|
"Tell the master the form of binary logging to use: either 'row' for "
|
||||||
"row-based binary logging, or 'statement' for statement-based binary "
|
"row-based binary logging, or 'statement' for statement-based binary "
|
||||||
"logging, or 'mixed'. 'mixed' is statement-based binary logging except "
|
"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 "
|
"involve user-defined functions (i.e. UDFs) or the UUID() function; for "
|
||||||
"those, row-based binary logging is automatically used. "
|
"those, row-based binary logging is automatically used. "
|
||||||
#ifdef HAVE_NDB_BINLOG
|
#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
|
#endif
|
||||||
, 0, 0, 0, GET_STR, REQUIRED_ARG,
|
,(gptr*) &opt_binlog_format, (gptr*) &opt_binlog_format,
|
||||||
BINLOG_FORMAT_MIXED
|
0, GET_STR, REQUIRED_ARG, BINLOG_FORMAT_MIXED, BINLOG_FORMAT_STMT,
|
||||||
, 0, 0, 0, 0, 0 },
|
BINLOG_FORMAT_MIXED, 0, 0, 0},
|
||||||
{"binlog-do-db", OPT_BINLOG_DO_DB,
|
{"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.",
|
"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},
|
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]);
|
binlog_format_names[BINLOG_FORMAT_MIXED]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
global_system_variables.binlog_format= id-1;
|
global_system_variables.binlog_format= opt_binlog_format_id= id - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_BINLOG_DO_DB:
|
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 */
|
case (int) OPT_STANDALONE: /* Dummy option for NT */
|
||||||
break;
|
break;
|
||||||
#endif
|
#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:
|
case OPT_CONSOLE:
|
||||||
if (opt_console)
|
if (opt_console)
|
||||||
opt_error_log= 0; // Force logs to stdout
|
opt_error_log= 0; // Force logs to stdout
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "rpl_rli.h"
|
#include "rpl_rli.h"
|
||||||
#include <my_dir.h> // For MY_STAT
|
#include <my_dir.h> // For MY_STAT
|
||||||
#include "sql_repl.h" // For check_binlog_magic
|
#include "sql_repl.h" // For check_binlog_magic
|
||||||
|
#include "rpl_utility.h"
|
||||||
|
|
||||||
static int count_relay_log_space(RELAY_LOG_INFO* rli);
|
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;
|
unsafe_to_stop_at= 0;
|
||||||
DBUG_VOID_RETURN;
|
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
|
#endif
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "rpl_tblmap.h"
|
#include "rpl_tblmap.h"
|
||||||
|
|
||||||
|
struct RPL_TABLE_LIST;
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
||||||
@ -279,7 +281,7 @@ typedef struct st_relay_log_info
|
|||||||
group_relay_log_pos);
|
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 */
|
uint tables_to_lock_count; /* RBR: Count of tables to lock */
|
||||||
table_mapping m_table_map; /* RBR: Mapping table-id to table */
|
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 transaction_end(THD*);
|
||||||
|
|
||||||
void cleanup_context(THD *, bool);
|
void cleanup_context(THD *, bool);
|
||||||
void clear_tables_to_lock() {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t unsafe_to_stop_at;
|
time_t unsafe_to_stop_at;
|
||||||
} RELAY_LOG_INFO;
|
} RELAY_LOG_INFO;
|
||||||
|
@ -22,98 +22,100 @@
|
|||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
|
|
||||||
uint32
|
struct st_relay_log_info;
|
||||||
field_length_from_packed(enum_field_types const field_type,
|
typedef st_relay_log_info RELAY_LOG_INFO;
|
||||||
byte const *const data);
|
|
||||||
|
|
||||||
/*
|
uint32
|
||||||
|
field_length_from_packed(enum_field_types field_type, byte const *data);
|
||||||
|
|
||||||
|
/**
|
||||||
A table definition from the master.
|
A table definition from the master.
|
||||||
|
|
||||||
RESPONSIBILITIES
|
The responsibilities of this class is:
|
||||||
|
|
||||||
- Extract and decode table definition data from the table map event
|
- Extract and decode table definition data from the table map event
|
||||||
- Check if table definition in table map is compatible with table
|
- Check if table definition in table map is compatible with table
|
||||||
definition on slave
|
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
|
@todo Add type operands to this structure to allow detection of
|
||||||
type operators that are present in the table map event.
|
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
|
class table_def
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*
|
/**
|
||||||
Convenience declaration of the type of the field type data in a
|
Convenience declaration of the type of the field type data in a
|
||||||
table map event.
|
table map event.
|
||||||
*/
|
*/
|
||||||
typedef unsigned char field_type;
|
typedef unsigned char field_type;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Constructor.
|
Constructor.
|
||||||
|
|
||||||
SYNOPSIS
|
@param types Array of types
|
||||||
table_def()
|
@param size Number of elements in array 'types'
|
||||||
types Array of types
|
|
||||||
size Number of elements in array 'types'
|
|
||||||
*/
|
*/
|
||||||
table_def(field_type *types, my_size_t size)
|
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.
|
Return the number of fields there is type data for.
|
||||||
|
|
||||||
SYNOPSIS
|
@return The number of fields that there is type data for.
|
||||||
size()
|
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
The number of fields that there is type data for.
|
|
||||||
*/
|
*/
|
||||||
my_size_t size() const { return m_size; }
|
my_size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return a representation of the type data for one field.
|
Return a representation of the type data for one field.
|
||||||
|
|
||||||
SYNOPSIS
|
@param index Field index to return data for
|
||||||
type()
|
|
||||||
i Field index to return data for
|
|
||||||
|
|
||||||
RETURN VALUE
|
@return Will return a representation of the type data for field
|
||||||
|
<code>index</code>. Currently, only the type identifier is
|
||||||
Will return a representation of the type data for field
|
returned.
|
||||||
'i'. 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.
|
Decide if the table definition is compatible with a table.
|
||||||
|
|
||||||
SYNOPSIS
|
Compare the definition with a table to see if it is compatible
|
||||||
compatible_with()
|
with it.
|
||||||
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:
|
|
||||||
|
|
||||||
|
A table definition is compatible with a table if:
|
||||||
- the columns types of the table definition is a (not
|
- the columns types of the table definition is a (not
|
||||||
necessarily proper) prefix of the column type of the table, or
|
necessarily proper) prefix of the column type of the table, or
|
||||||
|
|
||||||
- the other way around
|
- the other way around
|
||||||
|
|
||||||
RETURN VALUE
|
@param rli Pointer to relay log info
|
||||||
1 if the table definition is not compatible with 'table'
|
@param table Pointer to table to compare with.
|
||||||
0 if the table definition is compatible with 'table'
|
|
||||||
|
@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;
|
int compatible_with(RELAY_LOG_INFO *rli, TABLE *table) const;
|
||||||
|
|
||||||
@ -122,4 +124,15 @@ private:
|
|||||||
field_type *m_type; // Array of type descriptors
|
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 */
|
#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 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;
|
typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
|
||||||
|
|
||||||
@ -2205,11 +2206,16 @@ err:
|
|||||||
THD_CHECK_SENTRY(thd);
|
THD_CHECK_SENTRY(thd);
|
||||||
delete thd;
|
delete thd;
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
mi->abort_slave = 0;
|
mi->abort_slave= 0;
|
||||||
mi->slave_running = 0;
|
mi->slave_running= 0;
|
||||||
mi->io_thd = 0;
|
mi->io_thd= 0;
|
||||||
pthread_mutex_unlock(&mi->run_lock);
|
/*
|
||||||
|
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_cond_broadcast(&mi->stop_cond); // tell the world we are done
|
||||||
|
pthread_mutex_unlock(&mi->run_lock);
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
DBUG_RETURN(0); // Can't return anything here
|
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);
|
THD_CHECK_SENTRY(thd);
|
||||||
delete thd;
|
delete thd;
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
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);
|
pthread_cond_broadcast(&rli->stop_cond);
|
||||||
// tell the world we are done
|
pthread_mutex_unlock(&rli->run_lock); // tell the world we are done
|
||||||
pthread_mutex_unlock(&rli->run_lock);
|
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
DBUG_RETURN(0); // Can't return anything here
|
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
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||||
template class I_List_iterator<i_string>;
|
template class I_List_iterator<i_string>;
|
||||||
template class I_List_iterator<i_string_pair>;
|
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_master_info(THD* thd, MASTER_INFO* mi);
|
||||||
bool show_binlog_info(THD* thd);
|
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);
|
const char *print_slave_db_safe(const char *db);
|
||||||
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
|
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,
|
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
|
||||||
sp->m_name.str));
|
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)))
|
if (!(table= open_proc_table_for_update(thd)))
|
||||||
ret= SP_OPEN_TABLE_FAILED;
|
ret= SP_OPEN_TABLE_FAILED;
|
||||||
else
|
else
|
||||||
@ -634,6 +641,13 @@ db_drop_routine(THD *thd, int type, sp_name *name)
|
|||||||
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
||||||
type, name->m_name.length, name->m_name.str));
|
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)))
|
if (!(table= open_proc_table_for_update(thd)))
|
||||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
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",
|
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
||||||
type, name->m_name.length, name->m_name.str));
|
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)))
|
if (!(table= open_proc_table_for_update(thd)))
|
||||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
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)
|
if (need_binlog_call)
|
||||||
{
|
{
|
||||||
|
query_id_t q;
|
||||||
reset_dynamic(&thd->user_var_events);
|
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;
|
binlog_save_options= thd->options;
|
||||||
thd->options&= ~OPTION_BIN_LOG;
|
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].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
|
||||||
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
|
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
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
/*
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
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].lock_type=tables[1].lock_type=TL_WRITE;
|
||||||
tables[0].db=tables[1].db=(char*) "mysql";
|
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
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
/*
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
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].lock_type=tables[1].lock_type=TL_WRITE;
|
||||||
tables[0].db=tables[1].db=(char*) "mysql";
|
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
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
/*
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
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];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_create_user");
|
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. */
|
/* CREATE USER may be skipped on replication client. */
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
@ -5473,6 +5501,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_drop_user");
|
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. */
|
/* DROP USER may be skipped on replication client. */
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
@ -5537,6 +5572,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_rename_user");
|
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. */
|
/* RENAME USER may be skipped on replication client. */
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
@ -5612,6 +5654,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_revoke_all");
|
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)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
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);
|
rw_wrlock(&LOCK_grant);
|
||||||
VOID(pthread_mutex_lock(&acl_cache->lock));
|
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 */
|
/* Remove procedure access */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -997,6 +997,7 @@ sql_exchange::sql_exchange(char *name,bool flag)
|
|||||||
enclosed= line_start= &my_empty_string;
|
enclosed= line_start= &my_empty_string;
|
||||||
line_term= &default_line_term;
|
line_term= &default_line_term;
|
||||||
escaped= &default_escaped;
|
escaped= &default_escaped;
|
||||||
|
cs= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool select_send::send_fields(List<Item> &list, uint flags)
|
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)
|
!current_stmt_binlog_row_based)
|
||||||
{
|
{
|
||||||
options&= ~OPTION_BIN_LOG;
|
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 */
|
/* Disable result sets */
|
||||||
client_capabilities &= ~CLIENT_MULTI_RESULTS;
|
client_capabilities &= ~CLIENT_MULTI_RESULTS;
|
||||||
in_sub_stmt|= new_state;
|
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;
|
sent_row_count= backup->sent_row_count;
|
||||||
client_capabilities= backup->client_capabilities;
|
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
|
The following is added to the old values as we are interested in the
|
||||||
total complexity of the query
|
total complexity of the query
|
||||||
|
@ -1656,6 +1656,7 @@ public:
|
|||||||
bool opt_enclosed;
|
bool opt_enclosed;
|
||||||
bool dumpfile;
|
bool dumpfile;
|
||||||
ulong skip_lines;
|
ulong skip_lines;
|
||||||
|
CHARSET_INFO *cs;
|
||||||
sql_exchange(char *name,bool dumpfile_flag);
|
sql_exchange(char *name,bool dumpfile_flag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include "sql_trigger.h"
|
#include "sql_trigger.h"
|
||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
#include "sql_show.h"
|
#include "sql_show.h"
|
||||||
|
#include "slave.h"
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
|
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;
|
Name_resolution_context_state ctx_state;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
char *query= thd->query;
|
char *query= thd->query;
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
log_on is about delayed inserts only.
|
log_on is about delayed inserts only.
|
||||||
By default, both logs are enabled (this won't cause problems if the server
|
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) ||
|
bool log_on= ((thd->options & OPTION_BIN_LOG) ||
|
||||||
(!(thd->security_ctx->master_access & SUPER_ACL)));
|
(!(thd->security_ctx->master_access & SUPER_ACL)));
|
||||||
#endif
|
|
||||||
thr_lock_type lock_type = table_list->lock_type;
|
thr_lock_type lock_type = table_list->lock_type;
|
||||||
Item *unused_conds= 0;
|
Item *unused_conds= 0;
|
||||||
DBUG_ENTER("mysql_insert");
|
DBUG_ENTER("mysql_insert");
|
||||||
@ -391,6 +392,36 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
(duplic == DUP_UPDATE))
|
(duplic == DUP_UPDATE))
|
||||||
lock_type=TL_WRITE;
|
lock_type=TL_WRITE;
|
||||||
#endif
|
#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;
|
table_list->lock_type= lock_type;
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -505,6 +536,14 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
thd->cuted_fields = 0L;
|
thd->cuted_fields = 0L;
|
||||||
table->next_number_field=table->found_next_number_field;
|
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;
|
error=0;
|
||||||
thd->proc_info="update";
|
thd->proc_info="update";
|
||||||
if (duplic != DUP_ERROR || ignore)
|
if (duplic != DUP_ERROR || ignore)
|
||||||
@ -1195,14 +1234,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
if (res == VIEW_CHECK_ERROR)
|
if (res == VIEW_CHECK_ERROR)
|
||||||
goto before_trg_err;
|
goto before_trg_err;
|
||||||
|
|
||||||
|
table->file->restore_auto_increment(prev_insert_id);
|
||||||
if ((error=table->file->ha_update_row(table->record[1],
|
if ((error=table->file->ha_update_row(table->record[1],
|
||||||
table->record[0])))
|
table->record[0])))
|
||||||
{
|
{
|
||||||
if (info->ignore &&
|
if (info->ignore &&
|
||||||
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
!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 ok_or_after_trg_err;
|
||||||
}
|
}
|
||||||
goto 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
|
restore_record(table,s->default_values); // Get empty record
|
||||||
table->next_number_field=table->found_next_number_field;
|
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;
|
thd->cuted_fields=0;
|
||||||
if (info.ignore || info.handle_duplicates != DUP_ERROR)
|
if (info.ignore || info.handle_duplicates != DUP_ERROR)
|
||||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
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",
|
("Current statement %s row-based",
|
||||||
thd->current_stmt_binlog_row_based ? "is" : "is NOT"));
|
thd->current_stmt_binlog_row_based ? "is" : "is NOT"));
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
("Current table (at 0x%lx) %s a temporary (or non-existing) "
|
("Current table (at 0x%lu) %s a temporary (or non-existant) table",
|
||||||
"table",
|
|
||||||
(ulong) table,
|
(ulong) table,
|
||||||
table && !table->s->tmp_table ? "is NOT" : "is"));
|
table && !table->s->tmp_table ? "is NOT" : "is"));
|
||||||
DBUG_PRINT("info",
|
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.handle_duplicates=handle_duplicates;
|
||||||
info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
|
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,
|
*field_term,*ex->line_start, *ex->line_term, *enclosed,
|
||||||
info.escape_char, read_file_from_client, is_fifo);
|
info.escape_char, read_file_from_client, is_fifo);
|
||||||
if (read_info.error)
|
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,
|
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
|
||||||
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
|
||||||
send_ok(thd,info.copied+info.deleted,0L,name);
|
|
||||||
|
|
||||||
if (!transactional_table)
|
if (!transactional_table)
|
||||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
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)
|
if (transactional_table)
|
||||||
error=ha_autocommit_or_rollback(thd,error);
|
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:
|
err:
|
||||||
table->file->ha_release_auto_increment();
|
table->file->ha_release_auto_increment();
|
||||||
if (thd->lock)
|
if (thd->lock)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "sp_cache.h"
|
#include "sp_cache.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "event_data_objects.h"
|
#include "event_data_objects.h"
|
||||||
|
#include "sql_trigger.h"
|
||||||
|
|
||||||
/* Used in error handling only */
|
/* Used in error handling only */
|
||||||
#define SP_TYPE_STRING(LP) \
|
#define SP_TYPE_STRING(LP) \
|
||||||
@ -1682,6 +1683,30 @@ mysql_execute_command(THD *thd)
|
|||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
if (unlikely(thd->slave_thread))
|
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
|
Check if statment should be skipped because of slave filtering
|
||||||
rules
|
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 )
|
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("stop_slave");
|
||||||
|
|
||||||
int slave_errno;
|
int slave_errno;
|
||||||
if (!thd)
|
if (!thd)
|
||||||
thd = current_thd;
|
thd = current_thd;
|
||||||
|
|
||||||
if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
|
if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
|
||||||
return 1;
|
DBUG_RETURN(1);
|
||||||
thd->proc_info = "Killing slave";
|
thd->proc_info = "Killing slave";
|
||||||
int thread_mask;
|
int thread_mask;
|
||||||
lock_slave_threads(mi);
|
lock_slave_threads(mi);
|
||||||
@ -925,12 +927,12 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
|
|||||||
{
|
{
|
||||||
if (net_report)
|
if (net_report)
|
||||||
my_message(slave_errno, ER(slave_errno), MYF(0));
|
my_message(slave_errno, ER(slave_errno), MYF(0));
|
||||||
return 1;
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
else if (net_report)
|
else if (net_report)
|
||||||
send_ok(thd);
|
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;
|
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
|
||||||
SELECT_LEX sel;
|
SELECT_LEX sel;
|
||||||
INDEX_FIELD_VALUES idx_field_vals;
|
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;
|
uint len;
|
||||||
bool with_i_schema;
|
bool with_i_schema;
|
||||||
enum enum_schema_tables schema_table_idx;
|
enum enum_schema_tables schema_table_idx;
|
||||||
@ -2550,7 +2550,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||||||
#endif
|
#endif
|
||||||
DBUG_ENTER("get_all_tables");
|
DBUG_ENTER("get_all_tables");
|
||||||
|
|
||||||
LINT_INIT(end);
|
|
||||||
LINT_INIT(len);
|
LINT_INIT(len);
|
||||||
|
|
||||||
lex->view_prepare_mode= TRUE;
|
lex->view_prepare_mode= TRUE;
|
||||||
@ -2642,7 +2641,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
len= build_table_filename(path, sizeof(path), base_name, "", "", 0);
|
len= build_table_filename(path, sizeof(path), base_name, "", "", 0);
|
||||||
end= path + len;
|
|
||||||
len= FN_LEN - len;
|
len= FN_LEN - len;
|
||||||
find_files_result res= find_files(thd, &files, base_name,
|
find_files_result res= find_files(thd, &files, base_name,
|
||||||
path, idx_field_vals.table_value, 0);
|
path, idx_field_vals.table_value, 0);
|
||||||
@ -2692,7 +2690,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||||||
}
|
}
|
||||||
else
|
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)) {
|
switch (mysql_frm_type(thd, path, ¬_used)) {
|
||||||
case FRMTYPE_ERROR:
|
case FRMTYPE_ERROR:
|
||||||
table->field[3]->store(STRING_WITH_LEN("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
|
class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -1180,7 +1176,7 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
|||||||
1 Error
|
1 Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
int
|
||||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
||||||
TABLE_LIST **table)
|
TABLE_LIST **table)
|
||||||
{
|
{
|
||||||
|
@ -137,3 +137,7 @@ private:
|
|||||||
|
|
||||||
extern const LEX_STRING trg_action_time_type_names[];
|
extern const LEX_STRING trg_action_time_type_names[];
|
||||||
extern const LEX_STRING trg_event_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
|
old_or_new_charset_name_or_default
|
||||||
collation_name
|
collation_name
|
||||||
collation_name_or_default
|
collation_name_or_default
|
||||||
|
opt_load_data_charset
|
||||||
|
|
||||||
%type <variable> internal_variable_name
|
%type <variable> internal_variable_name
|
||||||
|
|
||||||
@ -4736,6 +4737,10 @@ charset_name_or_default:
|
|||||||
charset_name { $$=$1; }
|
charset_name { $$=$1; }
|
||||||
| DEFAULT { $$=NULL; } ;
|
| DEFAULT { $$=NULL; } ;
|
||||||
|
|
||||||
|
opt_load_data_charset:
|
||||||
|
/* Empty */ { $$= NULL; }
|
||||||
|
| charset charset_name_or_default { $$= $2; }
|
||||||
|
;
|
||||||
|
|
||||||
old_or_new_charset_name:
|
old_or_new_charset_name:
|
||||||
ident_or_text
|
ident_or_text
|
||||||
@ -9048,6 +9053,8 @@ load_data:
|
|||||||
lex->update_list.empty();
|
lex->update_list.empty();
|
||||||
lex->value_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_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
|
||||||
opt_load_data_set_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
|
If true, the current table row is considered to have all columns set to
|
||||||
NULL, including columns declared as "not null" (see maybe_null).
|
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 null_row;
|
||||||
my_bool force_index;
|
my_bool force_index;
|
||||||
@ -415,6 +419,7 @@ struct st_table {
|
|||||||
my_bool key_read, no_keyread;
|
my_bool key_read, no_keyread;
|
||||||
my_bool locked_by_flush;
|
my_bool locked_by_flush;
|
||||||
my_bool locked_by_logger;
|
my_bool locked_by_logger;
|
||||||
|
my_bool no_replicate;
|
||||||
my_bool locked_by_name;
|
my_bool locked_by_name;
|
||||||
my_bool fulltext_searched;
|
my_bool fulltext_searched;
|
||||||
my_bool no_cache;
|
my_bool no_cache;
|
||||||
|
@ -115,8 +115,6 @@ static const char table_name_separator = '/';
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
inline void* operator new(size_t, void* __p) { return __p; }
|
|
||||||
inline void* operator new[](size_t, void* __p) { return __p; }
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user