Merge remote-tracking branch 'shagalla/10.3-mdev12172' into 10.3
As a result of this merge the code for the following tasks appears in 10.3: - MDEV-12172 Implement tables specified by table value constructors - MDEV-12176 Transform [NOT] IN predicate with long list of values INTO [NOT] IN subquery.
This commit is contained in:
commit
6f1b6061d8
@ -118,6 +118,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||||||
../sql/temporary_tables.cc
|
../sql/temporary_tables.cc
|
||||||
../sql/session_tracker.cc
|
../sql/session_tracker.cc
|
||||||
../sql/proxy_protocol.cc
|
../sql/proxy_protocol.cc
|
||||||
|
../sql/sql_tvc.cc ../sql/sql_tvc.h
|
||||||
${GEN_SOURCES}
|
${GEN_SOURCES}
|
||||||
${MYSYS_LIBWRAP_SOURCE}
|
${MYSYS_LIBWRAP_SOURCE}
|
||||||
)
|
)
|
||||||
|
@ -232,7 +232,7 @@ CREATE TABLE t1 (a INT DEFAULT 10);
|
|||||||
INSERT INTO t1 VALUES (11);
|
INSERT INTO t1 VALUES (11);
|
||||||
CREATE VIEW v1 AS SELECT a AS a FROM t1;
|
CREATE VIEW v1 AS SELECT a AS a FROM t1;
|
||||||
CREATE VIEW v2 AS SELECT DEFAULT(a) AS a FROM t1;
|
CREATE VIEW v2 AS SELECT DEFAULT(a) AS a FROM t1;
|
||||||
CREATE VIEW v3 AS SELECT VALUES(a) AS a FROM t1;
|
CREATE VIEW v3 AS SELECT VALUE(a) AS a FROM t1;
|
||||||
SELECT * FROM v1;
|
SELECT * FROM v1;
|
||||||
a
|
a
|
||||||
11
|
11
|
||||||
@ -546,7 +546,7 @@ CREATE PROCEDURE p1() CREATE TABLE t1 (a INT DEFAULT par);
|
|||||||
CALL p1;
|
CALL p1;
|
||||||
ERROR 42S22: Unknown column 'par' in 'DEFAULT'
|
ERROR 42S22: Unknown column 'par' in 'DEFAULT'
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
CREATE TABLE t1 (a INT DEFAULT VALUES(a));
|
CREATE TABLE t1 (a INT DEFAULT VALUE(a));
|
||||||
ERROR HY000: Function or expression 'values()' cannot be used in the DEFAULT clause of `a`
|
ERROR HY000: Function or expression 'values()' cannot be used in the DEFAULT clause of `a`
|
||||||
CREATE TABLE t1 (a INT);
|
CREATE TABLE t1 (a INT);
|
||||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CREATE TABLE t2 (a INT DEFAULT NEW.a);
|
CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CREATE TABLE t2 (a INT DEFAULT NEW.a);
|
||||||
|
@ -150,17 +150,17 @@ ERROR 22003: BIGINT value is out of range in '-73 * -2465717823867977728'
|
|||||||
#
|
#
|
||||||
CREATE TABLE t1 (a INT);
|
CREATE TABLE t1 (a INT);
|
||||||
CREATE TABLE t2(a INT PRIMARY KEY, b INT);
|
CREATE TABLE t2(a INT PRIMARY KEY, b INT);
|
||||||
SELECT '' AS b FROM t1 GROUP BY VALUES(b);
|
SELECT '' AS b FROM t1 GROUP BY VALUE(b);
|
||||||
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
||||||
REPLACE t2(b) SELECT '' AS b FROM t1 GROUP BY VALUES(b);
|
REPLACE t2(b) SELECT '' AS b FROM t1 GROUP BY VALUE(b);
|
||||||
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
||||||
UPDATE t2 SET a=(SELECT '' AS b FROM t1 GROUP BY VALUES(b));
|
UPDATE t2 SET a=(SELECT '' AS b FROM t1 GROUP BY VALUE(b));
|
||||||
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
||||||
INSERT INTO t2 VALUES (1,0) ON DUPLICATE KEY UPDATE
|
INSERT INTO t2 VALUES (1,0) ON DUPLICATE KEY UPDATE
|
||||||
b=(SELECT '' AS b FROM t1 GROUP BY VALUES(b));
|
b=(SELECT '' AS b FROM t1 GROUP BY VALUE(b));
|
||||||
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
ERROR 42S22: Unknown column '' in 'VALUES() function'
|
||||||
INSERT INTO t2(a,b) VALUES (1,0) ON DUPLICATE KEY UPDATE
|
INSERT INTO t2(a,b) VALUES (1,0) ON DUPLICATE KEY UPDATE
|
||||||
b=(SELECT VALUES(a)+2 FROM t1);
|
b=(SELECT VALUE(a)+2 FROM t1);
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
#
|
#
|
||||||
# MDEV-492: incorrect error check before sending OK in mysql_update
|
# MDEV-492: incorrect error check before sending OK in mysql_update
|
||||||
|
@ -226,7 +226,7 @@ create table y select 1 b;
|
|||||||
select 1 from y group by b;
|
select 1 from y group by b;
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
select 1 from y group by values(b);
|
select 1 from y group by value(b);
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
drop table y;
|
drop table y;
|
||||||
|
@ -286,11 +286,11 @@ NAME_CONST('a', -(1)) OR 1
|
|||||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||||
INSERT INTO t1 VALUES (1,10);
|
INSERT INTO t1 VALUES (1,10);
|
||||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||||
EXPLAIN EXTENDED SELECT VALUES(b) FROM v1;
|
EXPLAIN EXTENDED SELECT VALUE(b) FROM v1;
|
||||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
|
1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select values(10) AS `VALUES(b)` from dual
|
Note 1003 select value(10) AS `VALUE(b)` from dual
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
End of 5.3 tests
|
End of 5.3 tests
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
create table t1 (a int);
|
create table t1 (a int);
|
||||||
insert into t1 values (1),(2);
|
insert into t1 values (1),(2);
|
||||||
select max('foo') from t1 group by values(a), extractvalue('bar','qux') order by "v";
|
select max('foo') from t1 group by value(a), extractvalue('bar','qux') order by "v";
|
||||||
max('foo')
|
max('foo')
|
||||||
foo
|
foo
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -49,23 +49,23 @@ a b c
|
|||||||
5 0 30
|
5 0 30
|
||||||
8 9 60
|
8 9 60
|
||||||
INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
||||||
SELECT *, VALUES(a) FROM t1;
|
SELECT *, VALUE(a) FROM t1;
|
||||||
a b c VALUES(a)
|
a b c VALUE(a)
|
||||||
1 2 10 NULL
|
1 2 10 NULL
|
||||||
3 4 127 NULL
|
3 4 127 NULL
|
||||||
5 0 30 NULL
|
5 0 30 NULL
|
||||||
8 9 60 NULL
|
8 9 60 NULL
|
||||||
2 1 11 NULL
|
2 1 11 NULL
|
||||||
explain extended SELECT *, VALUES(a) FROM t1;
|
explain extended SELECT *, VALUE(a) FROM t1;
|
||||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,values(`test`.`t1`.`a`) AS `VALUES(a)` from `test`.`t1`
|
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,value(`test`.`t1`.`a`) AS `VALUE(a)` from `test`.`t1`
|
||||||
explain extended select * from t1 where values(a);
|
explain extended select * from t1 where value(a);
|
||||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where values(`test`.`t1`.`a`)
|
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where value(`test`.`t1`.`a`)
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
create table t1(a int primary key, b int);
|
create table t1(a int primary key, b int);
|
||||||
insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);
|
insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);
|
||||||
@ -160,8 +160,8 @@ a b c
|
|||||||
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
||||||
ERROR 23000: Column 'c' in field list is ambiguous
|
ERROR 23000: Column 'c' in field list is ambiguous
|
||||||
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a);
|
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a);
|
||||||
SELECT *, VALUES(a) FROM t1;
|
SELECT *, VALUE(a) FROM t1;
|
||||||
a b c VALUES(a)
|
a b c VALUE(a)
|
||||||
1 2 10 NULL
|
1 2 10 NULL
|
||||||
3 4 127 NULL
|
3 4 127 NULL
|
||||||
5 0 30 NULL
|
5 0 30 NULL
|
||||||
|
@ -334,6 +334,10 @@ The following options may be given as the first argument:
|
|||||||
Specifies a directory to add to the ignore list when
|
Specifies a directory to add to the ignore list when
|
||||||
collecting database names from the datadir. Put a blank
|
collecting database names from the datadir. Put a blank
|
||||||
argument to reset the list accumulated so far.
|
argument to reset the list accumulated so far.
|
||||||
|
--in-subquery-conversion-threshold[=#]
|
||||||
|
The minimum number of scalar elements in the value list
|
||||||
|
of IN predicate that triggers its conversion to IN
|
||||||
|
subquery
|
||||||
--init-connect=name Command(s) that are executed for each new connection
|
--init-connect=name Command(s) that are executed for each new connection
|
||||||
(unless the user has SUPER privilege)
|
(unless the user has SUPER privilege)
|
||||||
--init-file=name Read SQL commands from this file at startup
|
--init-file=name Read SQL commands from this file at startup
|
||||||
@ -1354,6 +1358,7 @@ idle-transaction-timeout 0
|
|||||||
idle-write-transaction-timeout 0
|
idle-write-transaction-timeout 0
|
||||||
ignore-builtin-innodb FALSE
|
ignore-builtin-innodb FALSE
|
||||||
ignore-db-dirs
|
ignore-db-dirs
|
||||||
|
in-subquery-conversion-threshold 10000
|
||||||
init-connect
|
init-connect
|
||||||
init-file (No default value)
|
init-file (No default value)
|
||||||
init-rpl-role MASTER
|
init-rpl-role MASTER
|
||||||
|
551
mysql-test/r/opt_tvc.result
Normal file
551
mysql-test/r/opt_tvc.result
Normal file
@ -0,0 +1,551 @@
|
|||||||
|
create table t1 (a int, b int);
|
||||||
|
insert into t1
|
||||||
|
values (1,2), (4,6), (9,7),
|
||||||
|
(1,1), (2,5), (7,8);
|
||||||
|
create table t2 (a int, b int, c int);
|
||||||
|
insert into t2
|
||||||
|
values (1,2,3), (5,1,2), (4,3,7),
|
||||||
|
(8,9,0), (10,7,1), (5,5,1);
|
||||||
|
create table t3 (a int, b varchar(16), index idx(a));
|
||||||
|
insert into t3 values
|
||||||
|
(1, "abc"), (3, "egh"), (8, "axxx"), (10, "abc"),
|
||||||
|
(2, "ccw"), (8, "wqqe"), (7, "au"), (9, "waa"),
|
||||||
|
(3, "rass"), (9, "ert"), (9, "lok"), (8, "aww"),
|
||||||
|
(1, "todd"), (3, "rew"), (8, "aww"), (3, "sw"),
|
||||||
|
(11, "llk"), (7, "rbw"), (1, "sm"), (2, "jyp"),
|
||||||
|
(4, "yq"), (5, "pled"), (12, "ligin"), (12, "toww"),
|
||||||
|
(6, "mxm"), (15, "wanone"), (9, "sunqq"), (2, "abe");
|
||||||
|
# optimization is not used
|
||||||
|
select * from t1 where a in (1,2);
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
explain extended select * from t1 where a in (1,2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` in (1,2)
|
||||||
|
# set minimum number of values in VALUEs list when optimization works to 2
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
# single IN-predicate in WHERE-part
|
||||||
|
select * from t1 where a in (1,2);
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2)) as tvc_0
|
||||||
|
);
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
explain extended select * from t1 where a in (1,2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2)) as tvc_0
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
# AND-condition with IN-predicates in WHERE-part
|
||||||
|
select * from t1
|
||||||
|
where a in (1,2) and
|
||||||
|
b in (1,5);
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2)) as tvc_0
|
||||||
|
)
|
||||||
|
and b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(5)) as tvc_1
|
||||||
|
);
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in (1,2) and
|
||||||
|
b in (1,5);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1`
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2)) as tvc_0
|
||||||
|
)
|
||||||
|
and b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(5)) as tvc_1
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1`
|
||||||
|
# subquery with IN-predicate
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select a
|
||||||
|
from t2 where b in (3,4)
|
||||||
|
);
|
||||||
|
a b
|
||||||
|
4 6
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select a from t2
|
||||||
|
where b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (3),(4)) as tvc_0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
a b
|
||||||
|
4 6
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select a
|
||||||
|
from t2 where b in (3,4)
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
2 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`3`
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select a from t2
|
||||||
|
where b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (3),(4)) as tvc_0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
2 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`3`
|
||||||
|
# derived table with IN-predicate
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
) as dr_table;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
) as dr_table;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
explain extended select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
) as dr_table;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
explain extended select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
) as dr_table;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
# non-recursive CTE with IN-predicate
|
||||||
|
with tvc_0 as
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
)
|
||||||
|
select * from tvc_0;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
) as dr_table;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
explain extended with tvc_0 as
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
)
|
||||||
|
select * from tvc_0;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
explain extended select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
) as dr_table;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
# VIEW with IN-predicate
|
||||||
|
create view v1 as
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2);
|
||||||
|
create view v2 as
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
;
|
||||||
|
select * from v1;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
select * from v2;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
explain extended select * from v1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
explain extended select * from v2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
drop view v1,v2;
|
||||||
|
# subselect defined by derived table with IN-predicate
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select 1
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
)
|
||||||
|
as dr_table
|
||||||
|
);
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select 1
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
as dr_table
|
||||||
|
);
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select 1
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
)
|
||||||
|
as dr_table
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
2 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0` join `test`.`t1`) where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
explain extended select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select 1
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
as dr_table
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
|
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
2 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0` join `test`.`t1`) where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` = `tvc_0`.`1`
|
||||||
|
# derived table with IN-predicate and group by
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select max(a),b
|
||||||
|
from t1
|
||||||
|
where b in (3,5)
|
||||||
|
group by b
|
||||||
|
) as dr_table;
|
||||||
|
max(a) b
|
||||||
|
2 5
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select max(a),b
|
||||||
|
from t1
|
||||||
|
where b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (3),(5))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
group by b
|
||||||
|
) as dr_table;
|
||||||
|
max(a) b
|
||||||
|
2 5
|
||||||
|
explain extended select * from
|
||||||
|
(
|
||||||
|
select max(a),b
|
||||||
|
from t1
|
||||||
|
where b in (3,5)
|
||||||
|
group by b
|
||||||
|
) as dr_table;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
|
||||||
|
2 DERIVED t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
|
||||||
|
2 DERIVED <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `dr_table`.`max(a)` AS `max(a)`,`dr_table`.`b` AS `b` from (/* select#2 */ select max(`test`.`t1`.`a`) AS `max(a)`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(5)) `tvc_0`) where 1 group by `test`.`t1`.`b`) `dr_table`
|
||||||
|
explain extended select * from
|
||||||
|
(
|
||||||
|
select max(a),b
|
||||||
|
from t1
|
||||||
|
where b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (3),(5))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
group by b
|
||||||
|
) as dr_table;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
|
||||||
|
2 DERIVED t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
|
||||||
|
2 DERIVED <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
|
||||||
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `dr_table`.`max(a)` AS `max(a)`,`dr_table`.`b` AS `b` from (/* select#2 */ select max(`test`.`t1`.`a`) AS `max(a)`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(5)) `tvc_0`) where 1 group by `test`.`t1`.`b`) `dr_table`
|
||||||
|
# prepare statement
|
||||||
|
prepare stmt from "select * from t1 where a in (1,2)";
|
||||||
|
execute stmt;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
execute stmt;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
2 5
|
||||||
|
deallocate prepare stmt;
|
||||||
|
# use inside out access from tvc rows
|
||||||
|
set @@in_subquery_conversion_threshold= default;
|
||||||
|
select * from t3 where a in (1,4,10);
|
||||||
|
a b
|
||||||
|
1 abc
|
||||||
|
1 todd
|
||||||
|
1 sm
|
||||||
|
4 yq
|
||||||
|
10 abc
|
||||||
|
explain extended select * from t3 where a in (1,4,10);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 SIMPLE t3 range idx idx 5 NULL 5 100.00 Using index condition
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` where `test`.`t3`.`a` in (1,4,10)
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
select * from t3 where a in (1,4,10);
|
||||||
|
a b
|
||||||
|
1 abc
|
||||||
|
1 todd
|
||||||
|
1 sm
|
||||||
|
4 yq
|
||||||
|
10 abc
|
||||||
|
explain extended select * from t3 where a in (1,4,10);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t3 ref idx idx 5 tvc_0.1 3 100.00
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4),(10)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`1`
|
||||||
|
# use vectors in IN predeicate
|
||||||
|
set @@in_subquery_conversion_threshold= 4;
|
||||||
|
select * from t1 where (a,b) in ((1,2),(3,4));
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
explain extended select * from t1 where (a,b) in ((1,2),(3,4));
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` and `test`.`t1`.`b` = `tvc_0`.`2`
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
# trasformation works for the one IN predicate and doesn't work for the other
|
||||||
|
set @@in_subquery_conversion_threshold= 5;
|
||||||
|
select * from t2
|
||||||
|
where (a,b) in ((1,2),(8,9)) and
|
||||||
|
(a,c) in ((1,3),(8,0),(5,1));
|
||||||
|
a b c
|
||||||
|
1 2 3
|
||||||
|
8 9 0
|
||||||
|
explain extended select * from t2
|
||||||
|
where (a,b) in ((1,2),(8,9)) and
|
||||||
|
(a,c) in ((1,3),(8,0),(5,1));
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
|
||||||
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||||
|
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`1` and `test`.`t2`.`c` = `tvc_0`.`3` and (`tvc_0`.`1`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
drop table t1, t2, t3;
|
||||||
|
set @@in_subquery_conversion_threshold= default;
|
@ -4792,7 +4792,7 @@ EXECUTE IMMEDIATE MAX('SELECT 1 AS c');
|
|||||||
ERROR HY000: Invalid use of group function
|
ERROR HY000: Invalid use of group function
|
||||||
EXECUTE IMMEDIATE DEFAULT(a);
|
EXECUTE IMMEDIATE DEFAULT(a);
|
||||||
ERROR 42S22: Unknown column 'a' in 'field list'
|
ERROR 42S22: Unknown column 'a' in 'field list'
|
||||||
EXECUTE IMMEDIATE VALUES(a);
|
EXECUTE IMMEDIATE VALUE(a);
|
||||||
ERROR 42S22: Unknown column 'a' in 'field list'
|
ERROR 42S22: Unknown column 'a' in 'field list'
|
||||||
CREATE FUNCTION f1() RETURNS VARCHAR(64) RETURN 't1';
|
CREATE FUNCTION f1() RETURNS VARCHAR(64) RETURN 't1';
|
||||||
EXECUTE IMMEDIATE f1();
|
EXECUTE IMMEDIATE f1();
|
||||||
|
@ -400,7 +400,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 100.00 Using where
|
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,<expr_cache><`dbt3_s001`.`customer`.`c_custkey`>(exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`))) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
||||||
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
||||||
from (
|
from (
|
||||||
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
||||||
@ -441,7 +441,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 91.00 Using where
|
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 91.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,<expr_cache><`dbt3_s001`.`customer`.`c_custkey`>(exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`))) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
||||||
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
||||||
from (
|
from (
|
||||||
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
||||||
|
@ -403,7 +403,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 100.00 Using where
|
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,<expr_cache><`dbt3_s001`.`customer`.`c_custkey`>(exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`))) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
||||||
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
||||||
from (
|
from (
|
||||||
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
||||||
@ -444,7 +444,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 91.00 Using where
|
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 91.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,<expr_cache><`dbt3_s001`.`customer`.`c_custkey`>(exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`))) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
|
||||||
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
|
||||||
from (
|
from (
|
||||||
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
|
||||||
|
@ -4440,7 +4440,7 @@ create table t3 (id int not null primary key, county varchar(25))|
|
|||||||
insert into t3 (id, county) values (1, 'York')|
|
insert into t3 (id, county) values (1, 'York')|
|
||||||
create procedure bug15441(c varchar(25))
|
create procedure bug15441(c varchar(25))
|
||||||
begin
|
begin
|
||||||
update t3 set id=2, county=values(c);
|
update t3 set id=2, county=value(c);
|
||||||
end|
|
end|
|
||||||
call bug15441('county')|
|
call bug15441('county')|
|
||||||
ERROR 42S22: Unknown column 'c' in 'field list'
|
ERROR 42S22: Unknown column 'c' in 'field list'
|
||||||
@ -4451,7 +4451,7 @@ declare c varchar(25) default "hello";
|
|||||||
insert into t3 (id, county) values (1, county)
|
insert into t3 (id, county) values (1, county)
|
||||||
on duplicate key update county= values(county);
|
on duplicate key update county= values(county);
|
||||||
select * from t3;
|
select * from t3;
|
||||||
update t3 set id=2, county=values(id);
|
update t3 set id=2, county=value(id);
|
||||||
select * from t3;
|
select * from t3;
|
||||||
end|
|
end|
|
||||||
call bug15441('Yale')|
|
call bug15441('Yale')|
|
||||||
|
@ -143,7 +143,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.a2.id 2 100.00 Using index
|
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.a2.id 2 100.00 Using index
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = (/* select#3 */ select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `a2`.`id`)
|
Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = <expr_cache><`a2`.`id`>((/* select#3 */ select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `a2`.`id`))
|
||||||
This should use one table:
|
This should use one table:
|
||||||
explain select id from v2 where id=2;
|
explain select id from v2 where id=2;
|
||||||
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
|
||||||
@ -171,7 +171,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.f.id 2 100.00 Using index
|
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.f.id 2 100.00 Using index
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = (/* select#3 */ select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `f`.`id`)
|
Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = <expr_cache><`f`.`id`>((/* select#3 */ select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `f`.`id`))
|
||||||
drop view v1, v2;
|
drop view v1, v2;
|
||||||
drop table t0, t1, t2;
|
drop table t0, t1, t2;
|
||||||
create table t1 (a int);
|
create table t1 (a int);
|
||||||
|
2073
mysql-test/r/table_value_constr.result
Normal file
2073
mysql-test/r/table_value_constr.result
Normal file
File diff suppressed because it is too large
Load Diff
@ -2125,7 +2125,7 @@ SHOW TRIGGERS IN db1;
|
|||||||
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
|
||||||
trg1 INSERT t2 CREATE DEFINER=`root`@`localhost` TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERTINTOt1 VALUES (1) BEFORE # STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION latin1 latin1_swedish_ci latin1_swedish_ci
|
trg1 INSERT t2 CREATE DEFINER=`root`@`localhost` TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERTINTOt1 VALUES (1) BEFORE # STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION latin1 latin1_swedish_ci latin1_swedish_ci
|
||||||
INSERT INTO t2 VALUES (1);
|
INSERT INTO t2 VALUES (1);
|
||||||
ERROR 42000: Trigger 'trg1' has an error in its body: '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 'VALUES (1)' at line 1'
|
ERROR 42000: Trigger 'trg1' has an error in its body: '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 '(1)' at line 1'
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
b
|
b
|
||||||
# Work around Bug#45235
|
# Work around Bug#45235
|
||||||
|
@ -1789,7 +1789,7 @@ set session collation_database=2048;
|
|||||||
ERROR HY000: Unknown collation: '2048'
|
ERROR HY000: Unknown collation: '2048'
|
||||||
set session rand_seed1=DEFAULT;
|
set session rand_seed1=DEFAULT;
|
||||||
ERROR 42000: Variable 'rand_seed1' doesn't have a default value
|
ERROR 42000: Variable 'rand_seed1' doesn't have a default value
|
||||||
set autocommit = values(v);
|
set autocommit = value(v);
|
||||||
ERROR 42S22: Unknown column 'v' in 'field list'
|
ERROR 42S22: Unknown column 'v' in 'field list'
|
||||||
set session sql_mode=ansi_quotes;
|
set session sql_mode=ansi_quotes;
|
||||||
select * from information_schema.session_variables where variable_name='sql_mode';
|
select * from information_schema.session_variables where variable_name='sql_mode';
|
||||||
|
@ -5637,7 +5637,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1`
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>((/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)) AS `c` from `test`.`t1`
|
||||||
select * from v1;
|
select * from v1;
|
||||||
a c
|
a c
|
||||||
1 2
|
1 2
|
||||||
@ -5654,7 +5654,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a`
|
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>((/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)) AS `c` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a`
|
||||||
select * from t2, v1 where t2.a=v1.a;
|
select * from t2, v1 where t2.a=v1.a;
|
||||||
a b a c
|
a b a c
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
@ -5673,7 +5673,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a`
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>((/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a`
|
||||||
select * from t1, v1 where t1.a=v1.a;
|
select * from t1, v1 where t1.a=v1.a;
|
||||||
a b a c
|
a b a c
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
@ -5692,7 +5692,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`b` = (/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>((/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`b` = <expr_cache><`test`.`t1`.`a`>((/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
|
||||||
select * from t1, v1 where t1.b=v1.c;
|
select * from t1, v1 where t1.b=v1.c;
|
||||||
a b a c
|
a b a c
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
@ -5710,7 +5710,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
|
||||||
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t2` join `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`a` = `test`.`t2`.`a`
|
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>((/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)) AS `c` from `test`.`t2` join `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`a` = `test`.`t2`.`a`
|
||||||
select * from t2, t1, v1 where t1.a=t2.a and t1.a=v1.a;
|
select * from t2, t1, v1 where t1.a=t2.a and t1.a=v1.a;
|
||||||
a b a b a c
|
a b a b a c
|
||||||
1 2 1 2 1 2
|
1 2 1 2 1 2
|
||||||
|
@ -1550,6 +1550,20 @@ NUMERIC_BLOCK_SIZE 1
|
|||||||
ENUM_VALUE_LIST NULL
|
ENUM_VALUE_LIST NULL
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
|
VARIABLE_NAME IN_SUBQUERY_CONVERSION_THRESHOLD
|
||||||
|
SESSION_VALUE 10000
|
||||||
|
GLOBAL_VALUE 10000
|
||||||
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
|
DEFAULT_VALUE 10000
|
||||||
|
VARIABLE_SCOPE SESSION
|
||||||
|
VARIABLE_TYPE BIGINT UNSIGNED
|
||||||
|
VARIABLE_COMMENT The minimum number of scalar elements in the value list of IN predicate that triggers its conversion to IN subquery
|
||||||
|
NUMERIC_MIN_VALUE 0
|
||||||
|
NUMERIC_MAX_VALUE 18446744073709551615
|
||||||
|
NUMERIC_BLOCK_SIZE 1
|
||||||
|
ENUM_VALUE_LIST NULL
|
||||||
|
READ_ONLY NO
|
||||||
|
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||||
VARIABLE_NAME IN_TRANSACTION
|
VARIABLE_NAME IN_TRANSACTION
|
||||||
SESSION_VALUE 0
|
SESSION_VALUE 0
|
||||||
GLOBAL_VALUE NULL
|
GLOBAL_VALUE NULL
|
||||||
|
@ -180,7 +180,7 @@ CREATE TABLE t1 (a INT DEFAULT 10);
|
|||||||
INSERT INTO t1 VALUES (11);
|
INSERT INTO t1 VALUES (11);
|
||||||
CREATE VIEW v1 AS SELECT a AS a FROM t1;
|
CREATE VIEW v1 AS SELECT a AS a FROM t1;
|
||||||
CREATE VIEW v2 AS SELECT DEFAULT(a) AS a FROM t1;
|
CREATE VIEW v2 AS SELECT DEFAULT(a) AS a FROM t1;
|
||||||
CREATE VIEW v3 AS SELECT VALUES(a) AS a FROM t1;
|
CREATE VIEW v3 AS SELECT VALUE(a) AS a FROM t1;
|
||||||
SELECT * FROM v1;
|
SELECT * FROM v1;
|
||||||
SELECT * FROM v2;
|
SELECT * FROM v2;
|
||||||
SELECT * FROM v3;
|
SELECT * FROM v3;
|
||||||
@ -447,7 +447,7 @@ CALL p1;
|
|||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
|
||||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
CREATE TABLE t1 (a INT DEFAULT VALUES(a));
|
CREATE TABLE t1 (a INT DEFAULT VALUE(a));
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE t1 (a INT);
|
CREATE TABLE t1 (a INT);
|
||||||
|
@ -179,16 +179,16 @@ SELECT UPDATEXML(-73 * -2465717823867977728,@@global.auto_increment_increment,nu
|
|||||||
CREATE TABLE t1 (a INT);
|
CREATE TABLE t1 (a INT);
|
||||||
CREATE TABLE t2(a INT PRIMARY KEY, b INT);
|
CREATE TABLE t2(a INT PRIMARY KEY, b INT);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
SELECT '' AS b FROM t1 GROUP BY VALUES(b);
|
SELECT '' AS b FROM t1 GROUP BY VALUE(b);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
REPLACE t2(b) SELECT '' AS b FROM t1 GROUP BY VALUES(b);
|
REPLACE t2(b) SELECT '' AS b FROM t1 GROUP BY VALUE(b);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
UPDATE t2 SET a=(SELECT '' AS b FROM t1 GROUP BY VALUES(b));
|
UPDATE t2 SET a=(SELECT '' AS b FROM t1 GROUP BY VALUE(b));
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
INSERT INTO t2 VALUES (1,0) ON DUPLICATE KEY UPDATE
|
INSERT INTO t2 VALUES (1,0) ON DUPLICATE KEY UPDATE
|
||||||
b=(SELECT '' AS b FROM t1 GROUP BY VALUES(b));
|
b=(SELECT '' AS b FROM t1 GROUP BY VALUE(b));
|
||||||
INSERT INTO t2(a,b) VALUES (1,0) ON DUPLICATE KEY UPDATE
|
INSERT INTO t2(a,b) VALUES (1,0) ON DUPLICATE KEY UPDATE
|
||||||
b=(SELECT VALUES(a)+2 FROM t1);
|
b=(SELECT VALUE(a)+2 FROM t1);
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -168,7 +168,7 @@ set storage_engine=innodb;
|
|||||||
|
|
||||||
create table y select 1 b;
|
create table y select 1 b;
|
||||||
select 1 from y group by b;
|
select 1 from y group by b;
|
||||||
select 1 from y group by values(b);
|
select 1 from y group by value(b);
|
||||||
drop table y;
|
drop table y;
|
||||||
SET storage_engine=@old_engine;
|
SET storage_engine=@old_engine;
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
|||||||
INSERT INTO t1 VALUES (1,10);
|
INSERT INTO t1 VALUES (1,10);
|
||||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||||
|
|
||||||
EXPLAIN EXTENDED SELECT VALUES(b) FROM v1;
|
EXPLAIN EXTENDED SELECT VALUE(b) FROM v1;
|
||||||
|
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -3,5 +3,5 @@
|
|||||||
#
|
#
|
||||||
create table t1 (a int);
|
create table t1 (a int);
|
||||||
insert into t1 values (1),(2);
|
insert into t1 values (1),(2);
|
||||||
select max('foo') from t1 group by values(a), extractvalue('bar','qux') order by "v";
|
select max('foo') from t1 group by value(a), extractvalue('bar','qux') order by "v";
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -22,9 +22,9 @@ SELECT * FROM t1;
|
|||||||
INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0;
|
INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
||||||
SELECT *, VALUES(a) FROM t1;
|
SELECT *, VALUE(a) FROM t1;
|
||||||
explain extended SELECT *, VALUES(a) FROM t1;
|
explain extended SELECT *, VALUE(a) FROM t1;
|
||||||
explain extended select * from t1 where values(a);
|
explain extended select * from t1 where value(a);
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -79,7 +79,7 @@ SELECT * FROM t1;
|
|||||||
--error ER_NON_UNIQ_ERROR
|
--error ER_NON_UNIQ_ERROR
|
||||||
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a);
|
||||||
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a);
|
INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a);
|
||||||
SELECT *, VALUES(a) FROM t1;
|
SELECT *, VALUE(a) FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
|
|
||||||
|
286
mysql-test/t/opt_tvc.test
Normal file
286
mysql-test/t/opt_tvc.test
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
create table t1 (a int, b int);
|
||||||
|
|
||||||
|
insert into t1
|
||||||
|
values (1,2), (4,6), (9,7),
|
||||||
|
(1,1), (2,5), (7,8);
|
||||||
|
|
||||||
|
create table t2 (a int, b int, c int);
|
||||||
|
|
||||||
|
insert into t2
|
||||||
|
values (1,2,3), (5,1,2), (4,3,7),
|
||||||
|
(8,9,0), (10,7,1), (5,5,1);
|
||||||
|
|
||||||
|
create table t3 (a int, b varchar(16), index idx(a));
|
||||||
|
insert into t3 values
|
||||||
|
(1, "abc"), (3, "egh"), (8, "axxx"), (10, "abc"),
|
||||||
|
(2, "ccw"), (8, "wqqe"), (7, "au"), (9, "waa"),
|
||||||
|
(3, "rass"), (9, "ert"), (9, "lok"), (8, "aww"),
|
||||||
|
(1, "todd"), (3, "rew"), (8, "aww"), (3, "sw"),
|
||||||
|
(11, "llk"), (7, "rbw"), (1, "sm"), (2, "jyp"),
|
||||||
|
(4, "yq"), (5, "pled"), (12, "ligin"), (12, "toww"),
|
||||||
|
(6, "mxm"), (15, "wanone"), (9, "sunqq"), (2, "abe");
|
||||||
|
|
||||||
|
--echo # optimization is not used
|
||||||
|
|
||||||
|
let $query= select * from t1 where a in (1,2);
|
||||||
|
eval $query;
|
||||||
|
eval explain extended $query;
|
||||||
|
|
||||||
|
--echo # set minimum number of values in VALUEs list when optimization works to 2
|
||||||
|
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
|
||||||
|
--echo # single IN-predicate in WHERE-part
|
||||||
|
|
||||||
|
let $query= select * from t1 where a in (1,2);
|
||||||
|
|
||||||
|
let $optimized_query=
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2)) as tvc_0
|
||||||
|
);
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # AND-condition with IN-predicates in WHERE-part
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from t1
|
||||||
|
where a in (1,2) and
|
||||||
|
b in (1,5);
|
||||||
|
|
||||||
|
let $optimized_query=
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2)) as tvc_0
|
||||||
|
)
|
||||||
|
and b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(5)) as tvc_1
|
||||||
|
);
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # subquery with IN-predicate
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select a
|
||||||
|
from t2 where b in (3,4)
|
||||||
|
);
|
||||||
|
|
||||||
|
let $optimized_query=
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select a from t2
|
||||||
|
where b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (3),(4)) as tvc_0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # derived table with IN-predicate
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
) as dr_table;
|
||||||
|
|
||||||
|
let $optimized_query=
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
) as dr_table;
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # non-recursive CTE with IN-predicate
|
||||||
|
|
||||||
|
let $cte_query=
|
||||||
|
with tvc_0 as
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
)
|
||||||
|
select * from tvc_0;
|
||||||
|
|
||||||
|
eval $cte_query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $cte_query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # VIEW with IN-predicate
|
||||||
|
|
||||||
|
create view v1 as
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2);
|
||||||
|
|
||||||
|
create view v2 as
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
let $query= select * from v1;
|
||||||
|
let $optimized_query= select * from v2;
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
drop view v1,v2;
|
||||||
|
|
||||||
|
--echo # subselect defined by derived table with IN-predicate
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select 1
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in (1,2)
|
||||||
|
)
|
||||||
|
as dr_table
|
||||||
|
);
|
||||||
|
|
||||||
|
let $optimized_query=
|
||||||
|
select * from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select 1
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from t1
|
||||||
|
where a in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (1),(2))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
as dr_table
|
||||||
|
);
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # derived table with IN-predicate and group by
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select max(a),b
|
||||||
|
from t1
|
||||||
|
where b in (3,5)
|
||||||
|
group by b
|
||||||
|
) as dr_table;
|
||||||
|
|
||||||
|
let $optimized_query=
|
||||||
|
select * from
|
||||||
|
(
|
||||||
|
select max(a),b
|
||||||
|
from t1
|
||||||
|
where b in
|
||||||
|
(
|
||||||
|
select *
|
||||||
|
from (values (3),(5))
|
||||||
|
as tvc_0
|
||||||
|
)
|
||||||
|
group by b
|
||||||
|
) as dr_table;
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval $optimized_query;
|
||||||
|
eval explain extended $query;
|
||||||
|
eval explain extended $optimized_query;
|
||||||
|
|
||||||
|
--echo # prepare statement
|
||||||
|
|
||||||
|
prepare stmt from "select * from t1 where a in (1,2)";
|
||||||
|
execute stmt;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
|
||||||
|
--echo # use inside out access from tvc rows
|
||||||
|
|
||||||
|
let $query= select * from t3 where a in (1,4,10);
|
||||||
|
set @@in_subquery_conversion_threshold= default;
|
||||||
|
eval $query;
|
||||||
|
eval explain extended $query;
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
eval $query;
|
||||||
|
eval explain extended $query;
|
||||||
|
|
||||||
|
--echo # use vectors in IN predeicate
|
||||||
|
|
||||||
|
set @@in_subquery_conversion_threshold= 4;
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from t1 where (a,b) in ((1,2),(3,4));
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval explain extended $query;
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
|
||||||
|
--echo # trasformation works for the one IN predicate and doesn't work for the other
|
||||||
|
|
||||||
|
set @@in_subquery_conversion_threshold= 5;
|
||||||
|
|
||||||
|
let $query=
|
||||||
|
select * from t2
|
||||||
|
where (a,b) in ((1,2),(8,9)) and
|
||||||
|
(a,c) in ((1,3),(8,0),(5,1));
|
||||||
|
|
||||||
|
eval $query;
|
||||||
|
eval explain extended $query;
|
||||||
|
set @@in_subquery_conversion_threshold= 2;
|
||||||
|
|
||||||
|
drop table t1, t2, t3;
|
||||||
|
set @@in_subquery_conversion_threshold= default;
|
@ -4283,7 +4283,7 @@ EXECUTE IMMEDIATE MAX('SELECT 1 AS c');
|
|||||||
EXECUTE IMMEDIATE DEFAULT(a);
|
EXECUTE IMMEDIATE DEFAULT(a);
|
||||||
|
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
EXECUTE IMMEDIATE VALUES(a);
|
EXECUTE IMMEDIATE VALUE(a);
|
||||||
|
|
||||||
|
|
||||||
CREATE FUNCTION f1() RETURNS VARCHAR(64) RETURN 't1';
|
CREATE FUNCTION f1() RETURNS VARCHAR(64) RETURN 't1';
|
||||||
|
@ -5299,7 +5299,7 @@ insert into t3 (id, county) values (1, 'York')|
|
|||||||
|
|
||||||
create procedure bug15441(c varchar(25))
|
create procedure bug15441(c varchar(25))
|
||||||
begin
|
begin
|
||||||
update t3 set id=2, county=values(c);
|
update t3 set id=2, county=value(c);
|
||||||
end|
|
end|
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
call bug15441('county')|
|
call bug15441('county')|
|
||||||
@ -5326,7 +5326,7 @@ begin
|
|||||||
on duplicate key update county= values(county);
|
on duplicate key update county= values(county);
|
||||||
select * from t3;
|
select * from t3;
|
||||||
|
|
||||||
update t3 set id=2, county=values(id);
|
update t3 set id=2, county=value(id);
|
||||||
select * from t3;
|
select * from t3;
|
||||||
end|
|
end|
|
||||||
call bug15441('Yale')|
|
call bug15441('Yale')|
|
||||||
|
1046
mysql-test/t/table_value_constr.test
Normal file
1046
mysql-test/t/table_value_constr.test
Normal file
File diff suppressed because it is too large
Load Diff
@ -1521,7 +1521,7 @@ set session rand_seed1=DEFAULT;
|
|||||||
# Bug #14211565 CRASH WHEN ATTEMPTING TO SET SYSTEM VARIABLE TO RESULT OF VALUES()
|
# Bug #14211565 CRASH WHEN ATTEMPTING TO SET SYSTEM VARIABLE TO RESULT OF VALUES()
|
||||||
#
|
#
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
set autocommit = values(v);
|
set autocommit = value(v);
|
||||||
|
|
||||||
#
|
#
|
||||||
# MDEV-6673 I_S.SESSION_VARIABLES shows global values
|
# MDEV-6673 I_S.SESSION_VARIABLES shows global values
|
||||||
|
@ -142,6 +142,7 @@ SET (SQL_SOURCE
|
|||||||
item_windowfunc.cc sql_window.cc
|
item_windowfunc.cc sql_window.cc
|
||||||
sql_cte.cc
|
sql_cte.cc
|
||||||
sql_sequence.cc sql_sequence.h ha_sequence.h
|
sql_sequence.cc sql_sequence.h ha_sequence.h
|
||||||
|
sql_tvc.cc sql_tvc.h
|
||||||
${WSREP_SOURCES}
|
${WSREP_SOURCES}
|
||||||
table_cache.cc encryption.cc temporary_tables.cc
|
table_cache.cc encryption.cc temporary_tables.cc
|
||||||
proxy_protocol.cc
|
proxy_protocol.cc
|
||||||
|
@ -130,6 +130,8 @@ void compute_tokens()
|
|||||||
|
|
||||||
set_token(WITH_CUBE_SYM, "WITH CUBE");
|
set_token(WITH_CUBE_SYM, "WITH CUBE");
|
||||||
set_token(WITH_ROLLUP_SYM, "WITH ROLLUP");
|
set_token(WITH_ROLLUP_SYM, "WITH ROLLUP");
|
||||||
|
set_token(VALUES_IN_SYM, "VALUES IN");
|
||||||
|
set_token(VALUES_LESS_SYM, "VALUES LESS");
|
||||||
set_token(NOT2_SYM, "!");
|
set_token(NOT2_SYM, "!");
|
||||||
set_token(OR2_SYM, "|");
|
set_token(OR2_SYM, "|");
|
||||||
set_token(PARAM_MARKER, "?");
|
set_token(PARAM_MARKER, "?");
|
||||||
|
@ -5778,6 +5778,13 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
Field *from_field= (Field *)not_found_field;
|
Field *from_field= (Field *)not_found_field;
|
||||||
bool outer_fixed= false;
|
bool outer_fixed= false;
|
||||||
|
|
||||||
|
if (thd->lex->current_select->in_tvc)
|
||||||
|
{
|
||||||
|
my_error(ER_FIELD_REFERENCE_IN_TVC, MYF(0),
|
||||||
|
full_name(), thd->where);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!field) // If field is not checked
|
if (!field) // If field is not checked
|
||||||
{
|
{
|
||||||
@ -9194,7 +9201,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items)
|
|||||||
|
|
||||||
void Item_insert_value::print(String *str, enum_query_type query_type)
|
void Item_insert_value::print(String *str, enum_query_type query_type)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN("values("));
|
str->append(STRING_WITH_LEN("value("));
|
||||||
arg->print(str, query_type);
|
arg->print(str, query_type);
|
||||||
str->append(')');
|
str->append(')');
|
||||||
}
|
}
|
||||||
|
@ -1755,6 +1755,8 @@ public:
|
|||||||
virtual Item *derived_grouping_field_transformer_for_where(THD *thd,
|
virtual Item *derived_grouping_field_transformer_for_where(THD *thd,
|
||||||
uchar *arg)
|
uchar *arg)
|
||||||
{ return this; }
|
{ return this; }
|
||||||
|
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
|
||||||
|
{ return this; }
|
||||||
virtual bool expr_cache_is_needed(THD *) { return FALSE; }
|
virtual bool expr_cache_is_needed(THD *) { return FALSE; }
|
||||||
virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
|
virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
|
||||||
bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const
|
bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const
|
||||||
|
@ -4423,6 +4423,26 @@ longlong Item_func_in::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
|
||||||
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
|
||||||
|
Query_arena *arena, backup;
|
||||||
|
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||||
|
|
||||||
|
if (to_be_transformed_into_in_subq(thd))
|
||||||
|
{
|
||||||
|
transform_into_subq= true;
|
||||||
|
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
|
|
||||||
|
emb_on_expr_nest= embedding;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_bit_or::val_int()
|
longlong Item_func_bit_or::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
@ -2280,6 +2280,7 @@ class Item_func_in :public Item_func_opt_neg,
|
|||||||
protected:
|
protected:
|
||||||
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
|
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
|
||||||
Field *field, Item *value);
|
Field *field, Item *value);
|
||||||
|
bool transform_into_subq;
|
||||||
public:
|
public:
|
||||||
/// An array of values, created when the bisection lookup method is used
|
/// An array of values, created when the bisection lookup method is used
|
||||||
in_vector *array;
|
in_vector *array;
|
||||||
@ -2296,11 +2297,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool arg_types_compatible;
|
bool arg_types_compatible;
|
||||||
|
|
||||||
|
TABLE_LIST *emb_on_expr_nest;
|
||||||
|
|
||||||
Item_func_in(THD *thd, List<Item> &list):
|
Item_func_in(THD *thd, List<Item> &list):
|
||||||
Item_func_opt_neg(thd, list),
|
Item_func_opt_neg(thd, list),
|
||||||
Predicant_to_list_comparator(thd, arg_count - 1),
|
Predicant_to_list_comparator(thd, arg_count - 1),
|
||||||
array(0), have_null(0),
|
array(0), have_null(0),
|
||||||
arg_types_compatible(FALSE)
|
arg_types_compatible(FALSE), emb_on_expr_nest(0)
|
||||||
{ }
|
{ }
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
bool fix_fields(THD *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
@ -2392,7 +2395,11 @@ public:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
void mark_as_condition_AND_part(TABLE_LIST *embedding);
|
||||||
|
bool to_be_transformed_into_in_subq(THD *thd);
|
||||||
|
bool create_value_list_for_tvc(THD *thd, List< List<Item> > *values);
|
||||||
|
Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
class cmp_item_row :public cmp_item
|
class cmp_item_row :public cmp_item
|
||||||
|
@ -116,9 +116,10 @@ void Item_subselect::init(st_select_lex *select_lex,
|
|||||||
do not take into account expression inside aggregate functions because
|
do not take into account expression inside aggregate functions because
|
||||||
they can access original table fields
|
they can access original table fields
|
||||||
*/
|
*/
|
||||||
parsing_place= (outer_select->in_sum_expr ? NO_MATTER
|
parsing_place= (outer_select->in_sum_expr ?
|
||||||
: outer_select->parsing_place);
|
NO_MATTER :
|
||||||
if (unit->is_unit_op())
|
outer_select->parsing_place);
|
||||||
|
if (unit->is_unit_op() && unit->first_select()->next_select())
|
||||||
engine= new subselect_union_engine(unit, result, this);
|
engine= new subselect_union_engine(unit, result, this);
|
||||||
else
|
else
|
||||||
engine= new subselect_single_select_engine(select_lex, result, this);
|
engine= new subselect_single_select_engine(select_lex, result, this);
|
||||||
@ -264,6 +265,13 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
|
|||||||
if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
|
||||||
|
{
|
||||||
|
if (sl->tvc)
|
||||||
|
{
|
||||||
|
wrap_tvc_in_derived_table(thd, sl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(res= engine->prepare(thd)))
|
if (!(res= engine->prepare(thd)))
|
||||||
{
|
{
|
||||||
|
@ -266,6 +266,7 @@ public:
|
|||||||
Item* build_clone(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
Item* build_clone(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
||||||
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
||||||
|
|
||||||
|
bool wrap_tvc_in_derived_table(THD *thd, st_select_lex *tvc_sl);
|
||||||
|
|
||||||
friend class select_result_interceptor;
|
friend class select_result_interceptor;
|
||||||
friend class Item_in_optimizer;
|
friend class Item_in_optimizer;
|
||||||
@ -878,6 +879,7 @@ public:
|
|||||||
virtual enum_engine_type engine_type() { return SINGLE_SELECT_ENGINE; }
|
virtual enum_engine_type engine_type() { return SINGLE_SELECT_ENGINE; }
|
||||||
int get_identifier();
|
int get_identifier();
|
||||||
void force_reexecution();
|
void force_reexecution();
|
||||||
|
void change_select(st_select_lex *new_select) { select_lex= new_select; }
|
||||||
|
|
||||||
friend class subselect_hash_sj_engine;
|
friend class subselect_hash_sj_engine;
|
||||||
friend class Item_in_subselect;
|
friend class Item_in_subselect;
|
||||||
|
@ -1065,6 +1065,8 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
if (subq_sel->handle_derived(thd->lex, DT_MERGE))
|
if (subq_sel->handle_derived(thd->lex, DT_MERGE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
if (subq_sel->join->transform_in_predicates_into_in_subq(thd))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
subq_sel->update_used_tables();
|
subq_sel->update_used_tables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7786,3 +7786,7 @@ ER_COMPRESSED_COLUMN_USED_AS_KEY
|
|||||||
eng "Compressed column '%-.192s' can't be used in key specification"
|
eng "Compressed column '%-.192s' can't be used in key specification"
|
||||||
ER_UNKNOWN_COMPRESSION_METHOD
|
ER_UNKNOWN_COMPRESSION_METHOD
|
||||||
eng "Unknown compression method: %s"
|
eng "Unknown compression method: %s"
|
||||||
|
ER_WRONG_NUMBER_OF_VALUES_IN_TVC
|
||||||
|
eng "The used table value constructor has a different number of values"
|
||||||
|
ER_FIELD_REFERENCE_IN_TVC
|
||||||
|
eng "Field reference '%-.192s' can't be used in table value constructor"
|
||||||
|
@ -702,6 +702,7 @@ typedef struct system_variables
|
|||||||
uint idle_write_transaction_timeout;
|
uint idle_write_transaction_timeout;
|
||||||
uint column_compression_threshold;
|
uint column_compression_threshold;
|
||||||
uint column_compression_zlib_level;
|
uint column_compression_zlib_level;
|
||||||
|
ulong in_subquery_conversion_threshold;
|
||||||
} SV;
|
} SV;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6232,6 +6233,64 @@ inline bool lex_string_eq(const LEX_CSTRING *a,
|
|||||||
return strcasecmp(a->str, b->str) != 0;
|
return strcasecmp(a->str, b->str) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Type_holder: public Sql_alloc,
|
||||||
|
public Item_args,
|
||||||
|
public Type_handler_hybrid_field_type,
|
||||||
|
public Type_all_attributes,
|
||||||
|
public Type_geometry_attributes
|
||||||
|
{
|
||||||
|
TYPELIB *m_typelib;
|
||||||
|
bool m_maybe_null;
|
||||||
|
public:
|
||||||
|
Type_holder()
|
||||||
|
:m_typelib(NULL),
|
||||||
|
m_maybe_null(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void set_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; }
|
||||||
|
bool get_maybe_null() const { return m_maybe_null; }
|
||||||
|
|
||||||
|
uint decimal_precision() const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Type_holder is not used directly to create fields, so
|
||||||
|
its virtual decimal_precision() is never called.
|
||||||
|
We should eventually extend create_result_table() to accept
|
||||||
|
an array of Type_holders directly, without having to allocate
|
||||||
|
Item_type_holder's and put them into List<Item>.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void set_geometry_type(uint type)
|
||||||
|
{
|
||||||
|
Type_geometry_attributes::set_geometry_type(type);
|
||||||
|
}
|
||||||
|
uint uint_geometry_type() const
|
||||||
|
{
|
||||||
|
return Type_geometry_attributes::get_geometry_type();
|
||||||
|
}
|
||||||
|
void set_typelib(TYPELIB *typelib)
|
||||||
|
{
|
||||||
|
m_typelib= typelib;
|
||||||
|
}
|
||||||
|
TYPELIB *get_typelib() const
|
||||||
|
{
|
||||||
|
return m_typelib;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aggregate_attributes(THD *thd)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
m_maybe_null|= args[i]->maybe_null;
|
||||||
|
return
|
||||||
|
type_handler()->Item_hybrid_func_fix_attributes(thd,
|
||||||
|
"UNION", this, this,
|
||||||
|
args, arg_count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* MYSQL_SERVER */
|
#endif /* MYSQL_SERVER */
|
||||||
|
|
||||||
#endif /* SQL_CLASS_INCLUDED */
|
#endif /* SQL_CLASS_INCLUDED */
|
||||||
|
@ -1306,7 +1306,7 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
|
|||||||
{
|
{
|
||||||
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
|
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
|
||||||
int token;
|
int token;
|
||||||
|
|
||||||
if (lip->lookahead_token >= 0)
|
if (lip->lookahead_token >= 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1349,6 +1349,24 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
|
|||||||
return WITH;
|
return WITH;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case VALUES:
|
||||||
|
if (thd->lex->current_select->parsing_place == IN_UPDATE_ON_DUP_KEY ||
|
||||||
|
thd->lex->current_select->parsing_place == IN_PART_FUNC)
|
||||||
|
return VALUE_SYM;
|
||||||
|
token= lex_one_token(yylval, thd);
|
||||||
|
lip->add_digest_token(token, yylval);
|
||||||
|
switch(token) {
|
||||||
|
case LESS_SYM:
|
||||||
|
return VALUES_LESS_SYM;
|
||||||
|
case IN_SYM:
|
||||||
|
return VALUES_IN_SYM;
|
||||||
|
default:
|
||||||
|
lip->lookahead_yylval= lip->yylval;
|
||||||
|
lip->yylval= NULL;
|
||||||
|
lip->lookahead_token= token;
|
||||||
|
return VALUES;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2224,6 +2242,8 @@ void st_select_lex::init_query()
|
|||||||
m_agg_func_used= false;
|
m_agg_func_used= false;
|
||||||
window_specs.empty();
|
window_specs.empty();
|
||||||
window_funcs.empty();
|
window_funcs.empty();
|
||||||
|
tvc= 0;
|
||||||
|
in_tvc= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void st_select_lex::init_select()
|
void st_select_lex::init_select()
|
||||||
@ -2261,6 +2281,10 @@ void st_select_lex::init_select()
|
|||||||
with_dep= 0;
|
with_dep= 0;
|
||||||
join= 0;
|
join= 0;
|
||||||
lock_type= TL_READ_DEFAULT;
|
lock_type= TL_READ_DEFAULT;
|
||||||
|
tvc= 0;
|
||||||
|
in_funcs.empty();
|
||||||
|
curr_tvc_name= 0;
|
||||||
|
in_tvc= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4180,6 +4204,22 @@ bool SELECT_LEX::merge_subquery(THD *thd, TABLE_LIST *derived,
|
|||||||
if (in_subq->emb_on_expr_nest == NO_JOIN_NEST)
|
if (in_subq->emb_on_expr_nest == NO_JOIN_NEST)
|
||||||
in_subq->emb_on_expr_nest= derived;
|
in_subq->emb_on_expr_nest= derived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint cnt= sizeof(expr_cache_may_be_used)/sizeof(bool);
|
||||||
|
for (uint i= 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
if (subq_select->expr_cache_may_be_used[i])
|
||||||
|
expr_cache_may_be_used[i]= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List_iterator_fast<Item_func_in> it(subq_select->in_funcs);
|
||||||
|
Item_func_in *in_func;
|
||||||
|
while ((in_func= it++))
|
||||||
|
{
|
||||||
|
in_funcs.push_back(in_func, thd->mem_root);
|
||||||
|
if (in_func->emb_on_expr_nest == NO_JOIN_NEST)
|
||||||
|
in_func->emb_on_expr_nest= derived;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walk through child's tables and adjust table map, tablenr,
|
/* Walk through child's tables and adjust table map, tablenr,
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "sql_window.h"
|
#include "sql_window.h"
|
||||||
#include "sql_trigger.h"
|
#include "sql_trigger.h"
|
||||||
#include "sp.h" // enum stored_procedure_type
|
#include "sp.h" // enum stored_procedure_type
|
||||||
|
#include "sql_tvc.h"
|
||||||
|
|
||||||
/* YACC and LEX Definitions */
|
/* YACC and LEX Definitions */
|
||||||
|
|
||||||
@ -881,6 +881,17 @@ public:
|
|||||||
those converted to jtbm nests. The list is emptied when conversion is done.
|
those converted to jtbm nests. The list is emptied when conversion is done.
|
||||||
*/
|
*/
|
||||||
List<Item_in_subselect> sj_subselects;
|
List<Item_in_subselect> sj_subselects;
|
||||||
|
/*
|
||||||
|
List of IN-predicates in this st_select_lex that
|
||||||
|
can be transformed into IN-subselect defined with TVC.
|
||||||
|
*/
|
||||||
|
List<Item_func_in> in_funcs;
|
||||||
|
/*
|
||||||
|
Number of current derived table made with TVC during the
|
||||||
|
transformation of IN-predicate into IN-subquery for this
|
||||||
|
st_select_lex.
|
||||||
|
*/
|
||||||
|
uint curr_tvc_name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
|
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
|
||||||
@ -1017,6 +1028,9 @@ public:
|
|||||||
|
|
||||||
/* it is for correct printing SELECT options */
|
/* it is for correct printing SELECT options */
|
||||||
thr_lock_type lock_type;
|
thr_lock_type lock_type;
|
||||||
|
|
||||||
|
table_value_constr *tvc;
|
||||||
|
bool in_tvc;
|
||||||
|
|
||||||
void init_query();
|
void init_query();
|
||||||
void init_select();
|
void init_select();
|
||||||
@ -1232,7 +1246,7 @@ public:
|
|||||||
ORDER *find_common_window_func_partition_fields(THD *thd);
|
ORDER *find_common_window_func_partition_fields(THD *thd);
|
||||||
|
|
||||||
bool cond_pushdown_is_allowed() const
|
bool cond_pushdown_is_allowed() const
|
||||||
{ return !olap && !explicit_limit; }
|
{ return !olap && !explicit_limit && !tvc; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_non_agg_field_used;
|
bool m_non_agg_field_used;
|
||||||
@ -1256,7 +1270,12 @@ typedef class st_select_lex SELECT_LEX;
|
|||||||
inline bool st_select_lex_unit::is_unit_op ()
|
inline bool st_select_lex_unit::is_unit_op ()
|
||||||
{
|
{
|
||||||
if (!first_select()->next_select())
|
if (!first_select()->next_select())
|
||||||
return 0;
|
{
|
||||||
|
if (first_select()->tvc)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
enum sub_select_type linkage= first_select()->next_select()->linkage;
|
enum sub_select_type linkage= first_select()->next_select()->linkage;
|
||||||
return linkage == UNION_TYPE || linkage == INTERSECT_TYPE ||
|
return linkage == UNION_TYPE || linkage == INTERSECT_TYPE ||
|
||||||
|
@ -352,6 +352,8 @@ enum enum_parsing_place
|
|||||||
IN_ON,
|
IN_ON,
|
||||||
IN_GROUP_BY,
|
IN_GROUP_BY,
|
||||||
IN_ORDER_BY,
|
IN_ORDER_BY,
|
||||||
|
IN_UPDATE_ON_DUP_KEY,
|
||||||
|
IN_PART_FUNC,
|
||||||
PARSING_PLACE_SIZE /* always should be the last */
|
PARSING_PLACE_SIZE /* always should be the last */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1203,6 +1203,11 @@ JOIN::optimize_inner()
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
table_count= select_lex->leaf_tables.elements;
|
table_count= select_lex->leaf_tables.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (select_lex->first_cond_optimization &&
|
||||||
|
transform_in_predicates_into_in_subq(thd))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
// Update used tables after all handling derived table procedures
|
// Update used tables after all handling derived table procedures
|
||||||
select_lex->update_used_tables();
|
select_lex->update_used_tables();
|
||||||
|
|
||||||
@ -14221,7 +14226,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
|
|||||||
equals on top level, or the constant.
|
equals on top level, or the constant.
|
||||||
*/
|
*/
|
||||||
Item *head_item= (!item_const && current_sjm &&
|
Item *head_item= (!item_const && current_sjm &&
|
||||||
current_sjm_head != field_item) ? current_sjm_head: head;
|
current_sjm_head != field_item) ? current_sjm_head: head;
|
||||||
Item *head_real_item= head_item->real_item();
|
Item *head_real_item= head_item->real_item();
|
||||||
if (head_real_item->type() == Item::FIELD_ITEM)
|
if (head_real_item->type() == Item::FIELD_ITEM)
|
||||||
head_item= head_real_item;
|
head_item= head_real_item;
|
||||||
@ -25612,6 +25617,12 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
|
|||||||
void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(thd);
|
DBUG_ASSERT(thd);
|
||||||
|
|
||||||
|
if (tvc)
|
||||||
|
{
|
||||||
|
tvc->print(thd, str, query_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((query_type & QT_SHOW_SELECT_NUMBER) &&
|
if ((query_type & QT_SHOW_SELECT_NUMBER) &&
|
||||||
thd->lex->all_selects_list &&
|
thd->lex->all_selects_list &&
|
||||||
|
@ -1676,6 +1676,7 @@ public:
|
|||||||
bool inject_cond_into_where(Item *injected_cond);
|
bool inject_cond_into_where(Item *injected_cond);
|
||||||
bool push_splitting_cond_into_derived(THD *thd, Item *cond);
|
bool push_splitting_cond_into_derived(THD *thd, Item *cond);
|
||||||
bool improve_chosen_plan(THD *thd);
|
bool improve_chosen_plan(THD *thd);
|
||||||
|
bool transform_in_predicates_into_in_subq(THD *thd);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Create a temporary table to be used for processing DISTINCT/ORDER
|
Create a temporary table to be used for processing DISTINCT/ORDER
|
||||||
|
834
sql/sql_tvc.cc
Normal file
834
sql/sql_tvc.cc
Normal file
@ -0,0 +1,834 @@
|
|||||||
|
#include "sql_list.h"
|
||||||
|
#include "sql_tvc.h"
|
||||||
|
#include "sql_class.h"
|
||||||
|
#include "opt_range.h"
|
||||||
|
#include "sql_select.h"
|
||||||
|
#include "sql_explain.h"
|
||||||
|
#include "sql_parse.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Fix fields for TVC values
|
||||||
|
|
||||||
|
@param
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param li The iterator on the list of lists
|
||||||
|
|
||||||
|
@details
|
||||||
|
Call fix_fields procedure for TVC values.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
true if an error was reported
|
||||||
|
false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool fix_fields_for_tvc(THD *thd, List_iterator_fast<List_item> &li)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("fix_fields_for_tvc");
|
||||||
|
List_item *lst;
|
||||||
|
li.rewind();
|
||||||
|
|
||||||
|
while ((lst= li++))
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> it(*lst);
|
||||||
|
Item *item;
|
||||||
|
|
||||||
|
while ((item= it++))
|
||||||
|
{
|
||||||
|
if (item->fix_fields(thd, 0))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Defines types of matrix columns elements where matrix rows are defined by
|
||||||
|
some lists of values.
|
||||||
|
|
||||||
|
@param
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param li The iterator on the list of lists
|
||||||
|
@param holders The structure where types of matrix columns are stored
|
||||||
|
@param first_list_el_count Count of the list values. It should be the same
|
||||||
|
for each list of lists elements. It contains
|
||||||
|
number of elements of the first list from list of
|
||||||
|
lists.
|
||||||
|
|
||||||
|
@details
|
||||||
|
For each list list_a from list of lists the procedure gets its elements
|
||||||
|
types and aggregates them with the previous ones stored in holders. If
|
||||||
|
list_a is the first one in the list of lists its elements types are put in
|
||||||
|
holders. The errors can be reported when count of list_a elements is
|
||||||
|
different from the first_list_el_count. Also error can be reported whe
|
||||||
|
n aggregation can't be made.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
true if an error was reported
|
||||||
|
false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool join_type_handlers_for_tvc(THD *thd, List_iterator_fast<List_item> &li,
|
||||||
|
Type_holder *holders, uint first_list_el_count)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("join_type_handlers_for_tvc");
|
||||||
|
List_item *lst;
|
||||||
|
li.rewind();
|
||||||
|
bool first= true;
|
||||||
|
|
||||||
|
while ((lst= li++))
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> it(*lst);
|
||||||
|
Item *item;
|
||||||
|
|
||||||
|
if (first_list_el_count != lst->elements)
|
||||||
|
{
|
||||||
|
my_message(ER_WRONG_NUMBER_OF_VALUES_IN_TVC,
|
||||||
|
ER_THD(thd, ER_WRONG_NUMBER_OF_VALUES_IN_TVC),
|
||||||
|
MYF(0));
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
for (uint pos= 0; (item=it++); pos++)
|
||||||
|
{
|
||||||
|
const Type_handler *item_type_handler= item->real_type_handler();
|
||||||
|
if (first)
|
||||||
|
holders[pos].set_handler(item_type_handler);
|
||||||
|
else if (holders[pos].aggregate_for_result(item_type_handler))
|
||||||
|
{
|
||||||
|
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||||
|
holders[pos].type_handler()->name().ptr(),
|
||||||
|
item_type_handler->name().ptr(),
|
||||||
|
"TABLE VALUE CONSTRUCTOR");
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first= false;
|
||||||
|
}
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Define attributes of matrix columns elements where matrix rows are defined
|
||||||
|
by some lists of values.
|
||||||
|
|
||||||
|
@param
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param li The iterator on the list of lists
|
||||||
|
@param holders The structure where names of matrix columns are stored
|
||||||
|
@param count_of_lists Count of list of lists elements
|
||||||
|
@param first_list_el_count Count of the list values. It should be the same
|
||||||
|
for each list of lists elements. It contains
|
||||||
|
number of elements of the first list from list
|
||||||
|
of lists.
|
||||||
|
|
||||||
|
@details
|
||||||
|
For each list list_a from list of lists the procedure gets its elements
|
||||||
|
attributes and aggregates them with the previous ones stored in holders.
|
||||||
|
The errors can be reported when aggregation can't be made.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
true if an error was reported
|
||||||
|
false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool get_type_attributes_for_tvc(THD *thd,
|
||||||
|
List_iterator_fast<List_item> &li,
|
||||||
|
Type_holder *holders, uint count_of_lists,
|
||||||
|
uint first_list_el_count)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("get_type_attributes_for_tvc");
|
||||||
|
List_item *lst;
|
||||||
|
li.rewind();
|
||||||
|
|
||||||
|
for (uint pos= 0; pos < first_list_el_count; pos++)
|
||||||
|
{
|
||||||
|
if (holders[pos].alloc_arguments(thd, count_of_lists))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((lst= li++))
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> it(*lst);
|
||||||
|
Item *item;
|
||||||
|
for (uint holder_pos= 0 ; (item= it++); holder_pos++)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->fixed);
|
||||||
|
holders[holder_pos].add_argument(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint pos= 0; pos < first_list_el_count; pos++)
|
||||||
|
{
|
||||||
|
if (holders[pos].aggregate_attributes(thd))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Prepare of TVC
|
||||||
|
|
||||||
|
@param
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param sl The select where this TVC is defined
|
||||||
|
@param tmp_result Structure that contains the information
|
||||||
|
about where to send the result of the query
|
||||||
|
@param unit_arg The union where sl is defined
|
||||||
|
|
||||||
|
@details
|
||||||
|
Gets types and attributes of values of this TVC that will be used
|
||||||
|
for temporary table creation for this TVC. It creates Item_type_holders
|
||||||
|
for each element of the first list from list of lists (VALUES from tvc),
|
||||||
|
using its elements name, defined type and attribute.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
true if an error was reported
|
||||||
|
false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool table_value_constr::prepare(THD *thd, SELECT_LEX *sl,
|
||||||
|
select_result *tmp_result,
|
||||||
|
st_select_lex_unit *unit_arg)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("table_value_constr::prepare");
|
||||||
|
select_lex->in_tvc= true;
|
||||||
|
List_iterator_fast<List_item> li(lists_of_values);
|
||||||
|
|
||||||
|
List_item *first_elem= li++;
|
||||||
|
uint cnt= first_elem->elements;
|
||||||
|
Type_holder *holders;
|
||||||
|
|
||||||
|
if (fix_fields_for_tvc(thd, li))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
if (!(holders= new (thd->mem_root)
|
||||||
|
Type_holder[cnt]) ||
|
||||||
|
join_type_handlers_for_tvc(thd, li, holders,
|
||||||
|
cnt) ||
|
||||||
|
get_type_attributes_for_tvc(thd, li, holders,
|
||||||
|
lists_of_values.elements, cnt))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
List_iterator_fast<Item> it(*first_elem);
|
||||||
|
Item *item;
|
||||||
|
|
||||||
|
sl->item_list.empty();
|
||||||
|
for (uint pos= 0; (item= it++); pos++)
|
||||||
|
{
|
||||||
|
/* Error's in 'new' will be detected after loop */
|
||||||
|
Item_type_holder *new_holder= new (thd->mem_root)
|
||||||
|
Item_type_holder(thd,
|
||||||
|
&item->name,
|
||||||
|
holders[pos].type_handler(),
|
||||||
|
&holders[pos]/*Type_all_attributes*/,
|
||||||
|
holders[pos].get_maybe_null());
|
||||||
|
new_holder->fix_fields(thd, 0);
|
||||||
|
sl->item_list.push_back(new_holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thd->is_fatal_error)
|
||||||
|
DBUG_RETURN(true); // out of memory
|
||||||
|
|
||||||
|
result= tmp_result;
|
||||||
|
|
||||||
|
if (result && result->prepare(sl->item_list, unit_arg))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
select_lex->in_tvc= false;
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Save Query Plan Footprint
|
||||||
|
*/
|
||||||
|
|
||||||
|
int table_value_constr::save_explain_data_intern(THD *thd,
|
||||||
|
Explain_query *output)
|
||||||
|
{
|
||||||
|
const char *message= "No tables used";
|
||||||
|
DBUG_ENTER("table_value_constr::save_explain_data_intern");
|
||||||
|
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
|
||||||
|
(ulong)select_lex, select_lex->type,
|
||||||
|
message));
|
||||||
|
DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
|
||||||
|
|
||||||
|
/* There should be no attempts to save query plans for merged selects */
|
||||||
|
DBUG_ASSERT(!select_lex->master_unit()->derived ||
|
||||||
|
select_lex->master_unit()->derived->is_materialized_derived() ||
|
||||||
|
select_lex->master_unit()->derived->is_with_table());
|
||||||
|
|
||||||
|
explain= new (output->mem_root) Explain_select(output->mem_root,
|
||||||
|
thd->lex->analyze_stmt);
|
||||||
|
select_lex->set_explain_type(true);
|
||||||
|
|
||||||
|
explain->select_id= select_lex->select_number;
|
||||||
|
explain->select_type= select_lex->type;
|
||||||
|
explain->linkage= select_lex->linkage;
|
||||||
|
explain->using_temporary= NULL;
|
||||||
|
explain->using_filesort= NULL;
|
||||||
|
/* Setting explain->message means that all other members are invalid */
|
||||||
|
explain->message= message;
|
||||||
|
|
||||||
|
if (select_lex->master_unit()->derived)
|
||||||
|
explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
|
||||||
|
|
||||||
|
output->add_node(explain);
|
||||||
|
|
||||||
|
if (select_lex->is_top_level_node())
|
||||||
|
output->query_plan_ready();
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Optimization of TVC
|
||||||
|
*/
|
||||||
|
|
||||||
|
void table_value_constr::optimize(THD *thd)
|
||||||
|
{
|
||||||
|
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
|
||||||
|
have_query_plan= QEP_AVAILABLE;
|
||||||
|
|
||||||
|
if (select_lex->select_number != UINT_MAX &&
|
||||||
|
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
|
||||||
|
have_query_plan != QEP_NOT_PRESENT_YET &&
|
||||||
|
thd->lex->explain && // for "SET" command in SPs.
|
||||||
|
(!thd->lex->explain->get_select(select_lex->select_number)))
|
||||||
|
{
|
||||||
|
save_explain_data_intern(thd, thd->lex->explain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute of TVC
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool table_value_constr::exec(SELECT_LEX *sl)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("table_value_constr::exec");
|
||||||
|
List_iterator_fast<List_item> li(lists_of_values);
|
||||||
|
List_item *elem;
|
||||||
|
|
||||||
|
if (select_options & SELECT_DESCRIBE)
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
|
if (result->send_result_set_metadata(sl->item_list,
|
||||||
|
Protocol::SEND_NUM_ROWS |
|
||||||
|
Protocol::SEND_EOF))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((elem= li++))
|
||||||
|
{
|
||||||
|
result->send_data(*elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->send_eof())
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Print list
|
||||||
|
|
||||||
|
@param str The reference on the string representation of the list
|
||||||
|
@param list The list that needed to be print
|
||||||
|
@param query_type The mode of printing
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method saves a string representation of list in the
|
||||||
|
string str.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void print_list_item(String *str, List_item *list,
|
||||||
|
enum_query_type query_type)
|
||||||
|
{
|
||||||
|
bool is_first_elem= true;
|
||||||
|
List_iterator_fast<Item> it(*list);
|
||||||
|
Item *item;
|
||||||
|
|
||||||
|
str->append('(');
|
||||||
|
|
||||||
|
while ((item= it++))
|
||||||
|
{
|
||||||
|
if (is_first_elem)
|
||||||
|
is_first_elem= false;
|
||||||
|
else
|
||||||
|
str->append(',');
|
||||||
|
|
||||||
|
item->print(str, query_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
str->append(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Print this TVC
|
||||||
|
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param str The reference on the string representation of this TVC
|
||||||
|
@param query_type The mode of printing
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method saves a string representation of this TVC in the
|
||||||
|
string str.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void table_value_constr::print(THD *thd, String *str,
|
||||||
|
enum_query_type query_type)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(thd);
|
||||||
|
|
||||||
|
str->append(STRING_WITH_LEN("values "));
|
||||||
|
|
||||||
|
bool is_first_elem= true;
|
||||||
|
List_iterator_fast<List_item> li(lists_of_values);
|
||||||
|
List_item *list;
|
||||||
|
|
||||||
|
while ((list= li++))
|
||||||
|
{
|
||||||
|
if (is_first_elem)
|
||||||
|
is_first_elem= false;
|
||||||
|
else
|
||||||
|
str->append(',');
|
||||||
|
|
||||||
|
print_list_item(str, list, query_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Create list of lists for TVC from the list of this IN predicate
|
||||||
|
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param values TVC list of values
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method uses the list of values of this IN predicate to build
|
||||||
|
an equivalent list of values that can be used in TVC.
|
||||||
|
|
||||||
|
E.g.:
|
||||||
|
|
||||||
|
<value_list> = 5,2,7
|
||||||
|
<transformed_value_list> = (5),(2),(7)
|
||||||
|
|
||||||
|
<value_list> = (5,2),(7,1)
|
||||||
|
<transformed_value_list> = (5,2),(7,1)
|
||||||
|
|
||||||
|
@retval
|
||||||
|
false if the method succeeds
|
||||||
|
true otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_func_in::create_value_list_for_tvc(THD *thd,
|
||||||
|
List< List<Item> > *values)
|
||||||
|
{
|
||||||
|
bool is_list_of_rows= args[1]->type() == Item::ROW_ITEM;
|
||||||
|
|
||||||
|
for (uint i=1; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
List<Item> *tvc_value;
|
||||||
|
if (!(tvc_value= new (thd->mem_root) List<Item>()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (is_list_of_rows)
|
||||||
|
{
|
||||||
|
Item_row *row_list= (Item_row *)(args[i]);
|
||||||
|
|
||||||
|
for (uint j=0; j < row_list->cols(); j++)
|
||||||
|
{
|
||||||
|
if (tvc_value->push_back(row_list->element_index(j),
|
||||||
|
thd->mem_root))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tvc_value->push_back(args[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (values->push_back(tvc_value, thd->mem_root))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Create name for the derived table defined by TVC
|
||||||
|
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param parent_select The SELECT where derived table is used
|
||||||
|
@param alias The returned created name
|
||||||
|
|
||||||
|
@details
|
||||||
|
Create name for the derived table using current TVC number
|
||||||
|
for this parent_select stored in parent_select
|
||||||
|
|
||||||
|
@retval
|
||||||
|
true if creation fails
|
||||||
|
false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool create_tvc_name(THD *thd, st_select_lex *parent_select,
|
||||||
|
LEX_CSTRING *alias)
|
||||||
|
{
|
||||||
|
char buff[6];
|
||||||
|
|
||||||
|
alias->length= my_snprintf(buff, sizeof(buff),
|
||||||
|
"tvc_%u", parent_select->curr_tvc_name);
|
||||||
|
alias->str= thd->strmake(buff, alias->length);
|
||||||
|
if (!alias->str)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_subselect::wrap_tvc_in_derived_table(THD *thd,
|
||||||
|
st_select_lex *tvc_sl)
|
||||||
|
{
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
/* SELECT_LEX object where the transformation is performed */
|
||||||
|
SELECT_LEX *parent_select= lex->current_select;
|
||||||
|
uint8 save_derived_tables= lex->derived_tables;
|
||||||
|
|
||||||
|
Query_arena backup;
|
||||||
|
Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create SELECT_LEX of the subquery SQ used in the result of transformation
|
||||||
|
*/
|
||||||
|
lex->current_select= tvc_sl;
|
||||||
|
if (mysql_new_select(lex, 0, NULL))
|
||||||
|
goto err;
|
||||||
|
mysql_init_select(lex);
|
||||||
|
/* Create item list as '*' for the subquery SQ */
|
||||||
|
Item *item;
|
||||||
|
SELECT_LEX *sq_select; // select for IN subquery;
|
||||||
|
sq_select= lex->current_select;
|
||||||
|
sq_select->linkage= tvc_sl->linkage;
|
||||||
|
sq_select->parsing_place= SELECT_LIST;
|
||||||
|
item= new (thd->mem_root) Item_field(thd, &sq_select->context,
|
||||||
|
NULL, NULL, &star_clex_str);
|
||||||
|
if (item == NULL || add_item_to_list(thd, item))
|
||||||
|
goto err;
|
||||||
|
(sq_select->with_wild)++;
|
||||||
|
|
||||||
|
/* Exclude SELECT with TVC */
|
||||||
|
tvc_sl->exclude();
|
||||||
|
/*
|
||||||
|
Create derived table DT that will wrap TVC in the result of transformation
|
||||||
|
*/
|
||||||
|
SELECT_LEX *tvc_select; // select for tvc
|
||||||
|
SELECT_LEX_UNIT *derived_unit; // unit for tvc_select
|
||||||
|
if (mysql_new_select(lex, 1, tvc_sl))
|
||||||
|
goto err;
|
||||||
|
tvc_select= lex->current_select;
|
||||||
|
derived_unit= tvc_select->master_unit();
|
||||||
|
tvc_select->linkage= DERIVED_TABLE_TYPE;
|
||||||
|
|
||||||
|
lex->current_select= sq_select;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create the name of the wrapping derived table and
|
||||||
|
add it to the FROM list of the subquery SQ
|
||||||
|
*/
|
||||||
|
Table_ident *ti;
|
||||||
|
LEX_CSTRING alias;
|
||||||
|
TABLE_LIST *derived_tab;
|
||||||
|
if (!(ti= new (thd->mem_root) Table_ident(derived_unit)) ||
|
||||||
|
create_tvc_name(thd, parent_select, &alias))
|
||||||
|
goto err;
|
||||||
|
if (!(derived_tab=
|
||||||
|
sq_select->add_table_to_list(thd,
|
||||||
|
ti, &alias, 0,
|
||||||
|
TL_READ, MDL_SHARED_READ)))
|
||||||
|
goto err;
|
||||||
|
sq_select->add_joined_table(derived_tab);
|
||||||
|
sq_select->add_where_field(derived_unit->first_select());
|
||||||
|
sq_select->context.table_list= sq_select->table_list.first;
|
||||||
|
sq_select->context.first_name_resolution_table= sq_select->table_list.first;
|
||||||
|
sq_select->table_list.first->derived_type= DTYPE_TABLE | DTYPE_MATERIALIZE;
|
||||||
|
lex->derived_tables|= DERIVED_SUBQUERY;
|
||||||
|
|
||||||
|
sq_select->where= 0;
|
||||||
|
sq_select->set_braces(false);
|
||||||
|
derived_unit->set_with_clause(0);
|
||||||
|
|
||||||
|
if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
|
||||||
|
((subselect_single_select_engine *) engine)->change_select(sq_select);
|
||||||
|
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
|
lex->current_select= sq_select;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
|
lex->derived_tables= save_derived_tables;
|
||||||
|
lex->current_select= parent_select;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Transform IN predicate into IN subquery
|
||||||
|
|
||||||
|
@param thd The context of the statement
|
||||||
|
@param arg Not used
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method transforms this IN predicate into in equivalent IN subquery:
|
||||||
|
|
||||||
|
<left_expr> IN (<value_list>)
|
||||||
|
=>
|
||||||
|
<left_expr> IN (SELECT * FROM (VALUES <transformed_value_list>) AS tvc_#)
|
||||||
|
|
||||||
|
E.g.:
|
||||||
|
|
||||||
|
<value_list> = 5,2,7
|
||||||
|
<transformed_value_list> = (5),(2),(7)
|
||||||
|
|
||||||
|
<value_list> = (5,2),(7,1)
|
||||||
|
<transformed_value_list> = (5,2),(7,1)
|
||||||
|
|
||||||
|
If the transformation succeeds the method returns the result IN subquery,
|
||||||
|
otherwise this IN predicate is returned.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
pointer to the result of transformation if succeeded
|
||||||
|
pointer to this IN predicate otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
if (!transform_into_subq)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
transform_into_subq= false;
|
||||||
|
|
||||||
|
List<List_item> values;
|
||||||
|
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
/* SELECT_LEX object where the transformation is performed */
|
||||||
|
SELECT_LEX *parent_select= lex->current_select;
|
||||||
|
uint8 save_derived_tables= lex->derived_tables;
|
||||||
|
|
||||||
|
for (uint i=1; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (!args[i]->const_item())
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Query_arena backup;
|
||||||
|
Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create SELECT_LEX of the subquery SQ used in the result of transformation
|
||||||
|
*/
|
||||||
|
if (mysql_new_select(lex, 1, NULL))
|
||||||
|
goto err;
|
||||||
|
mysql_init_select(lex);
|
||||||
|
/* Create item list as '*' for the subquery SQ */
|
||||||
|
Item *item;
|
||||||
|
SELECT_LEX *sq_select; // select for IN subquery;
|
||||||
|
sq_select= lex->current_select;
|
||||||
|
sq_select->parsing_place= SELECT_LIST;
|
||||||
|
item= new (thd->mem_root) Item_field(thd, &sq_select->context,
|
||||||
|
NULL, NULL, &star_clex_str);
|
||||||
|
if (item == NULL || add_item_to_list(thd, item))
|
||||||
|
goto err;
|
||||||
|
(sq_select->with_wild)++;
|
||||||
|
/*
|
||||||
|
Create derived table DT that will wrap TVC in the result of transformation
|
||||||
|
*/
|
||||||
|
SELECT_LEX *tvc_select; // select for tvc
|
||||||
|
SELECT_LEX_UNIT *derived_unit; // unit for tvc_select
|
||||||
|
if (mysql_new_select(lex, 1, NULL))
|
||||||
|
goto err;
|
||||||
|
mysql_init_select(lex);
|
||||||
|
tvc_select= lex->current_select;
|
||||||
|
derived_unit= tvc_select->master_unit();
|
||||||
|
tvc_select->linkage= DERIVED_TABLE_TYPE;
|
||||||
|
|
||||||
|
/* Create TVC used in the transformation */
|
||||||
|
if (create_value_list_for_tvc(thd, &values))
|
||||||
|
goto err;
|
||||||
|
if (!(tvc_select->tvc=
|
||||||
|
new (thd->mem_root)
|
||||||
|
table_value_constr(values,
|
||||||
|
tvc_select,
|
||||||
|
tvc_select->options)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
lex->current_select= sq_select;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create the name of the wrapping derived table and
|
||||||
|
add it to the FROM list of the subquery SQ
|
||||||
|
*/
|
||||||
|
Table_ident *ti;
|
||||||
|
LEX_CSTRING alias;
|
||||||
|
TABLE_LIST *derived_tab;
|
||||||
|
if (!(ti= new (thd->mem_root) Table_ident(derived_unit)) ||
|
||||||
|
create_tvc_name(thd, parent_select, &alias))
|
||||||
|
goto err;
|
||||||
|
if (!(derived_tab=
|
||||||
|
sq_select->add_table_to_list(thd,
|
||||||
|
ti, &alias, 0,
|
||||||
|
TL_READ, MDL_SHARED_READ)))
|
||||||
|
goto err;
|
||||||
|
sq_select->add_joined_table(derived_tab);
|
||||||
|
sq_select->add_where_field(derived_unit->first_select());
|
||||||
|
sq_select->context.table_list= sq_select->table_list.first;
|
||||||
|
sq_select->context.first_name_resolution_table= sq_select->table_list.first;
|
||||||
|
sq_select->table_list.first->derived_type= DTYPE_TABLE | DTYPE_MATERIALIZE;
|
||||||
|
lex->derived_tables|= DERIVED_SUBQUERY;
|
||||||
|
|
||||||
|
sq_select->where= 0;
|
||||||
|
sq_select->set_braces(false);
|
||||||
|
derived_unit->set_with_clause(0);
|
||||||
|
|
||||||
|
/* Create IN subquery predicate */
|
||||||
|
sq_select->parsing_place= parent_select->parsing_place;
|
||||||
|
Item_in_subselect *in_subs;
|
||||||
|
if (!(in_subs=
|
||||||
|
new (thd->mem_root) Item_in_subselect(thd, args[0], sq_select)))
|
||||||
|
goto err;
|
||||||
|
in_subs->emb_on_expr_nest= emb_on_expr_nest;
|
||||||
|
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
|
thd->lex->current_select= parent_select;
|
||||||
|
|
||||||
|
if (in_subs->fix_fields(thd, (Item **)&in_subs))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
parent_select->curr_tvc_name++;
|
||||||
|
return in_subs;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (arena)
|
||||||
|
thd->restore_active_arena(arena, &backup);
|
||||||
|
lex->derived_tables= save_derived_tables;
|
||||||
|
thd->lex->current_select= parent_select;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Check if this IN-predicate can be transformed in IN-subquery
|
||||||
|
with TVC
|
||||||
|
|
||||||
|
@param thd The context of the statement
|
||||||
|
|
||||||
|
@details
|
||||||
|
Compare the number of elements in the list of
|
||||||
|
values in this IN-predicate with the
|
||||||
|
in_subquery_conversion_threshold special variable
|
||||||
|
|
||||||
|
@retval
|
||||||
|
true if transformation can be made
|
||||||
|
false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_func_in::to_be_transformed_into_in_subq(THD *thd)
|
||||||
|
{
|
||||||
|
uint values_count= arg_count-1;
|
||||||
|
|
||||||
|
if (args[1]->type() == Item::ROW_ITEM)
|
||||||
|
values_count*= ((Item_row *)(args[1]))->cols();
|
||||||
|
|
||||||
|
if (values_count < thd->variables.in_subquery_conversion_threshold)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Transform IN predicates into IN subqueries in WHERE and ON expressions
|
||||||
|
|
||||||
|
@param thd The context of the statement
|
||||||
|
|
||||||
|
@details
|
||||||
|
For each IN predicate from AND parts of the WHERE condition and/or
|
||||||
|
ON expressions of the SELECT for this join the method performs
|
||||||
|
the intransformation into an equivalent IN sunquery if it's needed.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
false always
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool JOIN::transform_in_predicates_into_in_subq(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("JOIN::transform_in_predicates_into_in_subq");
|
||||||
|
if (!select_lex->in_funcs.elements)
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
|
SELECT_LEX *save_current_select= thd->lex->current_select;
|
||||||
|
enum_parsing_place save_parsing_place= select_lex->parsing_place;
|
||||||
|
thd->lex->current_select= select_lex;
|
||||||
|
if (conds)
|
||||||
|
{
|
||||||
|
select_lex->parsing_place= IN_WHERE;
|
||||||
|
conds=
|
||||||
|
conds->transform(thd,
|
||||||
|
&Item::in_predicate_to_in_subs_transformer,
|
||||||
|
(uchar*) 0);
|
||||||
|
if (!conds)
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
select_lex->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
|
||||||
|
select_lex->where= conds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (join_list)
|
||||||
|
{
|
||||||
|
TABLE_LIST *table;
|
||||||
|
List_iterator<TABLE_LIST> li(*join_list);
|
||||||
|
select_lex->parsing_place= IN_ON;
|
||||||
|
|
||||||
|
while ((table= li++))
|
||||||
|
{
|
||||||
|
if (table->on_expr)
|
||||||
|
{
|
||||||
|
table->on_expr=
|
||||||
|
table->on_expr->transform(thd,
|
||||||
|
&Item::in_predicate_to_in_subs_transformer,
|
||||||
|
(uchar*) 0);
|
||||||
|
if (!table->on_expr)
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
table->prep_on_expr= table->on_expr ?
|
||||||
|
table->on_expr->copy_andor_structure(thd) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select_lex->in_funcs.empty();
|
||||||
|
select_lex->parsing_place= save_parsing_place;
|
||||||
|
thd->lex->current_select= save_current_select;
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
50
sql/sql_tvc.h
Normal file
50
sql/sql_tvc.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef SQL_TVC_INCLUDED
|
||||||
|
#define SQL_TVC_INCLUDED
|
||||||
|
#include "sql_type.h"
|
||||||
|
#include "item.h"
|
||||||
|
|
||||||
|
typedef List<Item> List_item;
|
||||||
|
class select_result;
|
||||||
|
|
||||||
|
class Explain_select;
|
||||||
|
class Explain_query;
|
||||||
|
class Item_func_in;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class table_value_constr
|
||||||
|
@brief Definition of a Table Value Construction(TVC)
|
||||||
|
|
||||||
|
It contains a list of lists of values which this TVC is defined by and
|
||||||
|
reference on SELECT where this TVC is defined.
|
||||||
|
*/
|
||||||
|
class table_value_constr : public Sql_alloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
List<List_item> lists_of_values;
|
||||||
|
select_result *result;
|
||||||
|
SELECT_LEX *select_lex;
|
||||||
|
|
||||||
|
enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE} have_query_plan;
|
||||||
|
|
||||||
|
Explain_select *explain;
|
||||||
|
ulonglong select_options;
|
||||||
|
|
||||||
|
table_value_constr(List<List_item> tvc_values, SELECT_LEX *sl,
|
||||||
|
ulonglong select_options_arg) :
|
||||||
|
lists_of_values(tvc_values), result(0), select_lex(sl),
|
||||||
|
have_query_plan(QEP_NOT_PRESENT_YET), explain(0),
|
||||||
|
select_options(select_options_arg)
|
||||||
|
{ };
|
||||||
|
|
||||||
|
bool prepare(THD *thd_arg, SELECT_LEX *sl,
|
||||||
|
select_result *tmp_result,
|
||||||
|
st_select_lex_unit *unit_arg);
|
||||||
|
|
||||||
|
int save_explain_data_intern(THD *thd_arg,
|
||||||
|
Explain_query *output);
|
||||||
|
void optimize(THD *thd_arg);
|
||||||
|
bool exec(SELECT_LEX *sl);
|
||||||
|
|
||||||
|
void print(THD *thd_arg, String *str, enum_query_type query_type);
|
||||||
|
};
|
||||||
|
#endif /* SQL_TVC_INCLUDED */
|
152
sql/sql_union.cc
152
sql/sql_union.cc
@ -693,64 +693,6 @@ bool st_select_lex_unit::prepare_join(THD *thd_arg, SELECT_LEX *sl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Type_holder: public Sql_alloc,
|
|
||||||
public Item_args,
|
|
||||||
public Type_handler_hybrid_field_type,
|
|
||||||
public Type_all_attributes,
|
|
||||||
public Type_geometry_attributes
|
|
||||||
{
|
|
||||||
TYPELIB *m_typelib;
|
|
||||||
bool m_maybe_null;
|
|
||||||
public:
|
|
||||||
Type_holder()
|
|
||||||
:m_typelib(NULL),
|
|
||||||
m_maybe_null(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void set_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; }
|
|
||||||
bool get_maybe_null() const { return m_maybe_null; }
|
|
||||||
|
|
||||||
uint decimal_precision() const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Type_holder is not used directly to create fields, so
|
|
||||||
its virtual decimal_precision() is never called.
|
|
||||||
We should eventually extend create_result_table() to accept
|
|
||||||
an array of Type_holders directly, without having to allocate
|
|
||||||
Item_type_holder's and put them into List<Item>.
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void set_geometry_type(uint type)
|
|
||||||
{
|
|
||||||
Type_geometry_attributes::set_geometry_type(type);
|
|
||||||
}
|
|
||||||
uint uint_geometry_type() const
|
|
||||||
{
|
|
||||||
return Type_geometry_attributes::get_geometry_type();
|
|
||||||
}
|
|
||||||
void set_typelib(TYPELIB *typelib)
|
|
||||||
{
|
|
||||||
m_typelib= typelib;
|
|
||||||
}
|
|
||||||
TYPELIB *get_typelib() const
|
|
||||||
{
|
|
||||||
return m_typelib;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool aggregate_attributes(THD *thd)
|
|
||||||
{
|
|
||||||
for (uint i= 0; i < arg_count; i++)
|
|
||||||
m_maybe_null|= args[i]->maybe_null;
|
|
||||||
return
|
|
||||||
type_handler()->Item_hybrid_func_fix_attributes(thd,
|
|
||||||
"UNION", this, this,
|
|
||||||
args, arg_count);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Aggregate data type handlers for the "count" leftmost UNION parts.
|
Aggregate data type handlers for the "count" leftmost UNION parts.
|
||||||
*/
|
*/
|
||||||
@ -889,6 +831,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
bool is_union_select;
|
bool is_union_select;
|
||||||
bool have_except= FALSE, have_intersect= FALSE;
|
bool have_except= FALSE, have_intersect= FALSE;
|
||||||
bool instantiate_tmp_table= false;
|
bool instantiate_tmp_table= false;
|
||||||
|
bool single_tvc= !first_sl->next_select() && first_sl->tvc;
|
||||||
DBUG_ENTER("st_select_lex_unit::prepare");
|
DBUG_ENTER("st_select_lex_unit::prepare");
|
||||||
DBUG_ASSERT(thd == thd_arg);
|
DBUG_ASSERT(thd == thd_arg);
|
||||||
DBUG_ASSERT(thd == current_thd);
|
DBUG_ASSERT(thd == current_thd);
|
||||||
@ -915,16 +858,26 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
/* fast reinit for EXPLAIN */
|
/* fast reinit for EXPLAIN */
|
||||||
for (sl= first_sl; sl; sl= sl->next_select())
|
for (sl= first_sl; sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
sl->join->result= result;
|
if (sl->tvc)
|
||||||
select_limit_cnt= HA_POS_ERROR;
|
|
||||||
offset_limit_cnt= 0;
|
|
||||||
if (!sl->join->procedure &&
|
|
||||||
result->prepare(sl->join->fields_list, this))
|
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
sl->tvc->result= result;
|
||||||
|
if (result->prepare(sl->item_list, this))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
sl->tvc->select_options|= SELECT_DESCRIBE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sl->join->result= result;
|
||||||
|
select_limit_cnt= HA_POS_ERROR;
|
||||||
|
offset_limit_cnt= 0;
|
||||||
|
if (!sl->join->procedure &&
|
||||||
|
result->prepare(sl->join->fields_list, this))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
sl->join->select_options|= SELECT_DESCRIBE;
|
||||||
|
sl->join->reinit();
|
||||||
}
|
}
|
||||||
sl->join->select_options|= SELECT_DESCRIBE;
|
|
||||||
sl->join->reinit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
@ -934,7 +887,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
thd_arg->lex->current_select= sl= first_sl;
|
thd_arg->lex->current_select= sl= first_sl;
|
||||||
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
|
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
|
||||||
is_union_select= is_unit_op() || fake_select_lex;
|
is_union_select= is_unit_op() || fake_select_lex || single_tvc;
|
||||||
|
|
||||||
for (SELECT_LEX *s= first_sl; s; s= s->next_select())
|
for (SELECT_LEX *s= first_sl; s; s= s->next_select())
|
||||||
{
|
{
|
||||||
@ -954,8 +907,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
if (is_union_select || is_recursive)
|
if (is_union_select || is_recursive)
|
||||||
{
|
{
|
||||||
if (is_unit_op() && !union_needs_tmp_table() &&
|
if ((is_unit_op() && !union_needs_tmp_table() &&
|
||||||
!have_except && !have_intersect)
|
!have_except && !have_intersect) || single_tvc)
|
||||||
{
|
{
|
||||||
SELECT_LEX *last= first_select();
|
SELECT_LEX *last= first_select();
|
||||||
while (last->next_select())
|
while (last->next_select())
|
||||||
@ -990,7 +943,12 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
if (!is_union_select && !is_recursive)
|
if (!is_union_select && !is_recursive)
|
||||||
{
|
{
|
||||||
if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
|
if (sl->tvc)
|
||||||
|
{
|
||||||
|
if (sl->tvc->prepare(thd_arg, sl, tmp_result, this))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
else if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
|
||||||
is_union_select))
|
is_union_select))
|
||||||
goto err;
|
goto err;
|
||||||
types= first_sl->item_list;
|
types= first_sl->item_list;
|
||||||
@ -999,8 +957,13 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
for (;sl; sl= sl->next_select(), union_part_count++)
|
for (;sl; sl= sl->next_select(), union_part_count++)
|
||||||
{
|
{
|
||||||
if (prepare_join(thd_arg, sl, tmp_result, additional_options,
|
if (sl->tvc)
|
||||||
is_union_select))
|
{
|
||||||
|
if (sl->tvc->prepare(thd_arg, sl, tmp_result, this))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
else if (prepare_join(thd_arg, sl, tmp_result, additional_options,
|
||||||
|
is_union_select))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1310,6 +1273,14 @@ bool st_select_lex_unit::optimize()
|
|||||||
}
|
}
|
||||||
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
|
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
|
if (sl->tvc)
|
||||||
|
{
|
||||||
|
sl->tvc->select_options=
|
||||||
|
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
||||||
|
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
||||||
|
sl->tvc->optimize(thd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
thd->lex->current_select= sl;
|
thd->lex->current_select= sl;
|
||||||
|
|
||||||
if (optimized)
|
if (optimized)
|
||||||
@ -1333,7 +1304,7 @@ bool st_select_lex_unit::optimize()
|
|||||||
we don't calculate found_rows() per union part.
|
we don't calculate found_rows() per union part.
|
||||||
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
|
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
|
||||||
*/
|
*/
|
||||||
sl->join->select_options=
|
sl->join->select_options=
|
||||||
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
||||||
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
||||||
|
|
||||||
@ -1417,15 +1388,28 @@ bool st_select_lex_unit::exec()
|
|||||||
we don't calculate found_rows() per union part.
|
we don't calculate found_rows() per union part.
|
||||||
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
|
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
|
||||||
*/
|
*/
|
||||||
sl->join->select_options=
|
if (sl->tvc)
|
||||||
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
{
|
||||||
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
sl->tvc->select_options=
|
||||||
saved_error= sl->join->optimize();
|
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
||||||
|
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
||||||
|
sl->tvc->optimize(thd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sl->join->select_options=
|
||||||
|
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
|
||||||
|
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
|
||||||
|
saved_error= sl->join->optimize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!saved_error)
|
if (!saved_error)
|
||||||
{
|
{
|
||||||
records_at_start= table->file->stats.records;
|
records_at_start= table->file->stats.records;
|
||||||
sl->join->exec();
|
if (sl->tvc)
|
||||||
|
sl->tvc->exec(sl);
|
||||||
|
else
|
||||||
|
sl->join->exec();
|
||||||
if (sl == union_distinct && !(with_element && with_element->is_recursive))
|
if (sl == union_distinct && !(with_element && with_element->is_recursive))
|
||||||
{
|
{
|
||||||
// This is UNION DISTINCT, so there should be a fake_select_lex
|
// This is UNION DISTINCT, so there should be a fake_select_lex
|
||||||
@ -1434,7 +1418,8 @@ bool st_select_lex_unit::exec()
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
table->no_keyread=1;
|
table->no_keyread=1;
|
||||||
}
|
}
|
||||||
saved_error= sl->join->error;
|
if (!sl->tvc)
|
||||||
|
saved_error= sl->join->error;
|
||||||
offset_limit_cnt= (ha_rows)(sl->offset_limit ?
|
offset_limit_cnt= (ha_rows)(sl->offset_limit ?
|
||||||
sl->offset_limit->val_uint() :
|
sl->offset_limit->val_uint() :
|
||||||
0);
|
0);
|
||||||
@ -1664,8 +1649,13 @@ bool st_select_lex_unit::exec_recursive()
|
|||||||
for (st_select_lex *sl= start ; sl != end; sl= sl->next_select())
|
for (st_select_lex *sl= start ; sl != end; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
thd->lex->current_select= sl;
|
thd->lex->current_select= sl;
|
||||||
sl->join->exec();
|
if (sl->tvc)
|
||||||
saved_error= sl->join->error;
|
sl->tvc->exec(sl);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sl->join->exec();
|
||||||
|
saved_error= sl->join->error;
|
||||||
|
}
|
||||||
if (!saved_error)
|
if (!saved_error)
|
||||||
{
|
{
|
||||||
examined_rows+= thd->get_examined_row_count();
|
examined_rows+= thd->get_examined_row_count();
|
||||||
|
133
sql/sql_yacc.yy
133
sql/sql_yacc.yy
@ -67,6 +67,7 @@
|
|||||||
#include "lex_token.h"
|
#include "lex_token.h"
|
||||||
#include "sql_lex.h"
|
#include "sql_lex.h"
|
||||||
#include "sql_sequence.h"
|
#include "sql_sequence.h"
|
||||||
|
#include "sql_tvc.h"
|
||||||
|
|
||||||
/* this is to get the bison compilation windows warnings out */
|
/* this is to get the bison compilation windows warnings out */
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -1554,6 +1555,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token UTC_TIMESTAMP_SYM
|
%token UTC_TIMESTAMP_SYM
|
||||||
%token UTC_TIME_SYM
|
%token UTC_TIME_SYM
|
||||||
%token VALUES /* SQL-2003-R */
|
%token VALUES /* SQL-2003-R */
|
||||||
|
%token VALUES_IN_SYM
|
||||||
|
%token VALUES_LESS_SYM
|
||||||
%token VALUE_SYM /* SQL-2003-R */
|
%token VALUE_SYM /* SQL-2003-R */
|
||||||
%token VARBINARY
|
%token VARBINARY
|
||||||
%token VARCHAR /* SQL-2003-R */
|
%token VARCHAR /* SQL-2003-R */
|
||||||
@ -1783,7 +1786,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
table_primary_ident table_primary_derived
|
table_primary_ident table_primary_derived
|
||||||
select_derived derived_table_list
|
select_derived derived_table_list
|
||||||
select_derived_union
|
select_derived_union
|
||||||
|
derived_simple_table
|
||||||
derived_query_specification
|
derived_query_specification
|
||||||
|
derived_table_value_constructor
|
||||||
%type <date_time_type> date_time_type;
|
%type <date_time_type> date_time_type;
|
||||||
%type <interval> interval
|
%type <interval> interval
|
||||||
|
|
||||||
@ -1824,11 +1829,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
|
|
||||||
%type <select_lex> subselect
|
%type <select_lex> subselect
|
||||||
get_select_lex get_select_lex_derived
|
get_select_lex get_select_lex_derived
|
||||||
|
simple_table
|
||||||
query_specification
|
query_specification
|
||||||
query_term_union_not_ready
|
query_term_union_not_ready
|
||||||
query_term_union_ready
|
query_term_union_ready
|
||||||
query_expression_body
|
query_expression_body
|
||||||
select_paren_derived
|
select_paren_derived
|
||||||
|
table_value_constructor
|
||||||
|
|
||||||
%type <boolfunc2creator> comp_op
|
%type <boolfunc2creator> comp_op
|
||||||
|
|
||||||
@ -4955,8 +4962,15 @@ part_type_def:
|
|||||||
{ Lex->part_info->part_type= RANGE_PARTITION; }
|
{ Lex->part_info->part_type= RANGE_PARTITION; }
|
||||||
| RANGE_SYM part_column_list
|
| RANGE_SYM part_column_list
|
||||||
{ Lex->part_info->part_type= RANGE_PARTITION; }
|
{ Lex->part_info->part_type= RANGE_PARTITION; }
|
||||||
| LIST_SYM part_func
|
| LIST_SYM
|
||||||
{ Lex->part_info->part_type= LIST_PARTITION; }
|
{
|
||||||
|
Select->parsing_place= IN_PART_FUNC;
|
||||||
|
}
|
||||||
|
part_func
|
||||||
|
{
|
||||||
|
Lex->part_info->part_type= LIST_PARTITION;
|
||||||
|
Select->parsing_place= NO_MATTER;
|
||||||
|
}
|
||||||
| LIST_SYM part_column_list
|
| LIST_SYM part_column_list
|
||||||
{ Lex->part_info->part_type= LIST_PARTITION; }
|
{ Lex->part_info->part_type= LIST_PARTITION; }
|
||||||
;
|
;
|
||||||
@ -5206,7 +5220,7 @@ opt_part_values:
|
|||||||
else
|
else
|
||||||
part_info->part_type= HASH_PARTITION;
|
part_info->part_type= HASH_PARTITION;
|
||||||
}
|
}
|
||||||
| VALUES LESS_SYM THAN_SYM
|
| VALUES_LESS_SYM THAN_SYM
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
partition_info *part_info= lex->part_info;
|
partition_info *part_info= lex->part_info;
|
||||||
@ -5220,7 +5234,7 @@ opt_part_values:
|
|||||||
part_info->part_type= RANGE_PARTITION;
|
part_info->part_type= RANGE_PARTITION;
|
||||||
}
|
}
|
||||||
part_func_max {}
|
part_func_max {}
|
||||||
| VALUES IN_SYM
|
| VALUES_IN_SYM
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
partition_info *part_info= lex->part_info;
|
partition_info *part_info= lex->part_info;
|
||||||
@ -8477,6 +8491,9 @@ select:
|
|||||||
|
|
||||||
select_init:
|
select_init:
|
||||||
SELECT_SYM select_options_and_item_list select_init3
|
SELECT_SYM select_options_and_item_list select_init3
|
||||||
|
| table_value_constructor
|
||||||
|
| table_value_constructor union_list
|
||||||
|
| table_value_constructor union_order_or_limit
|
||||||
| '(' select_paren ')'
|
| '(' select_paren ')'
|
||||||
| '(' select_paren ')' union_list
|
| '(' select_paren ')' union_list
|
||||||
| '(' select_paren ')' union_order_or_limit
|
| '(' select_paren ')' union_order_or_limit
|
||||||
@ -8484,12 +8501,23 @@ select_init:
|
|||||||
|
|
||||||
union_list_part2:
|
union_list_part2:
|
||||||
SELECT_SYM select_options_and_item_list select_init3_union_query_term
|
SELECT_SYM select_options_and_item_list select_init3_union_query_term
|
||||||
|
| table_value_constructor
|
||||||
|
| table_value_constructor union_list
|
||||||
|
| table_value_constructor union_order_or_limit
|
||||||
| '(' select_paren_union_query_term ')'
|
| '(' select_paren_union_query_term ')'
|
||||||
| '(' select_paren_union_query_term ')' union_list
|
| '(' select_paren_union_query_term ')' union_list
|
||||||
| '(' select_paren_union_query_term ')' union_order_or_limit
|
| '(' select_paren_union_query_term ')' union_order_or_limit
|
||||||
;
|
;
|
||||||
|
|
||||||
select_paren:
|
select_paren:
|
||||||
|
{
|
||||||
|
Lex->current_select->set_braces(true);
|
||||||
|
}
|
||||||
|
table_value_constructor
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(Lex->current_select->braces);
|
||||||
|
}
|
||||||
|
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
In order to correctly parse UNION's global ORDER BY we need to
|
In order to correctly parse UNION's global ORDER BY we need to
|
||||||
@ -8539,6 +8567,15 @@ select_paren_view:
|
|||||||
|
|
||||||
/* 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);
|
||||||
|
}
|
||||||
|
table_value_constructor
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(Lex->current_select->braces);
|
||||||
|
$$= Lex->current_select->master_unit()->first_select();
|
||||||
|
}
|
||||||
|
|
|
||||||
{
|
{
|
||||||
Lex->current_select->set_braces(true);
|
Lex->current_select->set_braces(true);
|
||||||
}
|
}
|
||||||
@ -9458,7 +9495,7 @@ column_default_non_parenthesized_expr:
|
|||||||
if ($$ == NULL)
|
if ($$ == NULL)
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
| VALUES '(' simple_ident_nospvar ')'
|
| VALUE_SYM '(' simple_ident_nospvar ')'
|
||||||
{
|
{
|
||||||
$$= new (thd->mem_root) Item_insert_value(thd, Lex->current_context(),
|
$$= new (thd->mem_root) Item_insert_value(thd, Lex->current_context(),
|
||||||
$3);
|
$3);
|
||||||
@ -11254,9 +11291,9 @@ select_derived_union:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
union_list_derived_part2
|
union_list_derived_part2
|
||||||
| derived_query_specification opt_select_lock_type
|
| derived_simple_table opt_select_lock_type
|
||||||
| derived_query_specification order_or_limit opt_select_lock_type
|
| derived_simple_table order_or_limit opt_select_lock_type
|
||||||
| derived_query_specification opt_select_lock_type union_list_derived
|
| derived_simple_table opt_select_lock_type union_list_derived
|
||||||
;
|
;
|
||||||
|
|
||||||
union_list_derived_part2:
|
union_list_derived_part2:
|
||||||
@ -11311,6 +11348,10 @@ select_derived:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
derived_simple_table:
|
||||||
|
derived_query_specification { $$= $1; }
|
||||||
|
| derived_table_value_constructor { $$= $1; }
|
||||||
|
;
|
||||||
/*
|
/*
|
||||||
Similar to query_specification, but for derived tables.
|
Similar to query_specification, but for derived tables.
|
||||||
Example: the inner parenthesized SELECT in this query:
|
Example: the inner parenthesized SELECT in this query:
|
||||||
@ -11325,6 +11366,41 @@ derived_query_specification:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
derived_table_value_constructor:
|
||||||
|
VALUES
|
||||||
|
{
|
||||||
|
LEX *lex=Lex;
|
||||||
|
lex->field_list.empty();
|
||||||
|
lex->many_values.empty();
|
||||||
|
lex->insert_list=0;
|
||||||
|
}
|
||||||
|
values_list
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->derived_tables|= DERIVED_SUBQUERY;
|
||||||
|
if (!lex->expr_allows_subselect ||
|
||||||
|
lex->sql_command == (int)SQLCOM_PURGE)
|
||||||
|
{
|
||||||
|
thd->parse_error();
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
|
||||||
|
mysql_new_select(lex, 1, NULL))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
mysql_init_select(lex);
|
||||||
|
lex->current_select->linkage= DERIVED_TABLE_TYPE;
|
||||||
|
|
||||||
|
if (!(lex->current_select->tvc=
|
||||||
|
new (lex->thd->mem_root) table_value_constr(lex->many_values,
|
||||||
|
lex->current_select,
|
||||||
|
lex->current_select->options)))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
lex->many_values.empty();
|
||||||
|
$$= NULL;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
select_derived2:
|
select_derived2:
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
@ -12630,7 +12706,14 @@ expr_or_default:
|
|||||||
opt_insert_update:
|
opt_insert_update:
|
||||||
/* empty */
|
/* empty */
|
||||||
| ON DUPLICATE_SYM { Lex->duplicates= DUP_UPDATE; }
|
| ON DUPLICATE_SYM { Lex->duplicates= DUP_UPDATE; }
|
||||||
KEY_SYM UPDATE_SYM insert_update_list
|
KEY_SYM UPDATE_SYM
|
||||||
|
{
|
||||||
|
Select->parsing_place= IN_UPDATE_ON_DUP_KEY;
|
||||||
|
}
|
||||||
|
insert_update_list
|
||||||
|
{
|
||||||
|
Select->parsing_place= NO_MATTER;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Update rows in a table */
|
/* Update rows in a table */
|
||||||
@ -16242,6 +16325,31 @@ union_option:
|
|||||||
| ALL { $$=0; }
|
| ALL { $$=0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
simple_table:
|
||||||
|
query_specification { $$= $1; }
|
||||||
|
| table_value_constructor { $$= $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
table_value_constructor:
|
||||||
|
VALUES
|
||||||
|
{
|
||||||
|
LEX *lex=Lex;
|
||||||
|
lex->field_list.empty();
|
||||||
|
lex->many_values.empty();
|
||||||
|
lex->insert_list=0;
|
||||||
|
}
|
||||||
|
values_list
|
||||||
|
{
|
||||||
|
LEX *lex=Lex;
|
||||||
|
$$= lex->current_select;
|
||||||
|
mysql_init_select(Lex);
|
||||||
|
if (!($$->tvc=
|
||||||
|
new (lex->thd->mem_root) table_value_constr(lex->many_values, $$, $$->options)))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
lex->many_values.empty();
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Corresponds to the SQL Standard
|
Corresponds to the SQL Standard
|
||||||
<query specification> ::=
|
<query specification> ::=
|
||||||
@ -16259,12 +16367,12 @@ query_specification:
|
|||||||
;
|
;
|
||||||
|
|
||||||
query_term_union_not_ready:
|
query_term_union_not_ready:
|
||||||
query_specification order_or_limit opt_select_lock_type { $$= $1; }
|
simple_table order_or_limit opt_select_lock_type { $$= $1; }
|
||||||
| '(' select_paren_derived ')' union_order_or_limit { $$= $2; }
|
| '(' select_paren_derived ')' union_order_or_limit { $$= $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
query_term_union_ready:
|
query_term_union_ready:
|
||||||
query_specification opt_select_lock_type { $$= $1; }
|
simple_table opt_select_lock_type { $$= $1; }
|
||||||
| '(' select_paren_derived ')' { $$= $2; }
|
| '(' select_paren_derived ')' { $$= $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -16475,6 +16583,9 @@ view_select:
|
|||||||
*/
|
*/
|
||||||
query_expression_body_view:
|
query_expression_body_view:
|
||||||
SELECT_SYM select_options_and_item_list select_init3_view
|
SELECT_SYM select_options_and_item_list select_init3_view
|
||||||
|
| table_value_constructor
|
||||||
|
| table_value_constructor union_order_or_limit
|
||||||
|
| table_value_constructor union_list_view
|
||||||
| '(' select_paren_view ')'
|
| '(' select_paren_view ')'
|
||||||
| '(' select_paren_view ')' union_order_or_limit
|
| '(' select_paren_view ')' union_order_or_limit
|
||||||
| '(' select_paren_view ')' union_list_view
|
| '(' select_paren_view ')' union_list_view
|
||||||
|
@ -5790,4 +5790,11 @@ static Sys_var_mybool Sys_session_track_state_change(
|
|||||||
ON_CHECK(0),
|
ON_CHECK(0),
|
||||||
ON_UPDATE(update_session_track_state_change));
|
ON_UPDATE(update_session_track_state_change));
|
||||||
|
|
||||||
|
static Sys_var_ulong Sys_in_subquery_conversion_threshold(
|
||||||
|
"in_subquery_conversion_threshold",
|
||||||
|
"The minimum number of scalar elements in the value list of "
|
||||||
|
"IN predicate that triggers its conversion to IN subquery",
|
||||||
|
SESSION_VAR(in_subquery_conversion_threshold), CMD_LINE(OPT_ARG),
|
||||||
|
VALID_RANGE(0, ULONG_MAX), DEFAULT(10000), BLOCK_SIZE(1));
|
||||||
|
|
||||||
#endif //EMBEDDED_LIBRARY
|
#endif //EMBEDDED_LIBRARY
|
||||||
|
Loading…
x
Reference in New Issue
Block a user