Merge mysql.com:/home/gluh/MySQL/Merge/5.0

into  mysql.com:/home/gluh/MySQL/Merge/5.0-opt
This commit is contained in:
gluh@mysql.com/eagle.(none) 2007-02-26 16:57:45 +04:00
commit e8635ad3cb
33 changed files with 780 additions and 127 deletions

View File

@ -1442,7 +1442,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const # Using where
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range t t 13 NULL # Using where
1 SIMPLE t1 ref t t 13 const # Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL # Using where

View File

@ -123,3 +123,14 @@ master-bin.000001 # Query 1 # use `test`; create table t3 like t1
master-bin.000001 # Query 1 # use `test`; insert into t1 select * from t3
master-bin.000001 # Query 1 # use `test`; replace into t1 select * from t3
drop table t1,t2,t3;
CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE;
DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 ADD INDEX(a);
DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 DROP INDEX a;
ALTER TABLE t1 ADD UNIQUE INDEX(a);
DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 DROP INDEX a;
ALTER TABLE t1 ADD PRIMARY KEY(a);
DELETE FROM t1 WHERE a=10;
DROP TABLE t1;

View File

@ -98,7 +98,7 @@ concat('|', text1, '|')
|teststring |
explain select concat('|', text1, '|') from t1 where text1='teststring ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range key1 key1 22 NULL 2 Using where
1 SIMPLE t1 ref key1 key1 22 const 2 Using where
select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
concat('|', text1, '|')
|teststring |

View File

@ -1991,7 +1991,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const # Using where; Using index
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range t t 13 NULL # Using where
1 SIMPLE t1 ref t t 13 const # Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL # Using where; Using index

View File

@ -731,3 +731,16 @@ select @@identity;
@@identity
0
drop table t1;
CREATE TABLE t1 (f1 INT, f2 INT );
CREATE TABLE t2 (f1 INT PRIMARY KEY, f2 INT);
INSERT INTO t1 VALUES (1,1),(2,2),(10,10);
INSERT INTO t2 (f1, f2) SELECT f1, f2 FROM t1;
INSERT INTO t2 (f1, f2)
SELECT f1, f1 FROM t2 src WHERE f1 < 2
ON DUPLICATE KEY UPDATE f1 = 100 + src.f1;
SELECT * FROM t2;
f1 f2
101 1
2 2
10 10
DROP TABLE t1, t2;

View File

@ -219,3 +219,20 @@ SELECT * FROM t1;
a b
45 2
DROP TABLE t1;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
INSERT INTO t1 SELECT 1, j;
ERROR 42S22: Unknown column 'j' in 'field list'
DROP TABLE t1;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
CREATE TABLE t2 (a INT, b INT);
CREATE TABLE t3 (a INT, c INT);
INSERT INTO t1 SELECT 1, a FROM t2 NATURAL JOIN t3
ON DUPLICATE KEY UPDATE j= a;
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
CREATE TABLE t2 (a INT);
INSERT INTO t1 VALUES (1, 1);
INSERT INTO t2 VALUES (1), (3);
INSERT INTO t1 SELECT 1, COUNT(*) FROM t2 ON DUPLICATE KEY UPDATE j= a;
ERROR 42S22: Unknown column 'a' in 'field list'
DROP TABLE t1,t2;

View File

@ -1071,7 +1071,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c c 11 const # Using where; Using index
explain select count(*) from t1 where t='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range t t 13 NULL # Using where
1 SIMPLE t1 ref t t 13 const # Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL # Using where; Using index

View File

@ -3785,4 +3785,152 @@ case when 1 then cast(1111111111111111111 as unsigned) else 1 end c,
coalesce(cast(1111111111111111111 as unsigned), 1) co;
i c co
1111111111111111111 1111111111111111111 1111111111111111111
CREATE TABLE t1 (name varchar(255));
CREATE TABLE t2 (name varchar(255), n int, KEY (name(3)));
INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
SELECT * FROM t2;
name n
bb 1
aa 2
cc 3
cc  4
cc 5
bb 6
cc 7
SELECT * FROM t2 ORDER BY name;
name n
aa 2
bb 1
bb 6
cc  4
cc 3
cc 5
cc 7
SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
name LENGTH(name) n
aa 2 2
bb 2 1
bb 3 6
cc  4 4
cc 5 3
cc 2 5
cc 3 7
EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref name name 6 const 3 Using where
SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
name LENGTH(name) n
cc 5 3
cc 2 5
cc 3 7
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range name name 6 NULL 3 Using where
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
name LENGTH(name) n
cc 5 3
cc  4 4
cc 2 5
cc 3 7
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range name name 6 NULL 3 Using where; Using filesort
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
name LENGTH(name) n
cc  4 4
cc 5 3
cc 2 5
cc 3 7
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5
1 SIMPLE t2 ref name name 6 test.t1.name 2
SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
name name n
ccc NULL NULL
bb bb 1
bb bb 6
cc cc 3
cc cc 5
cc cc 7
aa aa 2
aa aa 2
DROP TABLE t1,t2;
CREATE TABLE t1 (name text);
CREATE TABLE t2 (name text, n int, KEY (name(3)));
INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
SELECT * FROM t2;
name n
bb 1
aa 2
cc 3
cc  4
cc 5
bb 6
cc 7
SELECT * FROM t2 ORDER BY name;
name n
aa 2
bb 1
bb 6
cc  4
cc 3
cc 5
cc 7
SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
name LENGTH(name) n
aa 2 2
bb 2 1
bb 3 6
cc  4 4
cc 5 3
cc 2 5
cc 3 7
EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref name name 6 const 3 Using where
SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
name LENGTH(name) n
cc 5 3
cc 2 5
cc 3 7
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range name name 6 NULL 3 Using where
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
name LENGTH(name) n
cc 5 3
cc  4 4
cc 2 5
cc 3 7
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range name name 6 NULL 3 Using where; Using filesort
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
name LENGTH(name) n
cc  4 4
cc 5 3
cc 2 5
cc 3 7
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5
1 SIMPLE t2 ref name name 6 test.t1.name 2
SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
name name n
ccc NULL NULL
bb bb 1
bb bb 6
cc cc 3
cc cc 5
cc cc 7
aa aa 2
aa aa 2
DROP TABLE t1,t2;
End of 5.0 tests

View File

@ -224,7 +224,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where
Warnings:
Note 1276 Field or reference 't4.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select `test`.`t4`.`b` AS `b`,(select avg((`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) AS `min(t3.a)` from `test`.`t3` where (`test`.`t3`.`a` >= `test`.`t4`.`a`)))) AS `avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a))` from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
@ -313,8 +313,8 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 't2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 't2.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = `test`.`t2`.`a`) union select `test`.`t5`.`a` AS `a` from `test`.`t5` where (`test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
@ -330,9 +330,9 @@ patient_uq clinic_uq
explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t6 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 Using index
2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 t6.clinic_uq 1 Using where; Using index
Warnings:
Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where exists(select 1 AS `Not_used` from `test`.`t7` where (`test`.`t7`.`uq` = `test`.`t6`.`clinic_uq`))
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
ERROR 23000: Column 'a' in field list is ambiguous
@ -868,7 +868,7 @@ explain extended select (select a+1) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
Warnings:
Note 1276 Field or reference 'a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1249 Select 2 was reduced during optimization
Note 1003 select (`test`.`t1`.`a` + 1) AS `(select a+1)` from `test`.`t1`
select (select a+1) from t1;
@ -1741,9 +1741,9 @@ Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `tes
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 Using where; Using index
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 tt.id 1 Using where; Using index
Warnings:
Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where (not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and (`test`.`t1`.`id` = `test`.`tt`.`id`)) having (`test`.`t1`.`id` is not null))))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
@ -2279,7 +2279,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY up ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
Warnings:
Note 1276 Field or reference 'up.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.up.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where exists(select 1 AS `Not_used` from `test`.`t1` where (`test`.`t1`.`a` = `test`.`up`.`a`))
drop table t1;
CREATE TABLE t1 (t1_a int);
@ -3712,3 +3712,45 @@ bb 2
cc 3
dd 1
DROP TABLE t1,t2,t3;
CREATE TABLE t1(f1 int);
CREATE TABLE t2(f2 int, f21 int, f3 timestamp);
INSERT INTO t1 VALUES (1),(1),(2),(2);
INSERT INTO t2 VALUES (1,1,"2004-02-29 11:11:11"), (2,2,"2004-02-29 11:11:11");
SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1;
sq
2
4
SELECT (SELECT SUM(1) FROM t2 ttt GROUP BY t2.f3 LIMIT 1) AS tt FROM t2;
tt
2
2
PREPARE stmt1 FROM 'SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1';
EXECUTE stmt1;
sq
2
4
EXECUTE stmt1;
sq
2
4
DEALLOCATE PREPARE stmt1;
SELECT f2, AVG(f21),
(SELECT t.f3 FROM t2 AS t WHERE t2.f2=t.f2 AND t.f3=MAX(t2.f3)) AS test
FROM t2 GROUP BY f2;
f2 AVG(f21) test
1 1.0000 2004-02-29 11:11:11
2 2.0000 2004-02-29 11:11:11
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL);
INSERT INTO t1 VALUES
(1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'),
(2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'), (3,3,'j'),
(3,2,'k'), (3,1,'l'), (1,9,'m');
SELECT a, MAX(b),
(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) AS test
FROM t1 GROUP BY a;
a MAX(b) test
1 9 m
2 3 h
3 4 i
DROP TABLE t1;

View File

@ -29,7 +29,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 5
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 Using where; Using temporary; Using filesort
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) AS `max(ie)` from `test`.`t1` where (`test`.`t1`.`oref` = `test`.`t2`.`oref`) group by `test`.`t1`.`grp` having trigcond((<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `Z` from `test`.`t2`
explain extended
select a, oref from t2
@ -38,7 +38,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 Using where; Using temporary; Using filesort
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) AS `max(ie)` from `test`.`t1` where (`test`.`t1`.`oref` = `test`.`t2`.`oref`) group by `test`.`t1`.`grp` having (<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))
select a, oref, a in (
select max(ie) from t1 where oref=t2.oref group by grp union
@ -91,7 +91,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 4
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where (`test`.`t1`.`oref` = `test`.`t2`.`oref`) having trigcond(<is_not_null_test>(`test`.`t1`.`a`))))) AS `Z` from `test`.`t2`
flush status;
select oref, a from t2 where a in (select a from t1 where oref=t2.oref);
@ -156,7 +156,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 ref_or_null a a 5 func 4 Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 Using where
Warnings:
Note 1276 Field or reference 't3.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<in_optimizer>(`test`.`t3`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t2`.`b` = `test`.`t3`.`oref`) and trigcond(((<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`)))) having trigcond(<is_not_null_test>(`test`.`t1`.`a`)))) AS `Z` from `test`.`t3`
drop table t1, t2, t3;
create table t1 (a int NOT NULL, b int NOT NULL, key(a));
@ -184,7 +184,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 ref a a 4 func 2 Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 Using where
Warnings:
Note 1276 Field or reference 't3.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<in_optimizer>(`test`.`t3`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t2`.`b` = `test`.`t3`.`oref`) and trigcond((<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`))))) AS `Z` from `test`.`t3`
drop table t1,t2,t3;
create table t1 (oref int, grp int);
@ -240,7 +240,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where ((`test`.`t1`.`c` = `test`.`t2`.`oref`) and trigcond(((<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`))) and trigcond(((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)))) having (trigcond(<is_not_null_test>(`test`.`t1`.`a`)) and trigcond(<is_not_null_test>(`test`.`t1`.`b`)))))) AS `Z` from `test`.`t2`
select a,b, oref, (a,b) in (select a,b from t1 where c=t2.oref) Z from t2;
a b oref Z
@ -257,7 +257,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 ref_or_null a a 5 func 2 Using where; Full scan on NULL key
2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 Using where
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` join `test`.`t4` where ((`test`.`t1`.`c` = `test`.`t2`.`oref`) and trigcond(((<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`))) and trigcond(((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)))) having (trigcond(<is_not_null_test>(`test`.`t1`.`a`)) and trigcond(<is_not_null_test>(`test`.`t1`.`b`))))) AS `Z` from `test`.`t2`
select a,b, oref,
(a,b) in (select a,b from t1,t4 where c=t2.oref) Z
@ -302,7 +302,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 8 Using where
2 DEPENDENT SUBQUERY t1 index_subquery idx idx 5 func 4 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where ((`test`.`t1`.`oref` = `test`.`t2`.`oref`) and trigcond(((<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1`) or isnull(`test`.`t1`.`ie1`))) and trigcond(((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2`) or isnull(`test`.`t1`.`ie2`)))) having (trigcond(<is_not_null_test>(`test`.`t1`.`ie1`)) and trigcond(<is_not_null_test>(`test`.`t1`.`ie2`)))))) AS `Z` from `test`.`t2` where ((`test`.`t2`.`b` = 10) and (`test`.`t2`.`a` = 10))
drop table t1, t2;
create table t1 (oref char(4), grp int, ie int);
@ -432,7 +432,7 @@ alter table t1 add index idx(oref,ie);
explain select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 7
2 DEPENDENT SUBQUERY t1 ref_or_null idx idx 10 test.t2.oref,func 4 Using where; Using index; Full scan on NULL key
2 DEPENDENT SUBQUERY t1 ref_or_null idx idx 10 t2.oref,func 4 Using where; Using index; Full scan on NULL key
select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2;
oref a Z
ee NULL NULL
@ -457,7 +457,7 @@ group by grp having min(ie) > 1) Z
from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 7
2 DEPENDENT SUBQUERY t1 ref idx idx 5 test.t2.oref 2 Using where; Using temporary; Using filesort
2 DEPENDENT SUBQUERY t1 ref idx idx 5 t2.oref 2 Using where; Using temporary; Using filesort
select oref, a,
a in (select min(ie) from t1 where oref=t2.oref
group by grp having min(ie) > 1) Z
@ -572,7 +572,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 7
2 DEPENDENT SUBQUERY t1 index_subquery idx idx 5 func 4 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where ((`test`.`t1`.`oref` = `test`.`t2`.`oref`) and trigcond(((<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1`) or isnull(`test`.`t1`.`ie1`))) and trigcond(((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2`) or isnull(`test`.`t1`.`ie2`)))) having (trigcond(<is_not_null_test>(`test`.`t1`.`ie1`)) and trigcond(<is_not_null_test>(`test`.`t1`.`ie2`)))))) AS `Z` from `test`.`t2`
drop table t1,t2;
create table t1 (oref char(4), grp int, ie int primary key);

View File

@ -610,12 +610,12 @@ create table t1 (id integer primary key auto_increment, txt text, index txt_inde
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
id txt
3 NULL
1 Chevy
2 Chevy
3 NULL
explain select * from t1 where txt='Chevy' or txt is NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range txt_index txt_index 23 NULL 2 Using where
1 SIMPLE t1 ref_or_null txt_index txt_index 23 const 2 Using where
select * from t1 where txt='Chevy ';
id txt
1 Chevy

View File

@ -434,3 +434,22 @@ Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 21
DROP TABLE t1;
CREATE TABLE t1 (
a INT(11),
quux decimal( 31, 30 ),
UNIQUE KEY bar (a),
KEY quux (quux)
);
INSERT INTO
t1 ( a, quux )
VALUES
( 1, 1 ),
( 2, 0.1 );
INSERT INTO t1( a )
SELECT @newA := 1 + a FROM t1 WHERE quux <= 0.1;
SELECT * FROM t1;
a quux
1 1.000000000000000000000000000000
2 0.100000000000000000000000000000
3 NULL
DROP TABLE t1;

View File

@ -127,4 +127,19 @@ show binlog events;
drop table t1,t2,t3;
#
#Bug#19717: DELETE Query Error on BLACKHOLE when using WHERE on column with UNIQUE INDEX
#
CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE;
DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 ADD INDEX(a);
DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 DROP INDEX a;
ALTER TABLE t1 ADD UNIQUE INDEX(a);
DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 DROP INDEX a;
ALTER TABLE t1 ADD PRIMARY KEY(a);
DELETE FROM t1 WHERE a=10;
DROP TABLE t1;
# End of 4.1 tests

View File

@ -292,3 +292,18 @@ select @@identity;
insert ignore t1(f2) select 1;
select @@identity;
drop table t1;
#
# Bug#16630: wrong result, when INSERT t1 SELECT ... FROM t1 ON DUPLICATE
#
CREATE TABLE t1 (f1 INT, f2 INT );
CREATE TABLE t2 (f1 INT PRIMARY KEY, f2 INT);
INSERT INTO t1 VALUES (1,1),(2,2),(10,10);
INSERT INTO t2 (f1, f2) SELECT f1, f2 FROM t1;
INSERT INTO t2 (f1, f2)
SELECT f1, f1 FROM t2 src WHERE f1 < 2
ON DUPLICATE KEY UPDATE f1 = 100 + src.f1;
SELECT * FROM t2;
DROP TABLE t1, t2;

View File

@ -139,3 +139,26 @@ INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b =
SELECT * FROM t1;
DROP TABLE t1;
#
# Bug#25831: Deficiencies in INSERT ... SELECT ... field name resolving.
#
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
--error ER_BAD_FIELD_ERROR
INSERT INTO t1 SELECT 1, j;
DROP TABLE t1;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
CREATE TABLE t2 (a INT, b INT);
CREATE TABLE t3 (a INT, c INT);
INSERT INTO t1 SELECT 1, a FROM t2 NATURAL JOIN t3
ON DUPLICATE KEY UPDATE j= a;
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (i INT PRIMARY KEY, j INT);
CREATE TABLE t2 (a INT);
INSERT INTO t1 VALUES (1, 1);
INSERT INTO t2 VALUES (1), (3);
--error ER_BAD_FIELD_ERROR
INSERT INTO t1 SELECT 1, COUNT(*) FROM t2 ON DUPLICATE KEY UPDATE j= a;
DROP TABLE t1,t2;

View File

@ -3253,4 +3253,50 @@ select
case when 1 then cast(1111111111111111111 as unsigned) else 1 end c,
coalesce(cast(1111111111111111111 as unsigned), 1) co;
#
# Bug #22971: indexes on text columns are ignored for ref accesses
#
CREATE TABLE t1 (name varchar(255));
CREATE TABLE t2 (name varchar(255), n int, KEY (name(3)));
INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
SELECT * FROM t2;
SELECT * FROM t2 ORDER BY name;
SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
DROP TABLE t1,t2;
CREATE TABLE t1 (name text);
CREATE TABLE t2 (name text, n int, KEY (name(3)));
INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
SELECT * FROM t2;
SELECT * FROM t2 ORDER BY name;
SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
DROP TABLE t1,t2;
--echo End of 5.0 tests

View File

@ -2600,4 +2600,31 @@ SELECT * FROM t1
UNION
SELECT c from t2 WHERE c=t1.c);
DROP TABLE t1,t2,t3;
DROP TABLE t1,t2,t3;
#
# Bug#23800: Outer fields in correlated subqueries is used in a temporary
# table created for sorting.
#
CREATE TABLE t1(f1 int);
CREATE TABLE t2(f2 int, f21 int, f3 timestamp);
INSERT INTO t1 VALUES (1),(1),(2),(2);
INSERT INTO t2 VALUES (1,1,"2004-02-29 11:11:11"), (2,2,"2004-02-29 11:11:11");
SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1;
SELECT (SELECT SUM(1) FROM t2 ttt GROUP BY t2.f3 LIMIT 1) AS tt FROM t2;
PREPARE stmt1 FROM 'SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1';
EXECUTE stmt1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SELECT f2, AVG(f21),
(SELECT t.f3 FROM t2 AS t WHERE t2.f2=t.f2 AND t.f3=MAX(t2.f3)) AS test
FROM t2 GROUP BY f2;
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL);
INSERT INTO t1 VALUES
(1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'),
(2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'), (3,3,'j'),
(3,2,'k'), (3,1,'l'), (1,9,'m');
SELECT a, MAX(b),
(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) AS test
FROM t1 GROUP BY a;
DROP TABLE t1;

View File

@ -342,3 +342,29 @@ UPDATE t1 SET user_id=null WHERE request_id=999999999999999999999999999999;
show status like '%Handler_read%';
DROP TABLE t1;
#
# Bug #24010: INSERT INTO ... SELECT fails on unique constraint with data it
# doesn't select
#
CREATE TABLE t1 (
a INT(11),
quux decimal( 31, 30 ),
UNIQUE KEY bar (a),
KEY quux (quux)
);
INSERT INTO
t1 ( a, quux )
VALUES
( 1, 1 ),
( 2, 0.1 );
INSERT INTO t1( a )
SELECT @newA := 1 + a FROM t1 WHERE quux <= 0.1;
SELECT * FROM t1;
DROP TABLE t1;

View File

@ -180,7 +180,7 @@ int ha_blackhole::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
DBUG_ENTER("ha_blackhole::index_read");
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_END_OF_FILE);
}

View File

@ -1607,7 +1607,7 @@ void Item_ident_for_show::make_field(Send_field *tmp_field)
Item_field::Item_field(Field *f)
:Item_ident(0, NullS, *f->table_name, f->field_name),
item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
have_privileges(0), any_privileges(0), fixed_as_field(0)
{
set_field(f);
/*
@ -1621,7 +1621,7 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
Field *f)
:Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name),
item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
have_privileges(0), any_privileges(0), fixed_as_field(0)
{
/*
We always need to provide Item_field with a fully qualified field
@ -1660,9 +1660,12 @@ Item_field::Item_field(Name_resolution_context *context_arg,
const char *field_name_arg)
:Item_ident(context_arg, db_arg,table_name_arg,field_name_arg),
field(0), result_field(0), item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0)
have_privileges(0), any_privileges(0), fixed_as_field(0)
{
SELECT_LEX *select= current_thd->lex->current_select;
collation.set(DERIVATION_IMPLICIT);
if (select && select->parsing_place != IN_HAVING)
select->select_n_where_fields++;
}
// Constructor need to process subselect with temporary tables (see Item)
@ -1673,7 +1676,8 @@ Item_field::Item_field(THD *thd, Item_field *item)
item_equal(item->item_equal),
no_const_subst(item->no_const_subst),
have_privileges(item->have_privileges),
any_privileges(item->any_privileges)
any_privileges(item->any_privileges),
fixed_as_field(item->fixed_as_field)
{
collation.set(DERIVATION_IMPLICIT);
}
@ -3483,8 +3487,46 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
}
if (*from_field != view_ref_found)
{
prev_subselect_item->used_tables_cache|= (*from_field)->table->map;
prev_subselect_item->const_item_cache= 0;
if (!last_checked_context->select_lex->having_fix_field &&
!fixed_as_field)
{
Item_outer_ref *rf;
Query_arena *arena= 0, backup;
/*
Each outer field is replaced for an Item_outer_ref object.
This is done in order to get correct results when the outer
select employs a temporary table.
The original fields are saved in the inner_fields_list of the
outer select. This list is created by the following reasons:
1. We can't add field items to the outer select list directly
because the outer select hasn't been fully fixed yet.
2. We need a location to refer to in the Item_ref object
so the inner_fields_list is used as such temporary
reference storage.
The new Item_outer_ref object replaces the original field and is
also saved in the inner_refs_list of the outer select. Here
it is only created. It can be fixed only after the original
field has been fixed and this is done in the fix_inner_refs()
function.
*/
set_field(*from_field);
arena= thd->activate_stmt_arena_if_needed(&backup);
rf= new Item_outer_ref(context, this);
if (!rf)
{
if (arena)
thd->restore_active_arena(arena, &backup);
return -1;
}
*reference= rf;
select->inner_refs_list.push_back(rf);
if (arena)
thd->restore_active_arena(arena, &backup);
fixed_as_field= 1;
}
if (thd->lex->in_sum_func &&
thd->lex->in_sum_func->nest_level ==
thd->lex->current_select->nest_level)
@ -3612,7 +3654,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
{
mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex,
this, this);
this, (Item_ident*)*reference);
if (last_checked_context->select_lex->having_fix_field)
{
Item_ref *rf;
@ -4809,6 +4851,51 @@ void Item_field::update_null_value()
}
/*
Add the field to the select list and substitute it for the reference to
the field.
SYNOPSIS
Item_field::update_value_transformer()
select_arg current select
DESCRIPTION
If the field doesn't belong to the table being inserted into then it is
added to the select list, pointer to it is stored in the ref_pointer_array
of the select and the field itself is substituted for the Item_ref object.
This is done in order to get correct values from update fields that
belongs to the SELECT part in the INSERT .. SELECT .. ON DUPLICATE KEY
UPDATE statement.
RETURN
0 if error occured
ref if all conditions are met
this field otherwise
*/
Item *Item_field::update_value_transformer(byte *select_arg)
{
SELECT_LEX *select= (SELECT_LEX*)select_arg;
DBUG_ASSERT(fixed);
if (field->table != select->context.table_list->table &&
type() != Item::TRIGGER_FIELD_ITEM)
{
List<Item> *all_fields= &select->join->all_fields;
Item **ref_pointer_array= select->ref_pointer_array;
int el= all_fields->elements;
Item_ref *ref;
ref_pointer_array[el]= (Item*)this;
all_fields->push_front((Item*)this);
ref= new Item_ref(&select->context, ref_pointer_array + el,
table_name, field_name);
return ref;
}
return this;
}
Item_ref::Item_ref(Name_resolution_context *context_arg,
Item **item, const char *table_name_arg,
const char *field_name_arg)
@ -4818,8 +4905,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
/*
This constructor used to create some internals references over fixed items
*/
DBUG_ASSERT(ref != 0);
if (*ref && (*ref)->fixed)
if (ref && *ref && (*ref)->fixed)
set_properties();
}
@ -5120,7 +5206,7 @@ void Item_ref::print(String *str)
if (ref)
{
if ((*ref)->type() != Item::CACHE_ITEM && ref_type() != VIEW_REF &&
name && alias_name_used)
ref_type() != OUTER_REF && name && alias_name_used)
{
THD *thd= current_thd;
append_identifier(thd, str, name, (uint) strlen(name));
@ -5368,7 +5454,7 @@ bool Item_direct_ref::get_date(TIME *ltime,uint fuzzydate)
/*
Prepare referenced view viewld then call usual Item_direct_ref::fix_fields
Prepare referenced field then call usual Item_direct_ref::fix_fields
SYNOPSIS
Item_direct_view_ref::fix_fields()
@ -5391,6 +5477,31 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
return Item_direct_ref::fix_fields(thd, reference);
}
/*
Prepare referenced outer field then call usual Item_direct_ref::fix_fields
SYNOPSIS
Item_outer_ref::fix_fields()
thd thread handler
reference reference on reference where this item stored
RETURN
FALSE OK
TRUE Error
*/
bool Item_outer_ref::fix_fields(THD *thd, Item **reference)
{
DBUG_ASSERT(*ref);
/* outer_field->check_cols() will be made in Item_direct_ref::fix_fields */
outer_field->fixed_as_field= 1;
if (!outer_field->fixed &&
(outer_field->fix_fields(thd, reference)))
return TRUE;
table_name= outer_field->table_name;
return Item_direct_ref::fix_fields(thd, reference);
}
/*
Compare two view column references for equality.

View File

@ -325,10 +325,10 @@ private:
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
TABLE_LIST *save_next_local;
public:
Name_resolution_context_state() {} /* Remove gcc warning */
TABLE_LIST *save_next_local;
public:
/* Save the state of a name resolution context. */
@ -350,6 +350,11 @@ public:
context->first_name_resolution_table= save_first_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
}
TABLE_LIST *get_first_name_resolution_table()
{
return save_first_name_resolution_table;
}
};
/*************************************************************************/
@ -817,6 +822,7 @@ public:
virtual Item_field *filed_for_view_update() { return 0; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
virtual Item *update_value_transformer(byte *select_arg) { return this; }
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
void delete_self()
{
@ -1215,7 +1221,7 @@ public:
uint have_privileges;
/* field need any privileges (for VIEW creation) */
bool any_privileges;
bool fixed_as_field;
Item_field(Name_resolution_context *context_arg,
const char *db_arg,const char *table_name_arg,
const char *field_name_arg);
@ -1296,6 +1302,7 @@ public:
Item_field *filed_for_view_update() { return this; }
Item *safe_charset_converter(CHARSET_INFO *tocs);
int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *update_value_transformer(byte *select_arg);
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
@ -1818,7 +1825,7 @@ class Item_ref :public Item_ident
protected:
void set_properties();
public:
enum Ref_Type { REF, DIRECT_REF, VIEW_REF };
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF };
Field *result_field; /* Save result here */
Item **ref;
Item_ref(Name_resolution_context *context_arg,
@ -1879,7 +1886,7 @@ public:
(*ref)->get_tmp_table_item(thd));
}
table_map used_tables() const
{
{
return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
}
table_map not_null_tables() const { return (*ref)->not_null_tables(); }
@ -1952,6 +1959,40 @@ public:
};
class Item_outer_ref :public Item_direct_ref
{
public:
Item_field *outer_field;
Item_outer_ref(Name_resolution_context *context_arg,
Item_field *outer_field_arg)
:Item_direct_ref(context_arg, 0, outer_field_arg->table_name,
outer_field_arg->field_name),
outer_field(outer_field_arg)
{
ref= (Item**)&outer_field;
set_properties();
fixed= 0;
}
void cleanup()
{
ref= (Item**)&outer_field;
fixed= 0;
Item_direct_ref::cleanup();
outer_field->cleanup();
}
void save_in_result_field(bool no_conversions)
{
outer_field->save_org_in_field(result_field);
}
bool fix_fields(THD *, Item **);
table_map used_tables() const
{
return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT;
}
virtual Ref_Type ref_type() { return OUTER_REF; }
};
class Item_in_subselect;

View File

@ -754,6 +754,8 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields);
bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
Item **ref_pointer_array);
bool handle_select(THD *thd, LEX *lex, select_result *result,
ulong setup_tables_done_option);

View File

@ -4528,21 +4528,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
uint tablenr= 0;
DBUG_ENTER("setup_tables");
/*
Due to the various call paths that lead to setup_tables() it may happen
that context->table_list and context->first_name_resolution_table can be
NULL (this is typically done when creating TABLE_LISTs internally).
TODO:
Investigate all cases when this my happen, initialize the name resolution
context correctly in all those places, and remove the context reset below.
*/
if (!context->table_list || !context->first_name_resolution_table)
{
/* Test whether the context is in a consistent state. */
DBUG_ASSERT(!context->first_name_resolution_table && !context->table_list);
context->table_list= context->first_name_resolution_table= tables;
}
DBUG_ASSERT ((select_insert && !tables->next_name_resolution_table) || !tables ||
(context->table_list && context->first_name_resolution_table));
/*
this is used for INSERT ... SELECT.
For select we setup tables except first (and its underlying tables)

View File

@ -353,6 +353,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
Item *fake_conds= 0;
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete");
List<Item> all_fields;
thd->lex->allow_sum_func= 0;
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
@ -376,6 +377,11 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
DBUG_RETURN(TRUE);
}
}
if (select_lex->inner_refs_list.elements &&
fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
DBUG_RETURN(-1);
select_lex->fix_prepare_information(thd, conds, &fake_conds);
DBUG_RETURN(FALSE);
}

View File

@ -656,6 +656,8 @@ bool mysqld_help(THD *thd, const char *mask)
Init tables and fields to be usable from items
tables do not contain VIEWs => we can pass 0 as conds
*/
thd->lex->select_lex.context.table_list=
thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
setup_tables(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
tables, 0, &leaves, FALSE);

View File

@ -965,6 +965,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
(ulong)table_list, (ulong)table,
(int)insert_into_view));
/* INSERT should have a SELECT or VALUES clause */
DBUG_ASSERT (!select_insert || !values);
/*
For subqueries in VALUES() we should not see the table in which we are
@ -997,44 +999,40 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
select_insert))
DBUG_RETURN(TRUE);
/* Save the state of the current name resolution context. */
ctx_state.save_state(context, table_list);
/*
Perform name resolution only in the first table - 'table_list',
which is the table that is inserted into.
*/
table_list->next_local= 0;
context->resolve_in_table_list_only(table_list);
/* Prepare the fields in the statement. */
if (values &&
!(res= check_insert_fields(thd, context->table_list, fields, *values,
!insert_into_view, &map) ||
setup_fields(thd, 0, *values, 0, 0, 0)) &&
duplic == DUP_UPDATE)
if (values)
{
select_lex->no_wrap_view_item= TRUE;
res= check_update_fields(thd, context->table_list, update_fields, &map);
select_lex->no_wrap_view_item= FALSE;
/* if we have INSERT ... VALUES () we cannot have a GROUP BY clause */
DBUG_ASSERT (!select_lex->group_list.elements);
/* Save the state of the current name resolution context. */
ctx_state.save_state(context, table_list);
/*
When we are not using GROUP BY we can refer to other tables in the
ON DUPLICATE KEY part.
*/
if (select_lex->group_list.elements == 0)
Perform name resolution only in the first table - 'table_list',
which is the table that is inserted into.
*/
table_list->next_local= 0;
context->resolve_in_table_list_only(table_list);
if (!(res= check_insert_fields(thd, context->table_list, fields, *values,
!insert_into_view, &map) ||
setup_fields(thd, 0, *values, 0, 0, 0))
&& duplic == DUP_UPDATE)
{
context->table_list->next_local= ctx_state.save_next_local;
/* first_name_resolution_table was set by resolve_in_table_list_only() */
context->first_name_resolution_table->
next_name_resolution_table= ctx_state.save_next_local;
select_lex->no_wrap_view_item= TRUE;
res= check_update_fields(thd, context->table_list, update_fields, &map);
select_lex->no_wrap_view_item= FALSE;
}
/* Restore the current context. */
ctx_state.restore_state(context, table_list);
if (!res)
res= setup_fields(thd, 0, update_values, 1, 0, 0);
}
/* Restore the current context. */
ctx_state.restore_state(context, table_list);
if (res)
DBUG_RETURN(res);
@ -2360,7 +2358,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (info.handle_duplicates == DUP_UPDATE)
{
/* Save the state of the current name resolution context. */
Name_resolution_context *context= &lex->select_lex.context;
Name_resolution_context_state ctx_state;
@ -2376,18 +2373,38 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*info.update_fields, &map);
lex->select_lex.no_wrap_view_item= FALSE;
/*
When we are not using GROUP BY we can refer to other tables in the
ON DUPLICATE KEY part
When we are not using GROUP BY and there are no ungrouped aggregate functions
we can refer to other tables in the ON DUPLICATE KEY part.
We use next_name_resolution_table descructively, so check it first (views?)
*/
if (lex->select_lex.group_list.elements == 0)
{
context->table_list->next_local= ctx_state.save_next_local;
/* first_name_resolution_table was set by resolve_in_table_list_only() */
context->first_name_resolution_table->
next_name_resolution_table= ctx_state.save_next_local;
}
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
DBUG_ASSERT (!table_list->next_name_resolution_table);
if (lex->select_lex.group_list.elements == 0 &&
!lex->select_lex.with_sum_func)
/*
We must make a single context out of the two separate name resolution contexts :
the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
To do that we must concatenate the two lists
*/
table_list->next_name_resolution_table= ctx_state.get_first_name_resolution_table();
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
if (!res)
{
/*
Traverse the update values list and substitute fields from the
select for references (Item_ref objects) to them. This is done in
order to get correct values from those fields when the select
employs a temporary table.
*/
List_iterator<Item> li(*info.update_values);
Item *item;
while ((item= li++))
{
item->transform(&Item::update_value_transformer,
(byte*)lex->current_select);
}
}
/* Restore the current context. */
ctx_state.restore_state(context, table_list);
}

View File

@ -1153,6 +1153,7 @@ void st_select_lex::init_query()
cond_count= between_count= with_wild= 0;
conds_processed_with_permanent_arena= 0;
ref_pointer_array= 0;
select_n_where_fields= 0;
select_n_having_items= 0;
subquery_in_having= explicit_limit= 0;
is_item_list_lookup= 0;
@ -1194,6 +1195,7 @@ void st_select_lex::init_select()
is_correlated= 0;
cur_pos_in_select_list= UNDEF_POS;
non_agg_fields.empty();
inner_refs_list.empty();
}
/*
@ -1551,6 +1553,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
(Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
item_list.elements +
select_n_having_items +
select_n_where_fields +
order_group_num)*5)) == 0;
}

View File

@ -531,6 +531,11 @@ public:
uint select_n_having_items;
uint cond_count; /* number of arguments of and/or/xor in where/having/on */
uint between_count; /* number of between predicates in where/having/on */
/*
Number of fields used in select list or where clause of current select
and all inner subselects.
*/
uint select_n_where_fields;
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
/*
@ -548,7 +553,8 @@ public:
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
/* List of references to fields referenced from inner selects */
List<Item_outer_ref> inner_refs_list;
/* Number of Item_sum-derived objects in this SELECT */
uint n_sum_items;
/* Number of Item_sum-derived objects in children and descendant SELECTs */

View File

@ -1570,21 +1570,16 @@ error:
static bool mysql_insert_select_prepare_tester(THD *thd)
{
TABLE_LIST *first;
bool res;
SELECT_LEX *first_select= &thd->lex->select_lex;
TABLE_LIST *second_table= ((TABLE_LIST*)first_select->table_list.first)->
next_local;
/* Skip first table, which is the table we are inserting in */
first_select->table_list.first= (byte*)(first=
((TABLE_LIST*)first_select->
table_list.first)->next_local);
res= mysql_insert_select_prepare(thd);
/*
insert/replace from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
thd->lex->select_lex.context.resolve_in_select_list= TRUE;
thd->lex->select_lex.context.table_list= first;
return res;
first_select->table_list.first= (byte *) second_table;
thd->lex->select_lex.context.table_list=
thd->lex->select_lex.context.first_name_resolution_table= second_table;
return mysql_insert_select_prepare(thd);
}

View File

@ -267,6 +267,70 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
}
/*
Fix fields referenced from inner selects.
SYNOPSIS
fix_inner_refs()
thd Thread handle
all_fields List of all fields used in select
select Current select
ref_pointer_array Array of references to Items used in current select
DESCRIPTION
The function fixes fields referenced from inner selects and
also fixes references (Item_ref objects) to these fields. Each field
is fixed as a usual hidden field of the current select - it is added
to the all_fields list and the pointer to it is saved in the
ref_pointer_array if latter is provided.
After the field has been fixed we proceed with fixing references
(Item_ref objects) to this field from inner subqueries. If the
ref_pointer_array is provided then Item_ref objects is set to
reference element in that array with the pointer to the field.
RETURN
TRUE an error occured
FALSE ok
*/
bool
fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
Item **ref_pointer_array)
{
Item_outer_ref *ref;
bool res= FALSE;
List_iterator<Item_outer_ref> ref_it(select->inner_refs_list);
while ((ref= ref_it++))
{
Item_field *item= ref->outer_field;
/*
TODO: this field item already might be present in the select list.
In this case instead of adding new field item we could use an
existing one. The change will lead to less operations for copying fields,
smaller temporary tables and less data passed through filesort.
*/
if (ref_pointer_array)
{
int el= all_fields.elements;
ref_pointer_array[el]= (Item*)item;
/* Add the field item to the select list of the current select. */
all_fields.push_front((Item*)item);
/*
If it's needed reset each Item_ref item that refers this field with
a new reference taken from ref_pointer_array.
*/
ref->ref= ref_pointer_array + el;
}
if (!ref->fixed && ref->fix_fields(thd, 0))
{
res= TRUE;
break;
}
thd->used_tables|= item->used_tables();
}
return res;
}
/*
Function to setup clauses without sum functions
*/
@ -394,6 +458,10 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having && having->with_sum_func)
having->split_sum_func2(thd, ref_pointer_array, all_fields,
&having, TRUE);
if (select_lex->inner_refs_list.elements &&
fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array))
DBUG_RETURN(-1);
if (select_lex->inner_sum_func_list)
{
Item_sum *end=select_lex->inner_sum_func_list;
@ -481,6 +549,9 @@ JOIN::prepare(Item ***rref_pointer_array,
}
}
if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
/* Init join struct */
count_field_types(&tmp_table_param, all_fields, 0);
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
@ -494,9 +565,6 @@ JOIN::prepare(Item ***rref_pointer_array,
goto err;
}
#endif
if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
if (select_lex->olap == ROLLUP_TYPE && rollup_init())
goto err;
if (alloc_func_list())
@ -2853,15 +2921,9 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
/*
We can't use indexes if the effective collation
of the operation differ from the field collation.
We also cannot use index on a text column, as the column may
contain 'x' 'x\t' 'x ' and 'read_next_same' will stop after
'x' when searching for WHERE col='x '
*/
if (field->cmp_type() == STRING_RESULT &&
(((Field_str*)field)->charset() != cond->compare_collation() ||
((*value)->type() != Item::NULL_ITEM &&
(field->flags & BLOB_FLAG) && !field->binary())))
((Field_str*)field)->charset() != cond->compare_collation())
return;
}
}
@ -5131,13 +5193,15 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
key_part->length,
keyuse->val);
}
else if (keyuse->val->type() == Item::FIELD_ITEM)
else if (keyuse->val->type() == Item::FIELD_ITEM ||
(keyuse->val->type() == Item::REF_ITEM &&
((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF) )
return new store_key_field(thd,
key_part->field,
key_buff + maybe_null,
maybe_null ? key_buff : 0,
key_part->length,
((Item_field*) keyuse->val)->field,
((Item_field*) keyuse->val->real_item())->field,
keyuse->val->full_name());
return new store_key_item(thd,
key_part->field,
@ -8704,7 +8768,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
type they needed to be handled separately.
*/
if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE)
type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE ||
type == MYSQL_TYPE_TIMESTAMP)
new_field= item->tmp_table_field_from_field_type(table);
/*
Make sure that the blob fits into a Field_varstring which has
@ -8811,8 +8876,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item *orig_item= 0;
if (type != Item::FIELD_ITEM &&
item->real_item()->type() == Item::FIELD_ITEM &&
!((Item_ref *) item)->depended_from)
item->real_item()->type() == Item::FIELD_ITEM)
{
orig_item= item;
item= item->real_item();
@ -13472,8 +13536,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
{
Item::Type type=field->type();
Item::Type real_type= field->real_item()->type();
if (type == Item::FIELD_ITEM || (real_type == Item::FIELD_ITEM &&
!((Item_ref *) field)->depended_from))
if (real_type == Item::FIELD_ITEM)
param->field_count++;
else if (real_type == Item::SUM_FUNC_ITEM)
{

View File

@ -147,6 +147,8 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg)
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
(byte **)
&result_table_list.next_local);
fake_select_lex->context.table_list= fake_select_lex->context.first_name_resolution_table=
fake_select_lex->get_table_list();
for (ORDER *order= (ORDER *)global_parameters->order_list.first;
order;
order=order->next)

View File

@ -133,6 +133,7 @@ int mysql_update(THD *thd,
READ_RECORD info;
SELECT_LEX *select_lex= &thd->lex->select_lex;
bool need_reopen;
List<Item> all_fields;
DBUG_ENTER("mysql_update");
LINT_INIT(timestamp_query_id);
@ -225,6 +226,10 @@ int mysql_update(THD *thd,
DBUG_RETURN(1); /* purecov: inspected */
}
if (select_lex->inner_refs_list.elements &&
fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
DBUG_RETURN(-1);
if (conds)
{
Item::cond_result cond_value;

View File

@ -4188,8 +4188,13 @@ select_into:
| select_from into;
select_from:
FROM join_table_list where_clause group_clause having_clause
FROM join_table_list where_clause group_clause having_clause
opt_order_clause opt_limit_clause procedure_clause
{
Select->context.table_list=
Select->context.first_name_resolution_table=
(TABLE_LIST *) Select->table_list.first;
}
| FROM DUAL_SYM where_clause opt_limit_clause
/* oracle compatibility: oracle always requires FROM clause,
and DUAL is system table without fields.
@ -9266,6 +9271,12 @@ subselect_end:
lex->current_select = lex->current_select->return_after_parsing();
lex->nest_level--;
lex->current_select->n_child_sum_items += child->n_sum_items;
/*
A subselect can add fields to an outer select. Reserve space for
them.
*/
lex->current_select->select_n_where_fields+=
child->select_n_where_fields;
};
/**************************************************************************