mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
MDEV-334: Backport of UNION ALL optimization from mysql-5.7.
Although the original code of mysql-5.7 was adjusted to the current MariaDB code the main ideas of the optimization were preserved.
This commit is contained in:
@@ -102,7 +102,6 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
|
||||||
2 DERIVED t1 ALL NULL NULL NULL NULL 4
|
2 DERIVED t1 ALL NULL NULL NULL NULL 4
|
||||||
3 UNION t1 ALL NULL NULL NULL NULL 4
|
3 UNION t1 ALL NULL NULL NULL NULL 4
|
||||||
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
||||||
CREATE TABLE t2 (a int not null);
|
CREATE TABLE t2 (a int not null);
|
||||||
insert into t2 values(1);
|
insert into t2 values(1);
|
||||||
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
|
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
|
||||||
|
@@ -126,7 +126,7 @@ group by
|
|||||||
a.text, b.id, b.betreff
|
a.text, b.id, b.betreff
|
||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -142,7 +142,7 @@ where
|
|||||||
match(c.beitrag) against ('+abc' in boolean mode)
|
match(c.beitrag) against ('+abc' in boolean mode)
|
||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -158,7 +158,7 @@ where
|
|||||||
match(c.beitrag) against ('+abc' in boolean mode)
|
match(c.beitrag) against ('+abc' in boolean mode)
|
||||||
order by
|
order by
|
||||||
match(betreff) against ('+abc' in boolean mode) desc;
|
match(betreff) against ('+abc' in boolean mode) desc;
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
text id betreff
|
||||||
(select b.id, b.betreff from t3 b) union
|
(select b.id, b.betreff from t3 b) union
|
||||||
(select b.id, b.betreff from t3 b)
|
(select b.id, b.betreff from t3 b)
|
||||||
order by match(betreff) against ('+abc' in boolean mode) desc;
|
order by match(betreff) against ('+abc' in boolean mode) desc;
|
||||||
|
@@ -3138,7 +3138,6 @@ explain partitions select 1 from t1 union all select 2;
|
|||||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY t1 NULL system NULL NULL NULL NULL 0 const row not found
|
1 PRIMARY t1 NULL system NULL NULL NULL NULL 0 const row not found
|
||||||
2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
NULL UNION RESULT <union1,2> NULL ALL NULL NULL NULL NULL NULL
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a bigint unsigned not null) partition by range(a) (
|
create table t1 (a bigint unsigned not null) partition by range(a) (
|
||||||
partition p0 values less than (10),
|
partition p0 values less than (10),
|
||||||
|
@@ -1052,6 +1052,8 @@ create table t1 (a float);
|
|||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -1056,6 +1056,8 @@ create table t1 (a float);
|
|||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -1059,6 +1059,8 @@ create table t1 (a float);
|
|||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -1055,6 +1055,8 @@ create table t1 (a float);
|
|||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -1058,6 +1058,8 @@ create table t1 (a float);
|
|||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -1055,6 +1055,8 @@ create table t1 (a float);
|
|||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
ERROR 42000: This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -107,7 +107,6 @@ explain select a,b from t1 union all select a,b from t2;
|
|||||||
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 PRIMARY t1 ALL NULL NULL NULL NULL 4
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
|
||||||
2 UNION t2 ALL NULL NULL NULL NULL 4
|
2 UNION t2 ALL NULL NULL NULL NULL 4
|
||||||
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
|
|
||||||
explain select xx from t1 union select 1;
|
explain select xx from t1 union select 1;
|
||||||
ERROR 42S22: Unknown column 'xx' in 'field list'
|
ERROR 42S22: Unknown column 'xx' in 'field list'
|
||||||
explain select a,b from t1 union select 1;
|
explain select a,b from t1 union select 1;
|
||||||
@@ -341,14 +340,13 @@ select found_rows();
|
|||||||
found_rows()
|
found_rows()
|
||||||
4
|
4
|
||||||
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1;
|
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1;
|
||||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
|
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
|
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
3
|
|
||||||
select found_rows();
|
select found_rows();
|
||||||
found_rows()
|
found_rows()
|
||||||
6
|
4
|
||||||
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
|
||||||
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@@ -362,7 +360,7 @@ a
|
|||||||
2
|
2
|
||||||
select found_rows();
|
select found_rows();
|
||||||
found_rows()
|
found_rows()
|
||||||
6
|
5
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@@ -374,31 +372,11 @@ select found_rows();
|
|||||||
found_rows()
|
found_rows()
|
||||||
5
|
5
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2;
|
||||||
a
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
select found_rows();
|
|
||||||
found_rows()
|
|
||||||
5
|
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2;
|
||||||
a
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
1
|
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
select found_rows();
|
|
||||||
found_rows()
|
|
||||||
6
|
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2 LIMIT 2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2 LIMIT 2;
|
||||||
a
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
1
|
|
||||||
3
|
|
||||||
select found_rows();
|
|
||||||
found_rows()
|
|
||||||
6
|
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2,2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2,2;
|
||||||
a
|
a
|
||||||
3
|
3
|
||||||
@@ -407,13 +385,7 @@ select found_rows();
|
|||||||
found_rows()
|
found_rows()
|
||||||
5
|
5
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2 UNION SELECT * FROM t2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2 UNION SELECT * FROM t2;
|
||||||
a
|
ERROR HY000: Incorrect usage of UNION and LIMIT
|
||||||
3
|
|
||||||
4
|
|
||||||
5
|
|
||||||
select found_rows();
|
|
||||||
found_rows()
|
|
||||||
5
|
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
|
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
|
||||||
a
|
a
|
||||||
5
|
5
|
||||||
@@ -430,7 +402,7 @@ drop temporary table t1;
|
|||||||
create table t1 select a from t1 union select a from t2;
|
create table t1 select a from t1 union select a from t2;
|
||||||
ERROR 42S01: Table 't1' already exists
|
ERROR 42S01: Table 't1' already exists
|
||||||
select a from t1 union select a from t2 order by t2.a;
|
select a from t1 union select a from t2 order by t2.a;
|
||||||
ERROR 42S22: Unknown column 't2.a' in 'order clause'
|
ERROR 42000: Table 't2' from one of the SELECTs cannot be used in field list
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
select length(version()) > 1 as `*` UNION select 2;
|
select length(version()) > 1 as `*` UNION select 2;
|
||||||
*
|
*
|
||||||
@@ -1202,32 +1174,32 @@ foo
|
|||||||
bar
|
bar
|
||||||
drop table t1;
|
drop table t1;
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
a ENUM('<EFBFBD>','<EFBFBD>','<EFBFBD>') character set utf8 not null default '<EFBFBD>',
|
a ENUM('ä','ö','ü') character set utf8 not null default 'ü',
|
||||||
b ENUM("one", "two") character set utf8,
|
b ENUM("one", "two") character set utf8,
|
||||||
c ENUM("one", "two")
|
c ENUM("one", "two")
|
||||||
);
|
);
|
||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`a` enum('<EFBFBD>','<EFBFBD>','<EFBFBD>') CHARACTER SET utf8 NOT NULL DEFAULT '<EFBFBD>',
|
`a` enum('ä','ö','ü') CHARACTER SET utf8 NOT NULL DEFAULT 'ü',
|
||||||
`b` enum('one','two') CHARACTER SET utf8 DEFAULT NULL,
|
`b` enum('one','two') CHARACTER SET utf8 DEFAULT NULL,
|
||||||
`c` enum('one','two') DEFAULT NULL
|
`c` enum('one','two') DEFAULT NULL
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
insert into t1 values ('<EFBFBD>', 'one', 'one'), ('<EFBFBD>', 'two', 'one'), ('<EFBFBD>', NULL, NULL);
|
insert into t1 values ('ä', 'one', 'one'), ('ö', 'two', 'one'), ('ü', NULL, NULL);
|
||||||
create table t2 select NULL union select a from t1;
|
create table t2 select NULL union select a from t1;
|
||||||
show columns from t2;
|
show columns from t2;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
NULL enum('<EFBFBD>','<EFBFBD>','<EFBFBD>') YES NULL
|
NULL enum('ä','ö','ü') YES NULL
|
||||||
drop table t2;
|
drop table t2;
|
||||||
create table t2 select a from t1 union select NULL;
|
create table t2 select a from t1 union select NULL;
|
||||||
show columns from t2;
|
show columns from t2;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
a enum('<EFBFBD>','<EFBFBD>','<EFBFBD>') YES NULL
|
a enum('ä','ö','ü') YES NULL
|
||||||
drop table t2;
|
drop table t2;
|
||||||
create table t2 select a from t1 union select a from t1;
|
create table t2 select a from t1 union select a from t1;
|
||||||
show columns from t2;
|
show columns from t2;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
a varchar(1) NO
|
a varchar(2) NO
|
||||||
drop table t2;
|
drop table t2;
|
||||||
create table t2 select a from t1 union select c from t1;
|
create table t2 select a from t1 union select c from t1;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
@@ -1616,11 +1588,18 @@ a
|
|||||||
EXPLAIN EXTENDED
|
EXPLAIN EXTENDED
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 UNION t1 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (match `a` against ('+abc' in boolean mode))
|
||||||
# Should not crash
|
# Should not crash
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
# Should not crash
|
# Should not crash
|
||||||
(SELECT * FROM t1) UNION (SELECT * FROM t1)
|
(SELECT * FROM t1) UNION (SELECT * FROM t1)
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
@@ -1638,7 +1617,7 @@ NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #-1
|
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #-1
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (select `a` from `test`.`t2` where (`test`.`t2`.`b` = 12))
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by <expr_cache><>((select `a` from `test`.`t2` where (`test`.`t2`.`b` = 12)))
|
||||||
# Should not crash
|
# Should not crash
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY (SELECT a FROM t2 WHERE b = 12);
|
ORDER BY (SELECT a FROM t2 WHERE b = 12);
|
||||||
@@ -1901,3 +1880,94 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
3 UNION t1 ALL NULL NULL NULL NULL 4
|
3 UNION t1 ALL NULL NULL NULL NULL 4
|
||||||
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# WL#1763 Avoid creating temporary table in UNION ALL
|
||||||
|
#
|
||||||
|
EXPLAIN SELECT 1 UNION ALL SELECT 1 LIMIT 1 OFFSET 1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
2 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
# Bug #17579498 CHANGES IN DATATYPE OF THE RESULT QUERY IN UNION.
|
||||||
|
CREATE TABLE t1 (a TIME);
|
||||||
|
CREATE TABLE t2 (b DATETIME);
|
||||||
|
CREATE TABLE t3
|
||||||
|
SELECT a FROM t1 UNION ALL SELECT b FROM t2;
|
||||||
|
SELECT column_name, column_type
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE TABLE_NAME='t3';
|
||||||
|
column_name column_type
|
||||||
|
a datetime
|
||||||
|
DROP TABLE t1, t2, t3;
|
||||||
|
# Bug #17602922 RESULT DIFFERENCES IN UNION QUERIES WITH IN
|
||||||
|
# (SUBQUERY-UNION ALL)
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1));
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES ('j');
|
||||||
|
INSERT INTO t1 VALUES ('k');
|
||||||
|
INSERT INTO t1 VALUES ('r');
|
||||||
|
INSERT INTO t1 VALUES ('r');
|
||||||
|
INSERT INTO t1 VALUES ('h');
|
||||||
|
SELECT a FROM t1 WHERE a IN (SELECT 'r' FROM t1 UNION ALL SELECT 'j');
|
||||||
|
a
|
||||||
|
j
|
||||||
|
r
|
||||||
|
r
|
||||||
|
CREATE TABLE t2
|
||||||
|
SELECT a FROM t1 WHERE a IN (SELECT 'r' FROM t1 UNION ALL SELECT 'j');
|
||||||
|
SELECT * FROM t2;
|
||||||
|
a
|
||||||
|
j
|
||||||
|
r
|
||||||
|
r
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY);
|
||||||
|
CREATE TABLE t2 (a INT PRIMARY KEY);
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
SELECT a, SUM(a) FROM t2 UNION ALL SELECT a, MIN(a) FROM t1 ;
|
||||||
|
a SUM(a)
|
||||||
|
1 1
|
||||||
|
NULL NULL
|
||||||
|
SELECT FOUND_ROWS();
|
||||||
|
FOUND_ROWS()
|
||||||
|
2
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
# Bug #17669551 CRASH/ASSERT AT SELECT_CREATE::PREPARE2 AT
|
||||||
|
# SQL_INSERT.CC
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
CREATE TABLE t2 SELECT a, a FROM t1 UNION ALL SELECT a, a FROM t1;
|
||||||
|
ERROR 42S21: Duplicate column name 'a'
|
||||||
|
DROP TABLE t1;
|
||||||
|
# Bug #17694956 RESULT DIFFERENCES IN UNION ALL QUERIES WITH LIMIT
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
(SELECT a FROM t1 ORDER BY a LIMIT 0) UNION ALL SELECT a FROM t1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
|
# Bug #17708480 FOUND_ROWS() VALUE DO NOT MATCH WITH UNION ALL QUERIES
|
||||||
|
CREATE TABLE t1 (a INT) ENGINE=MEMORY;
|
||||||
|
CREATE TABLE t2 (a INT) ENGINE=MEMORY;
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
SELECT COUNT(*) FROM (
|
||||||
|
SELECT * FROM t2 UNION ALL SELECT * FROM t1) q;
|
||||||
|
COUNT(*)
|
||||||
|
1
|
||||||
|
SELECT SQL_CALC_FOUND_ROWS * FROM t2 UNION ALL SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
SELECT FOUND_ROWS();
|
||||||
|
FOUND_ROWS()
|
||||||
|
1
|
||||||
|
SELECT COUNT(*) FROM (
|
||||||
|
SELECT * FROM t1 UNION ALL SELECT * FROM t2) q;
|
||||||
|
COUNT(*)
|
||||||
|
1
|
||||||
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION ALL SELECT * FROM t2;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
SELECT FOUND_ROWS();
|
||||||
|
FOUND_ROWS()
|
||||||
|
1
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
# End of WL1763 tests
|
||||||
|
@@ -140,16 +140,6 @@ key_len NULL
|
|||||||
ref NULL
|
ref NULL
|
||||||
rows NULL
|
rows NULL
|
||||||
Extra No tables used
|
Extra No tables used
|
||||||
id NULL
|
|
||||||
select_type UNION RESULT
|
|
||||||
table <union2,3>
|
|
||||||
type ALL
|
|
||||||
possible_keys NULL
|
|
||||||
key NULL
|
|
||||||
key_len NULL
|
|
||||||
ref NULL
|
|
||||||
rows NULL
|
|
||||||
Extra
|
|
||||||
#
|
#
|
||||||
# Demonstrate that the reported SELECT statement
|
# Demonstrate that the reported SELECT statement
|
||||||
# no longer produces warnings.
|
# no longer produces warnings.
|
||||||
@@ -344,16 +334,6 @@ key_len NULL
|
|||||||
ref NULL
|
ref NULL
|
||||||
rows NULL
|
rows NULL
|
||||||
Extra No tables used
|
Extra No tables used
|
||||||
id NULL
|
|
||||||
select_type UNION RESULT
|
|
||||||
table <union2,3>
|
|
||||||
type ALL
|
|
||||||
possible_keys NULL
|
|
||||||
key NULL
|
|
||||||
key_len NULL
|
|
||||||
ref NULL
|
|
||||||
rows NULL
|
|
||||||
Extra
|
|
||||||
# Lock the record.
|
# Lock the record.
|
||||||
select 1 from t1 natural join (select 3 as a, 2 as b union all
|
select 1 from t1 natural join (select 3 as a, 2 as b union all
|
||||||
select 3 as a, 1 as b) as t2 for update;
|
select 3 as a, 1 as b) as t2 for update;
|
||||||
|
@@ -158,11 +158,18 @@ a
|
|||||||
EXPLAIN EXTENDED
|
EXPLAIN EXTENDED
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 UNION t1 ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (match `a` against ('+abc' in boolean mode))
|
||||||
# Should not crash
|
# Should not crash
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
# Should not crash
|
# Should not crash
|
||||||
EXPLAIN EXTENDED
|
EXPLAIN EXTENDED
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
@@ -174,7 +181,7 @@ NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #-1
|
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #-1
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (select `a` from `test`.`t2` where (`test`.`t2`.`b` = 12))
|
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by <expr_cache><>((select `a` from `test`.`t2` where (`test`.`t2`.`b` = 12)))
|
||||||
# Should not crash
|
# Should not crash
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY (SELECT a FROM t2 WHERE b = 12);
|
ORDER BY (SELECT a FROM t2 WHERE b = 12);
|
||||||
|
@@ -129,7 +129,7 @@ group by
|
|||||||
a.text, b.id, b.betreff
|
a.text, b.id, b.betreff
|
||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -145,7 +145,7 @@ where
|
|||||||
match(c.beitrag) against ('+abc' in boolean mode)
|
match(c.beitrag) against ('+abc' in boolean mode)
|
||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -161,7 +161,7 @@ where
|
|||||||
match(c.beitrag) against ('+abc' in boolean mode)
|
match(c.beitrag) against ('+abc' in boolean mode)
|
||||||
order by
|
order by
|
||||||
match(betreff) against ('+abc' in boolean mode) desc;
|
match(betreff) against ('+abc' in boolean mode) desc;
|
||||||
ERROR 42000: Incorrect usage/placement of 'MATCH()'
|
text id betreff
|
||||||
(select b.id, b.betreff from t3 b) union
|
(select b.id, b.betreff from t3 b) union
|
||||||
(select b.id, b.betreff from t3 b)
|
(select b.id, b.betreff from t3 b)
|
||||||
order by match(betreff) against ('+abc' in boolean mode) desc;
|
order by match(betreff) against ('+abc' in boolean mode) desc;
|
||||||
|
@@ -177,13 +177,11 @@ SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12;
|
|||||||
|
|
||||||
|
|
||||||
--echo # Should not crash
|
--echo # Should not crash
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
|
||||||
EXPLAIN EXTENDED
|
EXPLAIN EXTENDED
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
|
|
||||||
--echo # Should not crash
|
--echo # Should not crash
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
|
|
||||||
|
@@ -93,7 +93,7 @@ CREATE TABLE t3 (
|
|||||||
FULLTEXT KEY betreff (betreff)
|
FULLTEXT KEY betreff (betreff)
|
||||||
) ENGINE = InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ;
|
) ENGINE = InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ;
|
||||||
|
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
--error ER_TABLENAME_NOT_ALLOWED_HERE
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -113,7 +113,7 @@ group by
|
|||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
|
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
--error ER_TABLENAME_NOT_ALLOWED_HERE
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -130,7 +130,6 @@ where
|
|||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
|
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
|
@@ -80,7 +80,7 @@ CREATE TABLE t3 (
|
|||||||
FULLTEXT KEY betreff (betreff)
|
FULLTEXT KEY betreff (betreff)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ;
|
||||||
|
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
--error ER_TABLENAME_NOT_ALLOWED_HERE
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -100,7 +100,7 @@ group by
|
|||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
|
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
--error ER_TABLENAME_NOT_ALLOWED_HERE
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
@@ -117,7 +117,6 @@ where
|
|||||||
order by
|
order by
|
||||||
match(b.betreff) against ('+abc' in boolean mode) desc;
|
match(b.betreff) against ('+abc' in boolean mode) desc;
|
||||||
|
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
|
||||||
select a.text, b.id, b.betreff
|
select a.text, b.id, b.betreff
|
||||||
from
|
from
|
||||||
t2 a inner join t3 b on a.id = b.forum inner join
|
t2 a inner join t3 b on a.id = b.forum inner join
|
||||||
|
@@ -569,8 +569,10 @@ drop table t1, t2;
|
|||||||
create table t1 (a float);
|
create table t1 (a float);
|
||||||
-- error ER_NOT_SUPPORTED_YET
|
-- error ER_NOT_SUPPORTED_YET
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
select 10.5 IN (SELECT * from t1 LIMIT 1);
|
||||||
-- error ER_NOT_SUPPORTED_YET
|
-- error ER_WRONG_USAGE
|
||||||
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
|
||||||
|
-- error ER_NOT_SUPPORTED_YET
|
||||||
|
select 10.5 IN (SELECT * from t1 UNION SELECT 1.5 LIMIT 1);
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
|
@@ -216,14 +216,12 @@ select found_rows();
|
|||||||
select found_rows();
|
select found_rows();
|
||||||
(SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1);
|
(SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1);
|
||||||
select found_rows();
|
select found_rows();
|
||||||
# This used to work in 4.0 but not anymore in 4.1
|
|
||||||
--error 1064
|
|
||||||
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1;
|
(SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1;
|
||||||
#select found_rows();
|
select found_rows();
|
||||||
|
|
||||||
# In these case found_rows() should work
|
# In these case found_rows() should work
|
||||||
|
--error ER_WRONG_USAGE
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2;
|
||||||
select found_rows();
|
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2;
|
||||||
select found_rows();
|
select found_rows();
|
||||||
|
|
||||||
@@ -232,16 +230,16 @@ SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2;
|
|||||||
select found_rows();
|
select found_rows();
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100;
|
||||||
select found_rows();
|
select found_rows();
|
||||||
|
--error ER_WRONG_USAGE
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 100 UNION SELECT * FROM t2;
|
||||||
select found_rows();
|
--error ER_WRONG_USAGE
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2;
|
||||||
select found_rows();
|
--error ER_WRONG_USAGE
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2 LIMIT 2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION SELECT * FROM t2 LIMIT 2;
|
||||||
select found_rows();
|
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2,2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2,2;
|
||||||
select found_rows();
|
select found_rows();
|
||||||
|
--error ER_WRONG_USAGE
|
||||||
SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2 UNION SELECT * FROM t2;
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 limit 2,2 UNION SELECT * FROM t2;
|
||||||
select found_rows();
|
|
||||||
|
|
||||||
# Test some limits with ORDER BY
|
# Test some limits with ORDER BY
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
|
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
|
||||||
@@ -255,7 +253,7 @@ create temporary table t1 select a from t1 union select a from t2;
|
|||||||
drop temporary table t1;
|
drop temporary table t1;
|
||||||
--error ER_TABLE_EXISTS_ERROR
|
--error ER_TABLE_EXISTS_ERROR
|
||||||
create table t1 select a from t1 union select a from t2;
|
create table t1 select a from t1 union select a from t2;
|
||||||
--error 1054
|
--error ER_TABLENAME_NOT_ALLOWED_HERE
|
||||||
select a from t1 union select a from t2 order by t2.a;
|
select a from t1 union select a from t2 order by t2.a;
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
@@ -723,12 +721,12 @@ drop table t1;
|
|||||||
# Enum merging test
|
# Enum merging test
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
a ENUM('<EFBFBD>','<EFBFBD>','<EFBFBD>') character set utf8 not null default '<EFBFBD>',
|
a ENUM('ä','ö','ü') character set utf8 not null default 'ü',
|
||||||
b ENUM("one", "two") character set utf8,
|
b ENUM("one", "two") character set utf8,
|
||||||
c ENUM("one", "two")
|
c ENUM("one", "two")
|
||||||
);
|
);
|
||||||
show create table t1;
|
show create table t1;
|
||||||
insert into t1 values ('<EFBFBD>', 'one', 'one'), ('<EFBFBD>', 'two', 'one'), ('<EFBFBD>', NULL, NULL);
|
insert into t1 values ('ä', 'one', 'one'), ('ö', 'two', 'one'), ('ü', NULL, NULL);
|
||||||
create table t2 select NULL union select a from t1;
|
create table t2 select NULL union select a from t1;
|
||||||
show columns from t2;
|
show columns from t2;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
@@ -1086,13 +1084,11 @@ SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12;
|
|||||||
|
|
||||||
|
|
||||||
--echo # Should not crash
|
--echo # Should not crash
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
|
||||||
EXPLAIN EXTENDED
|
EXPLAIN EXTENDED
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
|
|
||||||
--echo # Should not crash
|
--echo # Should not crash
|
||||||
--error ER_CANT_USE_OPTION_HERE
|
|
||||||
SELECT * FROM t1 UNION SELECT * FROM t1
|
SELECT * FROM t1 UNION SELECT * FROM t1
|
||||||
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
|
||||||
|
|
||||||
@@ -1300,3 +1296,94 @@ create table t1 (a int);
|
|||||||
insert t1 values (1),(2),(3),(1);
|
insert t1 values (1),(2),(3),(1);
|
||||||
explain select 1 from dual where exists (select max(a) from t1 group by a union select a+2 from t1);
|
explain select 1 from dual where exists (select max(a) from t1 group by a union select a+2 from t1);
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # WL#1763 Avoid creating temporary table in UNION ALL
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
EXPLAIN SELECT 1 UNION ALL SELECT 1 LIMIT 1 OFFSET 1;
|
||||||
|
|
||||||
|
--echo # Bug #17579498 CHANGES IN DATATYPE OF THE RESULT QUERY IN UNION.
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a TIME);
|
||||||
|
CREATE TABLE t2 (b DATETIME);
|
||||||
|
|
||||||
|
CREATE TABLE t3
|
||||||
|
SELECT a FROM t1 UNION ALL SELECT b FROM t2;
|
||||||
|
|
||||||
|
SELECT column_name, column_type
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE TABLE_NAME='t3';
|
||||||
|
|
||||||
|
DROP TABLE t1, t2, t3;
|
||||||
|
|
||||||
|
--echo # Bug #17602922 RESULT DIFFERENCES IN UNION QUERIES WITH IN
|
||||||
|
--echo # (SUBQUERY-UNION ALL)
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1));
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
INSERT INTO t1 VALUES ('j');
|
||||||
|
INSERT INTO t1 VALUES ('k');
|
||||||
|
INSERT INTO t1 VALUES ('r');
|
||||||
|
INSERT INTO t1 VALUES ('r');
|
||||||
|
INSERT INTO t1 VALUES ('h');
|
||||||
|
|
||||||
|
SELECT a FROM t1 WHERE a IN (SELECT 'r' FROM t1 UNION ALL SELECT 'j');
|
||||||
|
|
||||||
|
CREATE TABLE t2
|
||||||
|
SELECT a FROM t1 WHERE a IN (SELECT 'r' FROM t1 UNION ALL SELECT 'j');
|
||||||
|
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY);
|
||||||
|
CREATE TABLE t2 (a INT PRIMARY KEY);
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
|
||||||
|
SELECT a, SUM(a) FROM t2 UNION ALL SELECT a, MIN(a) FROM t1 ;
|
||||||
|
|
||||||
|
SELECT FOUND_ROWS();
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo # Bug #17669551 CRASH/ASSERT AT SELECT_CREATE::PREPARE2 AT
|
||||||
|
--echo # SQL_INSERT.CC
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
|
||||||
|
--error ER_DUP_FIELDNAME
|
||||||
|
CREATE TABLE t2 SELECT a, a FROM t1 UNION ALL SELECT a, a FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo # Bug #17694956 RESULT DIFFERENCES IN UNION ALL QUERIES WITH LIMIT
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
|
||||||
|
(SELECT a FROM t1 ORDER BY a LIMIT 0) UNION ALL SELECT a FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo # Bug #17708480 FOUND_ROWS() VALUE DO NOT MATCH WITH UNION ALL QUERIES
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT) ENGINE=MEMORY;
|
||||||
|
CREATE TABLE t2 (a INT) ENGINE=MEMORY;
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
|
||||||
|
SELECT COUNT(*) FROM (
|
||||||
|
SELECT * FROM t2 UNION ALL SELECT * FROM t1) q;
|
||||||
|
SELECT SQL_CALC_FOUND_ROWS * FROM t2 UNION ALL SELECT * FROM t1;
|
||||||
|
SELECT FOUND_ROWS();
|
||||||
|
|
||||||
|
SELECT COUNT(*) FROM (
|
||||||
|
SELECT * FROM t1 UNION ALL SELECT * FROM t2) q;
|
||||||
|
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION ALL SELECT * FROM t2;
|
||||||
|
SELECT FOUND_ROWS();
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo # End of WL1763 tests
|
||||||
|
|
||||||
|
@@ -1430,7 +1430,7 @@ void Item_exists_subselect::fix_length_and_dec()
|
|||||||
We need only 1 row to determine existence (i.e. any EXISTS that is not
|
We need only 1 row to determine existence (i.e. any EXISTS that is not
|
||||||
an IN always requires LIMIT 1)
|
an IN always requires LIMIT 1)
|
||||||
*/
|
*/
|
||||||
thd->change_item_tree(&unit->global_parameters->select_limit,
|
thd->change_item_tree(&unit->global_parameters()->select_limit,
|
||||||
new Item_int((int32) 1));
|
new Item_int((int32) 1));
|
||||||
DBUG_PRINT("info", ("Set limit to 1"));
|
DBUG_PRINT("info", ("Set limit to 1"));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@@ -2540,7 +2540,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
|
|||||||
select_lex->having->top_level_item();
|
select_lex->having->top_level_item();
|
||||||
join_arg->having= select_lex->having;
|
join_arg->having= select_lex->having;
|
||||||
}
|
}
|
||||||
join_arg->thd->change_item_tree(&unit->global_parameters->select_limit,
|
join_arg->thd->change_item_tree(&unit->global_parameters()->select_limit,
|
||||||
new Item_int((int32) 1));
|
new Item_int((int32) 1));
|
||||||
unit->select_limit_cnt= 1;
|
unit->select_limit_cnt= 1;
|
||||||
|
|
||||||
@@ -3593,7 +3593,7 @@ int subselect_single_select_engine::exec()
|
|||||||
{
|
{
|
||||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||||
|
|
||||||
unit->set_limit(unit->global_parameters);
|
unit->set_limit(unit->global_parameters());
|
||||||
if (join->optimize())
|
if (join->optimize())
|
||||||
{
|
{
|
||||||
thd->where= save_where;
|
thd->where= save_where;
|
||||||
@@ -4310,7 +4310,7 @@ subselect_single_select_engine::change_result(Item_subselect *si,
|
|||||||
that would not require a lot of extra code that would be harder to manage
|
that would not require a lot of extra code that would be harder to manage
|
||||||
than the current code.
|
than the current code.
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(select_lex->join->change_result(res));
|
DBUG_RETURN(select_lex->join->change_result(res, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4820,7 +4820,7 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
/* Let our engine reuse this query plan for materialization. */
|
/* Let our engine reuse this query plan for materialization. */
|
||||||
materialize_join= materialize_engine->join;
|
materialize_join= materialize_engine->join;
|
||||||
materialize_join->change_result(result);
|
materialize_join->change_result(result, NULL);
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
@@ -5224,7 +5224,7 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
|||||||
if (!(new_sink= new select_value_catcher(subq_pred)))
|
if (!(new_sink= new select_value_catcher(subq_pred)))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
|
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
|
||||||
engine->select_lex->join->change_result(new_sink) ||
|
engine->select_lex->join->change_result(new_sink, NULL) ||
|
||||||
engine->exec())
|
engine->exec())
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
@@ -5576,8 +5576,8 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
|
|||||||
Item_in_subselect::test_limit). However, once we allow this, here
|
Item_in_subselect::test_limit). However, once we allow this, here
|
||||||
we should set the correct limit if given in the query.
|
we should set the correct limit if given in the query.
|
||||||
*/
|
*/
|
||||||
in_subs->unit->global_parameters->select_limit= NULL;
|
in_subs->unit->global_parameters()->select_limit= NULL;
|
||||||
in_subs->unit->set_limit(unit->global_parameters);
|
in_subs->unit->set_limit(unit->global_parameters());
|
||||||
/*
|
/*
|
||||||
Set the limit of this JOIN object as well, because normally its being
|
Set the limit of this JOIN object as well, because normally its being
|
||||||
set in the beginning of JOIN::optimize, which was already done.
|
set in the beginning of JOIN::optimize, which was already done.
|
||||||
|
124
sql/sql_class.h
124
sql/sql_class.h
@@ -3914,6 +3914,23 @@ protected:
|
|||||||
public:
|
public:
|
||||||
select_result();
|
select_result();
|
||||||
virtual ~select_result() {};
|
virtual ~select_result() {};
|
||||||
|
/**
|
||||||
|
Change wrapped select_result.
|
||||||
|
|
||||||
|
Replace the wrapped result object with new_result and call
|
||||||
|
prepare() and prepare2() on new_result.
|
||||||
|
|
||||||
|
This base class implementation doesn't wrap other select_results.
|
||||||
|
|
||||||
|
@param new_result The new result object to wrap around
|
||||||
|
|
||||||
|
@retval false Success
|
||||||
|
@retval true Error
|
||||||
|
*/
|
||||||
|
virtual bool change_result(select_result *new_result)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||||
{
|
{
|
||||||
unit= u;
|
unit= u;
|
||||||
@@ -4321,9 +4338,19 @@ public:
|
|||||||
|
|
||||||
select_union() :write_err(0), table(0), records(0) { tmp_table_param.init(); }
|
select_union() :write_err(0), table(0), records(0) { tmp_table_param.init(); }
|
||||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||||
|
/**
|
||||||
|
Do prepare() and prepare2() if they have been postponed until
|
||||||
|
column type information is computed (used by select_union_direct).
|
||||||
|
|
||||||
|
@param types Column types
|
||||||
|
|
||||||
|
@return false on success, true on failure
|
||||||
|
*/
|
||||||
|
virtual bool postponed_prepare(List<Item> &types)
|
||||||
|
{ return false; }
|
||||||
int send_data(List<Item> &items);
|
int send_data(List<Item> &items);
|
||||||
bool send_eof();
|
bool send_eof();
|
||||||
bool flush();
|
virtual bool flush();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
||||||
bool is_distinct, ulonglong options,
|
bool is_distinct, ulonglong options,
|
||||||
@@ -4334,6 +4361,101 @@ public:
|
|||||||
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
|
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
UNION result that is passed directly to the receiving select_result
|
||||||
|
without filling a temporary table.
|
||||||
|
|
||||||
|
Function calls are forwarded to the wrapped select_result, but some
|
||||||
|
functions are expected to be called only once for each query, so
|
||||||
|
they are only executed for the first SELECT in the union (execept
|
||||||
|
for send_eof(), which is executed only for the last SELECT).
|
||||||
|
|
||||||
|
This select_result is used when a UNION is not DISTINCT and doesn't
|
||||||
|
have a global ORDER BY clause. @see st_select_lex_unit::prepare().
|
||||||
|
*/
|
||||||
|
|
||||||
|
class select_union_direct :public select_union
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/* Result object that receives all rows */
|
||||||
|
select_result *result;
|
||||||
|
/* The last SELECT_LEX of the union */
|
||||||
|
SELECT_LEX *last_select_lex;
|
||||||
|
|
||||||
|
/* Wrapped result has received metadata */
|
||||||
|
bool done_send_result_set_metadata;
|
||||||
|
/* Wrapped result has initialized tables */
|
||||||
|
bool done_initialize_tables;
|
||||||
|
|
||||||
|
/* Accumulated limit_found_rows */
|
||||||
|
ulonglong limit_found_rows;
|
||||||
|
|
||||||
|
/* Number of rows offset */
|
||||||
|
ha_rows offset;
|
||||||
|
/* Number of rows limit + offset, @see select_union_direct::send_data() */
|
||||||
|
ha_rows limit;
|
||||||
|
|
||||||
|
public:
|
||||||
|
select_union_direct(select_result *result, SELECT_LEX *last_select_lex)
|
||||||
|
:result(result), last_select_lex(last_select_lex),
|
||||||
|
done_send_result_set_metadata(false), done_initialize_tables(false),
|
||||||
|
limit_found_rows(0)
|
||||||
|
{}
|
||||||
|
bool change_result(select_result *new_result);
|
||||||
|
uint field_count(List<Item> &fields) const
|
||||||
|
{
|
||||||
|
// Only called for top-level select_results, usually select_send
|
||||||
|
DBUG_ASSERT(false); /* purecov: inspected */
|
||||||
|
return 0; /* purecov: inspected */
|
||||||
|
}
|
||||||
|
bool postponed_prepare(List<Item> &types);
|
||||||
|
bool send_result_set_metadata(List<Item> &list, uint flags);
|
||||||
|
int send_data(List<Item> &items);
|
||||||
|
bool initialize_tables (JOIN *join= NULL);
|
||||||
|
bool send_eof();
|
||||||
|
bool flush() { return false; }
|
||||||
|
bool check_simple_select() const
|
||||||
|
{
|
||||||
|
/* Only called for top-level select_results, usually select_send */
|
||||||
|
DBUG_ASSERT(false); /* purecov: inspected */
|
||||||
|
return false; /* purecov: inspected */
|
||||||
|
}
|
||||||
|
void abort_result_set()
|
||||||
|
{
|
||||||
|
result->abort_result_set(); /* purecov: inspected */
|
||||||
|
}
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Only called for top-level select_results, usually select_send,
|
||||||
|
and for the results of subquery engines
|
||||||
|
(select_<something>_subselect).
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(false); /* purecov: inspected */
|
||||||
|
}
|
||||||
|
void set_thd(THD *thd_arg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Only called for top-level select_results, usually select_send,
|
||||||
|
and for the results of subquery engines
|
||||||
|
(select_<something>_subselect).
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(false); /* purecov: inspected */
|
||||||
|
}
|
||||||
|
void reset_offset_limit_cnt()
|
||||||
|
{
|
||||||
|
// EXPLAIN should never output to a select_union_direct
|
||||||
|
DBUG_ASSERT(false); /* purecov: inspected */
|
||||||
|
}
|
||||||
|
void begin_dataset()
|
||||||
|
{
|
||||||
|
// Only called for sp_cursor::Select_fetch_into_spvars
|
||||||
|
DBUG_ASSERT(false); /* purecov: inspected */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Base subselect interface class */
|
/* Base subselect interface class */
|
||||||
class select_subselect :public select_result_interceptor
|
class select_subselect :public select_result_interceptor
|
||||||
{
|
{
|
||||||
|
@@ -788,7 +788,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
if (!derived->is_merged_derived())
|
if (!derived->is_merged_derived())
|
||||||
{
|
{
|
||||||
JOIN *join= first_select->join;
|
JOIN *join= first_select->join;
|
||||||
unit->set_limit(unit->global_parameters);
|
unit->set_limit(unit->global_parameters());
|
||||||
unit->optimized= TRUE;
|
unit->optimized= TRUE;
|
||||||
if ((res= join->optimize()))
|
if ((res= join->optimize()))
|
||||||
goto err;
|
goto err;
|
||||||
@@ -905,7 +905,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unit->set_limit(unit->global_parameters);
|
unit->set_limit(unit->global_parameters());
|
||||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||||
first_select->options&= ~OPTION_FOUND_ROWS;
|
first_select->options&= ~OPTION_FOUND_ROWS;
|
||||||
|
|
||||||
|
@@ -229,6 +229,9 @@ int Explain_union::print_explain(Explain_query *query,
|
|||||||
sel->print_explain(query, output, explain_flags, is_analyze);
|
sel->print_explain(query, output, explain_flags, is_analyze);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!using_tmp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Print a line with "UNION RESULT" */
|
/* Print a line with "UNION RESULT" */
|
||||||
List<Item> item_list;
|
List<Item> item_list;
|
||||||
Item *item_null= new Item_null();
|
Item *item_null= new Item_null();
|
||||||
|
@@ -225,6 +225,7 @@ public:
|
|||||||
|
|
||||||
const char *fake_select_type;
|
const char *fake_select_type;
|
||||||
bool using_filesort;
|
bool using_filesort;
|
||||||
|
bool using_tmp;
|
||||||
|
|
||||||
Table_access_tracker *get_fake_select_lex_tracker()
|
Table_access_tracker *get_fake_select_lex_tracker()
|
||||||
{
|
{
|
||||||
|
195
sql/sql_lex.cc
195
sql/sql_lex.cc
@@ -470,7 +470,7 @@ void lex_start(THD *thd)
|
|||||||
lex->unit.next= lex->unit.master=
|
lex->unit.next= lex->unit.master=
|
||||||
lex->unit.link_next= lex->unit.return_to= 0;
|
lex->unit.link_next= lex->unit.return_to= 0;
|
||||||
lex->unit.prev= lex->unit.link_prev= 0;
|
lex->unit.prev= lex->unit.link_prev= 0;
|
||||||
lex->unit.slave= lex->unit.global_parameters= lex->current_select=
|
lex->unit.slave= lex->current_select=
|
||||||
lex->all_selects_list= &lex->select_lex;
|
lex->all_selects_list= &lex->select_lex;
|
||||||
lex->select_lex.master= &lex->unit;
|
lex->select_lex.master= &lex->unit;
|
||||||
lex->select_lex.prev= &lex->unit.slave;
|
lex->select_lex.prev= &lex->unit.slave;
|
||||||
@@ -1819,7 +1819,6 @@ void st_select_lex_unit::init_query()
|
|||||||
{
|
{
|
||||||
st_select_lex_node::init_query();
|
st_select_lex_node::init_query();
|
||||||
linkage= GLOBAL_OPTIONS_TYPE;
|
linkage= GLOBAL_OPTIONS_TYPE;
|
||||||
global_parameters= first_select();
|
|
||||||
select_limit_cnt= HA_POS_ERROR;
|
select_limit_cnt= HA_POS_ERROR;
|
||||||
offset_limit_cnt= 0;
|
offset_limit_cnt= 0;
|
||||||
union_distinct= 0;
|
union_distinct= 0;
|
||||||
@@ -1828,6 +1827,7 @@ void st_select_lex_unit::init_query()
|
|||||||
union_result= 0;
|
union_result= 0;
|
||||||
table= 0;
|
table= 0;
|
||||||
fake_select_lex= 0;
|
fake_select_lex= 0;
|
||||||
|
saved_fake_select_lex= 0;
|
||||||
cleaned= 0;
|
cleaned= 0;
|
||||||
item_list.empty();
|
item_list.empty();
|
||||||
describe= 0;
|
describe= 0;
|
||||||
@@ -1901,7 +1901,6 @@ void st_select_lex::init_select()
|
|||||||
in_sum_expr= with_wild= 0;
|
in_sum_expr= with_wild= 0;
|
||||||
options= 0;
|
options= 0;
|
||||||
sql_cache= SQL_CACHE_UNSPECIFIED;
|
sql_cache= SQL_CACHE_UNSPECIFIED;
|
||||||
braces= 0;
|
|
||||||
interval_list.empty();
|
interval_list.empty();
|
||||||
ftfunc_list_alloc.empty();
|
ftfunc_list_alloc.empty();
|
||||||
inner_sum_func_list= 0;
|
inner_sum_func_list= 0;
|
||||||
@@ -2214,6 +2213,7 @@ bool st_select_lex::test_limit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
st_select_lex_unit* st_select_lex_unit::master_unit()
|
st_select_lex_unit* st_select_lex_unit::master_unit()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@@ -2226,6 +2226,75 @@ st_select_lex* st_select_lex_unit::outer_select()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ha_rows st_select_lex::get_offset()
|
||||||
|
{
|
||||||
|
ulonglong val= 0;
|
||||||
|
|
||||||
|
if (offset_limit)
|
||||||
|
{
|
||||||
|
// see comment for st_select_lex::get_limit()
|
||||||
|
bool fix_fields_successful= true;
|
||||||
|
if (!offset_limit->fixed)
|
||||||
|
{
|
||||||
|
fix_fields_successful= !offset_limit->fix_fields(master_unit()->thd,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
DBUG_ASSERT(fix_fields_successful);
|
||||||
|
}
|
||||||
|
val= fix_fields_successful ? offset_limit->val_uint() : HA_POS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ha_rows)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ha_rows st_select_lex::get_limit()
|
||||||
|
{
|
||||||
|
ulonglong val= HA_POS_ERROR;
|
||||||
|
|
||||||
|
if (select_limit)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
fix_fields() has not been called for select_limit. That's due to the
|
||||||
|
historical reasons -- this item could be only of type Item_int, and
|
||||||
|
Item_int does not require fix_fields(). Thus, fix_fields() was never
|
||||||
|
called for select_limit.
|
||||||
|
|
||||||
|
Some time ago, Item_splocal was also allowed for LIMIT / OFFSET clauses.
|
||||||
|
However, the fix_fields() behavior was not updated, which led to a crash
|
||||||
|
in some cases.
|
||||||
|
|
||||||
|
There is no single place where to call fix_fields() for LIMIT / OFFSET
|
||||||
|
items during the fix-fields-phase. Thus, for the sake of readability,
|
||||||
|
it was decided to do it here, on the evaluation phase (which is a
|
||||||
|
violation of design, but we chose the lesser of two evils).
|
||||||
|
|
||||||
|
We can call fix_fields() here, because select_limit can be of two
|
||||||
|
types only: Item_int and Item_splocal. Item_int::fix_fields() is trivial,
|
||||||
|
and Item_splocal::fix_fields() (or rather Item_sp_variable::fix_fields())
|
||||||
|
has the following properties:
|
||||||
|
1) it does not affect other items;
|
||||||
|
2) it does not fail.
|
||||||
|
|
||||||
|
Nevertheless DBUG_ASSERT was added to catch future changes in
|
||||||
|
fix_fields() implementation. Also added runtime check against a result
|
||||||
|
of fix_fields() in order to handle error condition in non-debug build.
|
||||||
|
*/
|
||||||
|
bool fix_fields_successful= true;
|
||||||
|
if (!select_limit->fixed)
|
||||||
|
{
|
||||||
|
fix_fields_successful= !select_limit->fix_fields(master_unit()->thd,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
DBUG_ASSERT(fix_fields_successful);
|
||||||
|
}
|
||||||
|
val= fix_fields_successful ? select_limit->val_uint() : HA_POS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ha_rows)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
|
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
|
||||||
{
|
{
|
||||||
return add_to_list(thd, order_list, item, asc);
|
return add_to_list(thd, order_list, item, asc);
|
||||||
@@ -2237,6 +2306,7 @@ bool st_select_lex::add_gorder_to_list(THD *thd, Item *item, bool asc)
|
|||||||
return add_to_list(thd, gorder_list, item, asc);
|
return add_to_list(thd, gorder_list, item, asc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
|
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("st_select_lex::add_item_to_list");
|
DBUG_ENTER("st_select_lex::add_item_to_list");
|
||||||
@@ -2364,7 +2434,7 @@ void st_select_lex_unit::print(String *str, enum_query_type query_type)
|
|||||||
if (sl->braces)
|
if (sl->braces)
|
||||||
str->append(')');
|
str->append(')');
|
||||||
}
|
}
|
||||||
if (fake_select_lex == global_parameters)
|
if (fake_select_lex)
|
||||||
{
|
{
|
||||||
if (fake_select_lex->order_list.elements)
|
if (fake_select_lex->order_list.elements)
|
||||||
{
|
{
|
||||||
@@ -2375,6 +2445,8 @@ void st_select_lex_unit::print(String *str, enum_query_type query_type)
|
|||||||
}
|
}
|
||||||
fake_select_lex->print_limit(thd, str, query_type);
|
fake_select_lex->print_limit(thd, str, query_type);
|
||||||
}
|
}
|
||||||
|
else if (saved_fake_select_lex)
|
||||||
|
saved_fake_select_lex->print_limit(thd, str, query_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2425,7 +2497,7 @@ void st_select_lex::print_limit(THD *thd,
|
|||||||
SELECT_LEX_UNIT *unit= master_unit();
|
SELECT_LEX_UNIT *unit= master_unit();
|
||||||
Item_subselect *item= unit->item;
|
Item_subselect *item= unit->item;
|
||||||
|
|
||||||
if (item && unit->global_parameters == this)
|
if (item && unit->global_parameters() == this)
|
||||||
{
|
{
|
||||||
Item_subselect::subs_type subs_type= item->substype();
|
Item_subselect::subs_type subs_type= item->substype();
|
||||||
if (subs_type == Item_subselect::EXISTS_SUBS ||
|
if (subs_type == Item_subselect::EXISTS_SUBS ||
|
||||||
@@ -2817,98 +2889,40 @@ LEX::copy_db_to(char **p_db, size_t *p_db_length) const
|
|||||||
return thd->copy_db_to(p_db, p_db_length);
|
return thd->copy_db_to(p_db, p_db_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
initialize limit counters
|
Initialize offset and limit counters.
|
||||||
|
|
||||||
SYNOPSIS
|
@param sl SELECT_LEX to get offset and limit from.
|
||||||
st_select_lex_unit::set_limit()
|
|
||||||
values - SELECT_LEX with initial values for counters
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void st_select_lex_unit::set_limit(st_select_lex *sl)
|
void st_select_lex_unit::set_limit(st_select_lex *sl)
|
||||||
{
|
{
|
||||||
ha_rows select_limit_val;
|
DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());
|
||||||
ulonglong val;
|
|
||||||
|
|
||||||
DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
|
offset_limit_cnt= sl->get_offset();
|
||||||
if (sl->select_limit)
|
select_limit_cnt= sl->get_limit();
|
||||||
{
|
if (select_limit_cnt + offset_limit_cnt >= select_limit_cnt)
|
||||||
Item *item = sl->select_limit;
|
select_limit_cnt+= offset_limit_cnt;
|
||||||
/*
|
|
||||||
fix_fields() has not been called for sl->select_limit. That's due to the
|
|
||||||
historical reasons -- this item could be only of type Item_int, and
|
|
||||||
Item_int does not require fix_fields(). Thus, fix_fields() was never
|
|
||||||
called for sl->select_limit.
|
|
||||||
|
|
||||||
Some time ago, Item_splocal was also allowed for LIMIT / OFFSET clauses.
|
|
||||||
However, the fix_fields() behavior was not updated, which led to a crash
|
|
||||||
in some cases.
|
|
||||||
|
|
||||||
There is no single place where to call fix_fields() for LIMIT / OFFSET
|
|
||||||
items during the fix-fields-phase. Thus, for the sake of readability,
|
|
||||||
it was decided to do it here, on the evaluation phase (which is a
|
|
||||||
violation of design, but we chose the lesser of two evils).
|
|
||||||
|
|
||||||
We can call fix_fields() here, because sl->select_limit can be of two
|
|
||||||
types only: Item_int and Item_splocal. Item_int::fix_fields() is trivial,
|
|
||||||
and Item_splocal::fix_fields() (or rather Item_sp_variable::fix_fields())
|
|
||||||
has the following specific:
|
|
||||||
1) it does not affect other items;
|
|
||||||
2) it does not fail.
|
|
||||||
|
|
||||||
Nevertheless DBUG_ASSERT was added to catch future changes in
|
|
||||||
fix_fields() implementation. Also added runtime check against a result
|
|
||||||
of fix_fields() in order to handle error condition in non-debug build.
|
|
||||||
*/
|
|
||||||
bool fix_fields_successful= true;
|
|
||||||
if (!item->fixed)
|
|
||||||
{
|
|
||||||
fix_fields_successful= !item->fix_fields(thd, NULL);
|
|
||||||
|
|
||||||
DBUG_ASSERT(fix_fields_successful);
|
|
||||||
}
|
|
||||||
val= fix_fields_successful ? item->val_uint() : HA_POS_ERROR;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
val= HA_POS_ERROR;
|
select_limit_cnt= HA_POS_ERROR;
|
||||||
|
|
||||||
select_limit_val= (ha_rows)val;
|
|
||||||
#ifndef BIG_TABLES
|
|
||||||
/*
|
|
||||||
Check for overflow : ha_rows can be smaller then ulonglong if
|
|
||||||
BIG_TABLES is off.
|
|
||||||
*/
|
|
||||||
if (val != (ulonglong)select_limit_val)
|
|
||||||
select_limit_val= HA_POS_ERROR;
|
|
||||||
#endif
|
|
||||||
if (sl->offset_limit)
|
|
||||||
{
|
|
||||||
Item *item = sl->offset_limit;
|
|
||||||
// see comment for sl->select_limit branch.
|
|
||||||
bool fix_fields_successful= true;
|
|
||||||
if (!item->fixed)
|
|
||||||
{
|
|
||||||
fix_fields_successful= !item->fix_fields(thd, NULL);
|
|
||||||
|
|
||||||
DBUG_ASSERT(fix_fields_successful);
|
|
||||||
}
|
|
||||||
val= fix_fields_successful ? item->val_uint() : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
val= 0;
|
|
||||||
|
|
||||||
offset_limit_cnt= (ha_rows)val;
|
|
||||||
#ifndef BIG_TABLES
|
|
||||||
/* Check for truncation. */
|
|
||||||
if (val != (ulonglong)offset_limit_cnt)
|
|
||||||
offset_limit_cnt= HA_POS_ERROR;
|
|
||||||
#endif
|
|
||||||
select_limit_cnt= select_limit_val + offset_limit_cnt;
|
|
||||||
if (select_limit_cnt < select_limit_val)
|
|
||||||
select_limit_cnt= HA_POS_ERROR; // no limit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Decide if a temporary table is needed for the UNION.
|
||||||
|
|
||||||
|
@retval true A temporary table is needed.
|
||||||
|
@retval false A temporary table is not needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool st_select_lex_unit::union_needs_tmp_table()
|
||||||
|
{
|
||||||
|
return union_distinct != NULL ||
|
||||||
|
global_parameters()->order_list.elements != 0 ||
|
||||||
|
thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
|
||||||
|
thd->lex->sql_command == SQLCOM_REPLACE_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Set the initial purpose of this TABLE_LIST object in the list of used
|
@brief Set the initial purpose of this TABLE_LIST object in the list of used
|
||||||
tables.
|
tables.
|
||||||
@@ -3496,7 +3510,7 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
|
|||||||
ulonglong save_options;
|
ulonglong save_options;
|
||||||
int res;
|
int res;
|
||||||
/* We need only 1 row to determine existence */
|
/* We need only 1 row to determine existence */
|
||||||
un->set_limit(un->global_parameters);
|
un->set_limit(un->global_parameters());
|
||||||
un->thd->lex->current_select= sl;
|
un->thd->lex->current_select= sl;
|
||||||
save_options= inner_join->select_options;
|
save_options= inner_join->select_options;
|
||||||
if (options & SELECT_DESCRIBE)
|
if (options & SELECT_DESCRIBE)
|
||||||
@@ -3896,7 +3910,7 @@ void SELECT_LEX::update_used_tables()
|
|||||||
}
|
}
|
||||||
for (ORDER *order= group_list.first; order; order= order->next)
|
for (ORDER *order= group_list.first; order; order= order->next)
|
||||||
(*order->item)->update_used_tables();
|
(*order->item)->update_used_tables();
|
||||||
if (!master_unit()->is_union() || master_unit()->global_parameters != this)
|
if (!master_unit()->is_union() || master_unit()->global_parameters() != this)
|
||||||
{
|
{
|
||||||
for (ORDER *order= order_list.first; order; order= order->next)
|
for (ORDER *order= order_list.first; order; order= order->next)
|
||||||
(*order->item)->update_used_tables();
|
(*order->item)->update_used_tables();
|
||||||
@@ -4244,7 +4258,8 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
|
|||||||
eu->add_select(sl->select_number);
|
eu->add_select(sl->select_number);
|
||||||
|
|
||||||
eu->fake_select_type= "UNION RESULT";
|
eu->fake_select_type= "UNION RESULT";
|
||||||
eu->using_filesort= MY_TEST(global_parameters->order_list.first);
|
eu->using_filesort= MY_TEST(global_parameters()->order_list.first);
|
||||||
|
eu->using_tmp= union_needs_tmp_table();
|
||||||
|
|
||||||
// Save the UNION node
|
// Save the UNION node
|
||||||
output->add_node(eu);
|
output->add_node(eu);
|
||||||
|
@@ -577,11 +577,28 @@ public:
|
|||||||
any SELECT of this unit execution
|
any SELECT of this unit execution
|
||||||
*/
|
*/
|
||||||
List<Item> types;
|
List<Item> types;
|
||||||
/*
|
/**
|
||||||
Pointer to 'last' select or pointer to unit where stored
|
Pointer to 'last' select, or pointer to select where we stored
|
||||||
global parameters for union
|
global parameters for union.
|
||||||
|
|
||||||
|
If this is a union of multiple selects, the parser puts the global
|
||||||
|
parameters in fake_select_lex. If the union doesn't use a
|
||||||
|
temporary table, st_select_lex_unit::prepare() nulls out
|
||||||
|
fake_select_lex, but saves a copy in saved_fake_select_lex in
|
||||||
|
order to preserve the global parameters.
|
||||||
|
|
||||||
|
If it is not a union, first_select() is the last select.
|
||||||
|
|
||||||
|
@return select containing the global parameters
|
||||||
*/
|
*/
|
||||||
st_select_lex *global_parameters;
|
inline st_select_lex *global_parameters()
|
||||||
|
{
|
||||||
|
if (fake_select_lex != NULL)
|
||||||
|
return fake_select_lex;
|
||||||
|
else if (saved_fake_select_lex != NULL)
|
||||||
|
return saved_fake_select_lex;
|
||||||
|
return first_select();
|
||||||
|
};
|
||||||
//node on wich we should return current_select pointer after parsing subquery
|
//node on wich we should return current_select pointer after parsing subquery
|
||||||
st_select_lex *return_to;
|
st_select_lex *return_to;
|
||||||
/* LIMIT clause runtime counters */
|
/* LIMIT clause runtime counters */
|
||||||
@@ -600,6 +617,11 @@ public:
|
|||||||
ORDER BY and LIMIT
|
ORDER BY and LIMIT
|
||||||
*/
|
*/
|
||||||
st_select_lex *fake_select_lex;
|
st_select_lex *fake_select_lex;
|
||||||
|
/**
|
||||||
|
SELECT_LEX that stores LIMIT and OFFSET for UNION ALL when no
|
||||||
|
fake_select_lex is used.
|
||||||
|
*/
|
||||||
|
st_select_lex *saved_fake_select_lex;
|
||||||
|
|
||||||
st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */
|
st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */
|
||||||
bool describe; /* union exec() called for EXPLAIN */
|
bool describe; /* union exec() called for EXPLAIN */
|
||||||
@@ -645,6 +667,7 @@ public:
|
|||||||
void set_limit(st_select_lex *values);
|
void set_limit(st_select_lex *values);
|
||||||
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
||||||
inline bool is_union ();
|
inline bool is_union ();
|
||||||
|
bool union_needs_tmp_table();
|
||||||
|
|
||||||
void set_unique_exclude();
|
void set_unique_exclude();
|
||||||
|
|
||||||
@@ -904,9 +927,26 @@ public:
|
|||||||
*/
|
*/
|
||||||
void cut_subtree() { slave= 0; }
|
void cut_subtree() { slave= 0; }
|
||||||
bool test_limit();
|
bool test_limit();
|
||||||
|
/**
|
||||||
|
Get offset for LIMIT.
|
||||||
|
|
||||||
|
Evaluate offset item if necessary.
|
||||||
|
|
||||||
|
@return Number of rows to skip.
|
||||||
|
*/
|
||||||
|
ha_rows get_offset();
|
||||||
|
/**
|
||||||
|
Get limit.
|
||||||
|
|
||||||
|
Evaluate limit item if necessary.
|
||||||
|
|
||||||
|
@return Limit of rows in result.
|
||||||
|
*/
|
||||||
|
ha_rows get_limit();
|
||||||
|
|
||||||
friend void lex_start(THD *thd);
|
friend void lex_start(THD *thd);
|
||||||
st_select_lex() : group_list_ptrs(NULL), n_sum_items(0), n_child_sum_items(0)
|
st_select_lex() : group_list_ptrs(NULL), braces(0),
|
||||||
|
n_sum_items(0), n_child_sum_items(0)
|
||||||
{}
|
{}
|
||||||
void make_empty_select()
|
void make_empty_select()
|
||||||
{
|
{
|
||||||
|
@@ -5592,7 +5592,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
|
|||||||
bool res;
|
bool res;
|
||||||
/* assign global limit variable if limit is not given */
|
/* assign global limit variable if limit is not given */
|
||||||
{
|
{
|
||||||
SELECT_LEX *param= lex->unit.global_parameters;
|
SELECT_LEX *param= lex->unit.global_parameters();
|
||||||
if (!param->explicit_limit)
|
if (!param->explicit_limit)
|
||||||
param->select_limit=
|
param->select_limit=
|
||||||
new Item_int((ulonglong) thd->variables.select_limit);
|
new Item_int((ulonglong) thd->variables.select_limit);
|
||||||
@@ -6675,7 +6675,6 @@ mysql_new_select(LEX *lex, bool move_down)
|
|||||||
unit->first_select()->context.outer_context;
|
unit->first_select()->context.outer_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
select_lex->master_unit()->global_parameters= select_lex;
|
|
||||||
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
|
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
|
||||||
lex->current_select= select_lex;
|
lex->current_select= select_lex;
|
||||||
/*
|
/*
|
||||||
@@ -7642,7 +7641,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
|
|||||||
fake_select_lex->context.outer_context=first_sl->context.outer_context;
|
fake_select_lex->context.outer_context=first_sl->context.outer_context;
|
||||||
/* allow item list resolving in fake select for ORDER BY */
|
/* allow item list resolving in fake select for ORDER BY */
|
||||||
fake_select_lex->context.resolve_in_select_list= TRUE;
|
fake_select_lex->context.resolve_in_select_list= TRUE;
|
||||||
fake_select_lex->context.select_lex= fake_select_lex;
|
fake_select_lex->context.select_lex= fake_select_lex;
|
||||||
|
|
||||||
if (!is_union())
|
if (!is_union())
|
||||||
{
|
{
|
||||||
@@ -7652,7 +7651,6 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
|
|||||||
(SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
|
(SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
|
||||||
just before the parser starts processing order_list
|
just before the parser starts processing order_list
|
||||||
*/
|
*/
|
||||||
global_parameters= fake_select_lex;
|
|
||||||
fake_select_lex->no_table_names_allowed= 1;
|
fake_select_lex->no_table_names_allowed= 1;
|
||||||
thd_arg->lex->current_select= fake_select_lex;
|
thd_arg->lex->current_select= fake_select_lex;
|
||||||
}
|
}
|
||||||
|
@@ -351,7 +351,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
SELECT_LEX_UNIT *unit= &lex->unit;
|
SELECT_LEX_UNIT *unit= &lex->unit;
|
||||||
unit->set_limit(unit->global_parameters);
|
unit->set_limit(unit->global_parameters());
|
||||||
/*
|
/*
|
||||||
'options' of mysql_select will be set in JOIN, as far as JOIN for
|
'options' of mysql_select will be set in JOIN, as far as JOIN for
|
||||||
every PS/SP execution new, we will not need reset this flag if
|
every PS/SP execution new, we will not need reset this flag if
|
||||||
@@ -792,7 +792,8 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
ref_pointer_array= *rref_pointer_array;
|
ref_pointer_array= *rref_pointer_array;
|
||||||
|
|
||||||
/* Resolve the ORDER BY that was skipped, then remove it. */
|
/* Resolve the ORDER BY that was skipped, then remove it. */
|
||||||
if (skip_order_by && select_lex != select_lex->master_unit()->global_parameters)
|
if (skip_order_by && select_lex !=
|
||||||
|
select_lex->master_unit()->global_parameters())
|
||||||
{
|
{
|
||||||
if (setup_order(thd, (*rref_pointer_array), tables_list, fields_list,
|
if (setup_order(thd, (*rref_pointer_array), tables_list, fields_list,
|
||||||
all_fields, select_lex->order_list.first))
|
all_fields, select_lex->order_list.first))
|
||||||
@@ -2481,13 +2482,6 @@ void JOIN::exec_inner()
|
|||||||
thd->set_examined_row_count(0);
|
thd->set_examined_row_count(0);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Don't reset the found rows count if there're no tables as
|
|
||||||
FOUND_ROWS() may be called. Never reset the examined row count here.
|
|
||||||
It must be accumulated from all join iterations of all join parts.
|
|
||||||
*/
|
|
||||||
if (table_count)
|
|
||||||
thd->limit_found_rows= 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Evaluate expensive constant conditions that were not evaluated during
|
Evaluate expensive constant conditions that were not evaluated during
|
||||||
@@ -3091,7 +3085,6 @@ void JOIN::exec_inner()
|
|||||||
*curr_fields_list),
|
*curr_fields_list),
|
||||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
||||||
error= do_select(curr_join, curr_fields_list, NULL, procedure);
|
error= do_select(curr_join, curr_fields_list, NULL, procedure);
|
||||||
thd->limit_found_rows= curr_join->send_records;
|
|
||||||
if (curr_join->order && curr_join->filesort_found_rows)
|
if (curr_join->order && curr_join->filesort_found_rows)
|
||||||
{
|
{
|
||||||
/* Use info provided by filesort. */
|
/* Use info provided by filesort. */
|
||||||
@@ -3257,7 +3250,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
|||||||
if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
|
if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
|
||||||
{
|
{
|
||||||
//here is EXPLAIN of subselect or derived table
|
//here is EXPLAIN of subselect or derived table
|
||||||
if (join->change_result(result))
|
if (join->change_result(result, NULL))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
@@ -12088,6 +12081,14 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
|
|||||||
if (having && having->val_int() == 0)
|
if (having && having->val_int() == 0)
|
||||||
send_row=0;
|
send_row=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update results for FOUND_ROWS */
|
||||||
|
if (!join->send_row_on_empty_set())
|
||||||
|
{
|
||||||
|
join->thd->set_examined_row_count(0);
|
||||||
|
join->thd->limit_found_rows= 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(result->send_result_set_metadata(fields,
|
if (!(result->send_result_set_metadata(fields,
|
||||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
|
||||||
{
|
{
|
||||||
@@ -12097,9 +12098,6 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
|
|||||||
if (!send_error)
|
if (!send_error)
|
||||||
result->send_eof(); // Should be safe
|
result->send_eof(); // Should be safe
|
||||||
}
|
}
|
||||||
/* Update results for FOUND_ROWS */
|
|
||||||
join->thd->limit_found_rows= 0;
|
|
||||||
join->thd->set_examined_row_count(0);
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17300,6 +17298,9 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
|||||||
if (error == NESTED_LOOP_QUERY_LIMIT)
|
if (error == NESTED_LOOP_QUERY_LIMIT)
|
||||||
error= NESTED_LOOP_OK; /* select_limit used */
|
error= NESTED_LOOP_OK; /* select_limit used */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
join->thd->limit_found_rows= join->send_records;
|
||||||
|
|
||||||
if (error == NESTED_LOOP_NO_MORE_ROWS || join->thd->killed == ABORT_QUERY)
|
if (error == NESTED_LOOP_NO_MORE_ROWS || join->thd->killed == ABORT_QUERY)
|
||||||
error= NESTED_LOOP_OK;
|
error= NESTED_LOOP_OK;
|
||||||
|
|
||||||
@@ -23257,7 +23258,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
|
|||||||
/* rows */
|
/* rows */
|
||||||
item_list.push_back(item_null);
|
item_list.push_back(item_null);
|
||||||
/* extra */
|
/* extra */
|
||||||
if (select_lex->master_unit()->global_parameters->order_list.first)
|
if (select_lex->master_unit()->global_parameters()->order_list.first)
|
||||||
item_list.push_back(new Item_string("Using filesort",
|
item_list.push_back(new Item_string("Using filesort",
|
||||||
14, cs));
|
14, cs));
|
||||||
else
|
else
|
||||||
@@ -23934,16 +23935,19 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
|||||||
|
|
||||||
if (unit->is_union())
|
if (unit->is_union())
|
||||||
{
|
{
|
||||||
unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // jost for initialization
|
if (unit->union_needs_tmp_table())
|
||||||
unit->fake_select_lex->type= "UNION RESULT";
|
{
|
||||||
unit->fake_select_lex->options|= SELECT_DESCRIBE;
|
unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // just for initialization
|
||||||
|
unit->fake_select_lex->type= "UNION RESULT";
|
||||||
|
unit->fake_select_lex->options|= SELECT_DESCRIBE;
|
||||||
|
}
|
||||||
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
|
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
|
||||||
res= unit->exec();
|
res= unit->exec();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thd->lex->current_select= first;
|
thd->lex->current_select= first;
|
||||||
unit->set_limit(unit->global_parameters);
|
unit->set_limit(unit->global_parameters());
|
||||||
res= mysql_select(thd, &first->ref_pointer_array,
|
res= mysql_select(thd, &first->ref_pointer_array,
|
||||||
first->table_list.first,
|
first->table_list.first,
|
||||||
first->with_wild, first->item_list,
|
first->with_wild, first->item_list,
|
||||||
@@ -24427,28 +24431,34 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
change select_result object of JOIN.
|
Change the select_result object of the JOIN.
|
||||||
|
|
||||||
@param res new select_result object
|
If old_result is not used, forward the call to the current
|
||||||
|
select_result in case it is a wrapper around old_result.
|
||||||
|
|
||||||
@retval
|
Call prepare() and prepare2() on the new select_result if we decide
|
||||||
FALSE OK
|
to use it.
|
||||||
@retval
|
|
||||||
TRUE error
|
@param new_result New select_result object
|
||||||
|
@param old_result Old select_result object (NULL to force change)
|
||||||
|
|
||||||
|
@retval false Success
|
||||||
|
@retval true Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool JOIN::change_result(select_result *res)
|
bool JOIN::change_result(select_result *new_result, select_result *old_result)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("JOIN::change_result");
|
DBUG_ENTER("JOIN::change_result");
|
||||||
result= res;
|
if (old_result == NULL || result == old_result)
|
||||||
if (tmp_join)
|
|
||||||
tmp_join->result= res;
|
|
||||||
if (!procedure && (result->prepare(fields_list, select_lex->master_unit()) ||
|
|
||||||
result->prepare2()))
|
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
result= new_result;
|
||||||
|
if (result->prepare(fields_list, select_lex->master_unit()) ||
|
||||||
|
result->prepare2())
|
||||||
|
DBUG_RETURN(true); /* purecov: inspected */
|
||||||
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(FALSE);
|
else
|
||||||
|
DBUG_RETURN(result->change_result(new_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1413,7 +1413,7 @@ public:
|
|||||||
having_value != Item::COND_FALSE);
|
having_value != Item::COND_FALSE);
|
||||||
}
|
}
|
||||||
bool empty_result() { return (zero_result_cause && !implicit_grouping); }
|
bool empty_result() { return (zero_result_cause && !implicit_grouping); }
|
||||||
bool change_result(select_result *result);
|
bool change_result(select_result *new_result, select_result *old_result);
|
||||||
bool is_top_level_join() const
|
bool is_top_level_join() const
|
||||||
{
|
{
|
||||||
return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
|
return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
|
||||||
|
253
sql/sql_union.cc
253
sql/sql_union.cc
@@ -187,6 +187,103 @@ void select_union::cleanup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Replace the current result with new_result and prepare it.
|
||||||
|
|
||||||
|
@param new_result New result pointer
|
||||||
|
|
||||||
|
@retval FALSE Success
|
||||||
|
@retval TRUE Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool select_union_direct::change_result(select_result *new_result)
|
||||||
|
{
|
||||||
|
result= new_result;
|
||||||
|
return (result->prepare(unit->types, unit) || result->prepare2());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool select_union_direct::postponed_prepare(List<Item> &types)
|
||||||
|
{
|
||||||
|
if (result != NULL)
|
||||||
|
return (result->prepare(types, unit) || result->prepare2());
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool select_union_direct::send_result_set_metadata(List<Item> &list, uint flags)
|
||||||
|
{
|
||||||
|
if (done_send_result_set_metadata)
|
||||||
|
return false;
|
||||||
|
done_send_result_set_metadata= true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set global offset and limit to be used in send_data(). These can
|
||||||
|
be variables in prepared statements or stored programs, so they
|
||||||
|
must be reevaluated for each execution.
|
||||||
|
*/
|
||||||
|
offset= unit->global_parameters()->get_offset();
|
||||||
|
limit= unit->global_parameters()->get_limit();
|
||||||
|
if (limit + offset >= limit)
|
||||||
|
limit+= offset;
|
||||||
|
else
|
||||||
|
limit= HA_POS_ERROR; /* purecov: inspected */
|
||||||
|
|
||||||
|
return result->send_result_set_metadata(unit->types, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int select_union_direct::send_data(List<Item> &items)
|
||||||
|
{
|
||||||
|
if (!limit)
|
||||||
|
return false;
|
||||||
|
limit--;
|
||||||
|
if (offset)
|
||||||
|
{
|
||||||
|
offset--;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_record(thd, table, table->field, items, true, false);
|
||||||
|
if (thd->is_error())
|
||||||
|
return true; /* purecov: inspected */
|
||||||
|
|
||||||
|
return result->send_data(unit->item_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool select_union_direct::initialize_tables (JOIN *join)
|
||||||
|
{
|
||||||
|
if (done_initialize_tables)
|
||||||
|
return false;
|
||||||
|
done_initialize_tables= true;
|
||||||
|
|
||||||
|
return result->initialize_tables(join);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool select_union_direct::send_eof()
|
||||||
|
{
|
||||||
|
// Reset for each SELECT_LEX, so accumulate here
|
||||||
|
limit_found_rows+= thd->limit_found_rows;
|
||||||
|
|
||||||
|
if (unit->thd->lex->current_select == last_select_lex)
|
||||||
|
{
|
||||||
|
thd->limit_found_rows= limit_found_rows;
|
||||||
|
|
||||||
|
// Reset and make ready for re-execution
|
||||||
|
done_send_result_set_metadata= false;
|
||||||
|
done_initialize_tables= false;
|
||||||
|
|
||||||
|
return result->send_eof();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
initialization procedures before fake_select_lex preparation()
|
initialization procedures before fake_select_lex preparation()
|
||||||
|
|
||||||
@@ -217,12 +314,12 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg,
|
|||||||
*/
|
*/
|
||||||
if (!fake_select_lex->first_execution && first_execution)
|
if (!fake_select_lex->first_execution && first_execution)
|
||||||
{
|
{
|
||||||
for (ORDER *order= global_parameters->order_list.first;
|
for (ORDER *order= global_parameters()->order_list.first;
|
||||||
order;
|
order;
|
||||||
order= order->next)
|
order= order->next)
|
||||||
order->item= &order->item_ptr;
|
order->item= &order->item_ptr;
|
||||||
}
|
}
|
||||||
for (ORDER *order= global_parameters->order_list.first;
|
for (ORDER *order= global_parameters()->order_list.first;
|
||||||
order;
|
order;
|
||||||
order=order->next)
|
order=order->next)
|
||||||
{
|
{
|
||||||
@@ -241,10 +338,18 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
SELECT_LEX *sl, *first_sl= first_select();
|
SELECT_LEX *sl, *first_sl= first_select();
|
||||||
select_result *tmp_result;
|
select_result *tmp_result;
|
||||||
bool is_union_select;
|
bool is_union_select;
|
||||||
|
bool instantiate_tmp_table= false;
|
||||||
DBUG_ENTER("st_select_lex_unit::prepare");
|
DBUG_ENTER("st_select_lex_unit::prepare");
|
||||||
|
|
||||||
describe= MY_TEST(additional_options & SELECT_DESCRIBE);
|
describe= MY_TEST(additional_options & SELECT_DESCRIBE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Save fake_select_lex in case we don't need it for anything but
|
||||||
|
global parameters.
|
||||||
|
*/
|
||||||
|
if (saved_fake_select_lex == NULL) // Don't overwrite on PS second prepare
|
||||||
|
saved_fake_select_lex= fake_select_lex;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
result object should be reassigned even if preparing already done for
|
result object should be reassigned even if preparing already done for
|
||||||
max/min subquery (ALL/ANY optimization)
|
max/min subquery (ALL/ANY optimization)
|
||||||
@@ -283,10 +388,22 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
if (is_union_select)
|
if (is_union_select)
|
||||||
{
|
{
|
||||||
if (!(tmp_result= union_result= new select_union))
|
if (is_union() && !union_needs_tmp_table())
|
||||||
goto err;
|
{
|
||||||
if (describe)
|
SELECT_LEX *last= first_select();
|
||||||
tmp_result= sel_result;
|
while (last->next_select())
|
||||||
|
last= last->next_select();
|
||||||
|
if (!(tmp_result= union_result= new select_union_direct(sel_result, last)))
|
||||||
|
goto err; /* purecov: inspected */
|
||||||
|
fake_select_lex= NULL;
|
||||||
|
instantiate_tmp_table= false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(tmp_result= union_result= new select_union()))
|
||||||
|
goto err; /* purecov: inspected */
|
||||||
|
instantiate_tmp_table= true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tmp_result= sel_result;
|
tmp_result= sel_result;
|
||||||
@@ -387,6 +504,14 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the query is using select_union_direct, we have postponed
|
||||||
|
preparation of the underlying select_result until column types
|
||||||
|
are known.
|
||||||
|
*/
|
||||||
|
if (union_result != NULL && union_result->postponed_prepare(types))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
if (is_union_select)
|
if (is_union_select)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -423,13 +548,13 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
the meaning of these accumulated flags and what to carry over to the
|
the meaning of these accumulated flags and what to carry over to the
|
||||||
recipient query (SELECT_LEX).
|
recipient query (SELECT_LEX).
|
||||||
*/
|
*/
|
||||||
if (global_parameters->ftfunc_list->elements &&
|
if (global_parameters()->ftfunc_list->elements &&
|
||||||
global_parameters->order_list.elements &&
|
global_parameters()->order_list.elements &&
|
||||||
global_parameters != fake_select_lex)
|
global_parameters() != fake_select_lex)
|
||||||
{
|
{
|
||||||
ORDER *ord;
|
ORDER *ord;
|
||||||
Item_func::Functype ft= Item_func::FT_FUNC;
|
Item_func::Functype ft= Item_func::FT_FUNC;
|
||||||
for (ord= global_parameters->order_list.first; ord; ord= ord->next)
|
for (ord= global_parameters()->order_list.first; ord; ord= ord->next)
|
||||||
if ((*ord->item)->walk (&Item::find_function_processor, FALSE,
|
if ((*ord->item)->walk (&Item::find_function_processor, FALSE,
|
||||||
(uchar *) &ft))
|
(uchar *) &ft))
|
||||||
{
|
{
|
||||||
@@ -447,11 +572,12 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
from it (this should be removed in 5.2 when fulltext search is moved
|
from it (this should be removed in 5.2 when fulltext search is moved
|
||||||
out of MyISAM).
|
out of MyISAM).
|
||||||
*/
|
*/
|
||||||
if (global_parameters->ftfunc_list->elements)
|
if (global_parameters()->ftfunc_list->elements)
|
||||||
create_options= create_options | TMP_TABLE_FORCE_MYISAM;
|
create_options= create_options | TMP_TABLE_FORCE_MYISAM;
|
||||||
|
|
||||||
if (union_result->create_result_table(thd, &types, MY_TEST(union_distinct),
|
if (union_result->create_result_table(thd, &types, MY_TEST(union_distinct),
|
||||||
create_options, "", FALSE, TRUE))
|
create_options, "", false,
|
||||||
|
instantiate_tmp_table))
|
||||||
goto err;
|
goto err;
|
||||||
if (fake_select_lex && !fake_select_lex->first_cond_optimization)
|
if (fake_select_lex && !fake_select_lex->first_cond_optimization)
|
||||||
{
|
{
|
||||||
@@ -485,7 +611,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
if (saved_error)
|
if (saved_error)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (thd->stmt_arena->is_stmt_prepare())
|
if (fake_select_lex != NULL && thd->stmt_arena->is_stmt_prepare())
|
||||||
{
|
{
|
||||||
/* Validate the global parameters of this union */
|
/* Validate the global parameters of this union */
|
||||||
|
|
||||||
@@ -511,14 +637,14 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
We need to add up n_sum_items in order to make the correct
|
We need to add up n_sum_items in order to make the correct
|
||||||
allocation in setup_ref_array().
|
allocation in setup_ref_array().
|
||||||
*/
|
*/
|
||||||
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
|
fake_select_lex->n_child_sum_items+= global_parameters()->n_sum_items;
|
||||||
|
|
||||||
saved_error= fake_select_lex->join->
|
saved_error= fake_select_lex->join->
|
||||||
prepare(&fake_select_lex->ref_pointer_array,
|
prepare(&fake_select_lex->ref_pointer_array,
|
||||||
fake_select_lex->table_list.first,
|
fake_select_lex->table_list.first,
|
||||||
0, 0,
|
0, 0,
|
||||||
global_parameters->order_list.elements, // og_num
|
global_parameters()->order_list.elements, // og_num
|
||||||
global_parameters->order_list.first, // order
|
global_parameters()->order_list.first, // order
|
||||||
false, NULL, NULL, NULL,
|
false, NULL, NULL, NULL,
|
||||||
fake_select_lex, this);
|
fake_select_lex, this);
|
||||||
fake_select_lex->table_list.empty();
|
fake_select_lex->table_list.empty();
|
||||||
@@ -570,7 +696,11 @@ bool st_select_lex_unit::optimize()
|
|||||||
{
|
{
|
||||||
item->assigned(0); // We will reinit & rexecute unit
|
item->assigned(0); // We will reinit & rexecute unit
|
||||||
item->reset();
|
item->reset();
|
||||||
table->file->ha_delete_all_rows();
|
if (table->created)
|
||||||
|
{
|
||||||
|
table->file->ha_delete_all_rows();
|
||||||
|
table->file->info(HA_STATUS_VARIABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* re-enabling indexes for next subselect iteration */
|
/* re-enabling indexes for next subselect iteration */
|
||||||
if (union_distinct && table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
|
if (union_distinct && table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
|
||||||
@@ -587,7 +717,7 @@ bool st_select_lex_unit::optimize()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_limit(sl);
|
set_limit(sl);
|
||||||
if (sl == global_parameters || describe)
|
if (sl == global_parameters() || describe)
|
||||||
{
|
{
|
||||||
offset_limit_cnt= 0;
|
offset_limit_cnt= 0;
|
||||||
/*
|
/*
|
||||||
@@ -656,14 +786,17 @@ bool st_select_lex_unit::exec()
|
|||||||
{
|
{
|
||||||
ha_rows records_at_start= 0;
|
ha_rows records_at_start= 0;
|
||||||
thd->lex->current_select= sl;
|
thd->lex->current_select= sl;
|
||||||
if (sl != &thd->lex->select_lex)
|
if (fake_select_lex)
|
||||||
fake_select_lex->uncacheable|= sl->uncacheable;
|
{
|
||||||
else
|
if (sl != &thd->lex->select_lex)
|
||||||
fake_select_lex->uncacheable= 0;
|
fake_select_lex->uncacheable|= sl->uncacheable;
|
||||||
|
else
|
||||||
|
fake_select_lex->uncacheable= 0;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
set_limit(sl);
|
set_limit(sl);
|
||||||
if (sl == global_parameters || describe)
|
if (sl == global_parameters() || describe)
|
||||||
{
|
{
|
||||||
offset_limit_cnt= 0;
|
offset_limit_cnt= 0;
|
||||||
/*
|
/*
|
||||||
@@ -690,6 +823,8 @@ bool st_select_lex_unit::exec()
|
|||||||
sl->join->exec();
|
sl->join->exec();
|
||||||
if (sl == union_distinct)
|
if (sl == union_distinct)
|
||||||
{
|
{
|
||||||
|
// This is UNION DISTINCT, so there should be a fake_select_lex
|
||||||
|
DBUG_ASSERT(fake_select_lex != NULL);
|
||||||
if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
|
if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
table->no_keyread=1;
|
table->no_keyread=1;
|
||||||
@@ -714,12 +849,15 @@ bool st_select_lex_unit::exec()
|
|||||||
thd->lex->current_select= lex_select_save;
|
thd->lex->current_select= lex_select_save;
|
||||||
DBUG_RETURN(saved_error);
|
DBUG_RETURN(saved_error);
|
||||||
}
|
}
|
||||||
/* Needed for the following test and for records_at_start in next loop */
|
if (fake_select_lex != NULL)
|
||||||
int error= table->file->info(HA_STATUS_VARIABLE);
|
|
||||||
if(error)
|
|
||||||
{
|
{
|
||||||
table->file->print_error(error, MYF(0));
|
/* Needed for the following test and for records_at_start in next loop */
|
||||||
DBUG_RETURN(1);
|
int error= table->file->info(HA_STATUS_VARIABLE);
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
table->file->print_error(error, MYF(0));
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (found_rows_for_union && !sl->braces &&
|
if (found_rows_for_union && !sl->braces &&
|
||||||
select_limit_cnt != HA_POS_ERROR)
|
select_limit_cnt != HA_POS_ERROR)
|
||||||
@@ -752,8 +890,6 @@ bool st_select_lex_unit::exec()
|
|||||||
|
|
||||||
DBUG_EXECUTE_IF("show_explain_probe_union_read",
|
DBUG_EXECUTE_IF("show_explain_probe_union_read",
|
||||||
dbug_serve_apcs(thd, 1););
|
dbug_serve_apcs(thd, 1););
|
||||||
/* Send result to 'result' */
|
|
||||||
saved_error= TRUE;
|
|
||||||
{
|
{
|
||||||
List<Item_func_match> empty_list;
|
List<Item_func_match> empty_list;
|
||||||
empty_list.empty();
|
empty_list.empty();
|
||||||
@@ -763,11 +899,15 @@ bool st_select_lex_unit::exec()
|
|||||||
*/
|
*/
|
||||||
thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX;
|
thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX;
|
||||||
|
|
||||||
if (!thd->is_fatal_error) // Check if EOM
|
if (fake_select_lex != NULL && !thd->is_fatal_error) // Check if EOM
|
||||||
{
|
{
|
||||||
set_limit(global_parameters);
|
/* Send result to 'result' */
|
||||||
|
saved_error= true;
|
||||||
|
|
||||||
|
set_limit(global_parameters());
|
||||||
init_prepare_fake_select_lex(thd, first_execution);
|
init_prepare_fake_select_lex(thd, first_execution);
|
||||||
JOIN *join= fake_select_lex->join;
|
JOIN *join= fake_select_lex->join;
|
||||||
|
saved_error= false;
|
||||||
if (!join)
|
if (!join)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -799,7 +939,7 @@ bool st_select_lex_unit::exec()
|
|||||||
for this (with a different join object)
|
for this (with a different join object)
|
||||||
*/
|
*/
|
||||||
if (!fake_select_lex->ref_pointer_array)
|
if (!fake_select_lex->ref_pointer_array)
|
||||||
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
|
fake_select_lex->n_child_sum_items+= global_parameters()->n_sum_items;
|
||||||
|
|
||||||
if (!was_executed)
|
if (!was_executed)
|
||||||
save_union_explain_part2(thd->lex->explain);
|
save_union_explain_part2(thd->lex->explain);
|
||||||
@@ -807,8 +947,8 @@ bool st_select_lex_unit::exec()
|
|||||||
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
|
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
|
||||||
&result_table_list,
|
&result_table_list,
|
||||||
0, item_list, NULL,
|
0, item_list, NULL,
|
||||||
global_parameters->order_list.elements,
|
global_parameters()->order_list.elements,
|
||||||
global_parameters->order_list.first,
|
global_parameters()->order_list.first,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
fake_select_lex->options | SELECT_NO_UNLOCK,
|
fake_select_lex->options | SELECT_NO_UNLOCK,
|
||||||
result, this, fake_select_lex);
|
result, this, fake_select_lex);
|
||||||
@@ -830,8 +970,8 @@ bool st_select_lex_unit::exec()
|
|||||||
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
|
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
|
||||||
&result_table_list,
|
&result_table_list,
|
||||||
0, item_list, NULL,
|
0, item_list, NULL,
|
||||||
global_parameters->order_list.elements,
|
global_parameters()->order_list.elements,
|
||||||
global_parameters->order_list.first,
|
global_parameters()->order_list.first,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
fake_select_lex->options | SELECT_NO_UNLOCK,
|
fake_select_lex->options | SELECT_NO_UNLOCK,
|
||||||
result, this, fake_select_lex);
|
result, this, fake_select_lex);
|
||||||
@@ -907,11 +1047,11 @@ bool st_select_lex_unit::cleanup()
|
|||||||
Note: global_parameters and fake_select_lex are always
|
Note: global_parameters and fake_select_lex are always
|
||||||
initialized for UNION
|
initialized for UNION
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(global_parameters);
|
DBUG_ASSERT(global_parameters());
|
||||||
if (global_parameters->order_list.elements)
|
if (global_parameters()->order_list.elements)
|
||||||
{
|
{
|
||||||
ORDER *ord;
|
ORDER *ord;
|
||||||
for (ord= global_parameters->order_list.first; ord; ord= ord->next)
|
for (ord= global_parameters()->order_list.first; ord; ord= ord->next)
|
||||||
(*ord->item)->walk (&Item::cleanup_processor, 0, 0);
|
(*ord->item)->walk (&Item::cleanup_processor, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -942,32 +1082,33 @@ void st_select_lex_unit::reinit_exec_mechanism()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
change select_result object of unit
|
Change the select_result object used to return the final result of
|
||||||
|
the unit, replacing occurences of old_result with new_result.
|
||||||
|
|
||||||
SYNOPSIS
|
@param new_result New select_result object
|
||||||
st_select_lex_unit::change_result()
|
@param old_result Old select_result object
|
||||||
result new select_result object
|
|
||||||
old_result old select_result object
|
|
||||||
|
|
||||||
RETURN
|
@retval false Success
|
||||||
FALSE - OK
|
@retval true Error
|
||||||
TRUE - error
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool st_select_lex_unit::change_result(select_result_interceptor *new_result,
|
bool st_select_lex_unit::change_result(select_result_interceptor *new_result,
|
||||||
select_result_interceptor *old_result)
|
select_result_interceptor *old_result)
|
||||||
{
|
{
|
||||||
bool res= FALSE;
|
|
||||||
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
if (sl->join && sl->join->result == old_result)
|
if (sl->join)
|
||||||
if (sl->join->change_result(new_result))
|
if (sl->join->change_result(new_result, old_result))
|
||||||
return TRUE;
|
return true; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
if (fake_select_lex && fake_select_lex->join)
|
/*
|
||||||
res= fake_select_lex->join->change_result(new_result);
|
If there were a fake_select_lex->join, we would have to change the
|
||||||
return (res);
|
result of that also, but change_result() is called before such an
|
||||||
|
object is created.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(fake_select_lex == NULL || fake_select_lex->join == NULL);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
100
sql/sql_yacc.yy
100
sql/sql_yacc.yy
@@ -657,6 +657,17 @@ bool add_select_to_union_list(LEX *lex, bool is_union_distinct,
|
|||||||
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
|
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
if (lex->current_select->order_list.first && !lex->current_select->braces)
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lex->current_select->explicit_limit && !lex->current_select->braces)
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "LIMIT");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
||||||
{
|
{
|
||||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||||
@@ -684,11 +695,14 @@ bool add_select_to_union_list(LEX *lex, bool is_union_distinct,
|
|||||||
bool setup_select_in_parentheses(LEX *lex)
|
bool setup_select_in_parentheses(LEX *lex)
|
||||||
{
|
{
|
||||||
SELECT_LEX * sel= lex->current_select;
|
SELECT_LEX * sel= lex->current_select;
|
||||||
|
/*
|
||||||
if (sel->set_braces(1))
|
if (sel->set_braces(1))
|
||||||
{
|
{
|
||||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(sel->braces);
|
||||||
if (sel->linkage == UNION_TYPE &&
|
if (sel->linkage == UNION_TYPE &&
|
||||||
!sel->master_unit()->first_select()->braces &&
|
!sel->master_unit()->first_select()->braces &&
|
||||||
sel->master_unit()->first_select()->linkage ==
|
sel->master_unit()->first_select()->linkage ==
|
||||||
@@ -704,10 +718,6 @@ bool setup_select_in_parentheses(LEX *lex)
|
|||||||
my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
|
my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
/* select in braces, can't contain global parameters */
|
|
||||||
if (sel->master_unit()->fake_select_lex)
|
|
||||||
sel->master_unit()->global_parameters=
|
|
||||||
sel->master_unit()->fake_select_lex;
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8309,6 +8319,13 @@ select_init:
|
|||||||
;
|
;
|
||||||
|
|
||||||
select_paren:
|
select_paren:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
In order to correctly parse UNION's global ORDER BY we need to
|
||||||
|
set braces before parsing the clause.
|
||||||
|
*/
|
||||||
|
Lex->current_select->set_braces(true);
|
||||||
|
}
|
||||||
SELECT_SYM select_part2
|
SELECT_SYM select_part2
|
||||||
{
|
{
|
||||||
if (setup_select_in_parentheses(Lex))
|
if (setup_select_in_parentheses(Lex))
|
||||||
@@ -8319,6 +8336,9 @@ select_paren:
|
|||||||
|
|
||||||
/* The equivalent of select_paren for nested queries. */
|
/* The equivalent of select_paren for nested queries. */
|
||||||
select_paren_derived:
|
select_paren_derived:
|
||||||
|
{
|
||||||
|
Lex->current_select->set_braces(true);
|
||||||
|
}
|
||||||
SELECT_SYM select_part2_derived
|
SELECT_SYM select_part2_derived
|
||||||
{
|
{
|
||||||
if (setup_select_in_parentheses(Lex))
|
if (setup_select_in_parentheses(Lex))
|
||||||
@@ -8331,18 +8351,8 @@ select_init2:
|
|||||||
select_part2
|
select_part2
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
SELECT_LEX * sel= lex->current_select;
|
/* Parentheses carry no meaning here */
|
||||||
if (lex->current_select->set_braces(0))
|
lex->current_select->set_braces(false);
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (sel->linkage == UNION_TYPE &&
|
|
||||||
sel->master_unit()->first_select()->braces)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
union_clause
|
union_clause
|
||||||
;
|
;
|
||||||
@@ -8371,13 +8381,14 @@ select_into:
|
|||||||
;
|
;
|
||||||
|
|
||||||
select_from:
|
select_from:
|
||||||
FROM join_table_list where_clause group_clause having_clause
|
FROM join_table_list
|
||||||
opt_order_clause opt_limit_clause procedure_clause
|
|
||||||
{
|
{
|
||||||
Select->context.table_list=
|
Select->context.table_list=
|
||||||
Select->context.first_name_resolution_table=
|
Select->context.first_name_resolution_table=
|
||||||
Select->table_list.first;
|
Select->table_list.first;
|
||||||
}
|
}
|
||||||
|
where_clause group_clause having_clause
|
||||||
|
opt_order_clause opt_limit_clause procedure_clause
|
||||||
| FROM DUAL_SYM where_clause opt_limit_clause
|
| FROM DUAL_SYM where_clause opt_limit_clause
|
||||||
/* oracle compatibility: oracle always requires FROM clause,
|
/* oracle compatibility: oracle always requires FROM clause,
|
||||||
and DUAL is system table without fields.
|
and DUAL is system table without fields.
|
||||||
@@ -10698,10 +10709,6 @@ table_factor:
|
|||||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
/* select in braces, can't contain global parameters */
|
|
||||||
if (sel->master_unit()->fake_select_lex)
|
|
||||||
sel->master_unit()->global_parameters=
|
|
||||||
sel->master_unit()->fake_select_lex;
|
|
||||||
}
|
}
|
||||||
if ($2->init_nested_join(lex->thd))
|
if ($2->init_nested_join(lex->thd))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
@@ -11246,7 +11253,8 @@ order_clause:
|
|||||||
"CUBE/ROLLUP", "ORDER BY");
|
"CUBE/ROLLUP", "ORDER BY");
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
|
if (lex->sql_command != SQLCOM_ALTER_TABLE &&
|
||||||
|
!unit->fake_select_lex)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
A query of the of the form (SELECT ...) ORDER BY order_list is
|
A query of the of the form (SELECT ...) ORDER BY order_list is
|
||||||
@@ -11263,9 +11271,24 @@ order_clause:
|
|||||||
unit->add_fake_select_lex(lex->thd))
|
unit->add_fake_select_lex(lex->thd))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
|
if (sel->master_unit()->is_union() && !sel->braces)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
At this point we don't know yet whether this is the last
|
||||||
|
select in union or not, but we move ORDER BY to
|
||||||
|
fake_select_lex anyway. If there would be one more select
|
||||||
|
in union mysql_new_select will correctly throw error.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(sel->master_unit()->fake_select_lex);
|
||||||
|
lex->current_select= sel->master_unit()->fake_select_lex;
|
||||||
|
lex->push_context(&lex->current_select->context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
order_list
|
order_list
|
||||||
;
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
order_list:
|
order_list:
|
||||||
order_list ',' order_ident order_dir
|
order_list ',' order_ident order_dir
|
||||||
@@ -11285,6 +11308,13 @@ opt_limit_clause_init:
|
|||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
SELECT_LEX *sel= lex->current_select;
|
SELECT_LEX *sel= lex->current_select;
|
||||||
|
if (sel->master_unit()->is_union() && !sel->braces)
|
||||||
|
{
|
||||||
|
/* Move LIMIT that belongs to UNION to fake_select_lex */
|
||||||
|
Lex->current_select= sel->master_unit()->fake_select_lex;
|
||||||
|
DBUG_ASSERT(Select);
|
||||||
|
}
|
||||||
|
sel= lex->current_select;
|
||||||
sel->offset_limit= 0;
|
sel->offset_limit= 0;
|
||||||
sel->select_limit= 0;
|
sel->select_limit= 0;
|
||||||
lex->limit_rows_examined= 0;
|
lex->limit_rows_examined= 0;
|
||||||
@@ -11297,19 +11327,33 @@ opt_limit_clause:
|
|||||||
| limit_clause {}
|
| limit_clause {}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
limit_clause_init:
|
||||||
|
LIMIT
|
||||||
|
{
|
||||||
|
SELECT_LEX *sel= Select;
|
||||||
|
if (sel->master_unit()->is_union() && !sel->braces)
|
||||||
|
{
|
||||||
|
/* Move LIMIT that belongs to UNION to fake_select_lex */
|
||||||
|
Lex->current_select= sel->master_unit()->fake_select_lex;
|
||||||
|
DBUG_ASSERT(Select);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
limit_clause:
|
limit_clause:
|
||||||
LIMIT limit_options
|
limit_clause_init limit_options
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select;
|
SELECT_LEX *sel= Select;
|
||||||
if (!sel->select_limit->basic_const_item() ||
|
if (!sel->select_limit->basic_const_item() ||
|
||||||
sel->select_limit->val_int() > 0)
|
sel->select_limit->val_int() > 0)
|
||||||
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
||||||
}
|
}
|
||||||
| LIMIT limit_options ROWS_SYM EXAMINED_SYM limit_rows_option
|
| limit_clause_init limit_options
|
||||||
|
ROWS_SYM EXAMINED_SYM limit_rows_option
|
||||||
{
|
{
|
||||||
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
||||||
}
|
}
|
||||||
| LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
|
| limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
|
||||||
{
|
{
|
||||||
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
||||||
}
|
}
|
||||||
@@ -12790,6 +12834,7 @@ flush_options:
|
|||||||
YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO;
|
YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO;
|
||||||
}
|
}
|
||||||
opt_table_list opt_flush_lock
|
opt_table_list opt_flush_lock
|
||||||
|
{}
|
||||||
| flush_options_list
|
| flush_options_list
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -15739,7 +15784,6 @@ union_order_or_limit:
|
|||||||
SELECT_LEX *fake= unit->fake_select_lex;
|
SELECT_LEX *fake= unit->fake_select_lex;
|
||||||
if (fake)
|
if (fake)
|
||||||
{
|
{
|
||||||
unit->global_parameters= fake;
|
|
||||||
fake->no_table_names_allowed= 1;
|
fake->no_table_names_allowed= 1;
|
||||||
lex->current_select= fake;
|
lex->current_select= fake;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user