Merge dl145h.mysql.com:/data0/mkindahl/mysql-5.0

into  dl145h.mysql.com:/data0/mkindahl/mysql-5.0-rpl-merge


client/mysql.cc:
  Auto merged
mysql-test/r/ctype_ucs.result:
  Auto merged
mysql-test/t/ctype_uca.test:
  Auto merged
mysql-test/t/ctype_ucs.test:
  Auto merged
mysql-test/t/subselect.test:
  Auto merged
sql/item_cmpfunc.cc:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
This commit is contained in:
unknown 2007-11-21 21:11:57 +01:00
commit d295bfaa76
59 changed files with 2218 additions and 404 deletions

55
BUILD/compile-solaris-amd64 Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/bash
function _find_mysql_root () (
while [ "x$PWD" != "x/" ]; do
# Check if some directories are present
if [ -d BUILD -a -d sql -a -d mysys ]; then
echo "$PWD"
return 0
fi
cd ..
done
return 1
)
make -k clean || true
/bin/rm -f */.deps/*.P config.cache
path=`dirname $0`
. "$path/autorun.sh"
warning_flags="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused"
compiler_flags="-g -O3 -fno-omit-frame-pointer"
export CC CXX CFLAGS CXXFLAGS LDFLAGS LIBS
CC="gcc"
CXX="gcc"
CFLAGS="$warning_flags $compiler_flags"
CXXFLAGS=""
LDFLAGS="-O3 -g -static-libgcc"
LIBS=-lmtmalloc
root=$(_find_mysql_root)
$root/configure \
--prefix=/usr/local/mysql \
--localstatedir=/usr/local/mysql/data \
--libexecdir=/usr/local/mysql/bin \
--with-extra-charsets=complex \
--enable-thread-safe-client \
--enable-local-infile \
--with-zlib-dir=bundled \
--with-big-tables \
--with-readline \
--with-archive-storage-engine \
--with-named-curses=-lcurses \
--with-big-tables \
--with-innodb \
--with-berkeley-db \
--with-example-storage-engine \
--with-blackhole-storage-engine \
--with-ndbcluster \
--with-federated-storage-engine \
--with-csv-storage-engine \
--with-ssl \
--with-embedded-server \
--disable-shared

View file

@ -1052,6 +1052,17 @@ static int read_and_execute(bool interactive)
if (!interactive)
{
line=batch_readline(status.line_buff);
/*
Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF.
Editors like "notepad" put this marker in
the very beginning of a text file when
you save the file using "Unicode UTF-8" format.
*/
if (!line_number &&
(uchar) line[0] == 0xEF &&
(uchar) line[1] == 0xBB &&
(uchar) line[2] == 0xBF)
line+= 3;
line_number++;
if (!glob_buffer.length())
status.query_start_line=line_number;

View file

@ -0,0 +1,42 @@
#
# To test a desired collation, set session.collation_connection to
# this collation before including this file
#
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Create a table with two varchar(64) null-able column,
# using current values of
# @@character_set_connection and @@collation_connection.
#
create table t1 as
select repeat(' ', 64) as s1, repeat(' ',64) as s2
union
select null, null;
show create table t1;
delete from t1;
insert into t1 values('aaa','aaa');
insert into t1 values('aaa|qqq','qqq');
insert into t1 values('gheis','^[^a-dXYZ]+$');
insert into t1 values('aab','^aa?b');
insert into t1 values('Baaan','^Ba*n');
insert into t1 values('aaa','qqq|aaa');
insert into t1 values('qqq','qqq|aaa');
insert into t1 values('bbb','qqq|aaa');
insert into t1 values('bbb','qqq');
insert into t1 values('aaa','aba');
insert into t1 values(null,'abc');
insert into t1 values('def',null);
insert into t1 values(null,null);
insert into t1 values('ghi','ghi[');
select HIGH_PRIORITY s1 regexp s2 from t1;
drop table t1;

View file

@ -9,4 +9,48 @@ insert into t2 values (null, null), (null, get_lock("a", 10));
select @result /* must be zero either way */;
@result
0
select RELEASE_LOCK("a");
RELEASE_LOCK("a")
1
delete from t1;
delete from t2;
insert into t1 values (1,1),(2,2);
begin;
update t1 set b=11 where a=2;
begin;
update t1 set b=b+10;
kill query ID;
rollback;
rollback;
select * from t1 order by a /* must be the same as before (1,1),(2,2) */;
a b
1 1
2 2
begin;
delete from t1 where a=2;
begin;
delete from t1 where a=2;
kill query ID;
rollback;
rollback;
select * from t1 order by a /* must be the same as before (1,1),(2,2) */;
a b
1 1
2 2
drop table if exists t4;
create table t4 (a int, b int) engine=innodb;
insert into t4 values (3, 3);
begin;
insert into t1 values (3, 3);
begin;
insert into t1 select * from t4 for update;
kill query ID;
rollback;
rollback;
select * from t1 /* must be the same as before (1,1),(2,2) */;
a b
1 1
2 2
drop table t4;
drop table t1,t2,t3;
end of the tests

View file

@ -0,0 +1,33 @@
drop table if exists t1,t2;
create table t1 (a int) engine=MyISAM;
insert into t1 set a=1;
reset master;
update t1 set a=2 /* will be "killed" after work has been done */;
select
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
is not null;
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
is not null
1
select 1 /* must return 1 as query completed before got killed*/;
1
1
create table t2 (a int, b int) ENGINE=MyISAM;
reset master;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */;
ERROR 70100: Query execution was interrupted
show binlog events from 98;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 98 Begin_load_query 1 # ;file_id=1;block_len=12
master-bin.000001 133 Execute_load_query 1 # use `test`; load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */ ;file_id=1
select
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
is not null;
(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
is not null
1
select 0 /* must return 0 to mean the killed query is in */;
0
0
drop table t1,t2;
end of the tests

View file

@ -178,3 +178,44 @@ hex(a)
A2E6
FEF7
DROP TABLE t1;
create table t1 (s1 varchar(5) character set euckr);
insert into t1 values (0xA141);
insert into t1 values (0xA15A);
insert into t1 values (0xA161);
insert into t1 values (0xA17A);
insert into t1 values (0xA181);
insert into t1 values (0xA1FE);
insert into t1 values (0xA140);
Warnings:
Warning 1366 Incorrect string value: '\xA1@' for column 's1' at row 1
insert into t1 values (0xA15B);
Warnings:
Warning 1366 Incorrect string value: '\xA1[' for column 's1' at row 1
insert into t1 values (0xA160);
Warnings:
Warning 1366 Incorrect string value: '\xA1`' for column 's1' at row 1
insert into t1 values (0xA17B);
Warnings:
Warning 1366 Incorrect string value: '\xA1{' for column 's1' at row 1
insert into t1 values (0xA180);
Warnings:
Warning 1366 Incorrect string value: '\xA1\x80' for column 's1' at row 1
insert into t1 values (0xA1FF);
Warnings:
Warning 1366 Incorrect string value: '\xA1\xFF' for column 's1' at row 1
select hex(s1), hex(convert(s1 using utf8)) from t1 order by binary s1;
hex(s1) hex(convert(s1 using utf8))
A141 ECA2A5
A15A ECA381
A161 ECA382
A17A ECA3A5
A181 ECA3A6
A1FE EFBFA2
drop table t1;
End of 5.0 tests

View file

@ -2767,4 +2767,49 @@ a
c
ch
drop table t1;
set collation_connection=ucs2_unicode_ci;
drop table if exists t1;
create table t1 as
select repeat(' ', 64) as s1, repeat(' ',64) as s2
union
select null, null;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`s1` varchar(64) character set ucs2 collate ucs2_unicode_ci default NULL,
`s2` varchar(64) character set ucs2 collate ucs2_unicode_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
delete from t1;
insert into t1 values('aaa','aaa');
insert into t1 values('aaa|qqq','qqq');
insert into t1 values('gheis','^[^a-dXYZ]+$');
insert into t1 values('aab','^aa?b');
insert into t1 values('Baaan','^Ba*n');
insert into t1 values('aaa','qqq|aaa');
insert into t1 values('qqq','qqq|aaa');
insert into t1 values('bbb','qqq|aaa');
insert into t1 values('bbb','qqq');
insert into t1 values('aaa','aba');
insert into t1 values(null,'abc');
insert into t1 values('def',null);
insert into t1 values(null,null);
insert into t1 values('ghi','ghi[');
select HIGH_PRIORITY s1 regexp s2 from t1;
s1 regexp s2
1
1
1
1
1
1
1
0
0
0
NULL
NULL
NULL
NULL
drop table t1;
set names utf8;
End for 5.0 tests

View file

@ -928,6 +928,51 @@ ERROR HY000: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (ucs2_gen
select * from t1 where a=if(b<10,_ucs2 0x0062,_ucs2 0x00C0);
ERROR HY000: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (ucs2_general_ci,COERCIBLE) for operation '='
drop table t1;
set collation_connection=ucs2_general_ci;
drop table if exists t1;
create table t1 as
select repeat(' ', 64) as s1, repeat(' ',64) as s2
union
select null, null;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`s1` varchar(64) character set ucs2 default NULL,
`s2` varchar(64) character set ucs2 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
delete from t1;
insert into t1 values('aaa','aaa');
insert into t1 values('aaa|qqq','qqq');
insert into t1 values('gheis','^[^a-dXYZ]+$');
insert into t1 values('aab','^aa?b');
insert into t1 values('Baaan','^Ba*n');
insert into t1 values('aaa','qqq|aaa');
insert into t1 values('qqq','qqq|aaa');
insert into t1 values('bbb','qqq|aaa');
insert into t1 values('bbb','qqq');
insert into t1 values('aaa','aba');
insert into t1 values(null,'abc');
insert into t1 values('def',null);
insert into t1 values(null,null);
insert into t1 values('ghi','ghi[');
select HIGH_PRIORITY s1 regexp s2 from t1;
s1 regexp s2
1
1
1
1
1
1
1
0
0
0
NULL
NULL
NULL
NULL
drop table t1;
set names latin1;
select hex(char(0x41 using ucs2));
hex(char(0x41 using ucs2))
0041

View file

@ -267,6 +267,51 @@ b
select * from t1 where a = 'b' and a != 'b';
a
drop table t1;
set collation_connection=utf8_general_ci;
drop table if exists t1;
create table t1 as
select repeat(' ', 64) as s1, repeat(' ',64) as s2
union
select null, null;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`s1` varchar(64) character set utf8 default NULL,
`s2` varchar(64) character set utf8 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
delete from t1;
insert into t1 values('aaa','aaa');
insert into t1 values('aaa|qqq','qqq');
insert into t1 values('gheis','^[^a-dXYZ]+$');
insert into t1 values('aab','^aa?b');
insert into t1 values('Baaan','^Ba*n');
insert into t1 values('aaa','qqq|aaa');
insert into t1 values('qqq','qqq|aaa');
insert into t1 values('bbb','qqq|aaa');
insert into t1 values('bbb','qqq');
insert into t1 values('aaa','aba');
insert into t1 values(null,'abc');
insert into t1 values('def',null);
insert into t1 values(null,null);
insert into t1 values('ghi','ghi[');
select HIGH_PRIORITY s1 regexp s2 from t1;
s1 regexp s2
1
1
1
1
1
1
1
0
0
0
NULL
NULL
NULL
NULL
drop table t1;
set names utf8;
set names utf8;
select 'вася' rlike '[[:<:]]вася[[:>:]]';
'вася' rlike '[[:<:]]вася[[:>:]]'

View file

@ -1,5 +1,17 @@
drop table if exists t1;
create table t1 (s1 char(64),s2 char(64));
set names latin1;
drop table if exists t1;
create table t1 as
select repeat(' ', 64) as s1, repeat(' ',64) as s2
union
select null, null;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`s1` varchar(64) default NULL,
`s2` varchar(64) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
delete from t1;
insert into t1 values('aaa','aaa');
insert into t1 values('aaa|qqq','qqq');
insert into t1 values('gheis','^[^a-dXYZ]+$');

View file

@ -1119,6 +1119,19 @@ show master status /* there must be no UPDATE query event */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 98
drop table t1, t2;
drop table if exists t1, t2;
CREATE TABLE t1 (a int, PRIMARY KEY (a));
CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
create trigger trg_del_t2 after delete on t2 for each row
insert into t1 values (1);
insert into t1 values (1);
insert into t2 values (1),(2);
delete t2 from t2;
ERROR 23000: Duplicate entry '1' for key 1
select count(*) from t2 /* must be 2 as restored after rollback caused by the error */;
count(*)
2
drop table t1, t2;
create table t1 (a int, b int) engine=innodb;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
@ -1792,10 +1805,10 @@ Variable_name Value
Innodb_page_size 16384
show status like "Innodb_rows_deleted";
Variable_name Value
Innodb_rows_deleted 72
Innodb_rows_deleted 73
show status like "Innodb_rows_inserted";
Variable_name Value
Innodb_rows_inserted 29732
Innodb_rows_inserted 29734
show status like "Innodb_rows_updated";
Variable_name Value
Innodb_rows_updated 29532

View file

@ -351,7 +351,7 @@ drop function if exists bug27417;
drop table if exists t1,t2;
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));
create function bug27417(n int)
create function bug27417(n int)
RETURNS int(11)
begin
insert into t1 values (null);
@ -365,7 +365,7 @@ insert into t2 values (bug27417(2));
ERROR 23000: Duplicate entry '2' for key 1
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 98
master-bin.000001 196
/* only (!) with fixes for #23333 will show there is the query */;
select count(*) from t1 /* must be 3 */;
count(*)
@ -390,6 +390,119 @@ affected rows: 0
select count(*) from t1 /* must be 7 */;
count(*)
7
drop function bug27417;
drop table t1,t2;
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique) ENGINE=MyISAM;
CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique) ENGINE=Innodb;
CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
insert into t2 values (1);
reset master;
insert into t2 values (bug27417(1));
ERROR 23000: Duplicate entry '1' for key 1
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 267
select count(*) from t1 /* must be 1 */;
count(*)
1
delete from t1;
delete from t2;
insert into t2 values (2);
reset master;
insert into t2 select bug27417(1) union select bug27417(2);
ERROR 23000: Duplicate entry '2' for key 1
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 290
select count(*) from t1 /* must be 2 */;
count(*)
2
delete from t1;
insert into t3 values (1,1),(2,3),(3,4);
reset master;
update t3 set b=b+bug27417(1);
ERROR 23000: Duplicate entry '4' for key 2
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 190
select count(*) from t1 /* must be 2 */;
count(*)
2
delete from t3;
delete from t4;
insert into t3 values (1,1);
insert into t4 values (1,1),(2,2);
reset master;
UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */;
ERROR 23000: Duplicate entry '2' for key 1
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 301
select count(*) from t1 /* must be 4 */;
count(*)
4
delete from t1;
delete from t3;
delete from t4;
insert into t3 values (1,1),(2,2);
insert into t4 values (1,1),(2,2);
reset master;
UPDATE t3,t4 SET t3.a=t4.a + bug27417(1);
ERROR 23000: Duplicate entry '2' for key 1
select count(*) from t1 /* must be 1 */;
count(*)
1
drop table t4;
delete from t1;
delete from t2;
delete from t3;
insert into t2 values (1);
insert into t3 values (1,1);
create trigger trg_del before delete on t2 for each row
insert into t3 values (bug27417(1), 2);
reset master;
delete from t2;
ERROR 23000: Duplicate entry '1' for key 1
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 246
select count(*) from t1 /* must be 1 */;
count(*)
1
drop trigger trg_del;
delete from t1;
delete from t2;
delete from t5;
create trigger trg_del_t2 after delete on t2 for each row
insert into t1 values (1);
insert into t2 values (2),(3);
insert into t5 values (1),(2);
reset master;
delete t2.* from t2,t5 where t2.a=t5.a + 1;
ERROR 23000: Duplicate entry '1' for key 1
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 274
select count(*) from t1 /* must be 1 */;
count(*)
1
delete from t1;
create table t4 (a int default 0, b int primary key) engine=innodb;
insert into t4 values (0, 17);
reset master;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2);
ERROR 23000: Duplicate entry '17' for key 1
select * from t4;
a b
0 17
select count(*) from t1 /* must be 2 */;
count(*)
2
show master status /* the offset must denote there is the query */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 376
drop trigger trg_del_t2;
drop table t1,t2,t3,t4,t5;
drop function bug27417;
end of tests

View file

@ -545,7 +545,7 @@ a b
4 4
show master status /* there must be the UPDATE query event */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 189
master-bin.000001 260
delete from t1;
delete from t2;
insert into t1 values (1,2),(3,4),(4,4);
@ -555,6 +555,26 @@ UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
ERROR 23000: Duplicate entry '4' for key 1
show master status /* there must be the UPDATE query event */;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 204
master-bin.000001 275
drop table t1, t2;
drop table if exists t1, t2, t3;
CREATE TABLE t1 (a int, PRIMARY KEY (a));
CREATE TABLE t2 (a int, PRIMARY KEY (a));
CREATE TABLE t3 (a int, PRIMARY KEY (a)) ENGINE=MyISAM;
create trigger trg_del_t3 before delete on t3 for each row insert into t1 values (1);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
reset master;
delete t3.* from t2,t3 where t2.a=t3.a;
ERROR 23000: Duplicate entry '1' for key 1
select count(*) from t1 /* must be 1 */;
count(*)
1
select count(*) from t3 /* must be 1 */;
count(*)
1
show binlog events from 98;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 98 Query 1 # use `test`; delete t3.* from t2,t3 where t2.a=t3.a
drop table t1, t2, t3;
end of tests

View file

@ -178,4 +178,6 @@ ERROR at line 1: DELIMITER cannot contain a backslash character
1
1
1
This is a file starting with UTF8 BOM 0xEFBBBF
This is a file starting with UTF8 BOM 0xEFBBBF
End of 5.0 tests

View file

@ -325,4 +325,5 @@ flush logs;
drop table t1;
1
drop table t1;
shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql
End of 5.0 tests

View file

@ -21,6 +21,37 @@ STOP SLAVE;
START SLAVE;
CREATE TABLe `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048');
SHOW STATUS LIKE 'Slave_running';
Variable_name Value
Slave_running OFF
show slave status;
Slave_IO_State #
Master_Host 127.0.0.1
Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 2138
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running No
Slave_SQL_Running #
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 2138
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 #

View file

@ -0,0 +1,144 @@
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;
**** On Master ****
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
==== Skipping normal transactions ====
**** On Slave ****
STOP SLAVE;
**** On Master ****
BEGIN;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (4, 'master,slave');
INSERT INTO t1 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, 'master,slave');
COMMIT;
SELECT * FROM t1 ORDER BY a;
a b
1 master
2 master
3 master
4 master,slave
5 master,slave
6 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
4 master,slave
5 master,slave
6 master,slave
**** On Master ****
DELETE FROM t1;
==== Skipping two normal transactions ====
**** On Slave ****
STOP SLAVE;
**** On Master ****
BEGIN;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (4, 'master');
INSERT INTO t1 VALUES (5, 'master');
INSERT INTO t1 VALUES (6, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (7, 'master,slave');
INSERT INTO t1 VALUES (8, 'master,slave');
INSERT INTO t1 VALUES (9, 'master,slave');
COMMIT;
SELECT * FROM t1 ORDER BY a;
a b
1 master
2 master
3 master
4 master
5 master
6 master
7 master,slave
8 master,slave
9 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
7 master,slave
8 master,slave
9 master,slave
**** On Master ****
DELETE FROM t1;
==== Skipping without autocommit ====
**** On Slave ****
STOP SLAVE;
**** On Master ****
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
INSERT INTO t1 VALUES (4, 'master,slave');
INSERT INTO t1 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, 'master,slave');
COMMIT;
SELECT * FROM t1 ORDER BY a;
a b
1 master
2 master
3 master
4 master,slave
5 master,slave
6 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
4 master,slave
5 master,slave
6 master,slave
==== Rollback of transaction with non-transactional change ====
**** On Master ****
DELETE FROM t1;
SET AUTOCOMMIT=1;
**** On Slave ****
STOP SLAVE;
**** On Master ****
BEGIN;
INSERT INTO t1 VALUES (1, '');
INSERT INTO t2 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, '');
ROLLBACK;
BEGIN;
INSERT INTO t1 VALUES (4, '');
INSERT INTO t2 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, '');
ROLLBACK;
SELECT * FROM t1 ORDER BY a;
a b
SELECT * FROM t2 ORDER BY a;
a b
2 master
5 master,slave
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
SELECT * FROM t1 ORDER BY a;
a b
SELECT * FROM t2 ORDER BY a;
a b
5 master,slave
==== Cleanup ====
**** On Master ****
DROP TABLE t1, t2;

View file

@ -213,3 +213,44 @@ drop table t1;
drop function f1;
drop function f2;
drop procedure p1;
create table t2 (b BIT(7));
create procedure sp_bug26199(bitvalue BIT(7))
begin
insert into t2 set b = bitvalue;
end //
create function sf_bug26199(b BIT(7)) returns int
begin
insert into t2 values(b);
return 0;
end//
call sp_bug26199(b'1110');
call sp_bug26199('\0');
select sf_bug26199(b'1111111');
sf_bug26199(b'1111111')
0
select sf_bug26199(b'101111111');
sf_bug26199(b'101111111')
0
Warnings:
Warning 1264 Out of range value adjusted for column 'b' at row 1
select sf_bug26199('\'');
sf_bug26199('\'')
0
select hex(b) from t2;
hex(b)
E
0
7F
7F
27
select hex(b) from t2;
hex(b)
E
0
7F
7F
27
drop table t2;
drop procedure sp_bug26199;
drop function sf_bug26199;
end of the tests

View file

@ -12,8 +12,10 @@ end|
reset master|
insert into t2 values (bug23333(),1)|
ERROR 23000: Duplicate entry '1' for key 1
show binlog events from 98 /* with fixes for #23333 will show there is the query */|
show binlog events from 98 /* with fixes for #23333 will show there are 2 queries */|
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query 1 # #
master-bin.000001 # Query 1 # #
select count(*),@a from t1 /* must be 1,1 */|
count(*) @a
1 1

Binary file not shown.

View file

@ -0,0 +1,121 @@
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;
show slave status /* Second_behind reports 0 */;;
Slave_IO_State #
Master_Host 127.0.0.1
Master_User root
Master_Port 9306
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 98
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running Yes
Slave_SQL_Running Yes
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 98
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 0
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
create table t1 (f1 int);
flush logs /* contaminate rli->last_master_timestamp */;
lock table t1 write;
insert into t1 values (1);
show slave status /* bug emulated: reports slave threads starting time about 3*3 not 3 secs */;;
Slave_IO_State #
Master_Host 127.0.0.1
Master_User root
Master_Port 9306
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 359
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running Yes
Slave_SQL_Running Yes
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 271
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 10
unlock tables;
flush logs /* this time rli->last_master_timestamp is not affected */;
lock table t1 write;
insert into t1 values (2);
show slave status /* reports the correct diff with master query time about 3+3 secs */;;
Slave_IO_State #
Master_Host 127.0.0.1
Master_User root
Master_Port 9306
Connect_Retry 1
Master_Log_File master-bin.000001
Read_Master_Log_Pos 447
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
Slave_IO_Running Yes
Slave_SQL_Running Yes
Replicate_Do_DB
Replicate_Ignore_DB
Replicate_Do_Table
Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
Exec_Master_Log_Pos 359
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 6
unlock tables;
drop table t1;

View file

@ -0,0 +1 @@
--loose-debug=d,let_first_flush_log_change_timestamp

View file

@ -0,0 +1,71 @@
#
# Testing replication delay reporting (bug#29309)
# there is an unavoidable non-determinism in the test
# please compare the results with the comments
#
source include/master-slave.inc;
connection master;
#connection slave;
sync_slave_with_master;
--replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT
--replace_column 1 # 8 # 9 # 23 #
--query_vertical show slave status /* Second_behind reports 0 */;
sleep 3;
### bug emulation
connection master;
drop table if exists t1;
create table t1 (f1 int);
sleep 3;
#connection slave;
sync_slave_with_master;
flush logs /* contaminate rli->last_master_timestamp */;
connection slave;
lock table t1 write;
connection master;
insert into t1 values (1);
sleep 3;
connection slave;
--replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT
--replace_column 1 # 8 # 9 # 23 #
--query_vertical show slave status /* bug emulated: reports slave threads starting time about 3*3 not 3 secs */;
unlock tables;
connection master;
sync_slave_with_master;
### bugfix
connection slave;
flush logs /* this time rli->last_master_timestamp is not affected */;
lock table t1 write;
connection master;
insert into t1 values (2);
sleep 3;
connection slave;
--replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT
--replace_column 1 # 8 # 9 # 23 #
--query_vertical show slave status /* reports the correct diff with master query time about 3+3 secs */;
unlock tables;
connection master;
drop table t1;
#connection slave;
sync_slave_with_master;
# End of tests

View file

@ -55,194 +55,162 @@ enable_result_log;
select @result /* must be zero either way */;
# the functions are either *insensitive* to killing or killing can cause
# strange problmes with the error propagation out of SF's stack
# Bug#27563, Bug#27565, BUG#24971
#
# TODO: use if's block as regression test for the bugs or remove
#
if (0)
{
delimiter |;
create function bug27563()
RETURNS int(11)
DETERMINISTIC
begin
select get_lock("a", 10) into @a;
return 1;
end|
delimiter ;|
# the function is sensitive to killing requiring innodb though with wrong client error
# TO FIX in BUG#27565; TODO: remove --error 1105 afterwards
delimiter |;
create function bug27565()
RETURNS int(11)
DETERMINISTIC
begin
select a from t1 where a=1 into @a for update;
return 1;
end|
delimiter ;|
reset master;
### ta table case: killing causes rollback
# A. autocommit ON
connection con1;
select get_lock("a", 20);
connection con2;
let $ID= `select connection_id()`;
send insert into t1 values (bug27563(),1);
connection con1;
eval kill query $ID;
connection con2;
# todo (re-record test): after bugs 27563,27565 got fixed affected rows will report zero
--enable_info
# todo: remove 0 return after fixing Bug#27563
--error 0,ER_QUERY_INTERRUPTED
reap; ### pb: wrong error
--disable_info
###--replace_column 2 # 5 #
### show binlog events from 98 /* nothing in binlog unless Bug#27563 */;
show master status /* must be only FD event unless Bug#27563 */;
select count(*) from t1 /* must be zero unless Bug#27563 */;
# M. multi-statement-ta
connection con2;
let $ID= `select connection_id()`;
begin;
send insert into t1 values (bug27563(),1);
connection con1;
eval kill query $ID;
connection con2;
# todo (re-record test): after bugs 27563,27565 got fixed affected rows will report zero
--enable_info
# todo: remove 0 return after fixing Bug#27563
--error 0,ER_QUERY_INTERRUPTED
reap;
--disable_info
select count(*) from t1 /* must be zero unless Bug#27563 */;
commit;
### non-ta table case: killing must be recorded in binlog
reset master;
connection con2;
let $ID= `select connection_id()`;
send insert into t2 values (bug27563(),1);
connection con1;
eval kill query $ID;
connection con2;
# todo: remove 0 return after fixing Bug#27563
--error 0,ER_QUERY_INTERRUPTED
reap;
select count(*) from t2 /* must be one */;
#show binlog events from 98 /* must have the insert on non-ta table */;
show master status /* must have the insert event more to FD */;
# the value of the error flag of KILLED_QUERY is tested further
--remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog
connection con1;
select RELEASE_LOCK("a");
### test with effective killing of SF()
#
# bug#27571 asynchronous setting mysql_`query`::error and Query_log_e::error_code
#
# checking that killing inside of select loops is safe as before
# killing after the loop can be only simulated - another test
delete from t1;
delete from t2;
insert into t1 values (1,1);
insert into t2 values (1,1);
insert into t1 values (1,1),(2,2);
#
# Bug#27565
# test where KILL is propagated as error to the top level
# still another bug with the error message to the user
# todo: fix reexecute the result file after fixing
#
begin; update t1 set b=0 where a=1;
connection con2;
let $ID= `select connection_id()`;
send update t2 set b=bug27565()-1 where a=1;
connection con1;
eval kill query $ID;
commit;
connection con2;
# todo: fix Bug #27565 killed query of SF() is not reported correctly and
# remove 1105 (wrong)
#--error ER_QUERY_INTERRUPTED
--error 1105,ER_QUERY_INTERRUPTED
reap; ### pb: wrong error
select * from t1 /* must be: (1,0) */;
select * from t2 /* must be as before: (1,1) */;
## bug#22725 with effective and propagating killing
#
# top-level ta-table
# simple update
#
connection con1;
delete from t3;
reset master;
begin; update t1 set b=0 where a=1;
begin; update t1 set b=11 where a=2;
connection con2;
let $ID= `select connection_id()`;
# the query won't perform completely since the function gets interrupted
send insert into t3 values (0,0),(1,bug27565());
begin;
send update t1 set b=b+10;
connection con1;
--replace_result $ID ID
eval kill query $ID;
rollback;
# Bug #32148 killi query may be ineffective
# forced to comment out the test's outcome
# and mask out ineffective ER_QUERY_INTERRUPTED
# todo1: revert back upon fixing bug#32148
# todo2: the tests need refining in that
# killing should wait till the victim requested
# its lock (wait_condition available in 5.1 tests)
connection con2;
--error 0,ER_QUERY_INTERRUPTED
reap;
rollback;
select * from t1 order by a /* must be the same as before (1,1),(2,2) */;
#
# multi update
# commented out as Bug #31807 multi-update,delete killing does not report with ER_QUERY_INTERRUPTED
# in the way
#
# connection con1;
# begin; update t1 set b=b+10;
# connection con2;
# send update t1 as t_1,t1 as t_2 set t_1.b=11 where t_2.a=2;
# connection con1;
# --replace_result $ID ID
# eval kill query $ID;
# rollback;
# disable_abort_on_error;
# connection con2;
# --error HY000,ER_QUERY_INTERRUPTED
# reap;
# select * from t1 /* must be the same as before (1,1),(2,2) */;
# enable_abort_on_error;
#
# simple delete
#
connection con1;
begin; delete from t1 where a=2;
connection con2;
let $ID= `select connection_id()`;
begin;
send delete from t1 where a=2;
connection con1;
--replace_result $ID ID
eval kill query $ID;
rollback;
connection con2;
# todo: fix Bug #27565 killed query of SF() is not reported correctly and
# remove 1105 (wrong)
#--error ER_QUERY_INTERRUPTED
--error 1105,ER_QUERY_INTERRUPTED
reap; ### pb: wrong error
select count(*) from t3 /* must be zero */;
show master status /* nothing in binlog */;
--error 0,ER_QUERY_INTERRUPTED
reap;
rollback;
# todo1,2 above
select * from t1 order by a /* must be the same as before (1,1),(2,2) */;
# top-level non-ta-table
#
# multi delete
# the same as for multi-update
#
# connection con1;
# begin; delete from t1 where a=2;
# connection con2;
# send delete t1 from t1 where t1.a=2;
# connection con1;
# --replace_result $ID ID
# eval kill query $ID;
# rollback;
# connection con2;
# --error 0,ER_QUERY_INTERRUPTED
# reap;
# select * from t1 /* must be the same as before (1,1),(2,2) */;
#
# insert select
#
connection con1;
delete from t2;
reset master;
begin; update t1 set b=0 where a=1;
--disable_warnings
drop table if exists t4;
--enable_warnings
create table t4 (a int, b int) engine=innodb;
insert into t4 values (3, 3);
begin; insert into t1 values (3, 3);
connection con2;
let $ID= `select connection_id()`;
# the query won't perform completely since the function gets intrurrupted
send insert into t2 values (0,0),(1,bug27565()) /* non-ta t2 */;
begin;
send insert into t1 select * from t4 for update;
connection con1;
--replace_result $ID ID
eval kill query $ID;
rollback;
connection con2;
# todo: fix Bug #27565 killed query of SF() is not reported correctly and
# remove 1105 (wrong)
#--error ER_QUERY_INTERRUPTED
--error 1105,ER_QUERY_INTERRUPTED
reap; ### pb: wrong error
--error 0,ER_QUERY_INTERRUPTED
reap;
# todo 1,2 above
rollback;
select * from t1 /* must be the same as before (1,1),(2,2) */;
select count(*) from t2 /* count must be one */;
show master status /* insert into non-ta must be in binlog */;
drop table t4; # cleanup for the sub-case
drop function bug27563;
drop function bug27565;
}
###
## non-ta table case: killing must be recorded in binlog
###
system rm $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog ;
# In order to be deterministic the test needs INFORMATION_SCHEMA.PROCESSLIST
# which is not available on 5.0 at this time.
# Therefore, skip this part on 5.0.
#
# common cleanup
#
drop table t1,t2,t3;
--echo end of the tests

View file

@ -0,0 +1 @@
--loose-debug=d,simulate_kill_bug27571

View file

@ -0,0 +1,66 @@
-- source include/have_debug.inc
#
# bug#27571 asynchronous setting mysql_$query()'s local error and
# Query_log_event::error_code
#
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
#
# Checking that killing upon successful row-loop does not affect binlogging
#
create table t1 (a int) engine=MyISAM;
insert into t1 set a=1;
reset master;
update t1 set a=2 /* will be "killed" after work has been done */;
# a proof the query is binlogged with no error
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
is not null;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
let $error_code= `select @a like "%#%error_code=0%" /* must return 1 */`;
eval select $error_code /* must return 1 as query completed before got killed*/;
# cleanup for the sub-case
system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog;
#
# Checking that killing inside of row-loop for LOAD DATA into
# non-transactional table affects binlogging
#
create table t2 (a int, b int) ENGINE=MyISAM;
reset master;
--error ER_QUERY_INTERRUPTED
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */;
# a proof the query is binlogged with an error
source include/show_binlog_events.inc;
--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog"))
is not null;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`;
eval select $error_code /* must return 0 to mean the killed query is in */;
# cleanup for the sub-case
system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog;
drop table t1,t2;
--echo end of the tests

View file

@ -31,3 +31,26 @@ SELECT hex(a) FROM t1 ORDER BY a;
DROP TABLE t1;
# End of 4.1 tests
#
#Bug #30315 Character sets: insertion of euckr code value 0xa141 fails
#
create table t1 (s1 varchar(5) character set euckr);
# Insert some valid characters
insert into t1 values (0xA141);
insert into t1 values (0xA15A);
insert into t1 values (0xA161);
insert into t1 values (0xA17A);
insert into t1 values (0xA181);
insert into t1 values (0xA1FE);
# Insert some invalid characters
insert into t1 values (0xA140);
insert into t1 values (0xA15B);
insert into t1 values (0xA160);
insert into t1 values (0xA17B);
insert into t1 values (0xA180);
insert into t1 values (0xA1FF);
select hex(s1), hex(convert(s1 using utf8)) from t1 order by binary s1;
drop table t1;
--echo End of 5.0 tests

View file

@ -538,4 +538,8 @@ alter table t1 convert to character set ucs2 collate ucs2_czech_ci;
select * from t1 where a like 'c%';
drop table t1;
set collation_connection=ucs2_unicode_ci;
--source include/ctype_regex.inc
set names utf8;
-- echo End for 5.0 tests

View file

@ -659,6 +659,9 @@ select * from t1 where a=if(b<10,_ucs2 0x00C0,_ucs2 0x0062);
select * from t1 where a=if(b<10,_ucs2 0x0062,_ucs2 0x00C0);
drop table t1;
set collation_connection=ucs2_general_ci;
--source include/ctype_regex.inc
set names latin1;
#
# Bug#30981 CHAR(0x41 USING ucs2) doesn't add leading zero
#

View file

@ -185,6 +185,13 @@ select * from t1 where a = 'b' and a = 'b';
select * from t1 where a = 'b' and a != 'b';
drop table t1;
#
# Testing regexp
#
set collation_connection=utf8_general_ci;
--source include/ctype_regex.inc
set names utf8;
#
# Bug #3928 regexp [[:>:]] and UTF-8
#

View file

@ -6,28 +6,9 @@
drop table if exists t1;
--enable_warnings
create table t1 (s1 char(64),s2 char(64));
set names latin1;
--source include/ctype_regex.inc
insert into t1 values('aaa','aaa');
insert into t1 values('aaa|qqq','qqq');
insert into t1 values('gheis','^[^a-dXYZ]+$');
insert into t1 values('aab','^aa?b');
insert into t1 values('Baaan','^Ba*n');
insert into t1 values('aaa','qqq|aaa');
insert into t1 values('qqq','qqq|aaa');
insert into t1 values('bbb','qqq|aaa');
insert into t1 values('bbb','qqq');
insert into t1 values('aaa','aba');
insert into t1 values(null,'abc');
insert into t1 values('def',null);
insert into t1 values(null,null);
insert into t1 values('ghi','ghi[');
select HIGH_PRIORITY s1 regexp s2 from t1;
drop table t1;
#
# This test a bug in regexp on Alpha

View file

@ -792,6 +792,38 @@ show master status /* there must be no UPDATE query event */;
# cleanup bug#27716
drop table t1, t2;
#
# Bug #29136 erred multi-delete on trans table does not rollback
#
# prepare
--disable_warnings
drop table if exists t1, t2;
--enable_warnings
CREATE TABLE t1 (a int, PRIMARY KEY (a));
CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
create trigger trg_del_t2 after delete on t2 for each row
insert into t1 values (1);
insert into t1 values (1);
insert into t2 values (1),(2);
# exec cases A, B - see multi_update.test
# A. send_error() w/o send_eof() branch
--error ER_DUP_ENTRY
delete t2 from t2;
# check
select count(*) from t2 /* must be 2 as restored after rollback caused by the error */;
# cleanup bug#29136
drop table t1, t2;
#
# Testing of IFNULL
#

View file

@ -347,7 +347,7 @@ CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));
delimiter |;
create function bug27417(n int)
create function bug27417(n int)
RETURNS int(11)
begin
insert into t1 values (null);
@ -380,8 +380,190 @@ delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */;
--disable_info
select count(*) from t1 /* must be 7 */;
drop function bug27417;
# function bug27417 remains for the following testing of bug#23333
drop table t1,t2;
#
# Bug#23333 using the patch (and the test) for bug#27471
#
# throughout the bug tests
# t1 - non-trans side effects gatherer;
# t2 - transactional table;
#
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique) ENGINE=MyISAM;
CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique) ENGINE=Innodb;
CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
#
# INSERT
#
# prepare
insert into t2 values (1);
reset master;
# execute
--error ER_DUP_ENTRY
insert into t2 values (bug27417(1));
# check
show master status /* the offset must denote there is the query */;
select count(*) from t1 /* must be 1 */;
#
# INSERT SELECT
#
# prepare
delete from t1;
delete from t2;
insert into t2 values (2);
reset master;
# execute
--error ER_DUP_ENTRY
insert into t2 select bug27417(1) union select bug27417(2);
# check
show master status /* the offset must denote there is the query */;
select count(*) from t1 /* must be 2 */;
#
# UPDATE inc multi-update
#
# prepare
delete from t1;
insert into t3 values (1,1),(2,3),(3,4);
reset master;
# execute
--error ER_DUP_ENTRY
update t3 set b=b+bug27417(1);
# check
show master status /* the offset must denote there is the query */;
select count(*) from t1 /* must be 2 */;
## multi_update::send_eof() branch
# prepare
delete from t3;
delete from t4;
insert into t3 values (1,1);
insert into t4 values (1,1),(2,2);
reset master;
# execute
--error ER_DUP_ENTRY
UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */;
# check
show master status /* the offset must denote there is the query */;
select count(*) from t1 /* must be 4 */;
## send_error() branch of multi_update
# prepare
delete from t1;
delete from t3;
delete from t4;
insert into t3 values (1,1),(2,2);
insert into t4 values (1,1),(2,2);
reset master;
# execute
--error ER_DUP_ENTRY
UPDATE t3,t4 SET t3.a=t4.a + bug27417(1);
# check
select count(*) from t1 /* must be 1 */;
# cleanup
drop table t4;
#
# DELETE incl multi-delete
#
# prepare
delete from t1;
delete from t2;
delete from t3;
insert into t2 values (1);
insert into t3 values (1,1);
create trigger trg_del before delete on t2 for each row
insert into t3 values (bug27417(1), 2);
reset master;
# execute
--error ER_DUP_ENTRY
delete from t2;
# check
show master status /* the offset must denote there is the query */;
select count(*) from t1 /* must be 1 */;
# cleanup
drop trigger trg_del;
# prepare
delete from t1;
delete from t2;
delete from t5;
create trigger trg_del_t2 after delete on t2 for each row
insert into t1 values (1);
insert into t2 values (2),(3);
insert into t5 values (1),(2);
reset master;
# execute
--error ER_DUP_ENTRY
delete t2.* from t2,t5 where t2.a=t5.a + 1;
# check
show master status /* the offset must denote there is the query */;
select count(*) from t1 /* must be 1 */;
#
# LOAD DATA
#
# prepare
delete from t1;
create table t4 (a int default 0, b int primary key) engine=innodb;
insert into t4 values (0, 17);
reset master;
# execute
--error ER_DUP_ENTRY
load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2);
# check
select * from t4;
select count(*) from t1 /* must be 2 */;
show master status /* the offset must denote there is the query */;
#
# bug#23333 cleanup
#
drop trigger trg_del_t2;
drop table t1,t2,t3,t4,t5;
drop function bug27417;
--echo end of tests

View file

@ -574,4 +574,38 @@ show master status /* there must be the UPDATE query event */;
# cleanup bug#27716
drop table t1, t2;
#
# Bug #29136 erred multi-delete on trans table does not rollback
#
# prepare
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
CREATE TABLE t1 (a int, PRIMARY KEY (a));
CREATE TABLE t2 (a int, PRIMARY KEY (a));
CREATE TABLE t3 (a int, PRIMARY KEY (a)) ENGINE=MyISAM;
create trigger trg_del_t3 before delete on t3 for each row insert into t1 values (1);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
reset master;
# exec cases B, A - see innodb.test
# B. send_eof() and send_error() afterward
--error ER_DUP_ENTRY
delete t3.* from t2,t3 where t2.a=t3.a;
# check
select count(*) from t1 /* must be 1 */;
select count(*) from t3 /* must be 1 */;
# the query must be in binlog (no surprise though)
source include/show_binlog_events.inc;
# cleanup bug#29136
drop table t1, t2, t3;
--echo end of tests

View file

@ -281,4 +281,13 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug21412.sql;
#
--exec $MYSQL test -e "/*! \C latin1 */ select 1;"
#
# Bug#29323 mysql client only accetps ANSI encoded files
#
--write_file $MYSQLTEST_VARDIR/tmp/bug29323.sql
select "This is a file starting with UTF8 BOM 0xEFBBBF";
EOF
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug29323.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/bug29323.sql;
--echo End of 5.0 tests

View file

@ -237,4 +237,8 @@ let $c= `select $a=$b`;
--echo $c
drop table t1;
echo shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql;
error 1;
exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 > $MYSQLTEST_VARDIR/tmp/bug31793.sql;
--echo End of 5.0 tests

View file

@ -106,9 +106,3 @@ connection slave;
sync_with_master;
# End of 4.1 tests
# Cleanup
# The A->B->A replication causes the master to start writing relay logs
# in var/run, remove them
remove_file $MYSQLTEST_VARDIR/run/master-relay-bin.000001;
remove_file $MYSQLTEST_VARDIR/run/master-relay-bin.index;

View file

@ -64,9 +64,11 @@ CREATE TABLe `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048');
# The slave I/O thread must stop after trying to read the above event
connection slave;
sleep 2;
SHOW STATUS LIKE 'Slave_running';
connection slave;
--source include/wait_for_slave_io_to_stop.inc
--replace_result $MASTER_MYPORT MASTER_MYPORT
# import is only the 11th column Slave_IO_Running
--replace_column 1 # 8 # 9 # 12 # 23 # 33 #
query_vertical show slave status;
# End of tests

View file

@ -0,0 +1 @@
--innodb

View file

@ -0,0 +1,203 @@
source include/have_innodb.inc;
source include/master-slave.inc;
# This test is for checking that the use of SQL_SLAVE_SKIP_COUNTER
# behaves as expected, i.e., that it is guaranteed to skip an entire
# group and not start executing in the middle of a transaction.
# We are checking the correct behaviour when using both a
# transactional and non-transactional table. The non-transactional
# table comes into play when rolling back a transaction containing a
# write to this table. In that case, the transaction should still be
# written to the binary log, and the slave will apply it and then roll
# it back to get the non-transactional change into the table.
--echo **** On Master ****
CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB;
CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM;
--echo ==== Skipping normal transactions ====
--echo **** On Slave ****
sync_slave_with_master;
STOP SLAVE;
source include/wait_for_slave_to_stop.inc;
--echo **** On Master ****
connection master;
BEGIN;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (4, 'master,slave');
INSERT INTO t1 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, 'master,slave');
COMMIT;
save_master_pos;
SELECT * FROM t1 ORDER BY a;
# This will skip a begin event and the first INSERT of the
# transaction, and it should keep skipping until it has reached the
# transaction terminator.
--echo **** On Slave ****
connection slave;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
source include/wait_for_slave_to_start.inc;
sync_with_master;
SELECT * FROM t1 ORDER BY a;
--echo **** On Master ****
connection master;
DELETE FROM t1;
sync_slave_with_master;
--echo ==== Skipping two normal transactions ====
--echo **** On Slave ****
connection slave;
STOP SLAVE;
source include/wait_for_slave_to_stop.inc;
--echo **** On Master ****
connection master;
BEGIN;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (4, 'master');
INSERT INTO t1 VALUES (5, 'master');
INSERT INTO t1 VALUES (6, 'master');
COMMIT;
BEGIN;
INSERT INTO t1 VALUES (7, 'master,slave');
INSERT INTO t1 VALUES (8, 'master,slave');
INSERT INTO t1 VALUES (9, 'master,slave');
COMMIT;
save_master_pos;
SELECT * FROM t1 ORDER BY a;
# This will skip a begin event and the first INSERT of the
# transaction, and it should keep skipping until it has reached the
# transaction terminator.
--echo **** On Slave ****
connection slave;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=8;
START SLAVE;
source include/wait_for_slave_to_start.inc;
sync_with_master;
SELECT * FROM t1 ORDER BY a;
--echo **** On Master ****
connection master;
DELETE FROM t1;
sync_slave_with_master;
--echo ==== Skipping without autocommit ====
# Testing without using autocommit instead. It should still write a
# BEGIN event, so the behaviour should be the same
--echo **** On Slave ****
connection slave;
STOP SLAVE;
source include/wait_for_slave_to_stop.inc;
--echo **** On Master ****
connection master;
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1, 'master');
INSERT INTO t1 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, 'master');
COMMIT;
INSERT INTO t1 VALUES (4, 'master,slave');
INSERT INTO t1 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, 'master,slave');
COMMIT;
save_master_pos;
SELECT * FROM t1 ORDER BY a;
# This will skip a begin event and the first INSERT of the
# transaction, and it should keep skipping until it has reached the
# transaction terminator.
--echo **** On Slave ****
connection slave;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
source include/wait_for_slave_to_start.inc;
sync_with_master;
SELECT * FROM t1 ORDER BY a;
# Testing with a non-transactional table in the transaction. This will
# log a ROLLBACK as a transaction terminator, which is a normal Query
# log event.
--echo ==== Rollback of transaction with non-transactional change ====
--echo **** On Master ****
connection master;
DELETE FROM t1;
SET AUTOCOMMIT=1;
--echo **** On Slave ****
sync_slave_with_master;
STOP SLAVE;
source include/wait_for_slave_to_stop.inc;
--echo **** On Master ****
connection master;
disable_warnings;
BEGIN;
INSERT INTO t1 VALUES (1, '');
INSERT INTO t2 VALUES (2, 'master');
INSERT INTO t1 VALUES (3, '');
ROLLBACK;
BEGIN;
INSERT INTO t1 VALUES (4, '');
INSERT INTO t2 VALUES (5, 'master,slave');
INSERT INTO t1 VALUES (6, '');
ROLLBACK;
enable_warnings;
save_master_pos;
SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2 ORDER BY a;
--echo **** On Slave ****
connection slave;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
source include/wait_for_slave_to_start.inc;
sync_with_master;
SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2 ORDER BY a;
--echo ==== Cleanup ====
--echo **** On Master ****
connection master;
DROP TABLE t1, t2;
sync_slave_with_master;

View file

@ -195,9 +195,60 @@ sync_slave_with_master;
connection slave;
select 'slave', a from t1;
#
# cleanup
#
connection master;
drop table t1;
drop function f1;
drop function f2;
drop procedure p1;
sync_slave_with_master;
#
# bug#26199 Replication Failure on Slave when using stored procs
# with bit-type parameters
connection master;
create table t2 (b BIT(7));
delimiter //;
create procedure sp_bug26199(bitvalue BIT(7))
begin
insert into t2 set b = bitvalue;
end //
create function sf_bug26199(b BIT(7)) returns int
begin
insert into t2 values(b);
return 0;
end//
DELIMITER ;//
call sp_bug26199(b'1110');
call sp_bug26199('\0');
select sf_bug26199(b'1111111');
select sf_bug26199(b'101111111');
select sf_bug26199('\'');
select hex(b) from t2;
sync_slave_with_master;
#connection slave;
select hex(b) from t2;
#
# cleanup bug#26199
#
connection master;
drop table t2;
drop procedure sp_bug26199;
drop function sf_bug26199;
sync_slave_with_master;
--echo end of the tests

View file

@ -211,6 +211,8 @@ select * from t1;
connection master;
drop table t1;
--remove_file $MYSQLTEST_VARDIR/tmp/bug14157.sql
# Delete the anonymous users
source include/delete_anonymous_users.inc;

View file

@ -27,7 +27,7 @@ reset master|
--error ER_DUP_ENTRY
insert into t2 values (bug23333(),1)|
--replace_column 2 # 5 # 6 #
show binlog events from 98 /* with fixes for #23333 will show there is the query */|
show binlog events from 98 /* with fixes for #23333 will show there are 2 queries */|
select count(*),@a from t1 /* must be 1,1 */|
drop table t1, t2|

View file

@ -4280,6 +4280,51 @@ void Item_func_like::cleanup()
#ifdef USE_REGEX
bool
Item_func_regex::regcomp(bool send_error)
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),&my_charset_bin);
String *res= args[1]->val_str(&tmp);
int error;
if (args[1]->null_value)
return TRUE;
if (regex_compiled)
{
if (!stringcmp(res, &prev_regexp))
return FALSE;
prev_regexp.copy(*res);
my_regfree(&preg);
regex_compiled= 0;
}
if (cmp_collation.collation != regex_lib_charset)
{
/* Convert UCS2 strings to UTF8 */
uint dummy_errors;
if (conv.copy(res->ptr(), res->length(), res->charset(),
regex_lib_charset, &dummy_errors))
return TRUE;
res= &conv;
}
if ((error= my_regcomp(&preg, res->c_ptr_safe(),
regex_lib_flags, regex_lib_charset)))
{
if (send_error)
{
(void) my_regerror(error, &preg, buff, sizeof(buff));
my_error(ER_REGEXP_ERROR, MYF(0), buff);
}
return TRUE;
}
regex_compiled= 1;
return FALSE;
}
bool
Item_func_regex::fix_fields(THD *thd, Item **ref)
{
@ -4296,35 +4341,34 @@ Item_func_regex::fix_fields(THD *thd, Item **ref)
if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1))
return TRUE;
regex_lib_flags= (cmp_collation.collation->state &
(MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE;
/*
If the case of UCS2 and other non-ASCII character sets,
we will convert patterns and strings to UTF8.
*/
regex_lib_charset= (cmp_collation.collation->mbminlen > 1) ?
&my_charset_utf8_general_ci :
cmp_collation.collation;
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
not_null_tables_cache= (args[0]->not_null_tables() |
args[1]->not_null_tables());
const_item_cache=args[0]->const_item() && args[1]->const_item();
if (!regex_compiled && args[1]->const_item())
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),&my_charset_bin);
String *res=args[1]->val_str(&tmp);
if (args[1]->null_value)
{ // Will always return NULL
maybe_null=1;
fixed= 1;
return FALSE;
}
int error;
if ((error= my_regcomp(&preg,res->c_ptr(),
((cmp_collation.collation->state &
(MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE),
cmp_collation.collation)))
{
(void) my_regerror(error,&preg,buff,sizeof(buff));
my_error(ER_REGEXP_ERROR, MYF(0), buff);
if (regcomp(TRUE))
return TRUE;
}
regex_compiled=regex_is_const=1;
maybe_null=args[0]->maybe_null;
regex_is_const= 1;
maybe_null= args[0]->maybe_null;
}
else
maybe_null=1;
@ -4337,47 +4381,25 @@ longlong Item_func_regex::val_int()
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String *res, tmp(buff,sizeof(buff),&my_charset_bin);
String tmp(buff,sizeof(buff),&my_charset_bin);
String *res= args[0]->val_str(&tmp);
res=args[0]->val_str(&tmp);
if (args[0]->null_value)
{
null_value=1;
if ((null_value= (args[0]->null_value ||
(!regex_is_const && regcomp(FALSE)))))
return 0;
}
if (!regex_is_const)
{
char buff2[MAX_FIELD_WIDTH];
String *res2, tmp2(buff2,sizeof(buff2),&my_charset_bin);
res2= args[1]->val_str(&tmp2);
if (args[1]->null_value)
if (cmp_collation.collation != regex_lib_charset)
{
/* Convert UCS2 strings to UTF8 */
uint dummy_errors;
if (conv.copy(res->ptr(), res->length(), res->charset(),
regex_lib_charset, &dummy_errors))
{
null_value=1;
null_value= 1;
return 0;
}
if (!regex_compiled || stringcmp(res2,&prev_regexp))
{
prev_regexp.copy(*res2);
if (regex_compiled)
{
my_regfree(&preg);
regex_compiled=0;
}
if (my_regcomp(&preg,res2->c_ptr_safe(),
((cmp_collation.collation->state &
(MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE),
cmp_collation.collation))
{
null_value=1;
return 0;
}
regex_compiled=1;
}
res= &conv;
}
null_value=0;
return my_regexec(&preg,res->c_ptr_safe(),0,(my_regmatch_t*) 0,0) ? 0 : 1;
}

View file

@ -1318,6 +1318,10 @@ class Item_func_regex :public Item_bool_func
bool regex_is_const;
String prev_regexp;
DTCollation cmp_collation;
CHARSET_INFO *regex_lib_charset;
int regex_lib_flags;
String conv;
bool regcomp(bool send_error);
public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {}

View file

@ -448,13 +448,10 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
{
if (!log_name || !log_name[0])
{
/*
TODO: The following should be using fn_format(); We just need to
first change fn_format() to cut the file name if it's too long.
*/
strmake(buff, pidfile_name,FN_REFLEN-5);
strmov(fn_ext(buff),suffix);
return (const char *)buff;
strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
return (const char *)
fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR));
}
// get rid of extension if the log is binary to avoid problems
if (strip_ext)

View file

@ -27,6 +27,10 @@
#define log_cs &my_charset_latin1
#ifndef DBUG_OFF
uint debug_not_change_ts_if_art_event= 1; // bug#29309 simulation
#endif
/*
pretty_print_str()
*/
@ -481,6 +485,18 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
rli->inc_event_relay_log_pos();
else
{
/*
bug#29309 simulation: resetting the flag to force
wrong behaviour of artificial event to update
rli->last_master_timestamp for only one time -
the first FLUSH LOGS in the test.
*/
DBUG_EXECUTE_IF("let_first_flush_log_change_timestamp",
if (debug_not_change_ts_if_art_event == 1
&& is_artificial_event())
{
debug_not_change_ts_if_art_event= 0;
});
rli->inc_group_relay_log_pos(log_pos);
flush_relay_log_info(rli);
/*
@ -491,7 +507,21 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
rare cases, only consequence is that value may take some time to
display in Seconds_Behind_Master - not critical).
*/
rli->last_master_timestamp= when;
#ifndef DBUG_OFF
if (!(is_artificial_event() && debug_not_change_ts_if_art_event > 0))
#else
if (!is_artificial_event())
#endif
rli->last_master_timestamp= when;
/*
The flag is set back to be positive so that
any further FLUSH LOGS will be handled as prescribed.
*/
DBUG_EXECUTE_IF("let_first_flush_log_change_timestamp",
if (debug_not_change_ts_if_art_event == 0)
{
debug_not_change_ts_if_art_event= 2;
});
}
}
DBUG_RETURN(0);
@ -1370,18 +1400,48 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
/* 2 utility functions for the next method */
/*
Get the pointer for a string (src) that contains the length in
the first byte. Set the output string (dst) to the string value
and place the length of the string in the byte after the string.
/**
Read a string with length from memory.
This function reads the string-with-length stored at
<code>src</code> and extract the length into <code>*len</code> and
a pointer to the start of the string into <code>*dst</code>. The
string can then be copied using <code>memcpy()</code> with the
number of bytes given in <code>*len</code>.
@param src Pointer to variable holding a pointer to the memory to
read the string from.
@param dst Pointer to variable holding a pointer where the actual
string starts. Starting from this position, the string
can be copied using @c memcpy().
@param len Pointer to variable where the length will be stored.
@param end One-past-the-end of the memory where the string is
stored.
@return Zero if the entire string can be copied successfully,
@c UINT_MAX if the length could not be read from memory
(that is, if <code>*src >= end</code>), otherwise the
number of bytes that are missing to read the full
string, which happends <code>*dst + *len >= end</code>.
*/
static void get_str_len_and_pointer(const Log_event::Byte **src,
const char **dst,
uint *len)
static int
get_str_len_and_pointer(const Log_event::Byte **src,
const char **dst,
uint *len,
const Log_event::Byte *end)
{
if ((*len= **src))
*dst= (char *)*src + 1; // Will be copied later
(*src)+= *len + 1;
if (*src >= end)
return -1; // Will be UINT_MAX in two-complement arithmetics
uint length= **src;
if (length > 0)
{
if (*src + length >= end)
return *src + length - end + 1; // Number of bytes missing
*dst= (char *)*src + 1; // Will be copied later
}
*len= length;
*src+= length + 1;
return 0;
}
static void copy_str_and_move(const char **src,
@ -1394,6 +1454,46 @@ static void copy_str_and_move(const char **src,
*(*dst)++= 0;
}
#ifndef DBUG_OFF
static char const *
code_name(int code)
{
static char buf[255];
switch (code) {
case Q_FLAGS2_CODE: return "Q_FLAGS2_CODE";
case Q_SQL_MODE_CODE: return "Q_SQL_MODE_CODE";
case Q_CATALOG_CODE: return "Q_CATALOG_CODE";
case Q_AUTO_INCREMENT: return "Q_AUTO_INCREMENT";
case Q_CHARSET_CODE: return "Q_CHARSET_CODE";
case Q_TIME_ZONE_CODE: return "Q_TIME_ZONE_CODE";
case Q_CATALOG_NZ_CODE: return "Q_CATALOG_NZ_CODE";
case Q_LC_TIME_NAMES_CODE: return "Q_LC_TIME_NAMES_CODE";
case Q_CHARSET_DATABASE_CODE: return "Q_CHARSET_DATABASE_CODE";
}
sprintf(buf, "CODE#%d", code);
return buf;
}
#endif
/**
Macro to check that there is enough space to read from memory.
@param PTR Pointer to memory
@param END End of memory
@param CNT Number of bytes that should be read.
*/
#define CHECK_SPACE(PTR,END,CNT) \
do { \
DBUG_PRINT("info", ("Read %s", code_name(pos[-1]))); \
DBUG_ASSERT((PTR) + (CNT) <= (END)); \
if ((PTR) + (CNT) > (END)) { \
DBUG_PRINT("info", ("query= 0")); \
query= 0; \
DBUG_VOID_RETURN; \
} \
} while (0)
/*
Query_log_event::Query_log_event()
This is used by the SQL slave thread to prepare the event before execution.
@ -1445,6 +1545,19 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
if (tmp)
{
status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
/*
Check if status variable length is corrupt and will lead to very
wrong data. We could be even more strict and require data_len to
be even bigger, but this will suffice to catch most corruption
errors that can lead to a crash.
*/
if (status_vars_len > min(data_len, MAX_SIZE_LOG_EVENT_STATUS))
{
DBUG_PRINT("info", ("status_vars_len (%u) > data_len (%lu); query= 0",
status_vars_len, data_len));
query= 0;
DBUG_VOID_RETURN;
}
data_len-= status_vars_len;
DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u",
(uint) status_vars_len));
@ -1464,6 +1577,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
{
switch (*pos++) {
case Q_FLAGS2_CODE:
CHECK_SPACE(pos, end, 4);
flags2_inited= 1;
flags2= uint4korr(pos);
DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", (ulong) flags2));
@ -1474,6 +1588,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
#ifndef DBUG_OFF
char buff[22];
#endif
CHECK_SPACE(pos, end, 8);
sql_mode_inited= 1;
sql_mode= (ulong) uint8korr(pos); // QQ: Fix when sql_mode is ulonglong
DBUG_PRINT("info",("In Query_log_event, read sql_mode: %s",
@ -1482,15 +1597,24 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
break;
}
case Q_CATALOG_NZ_CODE:
get_str_len_and_pointer(&pos, &catalog, &catalog_len);
DBUG_PRINT("info", ("case Q_CATALOG_NZ_CODE; pos: 0x%lx; end: 0x%lx",
(ulong) pos, (ulong) end));
if (get_str_len_and_pointer(&pos, &catalog, &catalog_len, end))
{
DBUG_PRINT("info", ("query= 0"));
query= 0;
DBUG_VOID_RETURN;
}
break;
case Q_AUTO_INCREMENT:
CHECK_SPACE(pos, end, 4);
auto_increment_increment= uint2korr(pos);
auto_increment_offset= uint2korr(pos+2);
pos+= 4;
break;
case Q_CHARSET_CODE:
{
CHECK_SPACE(pos, end, 6);
charset_inited= 1;
memcpy(charset, pos, 6);
pos+= 6;
@ -1498,20 +1622,29 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
}
case Q_TIME_ZONE_CODE:
{
get_str_len_and_pointer(&pos, &time_zone_str, &time_zone_len);
if (get_str_len_and_pointer(&pos, &time_zone_str, &time_zone_len, end))
{
DBUG_PRINT("info", ("Q_TIME_ZONE_CODE: query= 0"));
query= 0;
DBUG_VOID_RETURN;
}
break;
}
case Q_CATALOG_CODE: /* for 5.0.x where 0<=x<=3 masters */
CHECK_SPACE(pos, end, 1);
if ((catalog_len= *pos))
catalog= (char*) pos+1; // Will be copied later
CHECK_SPACE(pos, end, catalog_len + 2);
pos+= catalog_len+2; // leap over end 0
catalog_nz= 0; // catalog has end 0 in event
break;
case Q_LC_TIME_NAMES_CODE:
CHECK_SPACE(pos, end, 2);
lc_time_names_number= uint2korr(pos);
pos+= 2;
break;
case Q_CHARSET_DATABASE_CODE:
CHECK_SPACE(pos, end, 2);
charset_database_number= uint2korr(pos);
pos+= 2;
break;
@ -2021,6 +2154,7 @@ end:
*/
thd->catalog= 0;
thd->set_db(NULL, 0); /* will free the current database */
DBUG_PRINT("info", ("end: query= 0"));
thd->query= 0; // just to be sure
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@ -4964,12 +5098,13 @@ int Begin_load_query_log_event::get_create_or_append() const
#ifndef MYSQL_CLIENT
Execute_load_query_log_event::
Execute_load_query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length_arg, uint fn_pos_start_arg,
uint fn_pos_end_arg,
enum_load_dup_handling dup_handling_arg,
bool using_trans, bool suppress_use):
ulong query_length_arg, uint fn_pos_start_arg,
uint fn_pos_end_arg,
enum_load_dup_handling dup_handling_arg,
bool using_trans, bool suppress_use,
THD::killed_state killed_err_arg):
Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
suppress_use),
suppress_use, killed_err_arg),
file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
{

View file

@ -1619,10 +1619,12 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_query_log_event(THD* thd, const char* query_arg,
ulong query_length, uint fn_pos_start_arg,
uint fn_pos_end_arg,
enum_load_dup_handling dup_handling_arg,
bool using_trans, bool suppress_use);
ulong query_length, uint fn_pos_start_arg,
uint fn_pos_end_arg,
enum_load_dup_handling dup_handling_arg,
bool using_trans, bool suppress_use,
THD::killed_state
killed_err_arg= THD::KILLED_NO_VALUE);
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);

View file

@ -2862,7 +2862,6 @@ static int init_common_variables(const char *conf_file_name, int argc,
global_system_variables.collation_connection= default_charset_info;
global_system_variables.character_set_results= default_charset_info;
global_system_variables.character_set_client= default_charset_info;
global_system_variables.collation_connection= default_charset_info;
if (!(character_set_filesystem=
get_charset_by_csname(character_set_filesystem_name,

View file

@ -3279,7 +3279,43 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
now the relay log starts with its Format_desc, has a Rotate etc).
*/
DBUG_PRINT("info",("type_code=%d, server_id=%d",type_code,ev->server_id));
DBUG_PRINT("info",("type_code: %d; server_id: %d; slave_skip_counter: %d",
type_code, ev->server_id, rli->slave_skip_counter));
/*
If the slave skip counter is positive, we still need to set the
OPTION_BEGIN flag correctly and not skip the log events that
start or end a transaction. If we do this, the slave will not
notice that it is inside a transaction, and happily start
executing from inside the transaction.
Note that the code block below is strictly 5.0.
*/
#if MYSQL_VERSION_ID < 50100
if (unlikely(rli->slave_skip_counter > 0))
{
switch (type_code)
{
case QUERY_EVENT:
{
Query_log_event* const qev= (Query_log_event*) ev;
DBUG_PRINT("info", ("QUERY_EVENT { query: '%s', q_len: %u }",
qev->query, qev->q_len));
if (memcmp("BEGIN", qev->query, qev->q_len+1) == 0)
thd->options|= OPTION_BEGIN;
else if (memcmp("COMMIT", qev->query, qev->q_len+1) == 0 ||
memcmp("ROLLBACK", qev->query, qev->q_len+1) == 0)
thd->options&= ~OPTION_BEGIN;
}
break;
case XID_EVENT:
DBUG_PRINT("info", ("XID_EVENT"));
thd->options&= ~OPTION_BEGIN;
break;
}
}
#endif
if ((ev->server_id == (uint32) ::server_id &&
!replicate_same_server_id &&
@ -3301,6 +3337,9 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
flush_relay_log_info(rli);
}
DBUG_PRINT("info", ("thd->options: %s",
(thd->options & OPTION_BEGIN) ? "OPTION_BEGIN" : ""))
/*
Protect against common user error of setting the counter to 1
instead of 2 while recovering from an insert which used auto_increment,
@ -3311,6 +3350,15 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
type_code == RAND_EVENT ||
type_code == USER_VAR_EVENT) &&
rli->slave_skip_counter == 1) &&
#if MYSQL_VERSION_ID < 50100
/*
Decrease the slave skip counter only if we are not inside
a transaction or the slave skip counter is more than
1. The slave skip counter will be decreased from 1 to 0
when reaching the final ROLLBACK, COMMIT, or XID_EVENT.
*/
(!(thd->options & OPTION_BEGIN) || rli->slave_skip_counter > 1) &&
#endif
/*
The events from ourselves which have something to do with the relay
log itself must be skipped, true, but they mustn't decrement
@ -3321,8 +3369,10 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
would not be skipped.
*/
!(ev->server_id == (uint32) ::server_id &&
(type_code == ROTATE_EVENT || type_code == STOP_EVENT ||
type_code == START_EVENT_V3 || type_code == FORMAT_DESCRIPTION_EVENT)))
(type_code == ROTATE_EVENT ||
type_code == STOP_EVENT ||
type_code == START_EVENT_V3 ||
type_code == FORMAT_DESCRIPTION_EVENT)))
--rli->slave_skip_counter;
pthread_mutex_unlock(&rli->data_lock);
delete ev;
@ -3530,7 +3580,7 @@ connected:
on with life.
*/
thd->proc_info = "Registering slave on master";
if (register_slave_on_master(mysql) || update_slave_list(mysql, mi))
if (register_slave_on_master(mysql))
goto err;
}
@ -4931,7 +4981,16 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
a new event and is queuing it; the false "0" will exist until SQL
finishes executing the new event; it will be look abnormal only if
the events have old timestamps (then you get "many", 0, "many").
Transient phases like this can't really be fixed.
Transient phases like this can be fixed with implemeting
Heartbeat event which provides the slave the status of the
master at time the master does not have any new update to send.
Seconds_Behind_Master would be zero only when master has no
more updates in binlog for slave. The heartbeat can be sent
in a (small) fraction of slave_net_timeout. Until it's done
rli->last_master_timestamp is temporarely (for time of
waiting for the following event) reset whenever EOF is
reached.
*/
time_t save_timestamp= rli->last_master_timestamp;
rli->last_master_timestamp= 0;

View file

@ -100,8 +100,9 @@ sp_get_item_value(THD *thd, Item *item, String *str)
case REAL_RESULT:
case INT_RESULT:
case DECIMAL_RESULT:
return item->val_str(str);
if (item->field_type() != MYSQL_TYPE_BIT)
return item->val_str(str);
else {/* Bit type is handled as binary string */}
case STRING_RESULT:
{
String *result= item->val_str(str);

View file

@ -159,7 +159,13 @@ typedef struct st_log_info
my_off_t pos;
bool fatal; // if the purge happens to give us a negative offset
pthread_mutex_t lock;
st_log_info():fatal(0) { pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);}
st_log_info()
: index_file_offset(0), index_file_start_offset(0),
pos(0), fatal(0)
{
log_file_name[0] = '\0';
pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);
}
~st_log_info() { pthread_mutex_destroy(&lock);}
} LOG_INFO;
@ -2372,6 +2378,11 @@ class multi_delete :public select_result_interceptor
/* True if at least one table we delete from is not transactional */
bool normal_tables;
bool delete_while_scanning;
/*
error handling (rollback and binlogging) can happen in send_eof()
so that afterward send_error() needs to find out that.
*/
bool error_handled;
public:
multi_delete(TABLE_LIST *dt, uint num_of_tables);
@ -2407,6 +2418,11 @@ class multi_update :public select_result_interceptor
/* True if the update operation has made a change in a transactional table */
bool transactional_tables;
bool ignore;
/*
error handling (rollback and binlogging) can happen in send_eof()
so that afterward send_error() needs to find out that.
*/
bool error_handled;
public:
multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,

View file

@ -38,6 +38,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
ha_rows deleted;
uint usable_index= MAX_KEY;
SELECT_LEX *select_lex= &thd->lex->select_lex;
THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_delete");
if (open_and_lock_tables(thd, table_list))
@ -280,8 +281,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
table->file->unlock_row(); // Row failed selection, release lock on it
}
if (thd->killed && !error)
error= 1; // Aborted
killed_status= thd->killed;
error= (killed_status == THD::NOT_KILLED)? error : 1;
thd->proc_info="end";
end_read_record(&info);
free_io_cache(table); // Will not do any harm
@ -319,14 +320,14 @@ cleanup:
thd->transaction.stmt.modified_non_trans_table= TRUE;
/* See similar binlogging code in sql_update.cc, for comments */
if ((error < 0) || (deleted && !transactional_table))
if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
if (error < 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_table, FALSE);
transactional_table, FALSE, killed_status);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
@ -504,7 +505,7 @@ bool mysql_multi_delete_prepare(THD *thd)
multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
: delete_tables(dt), deleted(0), found(0),
num_of_tables(num_of_tables_arg), error(0),
do_delete(0), transactional_tables(0), normal_tables(0)
do_delete(0), transactional_tables(0), normal_tables(0), error_handled(0)
{
tempfiles= (Unique **) sql_calloc(sizeof(Unique *) * num_of_tables);
}
@ -685,12 +686,14 @@ void multi_delete::send_error(uint errcode,const char *err)
/* First send error what ever it is ... */
my_message(errcode, err, MYF(0));
/* If nothing deleted return */
if (!deleted)
/* the error was handled or nothing deleted and no side effects return */
if (error_handled ||
!thd->transaction.stmt.modified_non_trans_table && !deleted)
DBUG_VOID_RETURN;
/* Something already deleted so we have to invalidate cache */
query_cache_invalidate3(thd, delete_tables, 1);
if (deleted)
query_cache_invalidate3(thd, delete_tables, 1);
/*
If rows from the first table only has been deleted and it is
@ -710,12 +713,30 @@ void multi_delete::send_error(uint errcode,const char *err)
*/
error= 1;
send_eof();
DBUG_ASSERT(error_handled);
DBUG_VOID_RETURN;
}
DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
if (thd->transaction.stmt.modified_non_trans_table)
{
/*
there is only side effects; to binlog with the error
*/
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_tables, FALSE);
mysql_bin_log.write(&qinfo);
}
thd->transaction.all.modified_non_trans_table= true;
}
DBUG_ASSERT(!normal_tables || !deleted ||
thd->transaction.stmt.modified_non_trans_table);
DBUG_VOID_RETURN;
}
/*
Do delete from other tables.
Returns values:
@ -798,6 +819,7 @@ int multi_delete::do_deletes()
bool multi_delete::send_eof()
{
THD::killed_state killed_status= THD::NOT_KILLED;
thd->proc_info="deleting from reference tables";
/* Does deletes for the last n - 1 tables, returns 0 if ok */
@ -805,7 +827,7 @@ bool multi_delete::send_eof()
/* compute a total error to know if something failed */
local_error= local_error || error;
killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
/* reset used flags */
thd->proc_info="end";
@ -817,21 +839,24 @@ bool multi_delete::send_eof()
{
query_cache_invalidate3(thd, delete_tables, 1);
}
if ((local_error == 0) || (deleted && normal_tables))
DBUG_ASSERT(!normal_tables || !deleted ||
thd->transaction.stmt.modified_non_trans_table);
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
if (local_error == 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_tables, FALSE);
transactional_tables, FALSE, killed_status);
if (mysql_bin_log.write(&qinfo) && !normal_tables)
local_error=1; // Log write failed: roll back the SQL statement
}
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
}
DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table);
if (local_error != 0)
error_handled= TRUE; // to force early leave from ::send_error()
/* Commit or rollback the current SQL statement */
if (transactional_tables)

View file

@ -864,8 +864,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
transactional_table= table->file->has_transactions();
if ((changed= (info.copied || info.deleted || info.updated)) ||
was_insert_delayed)
if ((changed= (info.copied || info.deleted || info.updated)))
{
/*
Invalidate the table in the query cache if something changed.
@ -874,46 +873,47 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
*/
if (changed)
query_cache_invalidate3(thd, table_list, 1);
if (error <= 0 || !transactional_table)
}
if (changed && error <= 0 || thd->transaction.stmt.modified_non_trans_table
|| was_insert_delayed)
{
if (mysql_bin_log.is_open())
{
if (mysql_bin_log.is_open())
if (error <= 0)
{
if (error <= 0)
{
/*
[Guilhem wrote] Temporary errors may have filled
thd->net.last_error/errno. For example if there has
been a disk full error when writing the row, and it was
MyISAM, then thd->net.last_error/errno will be set to
"disk full"... and the my_pwrite() will wait until free
space appears, and so when it finishes then the
write_row() was entirely successful
*/
/* todo: consider removing */
thd->clear_error();
}
/* bug#22725:
A query which per-row-loop can not be interrupted with
KILLED, like INSERT, and that does not invoke stored
routines can be binlogged with neglecting the KILLED error.
If there was no error (error == zero) until after the end of
inserting loop the KILLED flag that appeared later can be
disregarded since previously possible invocation of stored
routines did not result in any error due to the KILLED. In
such case the flag is ignored for constructing binlog event.
/*
[Guilhem wrote] Temporary errors may have filled
thd->net.last_error/errno. For example if there has
been a disk full error when writing the row, and it was
MyISAM, then thd->net.last_error/errno will be set to
"disk full"... and the my_pwrite() will wait until free
space appears, and so when it finishes then the
write_row() was entirely successful
*/
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_table, FALSE,
(error>0) ? thd->killed : THD::NOT_KILLED);
DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
/* todo: consider removing */
thd->clear_error();
}
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
/* bug#22725:
A query which per-row-loop can not be interrupted with
KILLED, like INSERT, and that does not invoke stored
routines can be binlogged with neglecting the KILLED error.
If there was no error (error == zero) until after the end of
inserting loop the KILLED flag that appeared later can be
disregarded since previously possible invocation of stored
routines did not result in any error due to the KILLED. In
such case the flag is ignored for constructing binlog event.
*/
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_table, FALSE,
(error>0) ? thd->killed : THD::NOT_KILLED);
DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
}
DBUG_ASSERT(transactional_table || !changed ||
thd->transaction.stmt.modified_non_trans_table);
@ -2938,6 +2938,7 @@ bool select_insert::send_eof()
{
int error, error2;
bool changed, transactional_table= table->file->has_transactions();
THD::killed_state killed_status= thd->killed;
DBUG_ENTER("select_insert::send_eof");
error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0;
@ -2967,7 +2968,7 @@ bool select_insert::send_eof()
if (!error)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_table, FALSE);
transactional_table, FALSE, killed_status);
mysql_bin_log.write(&qinfo);
}
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
@ -3004,6 +3005,7 @@ void select_insert::abort()
*/
DBUG_VOID_RETURN;
}
changed= (info.copied || info.deleted || info.updated);
transactional_table= table->file->has_transactions();
if (!thd->prelocked_mode)
table->file->end_bulk_insert();
@ -3013,8 +3015,7 @@ void select_insert::abort()
error while inserting into a MyISAM table) we must write to the binlog (and
the error code will make the slave stop).
*/
if ((changed= info.copied || info.deleted || info.updated) &&
!transactional_table)
if (thd->transaction.stmt.modified_non_trans_table)
{
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log

View file

@ -85,7 +85,8 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
#ifndef EMBEDDED_LIBRARY
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
bool transactional_table);
bool transactional_table,
THD::killed_state killed_status);
#endif /* EMBEDDED_LIBRARY */
/*
@ -135,6 +136,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
char *tdb= thd->db ? thd->db : db; // Result is never null
ulong skip_lines= ex->skip_lines;
bool transactional_table;
THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@ -404,7 +406,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
/*
simulated killing in the middle of per-row loop
must be effective for binlogging
*/
DBUG_EXECUTE_IF("simulate_kill_bug27571",
{
error=1;
thd->killed= THD::KILL_QUERY;
};);
killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
/*
We must invalidate the table in query cache before binlog writing and
ha_autocommit_...
@ -444,9 +455,10 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* If the file was not empty, wrote_create_file is true */
if (lf_info.wrote_create_file)
{
if ((info.copied || info.deleted) && !transactional_table)
if (thd->transaction.stmt.modified_non_trans_table)
write_execute_load_query_log_event(thd, handle_duplicates,
ignore, transactional_table);
ignore, transactional_table,
killed_status);
else
{
Delete_file_log_event d(thd, db, transactional_table);
@ -477,7 +489,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
read_info.end_io_cache();
if (lf_info.wrote_create_file)
write_execute_load_query_log_event(thd, handle_duplicates,
ignore, transactional_table);
ignore, transactional_table,
killed_status);
}
#endif /*!EMBEDDED_LIBRARY*/
if (transactional_table)
@ -504,7 +517,8 @@ err:
/* Not a very useful function; just to avoid duplication of code */
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
bool transactional_table)
bool transactional_table,
THD::killed_state killed_err_arg)
{
Execute_load_query_log_event
e(thd, thd->query, thd->query_length,
@ -512,7 +526,7 @@ static bool write_execute_load_query_log_event(THD *thd,
(char*)thd->lex->fname_end - (char*)thd->query,
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
transactional_table, FALSE);
transactional_table, FALSE, killed_err_arg);
return mysql_bin_log.write(&e);
}

View file

@ -2853,7 +2853,16 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
pthread_mutex_lock(&LOCK_active_mi);
res = show_master_info(thd,active_mi);
if (active_mi != NULL)
{
res = show_master_info(thd, active_mi);
}
else
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"the master info structure does not exist");
send_ok(thd);
}
pthread_mutex_unlock(&LOCK_active_mi);
break;
}
@ -3701,6 +3710,13 @@ end_with_restore_list:
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE,
del_result, unit, select_lex);
res|= thd->net.report_error;
if (unlikely(res))
{
/* If we had a another error reported earlier then this will be ignored */
del_result->send_error(ER_UNKNOWN_ERROR, "Execution of the query failed");
del_result->abort();
}
delete del_result;
}
else

View file

@ -364,7 +364,6 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
name=0; // Find first log
linfo.index_file_offset = 0;
thd->current_linfo = &linfo;
if (mysql_bin_log.find_log_pos(&linfo, name, 1))
{
@ -373,6 +372,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
goto err;
}
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = &linfo;
pthread_mutex_unlock(&LOCK_thread_count);
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
@ -1338,7 +1341,6 @@ bool mysql_show_binlog_events(THD* thd)
name=0; // Find first log
linfo.index_file_offset = 0;
thd->current_linfo = &linfo;
if (mysql_bin_log.find_log_pos(&linfo, name, 1))
{
@ -1346,6 +1348,10 @@ bool mysql_show_binlog_events(THD* thd)
goto err;
}
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = &linfo;
pthread_mutex_unlock(&LOCK_thread_count);
if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0)
goto err;

View file

@ -134,6 +134,7 @@ int mysql_update(THD *thd,
SELECT_LEX *select_lex= &thd->lex->select_lex;
bool need_reopen;
List<Item> all_fields;
THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_update");
LINT_INIT(timestamp_query_id);
@ -519,43 +520,26 @@ int mysql_update(THD *thd,
table->file->unlock_row();
thd->row_count++;
}
/*
Caching the killed status to pass as the arg to query event constuctor;
The cached value can not change whereas the killed status can
(externally) since this point and change of the latter won't affect
binlogging.
It's assumed that if an error was set in combination with an effective
killed status then the error is due to killing.
*/
killed_status= thd->killed; // get the status of the volatile
// simulated killing after the loop must be ineffective for binlogging
DBUG_EXECUTE_IF("simulate_kill_bug27571",
{
thd->killed= THD::KILL_QUERY;
};);
error= (killed_status == THD::NOT_KILLED)? error : 1;
if (!transactional_table && updated > 0)
thd->transaction.stmt.modified_non_trans_table= TRUE;
/*
todo bug#27571: to avoid asynchronization of `error' and
`error_code' of binlog event constructor
The concept, which is a bit different for insert(!), is to
replace `error' assignment with the following lines
killed_status= thd->killed; // get the status of the volatile
Notice: thd->killed is type of "state" whereas the lhs has
"status" the suffix which translates according to WordNet: a state
at a particular time - at the time of the end of per-row loop in
our case. Binlogging ops are conducted with the status.
error= (killed_status == THD::NOT_KILLED)? error : 1;
which applies to most mysql_$query functions.
Event's constructor will accept `killed_status' as an argument:
Query_log_event qinfo(..., killed_status);
thd->killed might be changed after killed_status had got cached and this
won't affect binlogging event but other effects remain.
Open issue: In a case the error happened not because of KILLED -
and then KILLED was caught later still within the loop - we shall
do something to avoid binlogging of incorrect ER_SERVER_SHUTDOWN
error_code.
*/
if (thd->killed && !error)
error= 1; // Aborted
end_read_record(&info);
free_io_cache(table); // If ORDER BY
delete select;
@ -580,14 +564,14 @@ int mysql_update(THD *thd,
Sometimes we want to binlog even if we updated no rows, in case user used
it to be sure master and slave are in same state.
*/
if ((error < 0) || (updated && !transactional_table))
if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
if (error < 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_table, FALSE);
transactional_table, FALSE, killed_status);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1; // Rollback update
}
@ -994,8 +978,8 @@ multi_update::multi_update(TABLE_LIST *table_list,
:all_tables(table_list), leaves(leaves_list), update_tables(0),
tmp_tables(0), updated(0), found(0), fields(field_list),
values(value_list), table_count(0), copy_field(0),
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
transactional_tables(1), ignore(ignore_arg)
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1),
transactional_tables(1), ignore(ignore_arg), error_handled(0)
{}
@ -1202,7 +1186,6 @@ multi_update::initialize_tables(JOIN *join)
if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
DBUG_RETURN(1);
main_table=join->join_tab->table;
trans_safe= transactional_tables= main_table->file->has_transactions();
table_to_update= 0;
/* Any update has at least one pair (field, value) */
@ -1484,12 +1467,14 @@ void multi_update::send_error(uint errcode,const char *err)
/* First send error what ever it is ... */
my_error(errcode, MYF(0), err);
/* If nothing updated return */
if (updated == 0) /* the counter might be reset in send_eof */
return; /* and then the query has been binlogged */
/* the error was handled or nothing deleted and no side effects return */
if (error_handled ||
!thd->transaction.stmt.modified_non_trans_table && !updated)
return;
/* Something already updated so we have to invalidate cache */
query_cache_invalidate3(thd, update_tables, 1);
if (updated)
query_cache_invalidate3(thd, update_tables, 1);
/*
If all tables that has been updated are trans safe then just do rollback.
If not attempt to do remaining updates.
@ -1521,12 +1506,16 @@ void multi_update::send_error(uint errcode,const char *err)
*/
if (mysql_bin_log.is_open())
{
/*
THD::killed status might not have been set ON at time of an error
got caught and if happens later the killed error is written
into repl event.
*/
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_tables, FALSE);
mysql_bin_log.write(&qinfo);
}
if (!trans_safe)
thd->transaction.all.modified_non_trans_table= TRUE;
thd->transaction.all.modified_non_trans_table= TRUE;
}
DBUG_ASSERT(trans_safe || !updated || thd->transaction.stmt.modified_non_trans_table);
@ -1709,10 +1698,19 @@ err2:
bool multi_update::send_eof()
{
char buff[STRING_BUFFER_USUAL_SIZE];
THD::killed_state killed_status= THD::NOT_KILLED;
thd->proc_info="updating reference tables";
/* Does updates for the last n - 1 tables, returns 0 if ok */
/*
Does updates for the last n - 1 tables, returns 0 if ok;
error takes into account killed status gained in do_updates()
*/
int local_error = (table_count) ? do_updates(0) : 0;
/*
if local_error is not set ON until after do_updates() then
later carried out killing should not affect binlogging.
*/
killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed;
thd->proc_info= "end";
/* We must invalidate the query cache before binlog writing and
@ -1739,16 +1737,16 @@ bool multi_update::send_eof()
{
if (local_error == 0)
thd->clear_error();
else
updated= 0; /* if there's an error binlog it here not in ::send_error */
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_tables, FALSE);
transactional_tables, FALSE, killed_status);
if (mysql_bin_log.write(&qinfo) && trans_safe)
local_error= 1; // Rollback update
}
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
}
if (local_error != 0)
error_handled= TRUE; // to force early leave from ::send_error()
if (transactional_tables)
{

View file

@ -179,20 +179,39 @@ static uchar NEAR sort_order_euc_kr[]=
/* Support for Korean(EUC_KR) characters, by powerm90@tinc.co.kr and mrpark@tinc.co.kr */
#define iseuc_kr(c) ((0xa1<=(uchar)(c) && (uchar)(c)<=0xfe))
/*
Unicode mapping is done according to:
ftp://ftp.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/KSC/KSC5601.TXT
Valid multi-byte characters:
[A1..FE][41..5A,61..7A,81..FE]
Note, 0x5C is not a valid MB tail,
so escape_with_backslash_is_dangerous is not set.
*/
#define iseuc_kr_head(c) ((0xa1<=(uchar)(c) && (uchar)(c)<=0xfe))
#define iseuc_kr_tail1(c) ((uchar) (c) >= 0x41 && (uchar) (c) <= 0x5A)
#define iseuc_kr_tail2(c) ((uchar) (c) >= 0x61 && (uchar) (c) <= 0x7A)
#define iseuc_kr_tail3(c) ((uchar) (c) >= 0x81 && (uchar) (c) <= 0xFE)
#define iseuc_kr_tail(c) (iseuc_kr_tail1(c) || \
iseuc_kr_tail2(c) || \
iseuc_kr_tail3(c))
static int ismbchar_euc_kr(CHARSET_INFO *cs __attribute__((unused)),
const char* p, const char *e)
{
return ((*(uchar*)(p)<0x80)? 0:\
iseuc_kr(*(p)) && (e)-(p)>1 && iseuc_kr(*((p)+1))? 2:\
iseuc_kr_head(*(p)) && (e)-(p)>1 && iseuc_kr_tail(*((p)+1))? 2:\
0);
}
static int mbcharlen_euc_kr(CHARSET_INFO *cs __attribute__((unused)),uint c)
{
return (iseuc_kr(c) ? 2 : 1);
return (iseuc_kr_head(c) ? 2 : 1);
}
@ -8653,7 +8672,7 @@ my_well_formed_len_euckr(CHARSET_INFO *cs __attribute__((unused)),
/* Single byte ascii character */
b++;
}
else if (b < emb && iseuc_kr(*b) && iseuc_kr(b[1]))
else if (b < emb && iseuc_kr_head(*b) && iseuc_kr_tail(b[1]))
{
/* Double byte character */
b+= 2;