mirror of
https://github.com/MariaDB/server.git
synced 2025-02-02 12:01:42 +01:00
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0
into poseidon.ndb.mysql.com:/home/tomas/mysql-5.0-ndb
This commit is contained in:
commit
be63bf616b
33 changed files with 603 additions and 128 deletions
|
@ -206,11 +206,13 @@ void __CDECL hfree(void *ptr);
|
|||
#endif
|
||||
#endif /* MSDOS */
|
||||
|
||||
#ifndef errno /* did we already get it? */
|
||||
#ifdef HAVE_ERRNO_AS_DEFINE
|
||||
#include <errno.h> /* errno is a define */
|
||||
#else
|
||||
extern int errno; /* declare errno */
|
||||
#endif
|
||||
#endif /* #ifndef errno */
|
||||
extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
|
||||
extern char *home_dir; /* Home directory for user */
|
||||
extern char *my_progname; /* program-name (printed in errors) */
|
||||
|
|
|
@ -18,5 +18,4 @@ master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table
|
|||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int)
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int)
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`,`drop-temp+table-test`.`table:name`,`drop-temp+table-test`.`shortn1`
|
||||
master-bin.000001 # Query 1 # use `drop-temp+table-test`; DO RELEASE_LOCK("a")
|
||||
drop database `drop-temp+table-test`;
|
||||
|
|
|
@ -93,7 +93,6 @@ master-bin.000001 96 Query 1 # use `test`; BEGIN
|
|||
master-bin.000001 165 Query 1 # use `test`; insert into t1 values(8)
|
||||
master-bin.000001 253 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 348 Query 1 # use `test`; ROLLBACK
|
||||
master-bin.000001 420 Query 1 # use `test`; DO RELEASE_LOCK("a")
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
|
|
@ -487,3 +487,40 @@ insert into t1 values ('foo');
|
|||
prepare stmt FROM 'SELECT char_length (a) FROM t1';
|
||||
ERROR 42000: FUNCTION test.char_length does not exist
|
||||
drop table t1;
|
||||
prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0";
|
||||
execute stmt;
|
||||
foo
|
||||
SELECT FOUND_ROWS();
|
||||
FOUND_ROWS()
|
||||
2
|
||||
execute stmt;
|
||||
foo
|
||||
SELECT FOUND_ROWS();
|
||||
FOUND_ROWS()
|
||||
2
|
||||
deallocate prepare stmt;
|
||||
create table t1 (a char(3) not null, b char(3) not null,
|
||||
c char(3) not null, primary key (a, b, c));
|
||||
create table t2 like t1;
|
||||
prepare stmt from
|
||||
"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
|
||||
where t1.a=1";
|
||||
execute stmt;
|
||||
a
|
||||
execute stmt;
|
||||
a
|
||||
execute stmt;
|
||||
a
|
||||
prepare stmt from
|
||||
"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
|
||||
(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
|
||||
left outer join t2 t3 on t3.a=? where t1.a=?";
|
||||
set @a:=1, @b:=1, @c:=1;
|
||||
execute stmt using @a, @b, @c;
|
||||
a b c a b c
|
||||
execute stmt using @a, @b, @c;
|
||||
a b c a b c
|
||||
execute stmt using @a, @b, @c;
|
||||
a b c a b c
|
||||
deallocate prepare stmt;
|
||||
drop table t1,t2;
|
||||
|
|
|
@ -33,27 +33,12 @@ select sum(length(word)) from t1;
|
|||
sum(length(word))
|
||||
1022
|
||||
drop table t1,t3;
|
||||
create table t1 (n int) engine=myisam;
|
||||
reset master;
|
||||
stop slave;
|
||||
reset slave;
|
||||
create table t1(n int);
|
||||
select get_lock("hold_slave",10);
|
||||
get_lock("hold_slave",10)
|
||||
1
|
||||
explain extended select get_lock("hold_slave",10);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select sql_no_cache get_lock(_latin1'hold_slave',10) AS `get_lock("hold_slave",10)`
|
||||
lock tables t1 read;
|
||||
start slave;
|
||||
select release_lock("hold_slave");
|
||||
release_lock("hold_slave")
|
||||
1
|
||||
explain extended select release_lock("hold_slave");
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select sql_no_cache release_lock(_latin1'hold_slave') AS `release_lock("hold_slave")`
|
||||
unlock tables;
|
||||
create table t2(id int);
|
||||
insert into t2 values(connection_id());
|
||||
|
|
|
@ -4,26 +4,20 @@ reset master;
|
|||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
select get_lock("a",5);
|
||||
get_lock("a",5)
|
||||
1
|
||||
create table t1(n int);
|
||||
insert into t1 values(1+get_lock("a",15)*0);
|
||||
insert into t1 values(2);
|
||||
stop slave;
|
||||
select * from t1;
|
||||
n
|
||||
1
|
||||
stop slave sql_thread;
|
||||
insert into t1 values(1);
|
||||
insert into t1 values(2);
|
||||
stop slave;
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running 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 Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 377 # # master-bin.000001 No No 0 0 289 # None 0 No #
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 358 # # master-bin.000001 No No 0 0 182 # None 0 No #
|
||||
change master to master_user='root';
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running 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 Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 289 # # master-bin.000001 No No 0 0 289 # None 0 No #
|
||||
select release_lock("a");
|
||||
release_lock("a")
|
||||
1
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 182 # # master-bin.000001 No No 0 0 182 # None 0 No #
|
||||
start slave;
|
||||
select * from t1;
|
||||
n
|
||||
|
|
81
mysql-test/r/rpl_deadlock.result
Normal file
81
mysql-test/r/rpl_deadlock.result
Normal file
|
@ -0,0 +1,81 @@
|
|||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
create table t1 (a int not null, key(a)) engine=innodb;
|
||||
create table t2 (a int not null, key(a)) engine=innodb;
|
||||
create table t3 (a int) engine=innodb;
|
||||
create table t4 (a int) engine=innodb;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
KEY `a` (`a`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL,
|
||||
KEY `a` (`a`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
stop slave;
|
||||
begin;
|
||||
insert into t3 select * from t2 for update;
|
||||
insert into t1 values(1);
|
||||
commit;
|
||||
begin;
|
||||
select * from t1 for update;
|
||||
a
|
||||
start slave;
|
||||
insert into t2 values(22);
|
||||
commit;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
22
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running 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 Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 19116 # # master-bin.000001 Yes Yes 0 0 19116 # None 0 No #
|
||||
stop slave;
|
||||
change master to master_log_pos=534;
|
||||
begin;
|
||||
select * from t2 for update;
|
||||
a
|
||||
22
|
||||
start slave;
|
||||
commit;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
22
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running 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 Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 19116 # # master-bin.000001 Yes Yes 0 0 19116 # None 0 No #
|
||||
set global max_relay_log_size=0;
|
||||
stop slave;
|
||||
change master to master_log_pos=534;
|
||||
begin;
|
||||
select * from t2 for update;
|
||||
a
|
||||
22
|
||||
start slave;
|
||||
commit;
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
1
|
||||
1
|
||||
select * from t2;
|
||||
a
|
||||
22
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running 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 Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 19116 # # master-bin.000001 Yes Yes 0 0 19116 # None 0 No #
|
||||
drop table t1,t2;
|
|
@ -2204,6 +2204,10 @@ call bug8757()|
|
|||
delete from t1|
|
||||
delete from t2|
|
||||
drop procedure bug8757|
|
||||
drop procedure if exists bug8762|
|
||||
drop procedure if exists bug8762; create procedure bug8762() begin end|
|
||||
drop procedure if exists bug8762; create procedure bug8762() begin end|
|
||||
drop procedure bug8762|
|
||||
drop table if exists fac|
|
||||
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
||||
drop procedure if exists ifac|
|
||||
|
@ -2538,3 +2542,41 @@ drop procedure bug7992|
|
|||
drop table t3|
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
CREATE TABLE t1 (
|
||||
lpitnumber int(11) default NULL,
|
||||
lrecordtype int(11) default NULL
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
lbsiid int(11) NOT NULL default '0',
|
||||
ltradingmodeid int(11) NOT NULL default '0',
|
||||
ltradingareaid int(11) NOT NULL default '0',
|
||||
csellingprice decimal(19,4) default NULL,
|
||||
PRIMARY KEY (lbsiid,ltradingmodeid,ltradingareaid)
|
||||
);
|
||||
CREATE TABLE t3 (
|
||||
lbsiid int(11) NOT NULL default '0',
|
||||
ltradingareaid int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (lbsiid,ltradingareaid)
|
||||
);
|
||||
CREATE PROCEDURE bug8849()
|
||||
begin
|
||||
insert into t3
|
||||
(
|
||||
t3.lbsiid,
|
||||
t3.ltradingareaid
|
||||
)
|
||||
select distinct t1.lpitnumber, t2.ltradingareaid
|
||||
from
|
||||
t2 join t1 on
|
||||
t1.lpitnumber = t2.lbsiid
|
||||
and t1.lrecordtype = 1
|
||||
left join t2 as price01 on
|
||||
price01.lbsiid = t2.lbsiid and
|
||||
price01.ltradingmodeid = 1 and
|
||||
t2.ltradingareaid = price01.ltradingareaid;
|
||||
end|
|
||||
call bug8849();
|
||||
call bug8849();
|
||||
call bug8849();
|
||||
drop procedure bug8849;
|
||||
drop tables t1,t2,t3;
|
||||
|
|
|
@ -497,3 +497,46 @@ insert into t1 values ('foo');
|
|||
prepare stmt FROM 'SELECT char_length (a) FROM t1';
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #6089: FOUND_ROWS returns wrong values when no table/view is used
|
||||
#
|
||||
|
||||
prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0";
|
||||
execute stmt;
|
||||
SELECT FOUND_ROWS();
|
||||
execute stmt;
|
||||
SELECT FOUND_ROWS();
|
||||
deallocate prepare stmt;
|
||||
|
||||
#
|
||||
# Bug#8115: equality propagation and prepared statements
|
||||
#
|
||||
|
||||
create table t1 (a char(3) not null, b char(3) not null,
|
||||
c char(3) not null, primary key (a, b, c));
|
||||
create table t2 like t1;
|
||||
|
||||
# reduced query
|
||||
prepare stmt from
|
||||
"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
|
||||
where t1.a=1";
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
|
||||
# original query
|
||||
prepare stmt from
|
||||
"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
|
||||
(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
|
||||
left outer join t2 t3 on t3.a=? where t1.a=?";
|
||||
|
||||
set @a:=1, @b:=1, @c:=1;
|
||||
|
||||
execute stmt using @a, @b, @c;
|
||||
execute stmt using @a, @b, @c;
|
||||
execute stmt using @a, @b, @c;
|
||||
|
||||
deallocate prepare stmt;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
|
|
|
@ -39,7 +39,13 @@ save_master_pos;
|
|||
connection slave;
|
||||
sync_with_master;
|
||||
|
||||
#test handling of aborted connection in the middle of update
|
||||
# Test if the slave SQL thread can be more than 16K behind the slave
|
||||
# I/O thread (> IO_SIZE)
|
||||
|
||||
connection master;
|
||||
# we'll use table-level locking to delay slave SQL thread
|
||||
create table t1 (n int) engine=myisam;
|
||||
sync_slave_with_master;
|
||||
connection master;
|
||||
reset master;
|
||||
connection slave;
|
||||
|
@ -47,29 +53,26 @@ stop slave;
|
|||
reset slave;
|
||||
|
||||
connection master;
|
||||
create table t1(n int);
|
||||
#we want the log to exceed 16K to test deal with the log that is bigger than
|
||||
#IO_SIZE
|
||||
let $1=5000;
|
||||
# Generate 16K of relay log
|
||||
disable_query_log;
|
||||
while ($1)
|
||||
{
|
||||
eval insert into t1 values($1+get_lock("hold_slave",10)*0);
|
||||
eval insert into t1 values($1);
|
||||
dec $1;
|
||||
}
|
||||
enable_query_log;
|
||||
|
||||
# Try to cause a large relay log lag on the slave
|
||||
# Try to cause a large relay log lag on the slave by locking t1
|
||||
connection slave;
|
||||
select get_lock("hold_slave",10);
|
||||
explain extended select get_lock("hold_slave",10);
|
||||
lock tables t1 read;
|
||||
start slave;
|
||||
#hope this is long enough for I/O thread to fetch over 16K relay log data
|
||||
sleep 3;
|
||||
select release_lock("hold_slave");
|
||||
explain extended select release_lock("hold_slave");
|
||||
unlock tables;
|
||||
|
||||
#test handling of aborted connection in the middle of update
|
||||
|
||||
connection master;
|
||||
create table t2(id int);
|
||||
insert into t2 values(connection_id());
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
# Verify that after CHANGE MASTER, replication (I/O thread and SQL
|
||||
# thread) restart from where SQL thread left, not from where
|
||||
# I/O thread left (some old bug fixed in 4.0.17)
|
||||
|
||||
source include/master-slave.inc;
|
||||
|
||||
connection slave;
|
||||
select get_lock("a",5);
|
||||
connection master;
|
||||
# Make SQL slave thread advance a bit
|
||||
create table t1(n int);
|
||||
insert into t1 values(1+get_lock("a",15)*0);
|
||||
sync_slave_with_master;
|
||||
select * from t1;
|
||||
# Now stop it and make I/O slave thread be ahead
|
||||
stop slave sql_thread;
|
||||
connection master;
|
||||
insert into t1 values(1);
|
||||
insert into t1 values(2);
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
--real_sleep 3; # can't sync_with_master as we should be blocked
|
||||
--real_sleep 3; # wait for I/O thread to have read updates
|
||||
stop slave;
|
||||
select * from t1;
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
--replace_column 1 # 8 # 9 # 23 # 33 #
|
||||
show slave status;
|
||||
|
@ -18,8 +25,6 @@ change master to master_user='root';
|
|||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
--replace_column 1 # 8 # 9 # 23 # 33 #
|
||||
show slave status;
|
||||
# Will restart from after the values(2), which is bug
|
||||
select release_lock("a");
|
||||
start slave;
|
||||
sync_with_master;
|
||||
select * from t1;
|
||||
|
|
1
mysql-test/t/rpl_deadlock-slave.opt
Normal file
1
mysql-test/t/rpl_deadlock-slave.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--innodb --loose-innodb_lock_wait_timeout=4 --slave-transaction-retries=2 --max-relay-log-size=4096
|
107
mysql-test/t/rpl_deadlock.test
Normal file
107
mysql-test/t/rpl_deadlock.test
Normal file
|
@ -0,0 +1,107 @@
|
|||
# See if slave restarts the transaction after failing on an InnoDB deadlock error.
|
||||
|
||||
# Note: testing what happens when too many retries is possible, but
|
||||
# needs large waits when running with --debug, so we don't do it.
|
||||
# The same way, this test may not test what is expected when run
|
||||
# under Valgrind, timings are too short then (with --valgrind I
|
||||
# (Guilhem) have seen the test manage to provoke lock wait timeout
|
||||
# error but not deadlock error; that is ok as code deals with the two
|
||||
# errors in exactly the same way.
|
||||
|
||||
source include/have_innodb.inc;
|
||||
source include/master-slave.inc;
|
||||
|
||||
connection master;
|
||||
create table t1 (a int not null, key(a)) engine=innodb;
|
||||
create table t2 (a int not null, key(a)) engine=innodb;
|
||||
create table t3 (a int) engine=innodb;
|
||||
create table t4 (a int) engine=innodb;
|
||||
sync_slave_with_master;
|
||||
|
||||
show create table t1;
|
||||
show create table t2;
|
||||
stop slave;
|
||||
|
||||
# 1) Test deadlock
|
||||
|
||||
connection master;
|
||||
begin;
|
||||
# Let's keep BEGIN and the locked statement in two different relay logs.
|
||||
let $1=200;
|
||||
disable_query_log;
|
||||
while ($1)
|
||||
{
|
||||
eval insert into t3 values( $1 );
|
||||
dec $1;
|
||||
}
|
||||
enable_query_log;
|
||||
insert into t3 select * from t2 for update;
|
||||
insert into t1 values(1);
|
||||
commit;
|
||||
save_master_pos;
|
||||
|
||||
connection slave;
|
||||
begin;
|
||||
# Let's make our transaction large so that it's slave who is chosen as
|
||||
# victim
|
||||
let $1=1000;
|
||||
disable_query_log;
|
||||
while ($1)
|
||||
{
|
||||
eval insert into t4 values( $1 );
|
||||
dec $1;
|
||||
}
|
||||
enable_query_log;
|
||||
select * from t1 for update;
|
||||
start slave;
|
||||
--sleep 3; # hope that slave is blocked now
|
||||
insert into t2 values(22); # provoke deadlock, slave should be victim
|
||||
commit;
|
||||
sync_with_master;
|
||||
select * from t1; # check that slave succeeded finally
|
||||
select * from t2;
|
||||
# check that no error is reported
|
||||
--replace_column 1 # 8 # 9 # 23 # 33 #
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
show slave status;
|
||||
|
||||
# 2) Test lock wait timeout
|
||||
|
||||
stop slave;
|
||||
change master to master_log_pos=534; # the BEGIN log event
|
||||
begin;
|
||||
select * from t2 for update; # hold lock
|
||||
start slave;
|
||||
--sleep 10; # slave should have blocked, and be retrying
|
||||
commit;
|
||||
sync_with_master;
|
||||
select * from t1; # check that slave succeeded finally
|
||||
select * from t2;
|
||||
# check that no error is reported
|
||||
--replace_column 1 # 8 # 9 # 23 # 33 #
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
show slave status;
|
||||
|
||||
# Now we repeat 2), but with BEGIN in the same relay log as
|
||||
# COMMIT (to see if seeking into hot log is ok).
|
||||
|
||||
set global max_relay_log_size=0;
|
||||
|
||||
# This is really copy-paste of 2) of above
|
||||
stop slave;
|
||||
change master to master_log_pos=534;
|
||||
begin;
|
||||
select * from t2 for update;
|
||||
start slave;
|
||||
--sleep 10;
|
||||
commit;
|
||||
sync_with_master;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
--replace_column 1 # 8 # 9 # 23 # 33 #
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
show slave status;
|
||||
|
||||
connection master;
|
||||
drop table t1,t2;
|
||||
sync_slave_with_master;
|
|
@ -22,6 +22,13 @@ connection slave;
|
|||
sync_with_master;
|
||||
select get_lock("lock",3);
|
||||
select * from t1;
|
||||
# There is no point in testing REPLICATIION of the IS_*_LOCK
|
||||
# functions; slave does not run with the same concurrency context as
|
||||
# master (generally in slave we can't know that on master this lock
|
||||
# was already held by another connection and so that the the
|
||||
# get_lock() we're replicating timed out on master hence returned 0,
|
||||
# or that the is_free_lock() we're playing returned 0 etc.
|
||||
# But here all we do is test these functions outside of replication.
|
||||
select is_free_lock("lock"), is_used_lock("lock") = connection_id();
|
||||
explain extended select is_free_lock("lock"), is_used_lock("lock");
|
||||
# Check lock functions
|
||||
|
|
|
@ -2714,6 +2714,19 @@ delete from t2|
|
|||
drop procedure bug8757|
|
||||
|
||||
|
||||
#
|
||||
# BUG#8762: Stored Procedures: Inconsistent behavior
|
||||
# of DROP PROCEDURE IF EXISTS statement.
|
||||
--disable_warnings
|
||||
drop procedure if exists bug8762|
|
||||
--enable_warnings
|
||||
# Doesn't exist
|
||||
drop procedure if exists bug8762; create procedure bug8762() begin end|
|
||||
# Does exist
|
||||
drop procedure if exists bug8762; create procedure bug8762() begin end|
|
||||
drop procedure bug8762|
|
||||
|
||||
|
||||
#
|
||||
# Some "real" examples
|
||||
#
|
||||
|
@ -3073,3 +3086,52 @@ delimiter ;|
|
|||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
#
|
||||
# Bug#8849: rolling back changes to AND/OR structure of ON and WHERE clauses
|
||||
# in SP
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
lpitnumber int(11) default NULL,
|
||||
lrecordtype int(11) default NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
lbsiid int(11) NOT NULL default '0',
|
||||
ltradingmodeid int(11) NOT NULL default '0',
|
||||
ltradingareaid int(11) NOT NULL default '0',
|
||||
csellingprice decimal(19,4) default NULL,
|
||||
PRIMARY KEY (lbsiid,ltradingmodeid,ltradingareaid)
|
||||
);
|
||||
|
||||
CREATE TABLE t3 (
|
||||
lbsiid int(11) NOT NULL default '0',
|
||||
ltradingareaid int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (lbsiid,ltradingareaid)
|
||||
);
|
||||
|
||||
delimiter |;
|
||||
CREATE PROCEDURE bug8849()
|
||||
begin
|
||||
insert into t3
|
||||
(
|
||||
t3.lbsiid,
|
||||
t3.ltradingareaid
|
||||
)
|
||||
select distinct t1.lpitnumber, t2.ltradingareaid
|
||||
from
|
||||
t2 join t1 on
|
||||
t1.lpitnumber = t2.lbsiid
|
||||
and t1.lrecordtype = 1
|
||||
left join t2 as price01 on
|
||||
price01.lbsiid = t2.lbsiid and
|
||||
price01.ltradingmodeid = 1 and
|
||||
t2.ltradingareaid = price01.ltradingareaid;
|
||||
end|
|
||||
delimiter ;|
|
||||
|
||||
call bug8849();
|
||||
call bug8849();
|
||||
call bug8849();
|
||||
drop procedure bug8849;
|
||||
drop tables t1,t2,t3;
|
||||
|
|
|
@ -2289,6 +2289,21 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
|
||||
if (check_stack_overrun(thd, buff))
|
||||
return TRUE; // Fatal error flag is set!
|
||||
/*
|
||||
The following optimization reduces the depth of an AND-OR tree.
|
||||
E.g. a WHERE clause like
|
||||
F1 AND (F2 AND (F2 AND F4))
|
||||
is parsed into a tree with the same nested structure as defined
|
||||
by braces. This optimization will transform such tree into
|
||||
AND (F1, F2, F3, F4).
|
||||
Trees of OR items are flattened as well:
|
||||
((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4)
|
||||
Items for removed AND/OR levels will dangle until the death of the
|
||||
entire statement.
|
||||
The optimization is currently prepared statements and stored procedures
|
||||
friendly as it doesn't allocate any memory and its effects are durable
|
||||
(i.e. do not depend on PS/SP arguments).
|
||||
*/
|
||||
while ((item=li++))
|
||||
{
|
||||
table_map tmp_table_map;
|
||||
|
@ -3265,6 +3280,7 @@ Item_equal::Item_equal(Item *c, Item_field *f)
|
|||
const_item= c;
|
||||
}
|
||||
|
||||
|
||||
Item_equal::Item_equal(Item_equal *item_equal)
|
||||
: Item_bool_func(), eval_item(0), cond_false(0)
|
||||
{
|
||||
|
@ -3301,12 +3317,7 @@ void Item_equal::add(Item_field *f)
|
|||
|
||||
uint Item_equal::members()
|
||||
{
|
||||
uint count= 0;
|
||||
List_iterator_fast<Item_field> li(fields);
|
||||
Item_field *item;
|
||||
while ((item= li++))
|
||||
count++;
|
||||
return count;
|
||||
return fields.elements;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1095,6 +1095,12 @@ public:
|
|||
predicates that can not be used to access tables in the investigated
|
||||
plan for those, obtained by substitution of some fields for equal fields,
|
||||
that can be used.
|
||||
|
||||
Prepared Statements/Stored Procedures note: instances of class
|
||||
Item_equal are created only at the time a PS/SP is executed and
|
||||
are deleted in the end of execution. All changes made to these
|
||||
objects need not be registered in the list of changes of the parse
|
||||
tree and do not harm PS/SP re-execution.
|
||||
*/
|
||||
|
||||
class Item_equal: public Item_bool_func
|
||||
|
|
|
@ -2856,18 +2856,6 @@ void item_user_lock_free(void)
|
|||
void item_user_lock_release(User_level_lock *ull)
|
||||
{
|
||||
ull->locked=0;
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
char buf[256];
|
||||
const char *command="DO RELEASE_LOCK(\"";
|
||||
String tmp(buf,sizeof(buf), system_charset_info);
|
||||
tmp.copy(command, strlen(command), tmp.charset());
|
||||
tmp.append(ull->key,ull->key_length);
|
||||
tmp.append("\")", 2);
|
||||
Query_log_event qev(current_thd, tmp.ptr(), tmp.length(), 0, FALSE);
|
||||
qev.error_code=0; // this query is always safe to run on slave
|
||||
mysql_bin_log.write(&qev);
|
||||
}
|
||||
if (--ull->count)
|
||||
pthread_cond_signal(&ull->cond);
|
||||
else
|
||||
|
@ -2991,6 +2979,16 @@ longlong Item_func_get_lock::val_int()
|
|||
User_level_lock *ull;
|
||||
int error=0;
|
||||
|
||||
/*
|
||||
In slave thread no need to get locks, everything is serialized. Anyway
|
||||
there is no way to make GET_LOCK() work on slave like it did on master
|
||||
(i.e. make it return exactly the same value) because we don't have the
|
||||
same other concurrent threads environment. No matter what we return here,
|
||||
it's not guaranteed to be same as on master.
|
||||
*/
|
||||
if (thd->slave_thread)
|
||||
return 1;
|
||||
|
||||
pthread_mutex_lock(&LOCK_user_locks);
|
||||
|
||||
if (!res || !res->length())
|
||||
|
|
|
@ -2457,7 +2457,7 @@ void sql_print_information(const char *format, ...)
|
|||
|
||||
static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
|
||||
|
||||
uint opt_tc_log_size=TC_LOG_MIN_SIZE;
|
||||
ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
|
||||
ulong tc_log_max_pages_used=0, tc_log_page_size=0,
|
||||
tc_log_page_waits=0, tc_log_cur_pages_used=0;
|
||||
|
||||
|
|
|
@ -1616,9 +1616,9 @@ end:
|
|||
probably, so data_buf will be freed, so the thd->... listed above will be
|
||||
pointers to freed memory.
|
||||
So we must set them to 0, so that those bad pointers values are not later
|
||||
used. Note that "cleanup" queries (automatic DO RELEASE_LOCK() and DROP
|
||||
TEMPORARY TABLE don't suffer from these assignments to 0 as DROP TEMPORARY
|
||||
TABLE uses the db.table syntax).
|
||||
used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
|
||||
don't suffer from these assignments to 0 as DROP TEMPORARY
|
||||
TABLE uses the db.table syntax.
|
||||
*/
|
||||
thd->db= thd->catalog= 0; // prevent db from being freed
|
||||
thd->query= 0; // just to be sure
|
||||
|
@ -3666,8 +3666,8 @@ void Stop_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev
|
|||
|
||||
The master stopped.
|
||||
We used to clean up all temporary tables but this is useless as, as the
|
||||
master has shut down properly, it has written all DROP TEMPORARY TABLE and DO
|
||||
RELEASE_LOCK (prepared statements' deletion is TODO).
|
||||
master has shut down properly, it has written all DROP TEMPORARY TABLE
|
||||
(prepared statements' deletion is TODO only when we binlog prep stmts).
|
||||
We used to clean up slave_load_tmpdir, but this is useless as it has been
|
||||
cleared at the end of LOAD DATA INFILE.
|
||||
So we have nothing to do here.
|
||||
|
|
|
@ -805,6 +805,7 @@ void mysql_stmt_free(THD *thd, char *packet);
|
|||
void mysql_stmt_reset(THD *thd, char *packet);
|
||||
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
|
||||
void reset_stmt_for_execute(THD *thd, LEX *lex);
|
||||
void init_stmt_after_parse(THD*, LEX*);
|
||||
|
||||
/* sql_error.cc */
|
||||
MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
|
||||
|
@ -1037,7 +1038,7 @@ extern ulong query_cache_size, query_cache_min_res_unit;
|
|||
extern ulong thd_startup_options, slow_launch_threads, slow_launch_time;
|
||||
extern ulong table_cache_size;
|
||||
extern ulong max_connections,max_connect_errors, connect_timeout;
|
||||
extern ulong slave_net_timeout;
|
||||
extern ulong slave_net_timeout, slave_trans_retries;
|
||||
extern uint max_user_connections;
|
||||
extern ulong what_to_log,flush_time;
|
||||
extern ulong query_buff_size, thread_stack,thread_stack_min;
|
||||
|
|
|
@ -334,7 +334,7 @@ ulong server_id, thd_startup_options;
|
|||
ulong table_cache_size, thread_stack, thread_stack_min, what_to_log;
|
||||
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
|
||||
ulong open_files_limit, max_binlog_size, max_relay_log_size;
|
||||
ulong slave_net_timeout;
|
||||
ulong slave_net_timeout, slave_trans_retries;
|
||||
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
|
||||
ulong query_cache_size=0;
|
||||
ulong refresh_version, flush_version; /* Increments on each reload */
|
||||
|
@ -4192,7 +4192,7 @@ enum options_mysqld
|
|||
OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
|
||||
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
|
||||
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
|
||||
OPT_READONLY, OPT_DEBUGGING,
|
||||
OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
|
||||
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
|
||||
OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
|
||||
OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
|
||||
|
@ -4566,7 +4566,7 @@ Disable with --skip-isam.",
|
|||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.",
|
||||
(gptr*) &opt_tc_log_size, (gptr*) &opt_tc_log_size, 0, GET_ULONG,
|
||||
REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0, 0, TC_LOG_PAGE_SIZE, 0},
|
||||
REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0},
|
||||
{"log-update", OPT_UPDATE_LOG,
|
||||
"The update log is deprecated since version 5.0, is replaced by the binary \
|
||||
log and this option justs turns on --log-bin instead.",
|
||||
|
@ -5222,7 +5222,7 @@ The minimum value for this variable is 4096.",
|
|||
(gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
|
||||
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
|
||||
{"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
|
||||
"If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 expected, the minimum value for this variable is 4096.",
|
||||
"If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.",
|
||||
(gptr*) &max_relay_log_size, (gptr*) &max_relay_log_size, 0, GET_ULONG,
|
||||
REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0},
|
||||
{ "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
|
||||
|
@ -5408,6 +5408,12 @@ The minimum value for this variable is 4096.",
|
|||
"Number of seconds to wait for more data from a master/slave connection before aborting the read.",
|
||||
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
|
||||
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
|
||||
{"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES,
|
||||
"Number of times the slave SQL thread will retry a transaction in case "
|
||||
"it failed with a deadlock or elapsed lock wait timeout, "
|
||||
"before giving up and stopping.",
|
||||
(gptr*) &slave_trans_retries, (gptr*) &slave_trans_retries, 0,
|
||||
GET_ULONG, REQUIRED_ARG, 0L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
|
||||
#endif /* HAVE_REPLICATION */
|
||||
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
|
||||
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
|
||||
|
@ -5793,7 +5799,7 @@ static void mysql_init_variables(void)
|
|||
opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
|
||||
opt_disable_networking= opt_skip_show_db=0;
|
||||
opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
|
||||
opt_tc_log_file= "tc.log"; // no hostname in tc_log file name !
|
||||
opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name !
|
||||
opt_secure_auth= 0;
|
||||
opt_bootstrap= opt_myisam_log= 0;
|
||||
mqh_used= 0;
|
||||
|
|
|
@ -340,6 +340,8 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
|
|||
#ifdef HAVE_REPLICATION
|
||||
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
|
||||
&slave_net_timeout);
|
||||
sys_var_long_ptr sys_slave_trans_retries("slave_transaction_retries",
|
||||
&slave_trans_retries);
|
||||
#endif
|
||||
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
|
||||
&slow_launch_time);
|
||||
|
@ -652,6 +654,7 @@ sys_var *sys_variables[]=
|
|||
#ifdef HAVE_REPLICATION
|
||||
&sys_slave_compressed_protocol,
|
||||
&sys_slave_net_timeout,
|
||||
&sys_slave_trans_retries,
|
||||
&sys_slave_skip_counter,
|
||||
#endif
|
||||
&sys_slow_launch_time,
|
||||
|
@ -931,6 +934,7 @@ struct show_var_st init_vars[]= {
|
|||
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
|
||||
#ifdef HAVE_REPLICATION
|
||||
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
|
||||
{sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS},
|
||||
#endif
|
||||
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
|
50
sql/slave.cc
50
sql/slave.cc
|
@ -3228,6 +3228,53 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
|
|||
DBUG_PRINT("info", ("Deleting the event after it has been executed"));
|
||||
delete ev;
|
||||
}
|
||||
if (slave_trans_retries)
|
||||
{
|
||||
if (exec_res &&
|
||||
(thd->net.last_errno == ER_LOCK_DEADLOCK ||
|
||||
thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) &&
|
||||
!thd->is_fatal_error)
|
||||
{
|
||||
const char *errmsg;
|
||||
/*
|
||||
We were in a transaction which has been rolled back because of a
|
||||
deadlock (currently, InnoDB deadlock detected by InnoDB) or lock
|
||||
wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to
|
||||
BEGIN log event and retry it all again.
|
||||
We have to not only seek but also
|
||||
a) init_master_info(), to seek back to hot relay log's start for later
|
||||
(for when we will come back to this hot log after re-processing the
|
||||
possibly existing old logs where BEGIN is: check_binlog_magic() will
|
||||
then need the cache to be at position 0 (see comments at beginning of
|
||||
init_master_info()).
|
||||
b) init_relay_log_pos(), because the BEGIN may be an older relay log.
|
||||
*/
|
||||
if (rli->trans_retries--)
|
||||
{
|
||||
sql_print_information("Slave SQL thread retries transaction");
|
||||
if (init_master_info(rli->mi, 0, 0, 0, SLAVE_SQL))
|
||||
sql_print_error("Failed to initialize the master info structure");
|
||||
else if (init_relay_log_pos(rli,
|
||||
rli->group_relay_log_name,
|
||||
rli->group_relay_log_pos,
|
||||
1, &errmsg, 1))
|
||||
sql_print_error("Error initializing relay log position: %s",
|
||||
errmsg);
|
||||
else
|
||||
{
|
||||
exec_res= 0;
|
||||
sleep(2); // chance for concurrent connection to get more locks
|
||||
}
|
||||
}
|
||||
else
|
||||
sql_print_error("Slave SQL thread retried transaction %lu time(s) "
|
||||
"in vain, giving up. Consider raising the value of "
|
||||
"the slave_transaction_retries variable.",
|
||||
slave_trans_retries);
|
||||
}
|
||||
if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
|
||||
rli->trans_retries= slave_trans_retries; // restart from fresh
|
||||
}
|
||||
return exec_res;
|
||||
}
|
||||
else
|
||||
|
@ -3642,6 +3689,7 @@ slave_begin:
|
|||
pthread_mutex_lock(&rli->log_space_lock);
|
||||
rli->ignore_log_space_limit= 0;
|
||||
pthread_mutex_unlock(&rli->log_space_lock);
|
||||
rli->trans_retries= slave_trans_retries; // start from "no error"
|
||||
|
||||
if (init_relay_log_pos(rli,
|
||||
rli->group_relay_log_name,
|
||||
|
@ -4188,7 +4236,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
|
|||
master server shutdown. The only thing this does is cleaning. But
|
||||
cleaning is already done on a per-master-thread basis (as the master
|
||||
server is shutting down cleanly, it has written all DROP TEMPORARY TABLE
|
||||
and DO RELEASE_LOCK; prepared statements' deletion are TODO).
|
||||
prepared statements' deletion are TODO only when we binlog prep stmts).
|
||||
|
||||
We don't even increment mi->master_log_pos, because we may be just after
|
||||
a Rotate event. Btw, in a few milliseconds we are going to have a Start
|
||||
|
|
|
@ -293,7 +293,8 @@ typedef struct st_relay_log_info
|
|||
} until_log_names_cmp_result;
|
||||
|
||||
char cached_charset[6];
|
||||
|
||||
ulong trans_retries;
|
||||
|
||||
st_relay_log_info();
|
||||
~st_relay_log_info();
|
||||
|
||||
|
|
|
@ -288,12 +288,14 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||
* in thd->lex (the unit and master stuff), and the easiest way to
|
||||
* do it is, is to call mysql_init_query(), but this unfortunately
|
||||
* resets teh value_list where we keep the CALL parameters. So we
|
||||
* copy the list and then restore it.
|
||||
* copy the list and then restore it. (... and found_semicolon too).
|
||||
*/
|
||||
List<Item> vals= thd->lex->value_list;
|
||||
List<Item> tmpvals= thd->lex->value_list;
|
||||
char *tmpfsc= thd->lex->found_semicolon;
|
||||
|
||||
lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
|
||||
thd->lex->value_list= vals;
|
||||
thd->lex->value_list= tmpvals;
|
||||
thd->lex->found_semicolon= tmpfsc;
|
||||
}
|
||||
|
||||
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
|
||||
|
|
|
@ -819,6 +819,7 @@ sp_head::restore_lex(THD *thd)
|
|||
LEX *sublex= thd->lex;
|
||||
LEX *oldlex= (LEX *)m_lex.pop();
|
||||
|
||||
init_stmt_after_parse(thd, sublex);
|
||||
if (! oldlex)
|
||||
return; // Nothing to restore
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ extern const char **errmesg;
|
|||
|
||||
#define TC_LOG_PAGE_SIZE 8192
|
||||
#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE)
|
||||
extern uint opt_tc_log_size;
|
||||
extern ulong opt_tc_log_size;
|
||||
extern ulong tc_log_max_pages_used;
|
||||
extern ulong tc_log_page_size;
|
||||
extern ulong tc_log_page_waits;
|
||||
|
|
|
@ -1837,8 +1837,6 @@ void st_select_lex_unit::set_limit(SELECT_LEX *values,
|
|||
select_limit_cnt= values->select_limit+values->offset_limit;
|
||||
if (select_limit_cnt < values->select_limit)
|
||||
select_limit_cnt= HA_POS_ERROR; // no limit
|
||||
if (select_limit_cnt == HA_POS_ERROR)
|
||||
sl->options&= ~OPTION_FOUND_ROWS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1809,20 +1809,33 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
|||
else
|
||||
{
|
||||
stmt->setup_set_params();
|
||||
SELECT_LEX *sl= stmt->lex->all_selects_list;
|
||||
/*
|
||||
Save WHERE clause pointers, because they may be changed during query
|
||||
optimisation.
|
||||
*/
|
||||
for (; sl; sl= sl->next_select_in_list())
|
||||
sl->prep_where= sl->where;
|
||||
init_stmt_after_parse(thd, stmt->lex);
|
||||
stmt->state= Item_arena::PREPARED;
|
||||
}
|
||||
DBUG_RETURN(!stmt);
|
||||
}
|
||||
|
||||
|
||||
/* Reinit statement before execution */
|
||||
/*
|
||||
Init PS/SP specific parse tree members.
|
||||
*/
|
||||
|
||||
void init_stmt_after_parse(THD *thd, LEX *lex)
|
||||
{
|
||||
SELECT_LEX *sl= lex->all_selects_list;
|
||||
/*
|
||||
Save WHERE clause pointers, because they may be changed during query
|
||||
optimisation.
|
||||
*/
|
||||
for (; sl; sl= sl->next_select_in_list())
|
||||
sl->prep_where= sl->where;
|
||||
|
||||
for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global)
|
||||
table->prep_on_expr= table->on_expr;
|
||||
}
|
||||
|
||||
|
||||
/* Reinit prepared statement/stored procedure before execution */
|
||||
|
||||
void reset_stmt_for_execute(THD *thd, LEX *lex)
|
||||
{
|
||||
|
@ -1883,6 +1896,12 @@ void reset_stmt_for_execute(THD *thd, LEX *lex)
|
|||
tables->table= 0;
|
||||
if (tables->nested_join)
|
||||
tables->nested_join->counter= 0;
|
||||
|
||||
if (tables->prep_on_expr)
|
||||
{
|
||||
tables->on_expr= tables->prep_on_expr->copy_andor_structure(thd);
|
||||
tables->on_expr->cleanup();
|
||||
}
|
||||
}
|
||||
lex->current_select= &lex->select_lex;
|
||||
|
||||
|
|
|
@ -6192,9 +6192,9 @@ finish:
|
|||
For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)])
|
||||
and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]).
|
||||
For b=2 it will be called with *cond_equal=(ptr(CE),[])
|
||||
and will transform *cond_equal into (ptr(CE,[Item_equal(2,a,b,c)]).
|
||||
and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]).
|
||||
For f=e it will be called with *cond_equal=(ptr(CE), [])
|
||||
and will transform *cond_equal into (ptr(CE,[Item_equal(f,e)]).
|
||||
and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]).
|
||||
|
||||
NOTES
|
||||
Now only fields that have the same type defintions (verified by
|
||||
|
@ -6463,6 +6463,11 @@ static COND *build_equal_items_for_cond(COND *cond,
|
|||
*/
|
||||
while ((item= li++))
|
||||
{
|
||||
/*
|
||||
PS/SP note: we can safely remove a node from AND-OR
|
||||
structure here because it's restored before each
|
||||
re-execution of any prepared statement/stored procedure.
|
||||
*/
|
||||
if (check_equality(item, &cond_equal))
|
||||
li.remove();
|
||||
}
|
||||
|
@ -6501,6 +6506,11 @@ static COND *build_equal_items_for_cond(COND *cond,
|
|||
if ((new_item = build_equal_items_for_cond(item, inherited))!= item)
|
||||
{
|
||||
/* This replacement happens only for standalone equalities */
|
||||
/*
|
||||
This is ok with PS/SP as the replacement is done for
|
||||
arguments of an AND/OR item, which are restored for each
|
||||
execution of PS/SP.
|
||||
*/
|
||||
li.replace(new_item);
|
||||
}
|
||||
}
|
||||
|
@ -6636,10 +6646,12 @@ static COND *build_equal_items(THD *thd, COND *cond,
|
|||
Item *expr;
|
||||
List<TABLE_LIST> *join_list= table->nested_join ?
|
||||
&table->nested_join->join_list : NULL;
|
||||
expr= build_equal_items(thd, table->on_expr, inherited, join_list,
|
||||
&table->cond_equal);
|
||||
if (expr != table->on_expr)
|
||||
thd->change_item_tree(&table->on_expr, expr);
|
||||
/*
|
||||
We can modify table->on_expr because its old value will
|
||||
be restored before re-execution of PS/SP.
|
||||
*/
|
||||
table->on_expr= build_equal_items(thd, table->on_expr, inherited,
|
||||
join_list, &table->cond_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6866,10 +6878,14 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
|||
while ((item= li++))
|
||||
{
|
||||
Item *new_item =substitute_for_best_equal_field(item, cond_equal,
|
||||
table_join_idx);
|
||||
table_join_idx);
|
||||
/*
|
||||
This works OK with PS/SP re-execution as changes are made to
|
||||
the arguments of AND/OR items only
|
||||
*/
|
||||
if (new_item != item)
|
||||
li.replace(new_item);
|
||||
}
|
||||
}
|
||||
|
||||
if (and_level)
|
||||
{
|
||||
|
@ -7198,7 +7214,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
|||
*/
|
||||
expr= simplify_joins(join, &nested_join->join_list,
|
||||
table->on_expr, FALSE);
|
||||
table->on_expr= expr;
|
||||
table->prep_on_expr= table->on_expr= expr;
|
||||
}
|
||||
nested_join->used_tables= (table_map) 0;
|
||||
nested_join->not_null_tables=(table_map) 0;
|
||||
|
@ -7238,7 +7254,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
|||
}
|
||||
else
|
||||
conds= table->on_expr;
|
||||
table->on_expr= 0;
|
||||
table->prep_on_expr= table->on_expr= 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7319,10 +7335,7 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
|
|||
DBUG_ENTER("optimize_cond");
|
||||
|
||||
if (!conds)
|
||||
{
|
||||
*cond_value= Item::COND_TRUE;
|
||||
select->prep_where= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -217,8 +217,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||
|
||||
thd_arg->lex->current_select= sl;
|
||||
set_limit(sl, sl);
|
||||
if (sl->braces)
|
||||
sl->options&= ~OPTION_FOUND_ROWS;
|
||||
|
||||
can_skip_order_by= is_union &&
|
||||
(!sl->braces || select_limit_cnt == HA_POS_ERROR);
|
||||
|
@ -342,10 +340,9 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||
if (arena->is_stmt_prepare())
|
||||
{
|
||||
/* prepare fake select to initialize it correctly */
|
||||
ulong options_tmp= init_prepare_fake_select_lex(thd);
|
||||
(void) init_prepare_fake_select_lex(thd);
|
||||
/*
|
||||
it should be done only once (because item_list builds only onece
|
||||
per statement)
|
||||
Should be done only once (the only item_list per statement).
|
||||
*/
|
||||
DBUG_ASSERT(fake_select_lex->join == 0);
|
||||
if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
|
||||
|
@ -452,21 +449,14 @@ bool st_select_lex_unit::exec()
|
|||
if (select_limit_cnt < sl->select_limit)
|
||||
select_limit_cnt= HA_POS_ERROR; // no limit
|
||||
|
||||
/*
|
||||
When using braces, SQL_CALC_FOUND_ROWS affects the whole query.
|
||||
We don't calculate found_rows() per union part
|
||||
*/
|
||||
if (select_limit_cnt == HA_POS_ERROR || sl->braces)
|
||||
sl->options&= ~OPTION_FOUND_ROWS;
|
||||
else
|
||||
{
|
||||
/*
|
||||
We are doing an union without braces. In this case
|
||||
SQL_CALC_FOUND_ROWS should be done on all sub parts
|
||||
*/
|
||||
sl->options|= found_rows_for_union;
|
||||
}
|
||||
sl->join->select_options=sl->options;
|
||||
/*
|
||||
When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
|
||||
we don't calculate found_rows() per union part.
|
||||
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
|
||||
*/
|
||||
sl->join->select_options=
|
||||
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
||||
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
||||
res= sl->join->optimize();
|
||||
}
|
||||
if (!res)
|
||||
|
@ -498,7 +488,8 @@ bool st_select_lex_unit::exec()
|
|||
}
|
||||
/* Needed for the following test and for records_at_start in next loop */
|
||||
table->file->info(HA_STATUS_VARIABLE);
|
||||
if (found_rows_for_union & sl->options)
|
||||
if (found_rows_for_union && !sl->braces &&
|
||||
select_limit_cnt != HA_POS_ERROR)
|
||||
{
|
||||
/*
|
||||
This is a union without braces. Remember the number of rows that
|
||||
|
|
|
@ -339,6 +339,15 @@ typedef struct st_table_list
|
|||
char *db, *alias, *table_name, *schema_table_name;
|
||||
char *option; /* Used by cache index */
|
||||
Item *on_expr; /* Used with outer join */
|
||||
/*
|
||||
The scturcture of ON expression presented in the member above
|
||||
can be changed during certain optimizations. This member
|
||||
contains a snapshot of AND-OR structure of the ON expression
|
||||
made after permanent transformations of the parse tree, and is
|
||||
used to restore ON clause before every reexecution of a prepared
|
||||
statement or stored procedure.
|
||||
*/
|
||||
Item *prep_on_expr;
|
||||
COND_EQUAL *cond_equal; /* Used with outer join */
|
||||
struct st_table_list *natural_join; /* natural join on this table*/
|
||||
/* ... join ... USE INDEX ... IGNORE INDEX */
|
||||
|
|
Loading…
Add table
Reference in a new issue