Merge debian.(none):/M51/mysql-5.1

into  debian.(none):/M51/push-5.1


sql/sql_parse.cc:
  Auto merged
This commit is contained in:
unknown 2007-07-26 16:21:01 +02:00
commit 41f2133f95
34 changed files with 896 additions and 145 deletions

View File

@ -814,6 +814,91 @@ create table t1 (a int) engine=innodb;
alter table t1 alter a set default 1; alter table t1 alter a set default 1;
drop table t1; drop table t1;
#
# Bug #28591: MySQL need not sort the records in case of ORDER BY
# primary_key on InnoDB table
#
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2);
INSERT INTO t1 SELECT a + 8, 2 FROM t1;
INSERT INTO t1 SELECT a + 16, 1 FROM t1;
query_vertical EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a;
SELECT * FROM t1 WHERE b=2 ORDER BY a;
query_vertical EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
query_vertical EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c))
ENGINE=InnoDB;
INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1);
INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2;
INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2;
query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a;
SELECT * FROM t2 WHERE b=1 ORDER BY a;
query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
DROP TABLE t1,t2;
#
# Bug #29644: alter table hangs if records locked in share mode by long
# running transaction
#
CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
INSERT INTO t1 SELECT a + 8 FROM t1;
INSERT INTO t1 SELECT a + 16 FROM t1;
DELIMITER |;
CREATE PROCEDURE p1 ()
BEGIN
DECLARE i INT DEFAULT 50;
DECLARE cnt INT;
START TRANSACTION;
ALTER TABLE t1 ENGINE=InnoDB;
COMMIT;
START TRANSACTION;
WHILE (i > 0) DO
SET i = i - 1;
SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE;
END WHILE;
COMMIT;
END;|
DELIMITER ;|
CONNECT (con1,localhost,root,,);
CONNECT (con2,localhost,root,,);
CONNECTION con1;
SEND CALL p1();
CONNECTION con2;
SEND CALL p1();
CONNECTION default;
CALL p1();
CONNECTION con1;
REAP;
CONNECTION con2;
REAP;
CONNECTION default;
DISCONNECT con1;
DISCONNECT con2;
DROP PROCEDURE p1;
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests

View File

@ -1516,6 +1516,35 @@ t1 CREATE TABLE `t1` (
`c17` int(11) DEFAULT NULL `c17` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
Bug #26104 Bug on foreign key class constructor
Check that ref_columns is initalized correctly in the constructor
and semantic checks in mysql_prepare_table work.
We do not need a storage engine that supports foreign keys
for this test, as the checks are purely syntax-based, and the
syntax is supported for all engines.
drop table if exists t1,t2;
create table t1(a int not null, b int not null, primary key (a, b));
create table t2(a int not null, b int not null, c int not null, primary key (a),
foreign key fk_bug26104 (b,c) references t1(a));
ERROR 42000: Incorrect foreign key definition for 'fk_bug26104': Key reference and table reference don't match
drop table t1;
create table t1(f1 int,f2 int);
insert into t1 value(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
flush status;
create table t2 select sql_big_result f1,count(f2) from t1 group by f1;
show status like 'handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 7
drop table t1,t2;
End of 5.0 tests End of 5.0 tests
CREATE TABLE t1 (a int, b int); CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2); insert into t1 values (1,1),(1,2);

View File

@ -158,6 +158,25 @@ EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
DROP table t1; DROP table t1;
CREATE TABLE t1 (a int PRIMARY KEY);
CREATE TABLE t2 (b int PRIMARY KEY, a int);
CREATE TABLE t3 (b int, flag int);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1,1), (2,1), (3,1);
INSERT INTO t3(b,flag) VALUES (2, 1);
SELECT t1.a
FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
a
SELECT DISTINCT t1.a, MAX(t3.flag)
FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
a MAX(t3.flag)
SELECT DISTINCT t1.a
FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
a
DROP TABLE t1,t2,t3;
create table t1 (col1 int, col2 varchar(5), col_t1 int); create table t1 (col1 int, col2 varchar(5), col_t1 int);
create table t2 (col1 int, col2 varchar(5), col_t2 int); create table t2 (col1 int, col2 varchar(5), col_t2 int);
create table t3 (col1 int, col2 varchar(5), col_t3 int); create table t3 (col1 int, col2 varchar(5), col_t3 int);

View File

@ -1640,7 +1640,7 @@ t2 CREATE TABLE `t2` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2; drop table t2;
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150) ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match
create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb; create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb;
show create table t2; show create table t2;
Table Create Table Table Create Table

View File

@ -814,6 +814,274 @@ drop table if exists t1;
create table t1 (a int) engine=innodb; create table t1 (a int) engine=innodb;
alter table t1 alter a set default 1; alter table t1 alter a set default 1;
drop table t1; drop table t1;
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2);
INSERT INTO t1 SELECT a + 8, 2 FROM t1;
INSERT INTO t1 SELECT a + 16, 1 FROM t1;
EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a;
id 1
select_type SIMPLE
table t1
type ref
possible_keys bkey
key bkey
key_len 5
ref const
rows 16
Extra Using where; Using index
SELECT * FROM t1 WHERE b=2 ORDER BY a;
a b
1 2
2 2
3 2
4 2
5 2
6 2
7 2
8 2
9 2
10 2
11 2
12 2
13 2
14 2
15 2
16 2
EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
id 1
select_type SIMPLE
table t1
type range
possible_keys bkey
key bkey
key_len 5
ref NULL
rows 16
Extra Using where; Using index; Using filesort
SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
a b
1 2
2 2
3 2
4 2
5 2
6 2
7 2
8 2
9 2
10 2
11 2
12 2
13 2
14 2
15 2
16 2
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 1
27 1
28 1
29 1
30 1
31 1
32 1
EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
id 1
select_type SIMPLE
table t1
type range
possible_keys bkey
key bkey
key_len 5
ref NULL
rows 16
Extra Using where; Using index
SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
a b
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 1
27 1
28 1
29 1
30 1
31 1
32 1
1 2
2 2
3 2
4 2
5 2
6 2
7 2
8 2
9 2
10 2
11 2
12 2
13 2
14 2
15 2
16 2
CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c))
ENGINE=InnoDB;
INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1);
INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2;
INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2;
EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a;
id 1
select_type SIMPLE
table t2
type ref
possible_keys bkey
key bkey
key_len 5
ref const
rows 8
Extra Using where; Using index; Using filesort
SELECT * FROM t2 WHERE b=1 ORDER BY a;
a b c
1 1 1
2 1 1
3 1 1
4 1 1
5 1 1
6 1 1
7 1 1
8 1 1
9 1 1
10 1 1
11 1 1
12 1 1
13 1 1
14 1 1
15 1 1
16 1 1
EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
id 1
select_type SIMPLE
table t2
type ref
possible_keys bkey
key bkey
key_len 10
ref const,const
rows 8
Extra Using where; Using index
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
a b c
1 1 1
2 1 1
3 1 1
4 1 1
5 1 1
6 1 1
7 1 1
8 1 1
9 1 1
10 1 1
11 1 1
12 1 1
13 1 1
14 1 1
15 1 1
16 1 1
EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
id 1
select_type SIMPLE
table t2
type ref
possible_keys bkey
key bkey
key_len 10
ref const,const
rows 8
Extra Using where; Using index
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
a b c
1 1 1
2 1 1
3 1 1
4 1 1
5 1 1
6 1 1
7 1 1
8 1 1
9 1 1
10 1 1
11 1 1
12 1 1
13 1 1
14 1 1
15 1 1
16 1 1
EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
id 1
select_type SIMPLE
table t2
type ref
possible_keys bkey
key bkey
key_len 10
ref const,const
rows 8
Extra Using where; Using index
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
a b c
1 1 1
2 1 1
3 1 1
4 1 1
5 1 1
6 1 1
7 1 1
8 1 1
9 1 1
10 1 1
11 1 1
12 1 1
13 1 1
14 1 1
15 1 1
16 1 1
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
INSERT INTO t1 SELECT a + 8 FROM t1;
INSERT INTO t1 SELECT a + 16 FROM t1;
CREATE PROCEDURE p1 ()
BEGIN
DECLARE i INT DEFAULT 50;
DECLARE cnt INT;
START TRANSACTION;
ALTER TABLE t1 ENGINE=InnoDB;
COMMIT;
START TRANSACTION;
WHILE (i > 0) DO
SET i = i - 1;
SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE;
END WHILE;
COMMIT;
END;|
CALL p1();
CALL p1();
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
CREATE TABLE `t2` ( CREATE TABLE `t2` (
`k` int(11) NOT NULL auto_increment, `k` int(11) NOT NULL auto_increment,

View File

@ -131,7 +131,7 @@ set global general_log=ON;
set global log_output=default; set global log_output=default;
show variables like 'log_output'; show variables like 'log_output';
Variable_name Value Variable_name Value
log_output TABLE log_output FILE
set global general_log=OFF; set global general_log=OFF;
set global log_output=FILE; set global log_output=FILE;
truncate table mysql.general_log; truncate table mysql.general_log;

View File

@ -3573,6 +3573,28 @@ SELECT * FROM v1;
1 1
DROP VIEW v1; DROP VIEW v1;
# #
# Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of
# the SQL_MODE variable after the dumping of triggers.
#
CREATE TABLE t1 (c1 INT);
CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END;
CREATE TABLE t2 (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
SET @TMP_SQL_MODE = @@SQL_MODE;
SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO';
INSERT INTO t2 VALUES (0), (1), (2);
SET SQL_MODE = @TMP_SQL_MODE;
SELECT * FROM t2;
c1
0
1
2
SELECT * FROM t2;
c1
0
1
2
DROP TABLE t1,t2;
#
# End of 5.0 tests # End of 5.0 tests
# #
drop table if exists t1; drop table if exists t1;

View File

@ -267,4 +267,26 @@ drop table bug_27907_logs;
insert into bug_27907_t1(a) values (1); insert into bug_27907_t1(a) values (1);
ERROR 42S02: Table 'test.bug_27907_logs' doesn't exist ERROR 42S02: Table 'test.bug_27907_logs' doesn't exist
drop table bug_27907_t1; drop table bug_27907_t1;
Bug#22427 create table if not exists + stored function results in
inconsistent behavior
Add a test case, the bug itself was fixed by the patch for
Bug#20662
drop table if exists t1;
drop function if exists f_bug22427;
create table t1 (i int);
insert into t1 values (1);
create function f_bug22427() returns int return (select max(i) from t1);
select f_bug22427();
f_bug22427()
1
create table if not exists t1 select f_bug22427() as i;
Warnings:
Note 1050 Table 't1' already exists
create table t1 select f_bug22427() as i;
ERROR 42S01: Table 't1' already exists
drop table t1;
drop function f_bug22427;
End of 5.0 tests End of 5.0 tests

View File

@ -1,5 +1,7 @@
use test; use test;
drop table if exists t1,t2,t3,t4; drop table if exists t1,t2,t3,t4;
drop function if exists f1;
drop function if exists f2;
create table t1 ( create table t1 (
id char(16) not null default '', id char(16) not null default '',
data int not null data int not null
@ -6249,7 +6251,7 @@ drop table t1,t2;
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM; CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
set @a=0; set @a=0;
CREATE function bug27354() RETURNS int deterministic CREATE function bug27354() RETURNS int not deterministic
begin begin
insert into t1 values (null); insert into t1 values (null);
set @a=@a+1; set @a=@a+1;
@ -6433,3 +6435,34 @@ where ROUTINE_NAME = "proc_26302";
ROUTINE_NAME ROUTINE_DEFINITION ROUTINE_NAME ROUTINE_DEFINITION
proc_26302 select 1 /* testing */ proc_26302 select 1 /* testing */
drop procedure proc_26302; drop procedure proc_26302;
CREATE FUNCTION f1() RETURNS INT DETERMINISTIC RETURN 2;
CREATE FUNCTION f2(I INT) RETURNS INT DETERMINISTIC RETURN 3;
CREATE TABLE t1 (c1 INT, INDEX(c1));
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
CREATE VIEW v1 AS SELECT c1 FROM t1;
EXPLAIN SELECT * FROM t1 WHERE c1=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
EXPLAIN SELECT * FROM t1 WHERE c1=f1();
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
EXPLAIN SELECT * FROM v1 WHERE c1=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
EXPLAIN SELECT * FROM v1 WHERE c1=f1();
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index
EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand());
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index
DROP VIEW v1;
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP TABLE t1;
End of 5.0 tests

View File

@ -1933,6 +1933,34 @@ Before UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi
After UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi-UPDATE After UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi-UPDATE
drop view v1; drop view v1;
drop table t1, t2, t1_op_log; drop table t1, t2, t1_op_log;
Bug#27248 Triggers: error if insert affects temporary table
The bug was fixed by the fix for Bug#26141
drop table if exists t1;
drop temporary table if exists t2;
create table t1 (s1 int);
create temporary table t2 (s1 int);
create trigger t1_bi before insert on t1 for each row insert into t2 values (0);
create trigger t1_bd before delete on t1 for each row delete from t2;
insert into t1 values (0);
insert into t1 values (0);
select * from t1;
s1
0
0
select * from t2;
s1
0
0
delete from t1;
select * from t1;
s1
select * from t2;
s1
drop table t1;
drop temporary table t2;
End of 5.0 tests End of 5.0 tests
drop table if exists table_25411_a; drop table if exists table_25411_a;
drop table if exists table_25411_b; drop table if exists table_25411_b;

View File

@ -1829,4 +1829,28 @@ c1 + 0
0 0
2 2
DROP TABLE t1,t2; DROP TABLE t1,t2;
CREATE TABLE t1(a enum('a','b','c','d'));
INSERT INTO t1 VALUES (4),(1),(0),(3);
Warnings:
Warning 1265 Data truncated for column 'a' at row 3
SELECT a FROM t1;
a
d
a
c
EXPLAIN SELECT a FROM t1 WHERE a=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
SELECT a FROM t1 WHERE a=0;
a
ALTER TABLE t1 ADD PRIMARY KEY (a);
EXPLAIN SELECT a FROM t1 WHERE a=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 1 const 1 Using index
SELECT a FROM t1 WHERE a=0;
a
DROP TABLE t1;
End of 5.1 tests End of 5.1 tests

View File

@ -1122,6 +1122,35 @@ show create table t1;
drop table t1; drop table t1;
--echo
--echo Bug #26104 Bug on foreign key class constructor
--echo
--echo Check that ref_columns is initalized correctly in the constructor
--echo and semantic checks in mysql_prepare_table work.
--echo
--echo We do not need a storage engine that supports foreign keys
--echo for this test, as the checks are purely syntax-based, and the
--echo syntax is supported for all engines.
--echo
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
create table t1(a int not null, b int not null, primary key (a, b));
--error ER_WRONG_FK_DEF
create table t2(a int not null, b int not null, c int not null, primary key (a),
foreign key fk_bug26104 (b,c) references t1(a));
drop table t1;
#
# Bug#15130:CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT.
#
create table t1(f1 int,f2 int);
insert into t1 value(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
flush status;
create table t2 select sql_big_result f1,count(f2) from t1 group by f1;
show status like 'handler_read%';
drop table t1,t2;
--echo End of 5.0 tests --echo End of 5.0 tests

View File

@ -151,6 +151,32 @@ EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
DROP table t1; DROP table t1;
#
# Bug #29911: HAVING clause depending on constant table and evaluated to false
#
CREATE TABLE t1 (a int PRIMARY KEY);
CREATE TABLE t2 (b int PRIMARY KEY, a int);
CREATE TABLE t3 (b int, flag int);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1,1), (2,1), (3,1);
INSERT INTO t3(b,flag) VALUES (2, 1);
SELECT t1.a
FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
SELECT DISTINCT t1.a, MAX(t3.flag)
FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
SELECT DISTINCT t1.a
FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b
GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0;
DROP TABLE t1,t2,t3;
# End of 4.1 tests # End of 4.1 tests
# #

View File

@ -1178,7 +1178,7 @@ drop table t2;
# Clean up filename -- embedded server reports whole path without .frm, # Clean up filename -- embedded server reports whole path without .frm,
# regular server reports relative path with .frm (argh!) # regular server reports relative path with .frm (argh!)
--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2 --replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2
--error 1005 --error ER_WRONG_FK_DEF
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
# bug#3749 # bug#3749

View File

@ -1554,6 +1554,28 @@ DROP VIEW v1;
SELECT * FROM v1; SELECT * FROM v1;
DROP VIEW v1; DROP VIEW v1;
--echo #
--echo # Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of
--echo # the SQL_MODE variable after the dumping of triggers.
--echo #
CREATE TABLE t1 (c1 INT);
CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END;
CREATE TABLE t2 (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
SET @TMP_SQL_MODE = @@SQL_MODE;
SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO';
INSERT INTO t2 VALUES (0), (1), (2);
SET SQL_MODE = @TMP_SQL_MODE;
SELECT * FROM t2;
--exec $MYSQL_DUMP --routines test >$MYSQLTEST_VARDIR/tmp/bug29788.sql
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug29788.sql
SELECT * FROM t2;
DROP TABLE t1,t2;
--echo # --echo #
--echo # End of 5.0 tests --echo # End of 5.0 tests
--echo # --echo #

View File

@ -333,4 +333,27 @@ insert into bug_27907_t1(a) values (1);
drop table bug_27907_t1; drop table bug_27907_t1;
--echo
--echo Bug#22427 create table if not exists + stored function results in
--echo inconsistent behavior
--echo
--echo Add a test case, the bug itself was fixed by the patch for
--echo Bug#20662
--echo
--disable_warnings
drop table if exists t1;
drop function if exists f_bug22427;
--enable_warnings
create table t1 (i int);
insert into t1 values (1);
create function f_bug22427() returns int return (select max(i) from t1);
select f_bug22427();
# Until this bug was fixed, the following emitted error
# ERROR 1213: Deadlock found when trying to get lock
create table if not exists t1 select f_bug22427() as i;
--error ER_TABLE_EXISTS_ERROR
create table t1 select f_bug22427() as i;
drop table t1;
drop function f_bug22427;
--echo End of 5.0 tests --echo End of 5.0 tests

View File

@ -24,6 +24,8 @@ use test;
# #
--disable_warnings --disable_warnings
drop table if exists t1,t2,t3,t4; drop table if exists t1,t2,t3,t4;
drop function if exists f1;
drop function if exists f2;
--enable_warnings --enable_warnings
create table t1 ( create table t1 (
id char(16) not null default '', id char(16) not null default '',
@ -7214,7 +7216,7 @@ CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
set @a=0; set @a=0;
delimiter |; delimiter |;
CREATE function bug27354() RETURNS int deterministic CREATE function bug27354() RETURNS int not deterministic
begin begin
insert into t1 values (null); insert into t1 values (null);
set @a=@a+1; set @a=@a+1;
@ -7368,3 +7370,33 @@ where ROUTINE_NAME = "proc_26302";
drop procedure proc_26302; drop procedure proc_26302;
# Bug #29338: no optimization for stored functions with a trivial body
# always returning constant.
#
CREATE FUNCTION f1() RETURNS INT DETERMINISTIC RETURN 2;
CREATE FUNCTION f2(I INT) RETURNS INT DETERMINISTIC RETURN 3;
CREATE TABLE t1 (c1 INT, INDEX(c1));
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
CREATE VIEW v1 AS SELECT c1 FROM t1;
EXPLAIN SELECT * FROM t1 WHERE c1=1;
EXPLAIN SELECT * FROM t1 WHERE c1=f1();
EXPLAIN SELECT * FROM v1 WHERE c1=1;
EXPLAIN SELECT * FROM v1 WHERE c1=f1();
EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand());
DROP VIEW v1;
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP TABLE t1;
--echo End of 5.0 tests

View File

@ -2194,6 +2194,29 @@ drop table t1, t2, t1_op_log;
# #
# TODO: test LOAD DATA INFILE # TODO: test LOAD DATA INFILE
#
--echo
--echo Bug#27248 Triggers: error if insert affects temporary table
--echo
--echo The bug was fixed by the fix for Bug#26141
--echo
--disable_warnings
drop table if exists t1;
drop temporary table if exists t2;
--enable_warnings
create table t1 (s1 int);
create temporary table t2 (s1 int);
create trigger t1_bi before insert on t1 for each row insert into t2 values (0);
create trigger t1_bd before delete on t1 for each row delete from t2;
insert into t1 values (0);
insert into t1 values (0);
select * from t1;
select * from t2;
delete from t1;
select * from t1;
select * from t2;
drop table t1;
drop temporary table t2;
--echo End of 5.0 tests --echo End of 5.0 tests
# #

View File

@ -200,4 +200,24 @@ CREATE TABLE t2 SELECT * FROM t1;
SELECT c1 + 0 FROM t2; SELECT c1 + 0 FROM t2;
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# Bug#29661: Lookup by 0 for a primary index over a enum type
#
CREATE TABLE t1(a enum('a','b','c','d'));
INSERT INTO t1 VALUES (4),(1),(0),(3);
SELECT a FROM t1;
EXPLAIN SELECT a FROM t1 WHERE a=0;
SELECT a FROM t1 WHERE a=0;
ALTER TABLE t1 ADD PRIMARY KEY (a);
EXPLAIN SELECT a FROM t1 WHERE a=0;
SELECT a FROM t1 WHERE a=0;
DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests

View File

@ -1226,12 +1226,12 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
/* fields count may be wrong */ /* fields count may be wrong */
DBUG_ASSERT((uint) (field - result) < fields); DBUG_ASSERT((uint) (field - result) < fields);
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
field->catalog = strdup_root(alloc,(char*) row->data[0]); field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]);
field->db = strdup_root(alloc,(char*) row->data[1]); field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]);
field->table = strdup_root(alloc,(char*) row->data[2]); field->table= strmake_root(alloc,(char*) row->data[2], lengths[2]);
field->org_table= strdup_root(alloc,(char*) row->data[3]); field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
field->name = strdup_root(alloc,(char*) row->data[4]); field->name= strmake_root(alloc,(char*) row->data[4], lengths[4]);
field->org_name = strdup_root(alloc,(char*) row->data[5]); field->org_name= strmake_root(alloc,(char*) row->data[5], lengths[5]);
field->catalog_length= lengths[0]; field->catalog_length= lengths[0];
field->db_length= lengths[1]; field->db_length= lengths[1];
@ -1252,7 +1252,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->flags|= NUM_FLAG; field->flags|= NUM_FLAG;
if (default_value && row->data[7]) if (default_value && row->data[7])
{ {
field->def=strdup_root(alloc,(char*) row->data[7]); field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
field->def_length= lengths[7]; field->def_length= lengths[7];
} }
else else

View File

@ -7901,8 +7901,11 @@ int Field_enum::store(longlong nr, bool unsigned_val)
if ((ulonglong) nr > typelib->count || nr == 0) if ((ulonglong) nr > typelib->count || nr == 0)
{ {
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
nr=0; if (nr != 0 || table->in_use->count_cuted_fields)
error=1; {
nr= 0;
error= 1;
}
} }
store_type((ulonglong) (uint) nr); store_type((ulonglong) (uint) nr);
return error; return error;

View File

@ -5599,10 +5599,20 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */ #endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
} }
if (!m_sp->m_chistics->detistic)
used_tables_cache |= RAND_TABLE_BIT;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
void Item_func_sp::update_used_tables()
{
Item_func::update_used_tables();
if (!m_sp->m_chistics->detistic)
used_tables_cache |= RAND_TABLE_BIT;
}
/* /*
uuid_short handling. uuid_short handling.

View File

@ -1472,7 +1472,7 @@ public:
virtual ~Item_func_sp() virtual ~Item_func_sp()
{} {}
table_map used_tables() const { return RAND_TABLE_BIT; } void update_used_tables();
void cleanup(); void cleanup();

View File

@ -2220,9 +2220,9 @@ void sys_var_log_output::set_default(THD *thd, enum_var_type type)
{ {
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
logger.lock(); logger.lock();
logger.init_slow_log(LOG_TABLE); logger.init_slow_log(LOG_FILE);
logger.init_general_log(LOG_TABLE); logger.init_general_log(LOG_FILE);
*value= LOG_TABLE; *value= LOG_FILE;
logger.unlock(); logger.unlock();
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
} }

View File

@ -64,11 +64,11 @@ Prelock_error_handler::handle_error(uint sql_errno,
if (sql_errno == ER_NO_SUCH_TABLE) if (sql_errno == ER_NO_SUCH_TABLE)
{ {
m_handled_errors++; m_handled_errors++;
return TRUE; // 'TRUE', as per coding style return TRUE;
} }
m_unhandled_errors++; m_unhandled_errors++;
return FALSE; // 'FALSE', as per coding style return FALSE;
} }
@ -3533,7 +3533,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
*/ */
for (tables= *start; tables ;tables= tables->next_global) for (tables= *start; tables ;tables= tables->next_global)
{ {
safe_to_ignore_table= FALSE; // 'FALSE', as per coding style safe_to_ignore_table= FALSE;
if (tables->lock_type == TL_WRITE_DEFAULT) if (tables->lock_type == TL_WRITE_DEFAULT)
{ {
@ -3797,13 +3797,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
if (table) if (table)
{ {
#if defined( __WIN__)
/* Win32 can't drop a file that is open */
if (lock_type == TL_WRITE_ALLOW_READ)
{
lock_type= TL_WRITE;
}
#endif /* __WIN__ */
table_list->lock_type= lock_type; table_list->lock_type= lock_type;
table_list->table= table; table_list->table= table;
table->grant= table_list->grant; table->grant= table_list->grant;

View File

@ -189,7 +189,7 @@ public:
Table_ident *table, List<Key_part_spec> &ref_cols, Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg) uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols), :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
ref_table(table), ref_columns(cols), ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg), delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg) match_opt(match_opt_arg)
{} {}

View File

@ -1763,18 +1763,18 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
thd->proc_info="waiting for delay_list"; thd->proc_info="waiting for delay_list";
pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list
I_List_iterator<Delayed_insert> it(delayed_threads); I_List_iterator<Delayed_insert> it(delayed_threads);
Delayed_insert *tmp; Delayed_insert *di;
while ((tmp=it++)) while ((di= it++))
{ {
if (!strcmp(tmp->thd.db, table_list->db) && if (!strcmp(table_list->db, di->table_list.db) &&
!strcmp(table_list->table_name, tmp->table->s->table_name.str)) !strcmp(table_list->table_name, di->table_list.table_name))
{ {
tmp->lock(); di->lock();
break; break;
} }
} }
pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list
return tmp; return di;
} }
@ -1800,21 +1800,41 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
Two latter cases indicate a request for lock upgrade. Two latter cases indicate a request for lock upgrade.
XXX: why do we regard INSERT DELAYED into a view as an error and XXX: why do we regard INSERT DELAYED into a view as an error and
do not simply a lock upgrade? do not simply perform a lock upgrade?
TODO: The approach with using two mutexes to work with the
delayed thread list -- LOCK_delayed_insert and
LOCK_delayed_create -- is redundant, and we only need one of
them to protect the list. The reason we have two locks is that
we do not want to block look-ups in the list while we're waiting
for the newly created thread to open the delayed table. However,
this wait itself is redundant -- we always call get_local_table
later on, and there wait again until the created thread acquires
a table lock.
As is redundant the concept of locks_in_memory, since we already
have another counter with similar semantics - tables_in_use,
both of them are devoted to counting the number of producers for
a given consumer (delayed insert thread), only at different
stages of producer-consumer relationship.
'dead' and 'status' variables in Delayed_insert are redundant
too, since there is already 'di->thd.killed' and
di->stacked_inserts.
*/ */
static static
bool delayed_get_table(THD *thd, TABLE_LIST *table_list) bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
{ {
int error; int error;
Delayed_insert *tmp; Delayed_insert *di;
DBUG_ENTER("delayed_get_table"); DBUG_ENTER("delayed_get_table");
/* Must be set in the parser */ /* Must be set in the parser */
DBUG_ASSERT(table_list->db); DBUG_ASSERT(table_list->db);
/* Find the thread which handles this table. */ /* Find the thread which handles this table. */
if (!(tmp=find_handler(thd,table_list))) if (!(di= find_handler(thd, table_list)))
{ {
/* /*
No match. Create a new thread to handle the table, but No match. Create a new thread to handle the table, but
@ -1828,9 +1848,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
The first search above was done without LOCK_delayed_create. The first search above was done without LOCK_delayed_create.
Another thread might have created the handler in between. Search again. Another thread might have created the handler in between. Search again.
*/ */
if (! (tmp= find_handler(thd, table_list))) if (! (di= find_handler(thd, table_list)))
{ {
if (!(tmp=new Delayed_insert())) if (!(di= new Delayed_insert()))
{ {
my_error(ER_OUTOFMEMORY,MYF(0),sizeof(Delayed_insert)); my_error(ER_OUTOFMEMORY,MYF(0),sizeof(Delayed_insert));
thd->fatal_error(); thd->fatal_error();
@ -1839,28 +1859,30 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thread_count++; thread_count++;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
tmp->thd.set_db(table_list->db, strlen(table_list->db)); di->thd.set_db(table_list->db, strlen(table_list->db));
tmp->thd.query= my_strdup(table_list->table_name,MYF(MY_WME)); di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME));
if (tmp->thd.db == NULL || tmp->thd.query == NULL) if (di->thd.db == NULL || di->thd.query == NULL)
{ {
/* The error is reported */ /* The error is reported */
delete tmp; delete di;
thd->fatal_error(); thd->fatal_error();
goto end_create; goto end_create;
} }
tmp->table_list= *table_list; // Needed to open table di->table_list= *table_list; // Needed to open table
tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query; /* Replace volatile strings with local copies */
tmp->lock(); di->table_list.alias= di->table_list.table_name= di->thd.query;
pthread_mutex_lock(&tmp->mutex); di->table_list.db= di->thd.db;
if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib, di->lock();
handle_delayed_insert,(void*) tmp))) pthread_mutex_lock(&di->mutex);
if ((error= pthread_create(&di->thd.real_id, &connection_attrib,
handle_delayed_insert, (void*) di)))
{ {
DBUG_PRINT("error", DBUG_PRINT("error",
("Can't create thread to handle delayed insert (error %d)", ("Can't create thread to handle delayed insert (error %d)",
error)); error));
pthread_mutex_unlock(&tmp->mutex); pthread_mutex_unlock(&di->mutex);
tmp->unlock(); di->unlock();
delete tmp; delete di;
my_error(ER_CANT_CREATE_THREAD, MYF(0), error); my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
thd->fatal_error(); thd->fatal_error();
goto end_create; goto end_create;
@ -1868,15 +1890,15 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
/* Wait until table is open */ /* Wait until table is open */
thd->proc_info="waiting for handler open"; thd->proc_info="waiting for handler open";
while (!tmp->thd.killed && !tmp->table && !thd->killed) while (!di->thd.killed && !di->table && !thd->killed)
{ {
pthread_cond_wait(&tmp->cond_client,&tmp->mutex); pthread_cond_wait(&di->cond_client, &di->mutex);
} }
pthread_mutex_unlock(&tmp->mutex); pthread_mutex_unlock(&di->mutex);
thd->proc_info="got old table"; thd->proc_info="got old table";
if (tmp->thd.killed) if (di->thd.killed)
{ {
if (tmp->thd.net.report_error) if (di->thd.net.report_error)
{ {
/* /*
Copy the error message. Note that we don't treat fatal Copy the error message. Note that we don't treat fatal
@ -1884,31 +1906,34 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
main thread. Use of my_message will enable stored main thread. Use of my_message will enable stored
procedures continue handlers. procedures continue handlers.
*/ */
my_message(tmp->thd.net.last_errno, tmp->thd.net.last_error, my_message(di->thd.net.last_errno, di->thd.net.last_error,
MYF(0)); MYF(0));
} }
tmp->unlock(); di->unlock();
goto end_create; goto end_create;
} }
if (thd->killed) if (thd->killed)
{ {
tmp->unlock(); di->unlock();
goto end_create; goto end_create;
} }
pthread_mutex_lock(&LOCK_delayed_insert);
delayed_threads.append(di);
pthread_mutex_unlock(&LOCK_delayed_insert);
} }
pthread_mutex_unlock(&LOCK_delayed_create); pthread_mutex_unlock(&LOCK_delayed_create);
} }
pthread_mutex_lock(&tmp->mutex); pthread_mutex_lock(&di->mutex);
table_list->table= tmp->get_local_table(thd); table_list->table= di->get_local_table(thd);
pthread_mutex_unlock(&tmp->mutex); pthread_mutex_unlock(&di->mutex);
if (table_list->table) if (table_list->table)
{ {
DBUG_ASSERT(thd->net.report_error == 0); DBUG_ASSERT(thd->net.report_error == 0);
thd->di=tmp; thd->di= di;
} }
/* Unlock the delayed insert object after its last access. */ /* Unlock the delayed insert object after its last access. */
tmp->unlock(); di->unlock();
DBUG_RETURN((table_list->table == NULL)); DBUG_RETURN((table_list->table == NULL));
end_create: end_create:
@ -1938,7 +1963,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
my_ptrdiff_t adjust_ptrs; my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field; Field **field,**org_field, *found_next_number_field;
TABLE *copy; TABLE *copy;
TABLE_SHARE *share= table->s; TABLE_SHARE *share;
uchar *bitmap; uchar *bitmap;
DBUG_ENTER("Delayed_insert::get_local_table"); DBUG_ENTER("Delayed_insert::get_local_table");
@ -1962,6 +1987,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
goto error; goto error;
} }
} }
share= table->s;
/* /*
Allocate memory for the TABLE object, the field pointers array, and Allocate memory for the TABLE object, the field pointers array, and
@ -2157,26 +2183,26 @@ void kill_delayed_threads(void)
VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list
I_List_iterator<Delayed_insert> it(delayed_threads); I_List_iterator<Delayed_insert> it(delayed_threads);
Delayed_insert *tmp; Delayed_insert *di;
while ((tmp=it++)) while ((di= it++))
{ {
tmp->thd.killed= THD::KILL_CONNECTION; di->thd.killed= THD::KILL_CONNECTION;
if (tmp->thd.mysys_var) if (di->thd.mysys_var)
{ {
pthread_mutex_lock(&tmp->thd.mysys_var->mutex); pthread_mutex_lock(&di->thd.mysys_var->mutex);
if (tmp->thd.mysys_var->current_cond) if (di->thd.mysys_var->current_cond)
{ {
/* /*
We need the following test because the main mutex may be locked We need the following test because the main mutex may be locked
in handle_delayed_insert() in handle_delayed_insert()
*/ */
if (&tmp->mutex != tmp->thd.mysys_var->current_mutex) if (&di->mutex != di->thd.mysys_var->current_mutex)
pthread_mutex_lock(tmp->thd.mysys_var->current_mutex); pthread_mutex_lock(di->thd.mysys_var->current_mutex);
pthread_cond_broadcast(tmp->thd.mysys_var->current_cond); pthread_cond_broadcast(di->thd.mysys_var->current_cond);
if (&tmp->mutex != tmp->thd.mysys_var->current_mutex) if (&di->mutex != di->thd.mysys_var->current_mutex)
pthread_mutex_unlock(tmp->thd.mysys_var->current_mutex); pthread_mutex_unlock(di->thd.mysys_var->current_mutex);
} }
pthread_mutex_unlock(&tmp->thd.mysys_var->mutex); pthread_mutex_unlock(&di->thd.mysys_var->mutex);
} }
} }
VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list
@ -2250,11 +2276,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
} }
di->table->copy_blobs=1; di->table->copy_blobs=1;
/* One can now use this */
pthread_mutex_lock(&LOCK_delayed_insert);
delayed_threads.append(di);
pthread_mutex_unlock(&LOCK_delayed_insert);
/* Tell client that the thread is initialized */ /* Tell client that the thread is initialized */
pthread_cond_signal(&di->cond_client); pthread_cond_signal(&di->cond_client);

View File

@ -124,7 +124,7 @@ Lex_input_stream::Lex_input_stream(THD *thd,
m_tok_start_prev(NULL), m_tok_start_prev(NULL),
m_buf(buffer), m_buf(buffer),
m_buf_length(length), m_buf_length(length),
m_echo(true), m_echo(TRUE),
m_cpp_tok_start(NULL), m_cpp_tok_start(NULL),
m_cpp_tok_start_prev(NULL), m_cpp_tok_start_prev(NULL),
m_cpp_tok_end(NULL), m_cpp_tok_end(NULL),
@ -1200,7 +1200,7 @@ int MYSQLlex(void *arg, void *yythd)
{ {
lip->in_comment= DISCARD_COMMENT; lip->in_comment= DISCARD_COMMENT;
/* Accept '/' '*' '!', but do not keep this marker. */ /* Accept '/' '*' '!', but do not keep this marker. */
lip->set_echo(false); lip->set_echo(FALSE);
lip->yySkip(); lip->yySkip();
lip->yySkip(); lip->yySkip();
lip->yySkip(); lip->yySkip();
@ -1233,7 +1233,7 @@ int MYSQLlex(void *arg, void *yythd)
if (version <= MYSQL_VERSION_ID) if (version <= MYSQL_VERSION_ID)
{ {
/* Expand the content of the special comment as real code */ /* Expand the content of the special comment as real code */
lip->set_echo(true); lip->set_echo(TRUE);
state=MY_LEX_START; state=MY_LEX_START;
break; break;
} }
@ -1241,7 +1241,7 @@ int MYSQLlex(void *arg, void *yythd)
else else
{ {
state=MY_LEX_START; state=MY_LEX_START;
lip->set_echo(true); lip->set_echo(TRUE);
break; break;
} }
} }
@ -1261,7 +1261,7 @@ int MYSQLlex(void *arg, void *yythd)
if (! lip->eof()) if (! lip->eof())
lip->yySkip(); // remove last '/' lip->yySkip(); // remove last '/'
state = MY_LEX_START; // Try again state = MY_LEX_START; // Try again
lip->set_echo(true); lip->set_echo(TRUE);
break; break;
case MY_LEX_END_LONG_COMMENT: case MY_LEX_END_LONG_COMMENT:
if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')
@ -1272,7 +1272,7 @@ int MYSQLlex(void *arg, void *yythd)
lip->set_echo(lip->in_comment == PRESERVE_COMMENT); lip->set_echo(lip->in_comment == PRESERVE_COMMENT);
lip->yySkipn(2); lip->yySkipn(2);
/* And start recording the tokens again */ /* And start recording the tokens again */
lip->set_echo(true); lip->set_echo(TRUE);
lip->in_comment=NO_COMMENT; lip->in_comment=NO_COMMENT;
state=MY_LEX_START; state=MY_LEX_START;
} }
@ -1297,7 +1297,7 @@ int MYSQLlex(void *arg, void *yythd)
lip->found_semicolon= lip->get_ptr(); lip->found_semicolon= lip->get_ptr();
thd->server_status|= SERVER_MORE_RESULTS_EXISTS; thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
lip->next_state= MY_LEX_END; lip->next_state= MY_LEX_END;
lip->set_echo(true); lip->set_echo(TRUE);
return (END_OF_INPUT); return (END_OF_INPUT);
} }
state= MY_LEX_CHAR; // Return ';' state= MY_LEX_CHAR; // Return ';'
@ -1309,9 +1309,9 @@ int MYSQLlex(void *arg, void *yythd)
if (lip->eof()) if (lip->eof())
{ {
lip->yyUnget(); // Reject the last '\0' lip->yyUnget(); // Reject the last '\0'
lip->set_echo(false); lip->set_echo(FALSE);
lip->yySkip(); lip->yySkip();
lip->set_echo(true); lip->set_echo(TRUE);
lip->next_state=MY_LEX_END; // Mark for next loop lip->next_state=MY_LEX_END; // Mark for next loop
return(END_OF_INPUT); return(END_OF_INPUT);
} }
@ -1770,7 +1770,7 @@ TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
LEX_STRING *alias, LEX_STRING *alias,
ulong table_join_options, ulong table_join_options,
thr_lock_type flags, thr_lock_type flags,
List<index_hint> *hints, List<Index_hint> *hints,
LEX_STRING *option) LEX_STRING *option)
{ {
return 0; return 0;
@ -2723,7 +2723,7 @@ void st_select_lex::set_index_hint_type(enum index_hint_type type,
void st_select_lex::alloc_index_hints (THD *thd) void st_select_lex::alloc_index_hints (THD *thd)
{ {
index_hints= new (thd->mem_root) List<index_hint>(); index_hints= new (thd->mem_root) List<Index_hint>();
} }
@ -2744,7 +2744,7 @@ void st_select_lex::alloc_index_hints (THD *thd)
bool st_select_lex::add_index_hint (THD *thd, char *str, uint length) bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
{ {
return index_hints->push_front (new (thd->mem_root) return index_hints->push_front (new (thd->mem_root)
index_hint(current_index_hint_type, Index_hint(current_index_hint_type,
current_index_hint_clause, current_index_hint_clause,
str, length)); str, length));
} }

View File

@ -236,7 +236,7 @@ typedef uchar index_clause_map;
INDEX_HINT_MASK_ORDER) INDEX_HINT_MASK_ORDER)
/* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */ /* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */
class index_hint : public Sql_alloc class Index_hint : public Sql_alloc
{ {
public: public:
/* The type of the hint : USE/FORCE/IGNORE */ /* The type of the hint : USE/FORCE/IGNORE */
@ -249,7 +249,7 @@ public:
*/ */
LEX_STRING key_name; LEX_STRING key_name;
index_hint (enum index_hint_type type_arg, index_clause_map clause_arg, Index_hint (enum index_hint_type type_arg, index_clause_map clause_arg,
char *str, uint length) : char *str, uint length) :
type(type_arg), clause(clause_arg) type(type_arg), clause(clause_arg)
{ {
@ -441,7 +441,7 @@ public:
LEX_STRING *alias, LEX_STRING *alias,
ulong table_options, ulong table_options,
thr_lock_type flags= TL_UNLOCK, thr_lock_type flags= TL_UNLOCK,
List<index_hint> *hints= 0, List<Index_hint> *hints= 0,
LEX_STRING *option= 0); LEX_STRING *option= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {} virtual void set_lock_for_tables(thr_lock_type lock_type) {}
@ -719,7 +719,7 @@ public:
LEX_STRING *alias, LEX_STRING *alias,
ulong table_options, ulong table_options,
thr_lock_type flags= TL_UNLOCK, thr_lock_type flags= TL_UNLOCK,
List<index_hint> *hints= 0, List<Index_hint> *hints= 0,
LEX_STRING *option= 0); LEX_STRING *option= 0);
TABLE_LIST* get_table_list(); TABLE_LIST* get_table_list();
bool init_nested_join(THD *thd); bool init_nested_join(THD *thd);
@ -779,9 +779,9 @@ public:
/* make a list to hold index hints */ /* make a list to hold index hints */
void alloc_index_hints (THD *thd); void alloc_index_hints (THD *thd);
/* read and clear the index hints */ /* read and clear the index hints */
List<index_hint>* pop_index_hints(void) List<Index_hint>* pop_index_hints(void)
{ {
List<index_hint> *hints= index_hints; List<Index_hint> *hints= index_hints;
index_hints= NULL; index_hints= NULL;
return hints; return hints;
} }
@ -793,7 +793,7 @@ private:
enum index_hint_type current_index_hint_type; enum index_hint_type current_index_hint_type;
index_clause_map current_index_hint_clause; index_clause_map current_index_hint_clause;
/* a list of USE/FORCE/IGNORE INDEX */ /* a list of USE/FORCE/IGNORE INDEX */
List<index_hint> *index_hints; List<Index_hint> *index_hints;
}; };
typedef class st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
@ -1239,19 +1239,19 @@ public:
} }
/** Get the raw query buffer. */ /** Get the raw query buffer. */
const char* get_buf() const char *get_buf()
{ {
return m_buf; return m_buf;
} }
/** Get the pre-processed query buffer. */ /** Get the pre-processed query buffer. */
const char* get_cpp_buf() const char *get_cpp_buf()
{ {
return m_cpp_buf; return m_cpp_buf;
} }
/** Get the end of the raw query buffer. */ /** Get the end of the raw query buffer. */
const char* get_end_of_query() const char *get_end_of_query()
{ {
return m_end_of_query; return m_end_of_query;
} }
@ -1279,43 +1279,43 @@ public:
} }
/** Get the token start position, in the raw buffer. */ /** Get the token start position, in the raw buffer. */
const char* get_tok_start() const char *get_tok_start()
{ {
return m_tok_start; return m_tok_start;
} }
/** Get the token start position, in the pre-processed buffer. */ /** Get the token start position, in the pre-processed buffer. */
const char* get_cpp_tok_start() const char *get_cpp_tok_start()
{ {
return m_cpp_tok_start; return m_cpp_tok_start;
} }
/** Get the token end position, in the raw buffer. */ /** Get the token end position, in the raw buffer. */
const char* get_tok_end() const char *get_tok_end()
{ {
return m_tok_end; return m_tok_end;
} }
/** Get the token end position, in the pre-processed buffer. */ /** Get the token end position, in the pre-processed buffer. */
const char* get_cpp_tok_end() const char *get_cpp_tok_end()
{ {
return m_cpp_tok_end; return m_cpp_tok_end;
} }
/** Get the previous token start position, in the raw buffer. */ /** Get the previous token start position, in the raw buffer. */
const char* get_tok_start_prev() const char *get_tok_start_prev()
{ {
return m_tok_start_prev; return m_tok_start_prev;
} }
/** Get the current stream pointer, in the raw buffer. */ /** Get the current stream pointer, in the raw buffer. */
const char* get_ptr() const char *get_ptr()
{ {
return m_ptr; return m_ptr;
} }
/** Get the current stream pointer, in the pre-processed buffer. */ /** Get the current stream pointer, in the pre-processed buffer. */
const char* get_cpp_ptr() const char *get_cpp_ptr()
{ {
return m_cpp_ptr; return m_cpp_ptr;
} }
@ -1365,22 +1365,22 @@ public:
private: private:
/** Pointer to the current position in the raw input stream. */ /** Pointer to the current position in the raw input stream. */
const char* m_ptr; const char *m_ptr;
/** Starting position of the last token parsed, in the raw buffer. */ /** Starting position of the last token parsed, in the raw buffer. */
const char* m_tok_start; const char *m_tok_start;
/** Ending position of the previous token parsed, in the raw buffer. */ /** Ending position of the previous token parsed, in the raw buffer. */
const char* m_tok_end; const char *m_tok_end;
/** End of the query text in the input stream, in the raw buffer. */ /** End of the query text in the input stream, in the raw buffer. */
const char* m_end_of_query; const char *m_end_of_query;
/** Starting position of the previous token parsed, in the raw buffer. */ /** Starting position of the previous token parsed, in the raw buffer. */
const char* m_tok_start_prev; const char *m_tok_start_prev;
/** Begining of the query text in the input stream, in the raw buffer. */ /** Begining of the query text in the input stream, in the raw buffer. */
const char* m_buf; const char *m_buf;
/** Length of the raw buffer. */ /** Length of the raw buffer. */
uint m_buf_length; uint m_buf_length;
@ -1389,28 +1389,28 @@ private:
bool m_echo; bool m_echo;
/** Pre-processed buffer. */ /** Pre-processed buffer. */
char* m_cpp_buf; char *m_cpp_buf;
/** Pointer to the current position in the pre-processed input stream. */ /** Pointer to the current position in the pre-processed input stream. */
char* m_cpp_ptr; char *m_cpp_ptr;
/** /**
Starting position of the last token parsed, Starting position of the last token parsed,
in the pre-processed buffer. in the pre-processed buffer.
*/ */
const char* m_cpp_tok_start; const char *m_cpp_tok_start;
/** /**
Starting position of the previous token parsed, Starting position of the previous token parsed,
in the pre-procedded buffer. in the pre-procedded buffer.
*/ */
const char* m_cpp_tok_start_prev; const char *m_cpp_tok_start_prev;
/** /**
Ending position of the previous token parsed, Ending position of the previous token parsed,
in the pre-processed buffer. in the pre-processed buffer.
*/ */
const char* m_cpp_tok_end; const char *m_cpp_tok_end;
/** UTF8-body buffer created during parsing. */ /** UTF8-body buffer created during parsing. */
char *m_body_utf8; char *m_body_utf8;
@ -1433,7 +1433,7 @@ public:
Position of ';' in the stream, to delimit multiple queries. Position of ';' in the stream, to delimit multiple queries.
This delimiter is in the raw buffer. This delimiter is in the raw buffer.
*/ */
const char* found_semicolon; const char *found_semicolon;
/** SQL_MODE = IGNORE_SPACE. */ /** SQL_MODE = IGNORE_SPACE. */
bool ignore_space; bool ignore_space;

View File

@ -5640,7 +5640,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
LEX_STRING *alias, LEX_STRING *alias,
ulong table_options, ulong table_options,
thr_lock_type lock_type, thr_lock_type lock_type,
List<index_hint> *index_hints_arg, List<Index_hint> *index_hints_arg,
LEX_STRING *option) LEX_STRING *option)
{ {
register TABLE_LIST *ptr; register TABLE_LIST *ptr;

View File

@ -12289,6 +12289,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
key_part_end=key_part+table->key_info[idx].key_parts; key_part_end=key_part+table->key_info[idx].key_parts;
key_part_map const_key_parts=table->const_key_parts[idx]; key_part_map const_key_parts=table->const_key_parts[idx];
int reverse=0; int reverse=0;
my_bool on_primary_key= FALSE;
DBUG_ENTER("test_if_order_by_key"); DBUG_ENTER("test_if_order_by_key");
for (; order ; order=order->next, const_key_parts>>=1) for (; order ; order=order->next, const_key_parts>>=1)
@ -12303,7 +12304,31 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
for (; const_key_parts & 1 ; const_key_parts>>= 1) for (; const_key_parts & 1 ; const_key_parts>>= 1)
key_part++; key_part++;
if (key_part == key_part_end || key_part->field != field) if (key_part == key_part_end)
{
/*
We are at the end of the key. Check if the engine has the primary
key as a suffix to the secondary keys. If it has continue to check
the primary key as a suffix.
*/
if (!on_primary_key &&
(table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
ha_legacy_type(table->s->db_type()) == DB_TYPE_INNODB &&
table->s->primary_key != MAX_KEY)
{
on_primary_key= TRUE;
key_part= table->key_info[table->s->primary_key].key_part;
key_part_end=key_part+table->key_info[table->s->primary_key].key_parts;
const_key_parts=table->const_key_parts[table->s->primary_key];
for (; const_key_parts & 1 ; const_key_parts>>= 1)
key_part++;
}
else
DBUG_RETURN(0);
}
if (key_part->field != field)
DBUG_RETURN(0); DBUG_RETURN(0);
/* set flag to 1 if we can use read-next on key, else to -1 */ /* set flag to 1 if we can use read-next on key, else to -1 */
@ -12314,7 +12339,8 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
reverse=flag; // Remember if reverse reverse=flag; // Remember if reverse
key_part++; key_part++;
} }
*used_key_parts= (uint) (key_part - table->key_info[idx].key_part); *used_key_parts= on_primary_key ? table->key_info[idx].key_parts :
(uint) (key_part - table->key_info[idx].key_part);
if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) & if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
HA_READ_PREV)) HA_READ_PREV))
reverse= 0; // Index can't be used reverse= 0; // Index can't be used
@ -13030,7 +13056,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
field_count++; field_count++;
} }
if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) if (!field_count && !(join->select_options & OPTION_FOUND_ROWS) && !having)
{ // only const items with no OPTION_FOUND_ROWS { // only const items with no OPTION_FOUND_ROWS
join->unit->select_limit_cnt= 1; // Only send first row join->unit->select_limit_cnt= 1; // Only send first row
DBUG_RETURN(0); DBUG_RETURN(0);

View File

@ -1349,7 +1349,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
the primary key, then we can use any key to find this column the primary key, then we can use any key to find this column
*/ */
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
{
field->part_of_key= share->keys_in_use; field->part_of_key= share->keys_in_use;
if (ha_legacy_type(share->db_type()) == DB_TYPE_INNODB &&
field->part_of_sortkey.is_set(key))
field->part_of_sortkey= share->keys_in_use;
}
} }
if (field->key_length() != key_part->length) if (field->key_length() != key_part->length)
{ {
@ -4642,11 +4647,11 @@ bool TABLE_LIST::process_index_hints(TABLE *table)
key_map index_join[INDEX_HINT_FORCE + 1]; key_map index_join[INDEX_HINT_FORCE + 1];
key_map index_order[INDEX_HINT_FORCE + 1]; key_map index_order[INDEX_HINT_FORCE + 1];
key_map index_group[INDEX_HINT_FORCE + 1]; key_map index_group[INDEX_HINT_FORCE + 1];
index_hint *hint; Index_hint *hint;
int type; int type;
bool have_empty_use_join= FALSE, have_empty_use_order= FALSE, bool have_empty_use_join= FALSE, have_empty_use_order= FALSE,
have_empty_use_group= FALSE; have_empty_use_group= FALSE;
List_iterator <index_hint> iter(*index_hints); List_iterator <Index_hint> iter(*index_hints);
/* initialize temporary variables used to collect hints of each kind */ /* initialize temporary variables used to collect hints of each kind */
for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++) for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)

View File

@ -754,7 +754,7 @@ public:
(TABLE_LIST::join_using_fields != NULL) (TABLE_LIST::join_using_fields != NULL)
*/ */
class index_hint; class Index_hint;
struct TABLE_LIST struct TABLE_LIST
{ {
TABLE_LIST() {} /* Remove gcc warning */ TABLE_LIST() {} /* Remove gcc warning */
@ -826,7 +826,7 @@ struct TABLE_LIST
*/ */
TABLE_LIST *next_name_resolution_table; TABLE_LIST *next_name_resolution_table;
/* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */ /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
List<index_hint> *index_hints; List<Index_hint> *index_hints;
TABLE *table; /* opened table */ TABLE *table; /* opened table */
uint table_id; /* table id (from binlog) for opened table */ uint table_id; /* table id (from binlog) for opened table */
/* /*

View File

@ -7042,18 +7042,6 @@ ha_innobase::store_lock(
&& !thd_tablespace_op(thd) && !thd_tablespace_op(thd)
&& sql_command != SQLCOM_TRUNCATE && sql_command != SQLCOM_TRUNCATE
&& sql_command != SQLCOM_OPTIMIZE && sql_command != SQLCOM_OPTIMIZE
#ifdef __WIN__
/* For alter table on win32 for successful
operation completion it is used TL_WRITE(=10) lock
instead of TL_WRITE_ALLOW_READ(=6), however here
in innodb handler TL_WRITE is lifted to
TL_WRITE_ALLOW_WRITE, which causes race condition
when several clients do alter table simultaneously
(bug #17264). This fix avoids the problem. */
&& sql_command != SQLCOM_ALTER_TABLE
#endif
&& sql_command != SQLCOM_CREATE_TABLE) { && sql_command != SQLCOM_CREATE_TABLE) {
lock_type = TL_WRITE_ALLOW_WRITE; lock_type = TL_WRITE_ALLOW_WRITE;