mirror of
https://github.com/MariaDB/server.git
synced 2025-12-04 17:23:46 +03:00
MDEV-12387 Push conditions into materialized subqueries
The logic and the implementation scheme are similar with the
MDEV-9197 Pushdown conditions into non-mergeable views/derived tables
How the push down is made on the example:
select * from t1
where a>3 and b>10 and
(a,b) in (select x,max(y) from t2 group by x);
-->
select * from t1
where a>3 and b>10 and
(a,b) in (select x,max(y)
from t2
where x>3
group by x
having max(y)>10);
The implementation scheme:
1. Search for the condition cond that depends only on the fields
from the left part of the IN subquery (left_part)
2. Find fields F_group in the select of the right part of the
IN subquery (right_part) that are used in the GROUP BY
3. Extract from the cond condition cond_where that depends only on the
fields from the left_part that stay at the same places in the left_part
(have the same indexes) as the F_group fields in the projection of the
right_part
4. Transform cond_where so it can be pushed into the WHERE clause of the
right_part and delete cond_where from the cond
5. Transform cond so it can be pushed into the HAVING clause of the right_part
The optimization is made in the
Item_in_subselect::pushdown_cond_for_in_subquery() and is controlled by the
variable condition_pushdown_for_subquery.
New test file in_subq_cond_pushdown.test is created.
There are also some changes made for setup_jtbm_semi_joins().
Now it is decomposed into the 2 procedures: setup_degenerate_jtbm_semi_joins()
that is called before optimize_cond() for cond and setup_jtbm_semi_joins()
that is called after optimize_cond().
New setup_jtbm_semi_joins() is made in the way so that the result of its work is
the same as if it was called before optimize_cond().
The code that is common for pushdown into materialized derived and into materialized
IN subqueries is factored out into pushdown_cond_for_derived(),
Item_in_subselect::pushdown_cond_for_in_subquery() and
st_select_lex::pushdown_cond_into_where_clause().
This commit is contained in:
@@ -632,7 +632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
2 DERIVED t1 system NULL NULL NULL NULL 1 100.00
|
2 DERIVED t1 system NULL NULL NULL NULL 1 100.00
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1
|
Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1
|
||||||
Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `test`.`t2`.`f3` = 6 and `<subquery4>`.`f3` = 9
|
Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `<subquery4>`.`f3` = 9 and `test`.`t2`.`f3` = 6
|
||||||
DROP TABLE t2,t1;
|
DROP TABLE t2,t1;
|
||||||
#
|
#
|
||||||
# MDEV-9462: Out of memory using explain on 2 empty tables
|
# MDEV-9462: Out of memory using explain on 2 empty tables
|
||||||
|
|||||||
3801
mysql-test/main/in_subq_cond_pushdown.result
Normal file
3801
mysql-test/main/in_subq_cond_pushdown.result
Normal file
File diff suppressed because it is too large
Load Diff
759
mysql-test/main/in_subq_cond_pushdown.test
Normal file
759
mysql-test/main/in_subq_cond_pushdown.test
Normal file
@@ -0,0 +1,759 @@
|
|||||||
|
LET $no_pushdown=
|
||||||
|
SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT, b INT, c INT, d INT);
|
||||||
|
CREATE TABLE t2 (e INT, f INT, g INT);
|
||||||
|
CREATE TABLE t3 (x INT, y INT);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,1,18,1), (2,1,25,1), (1,3,40,1), (2,3,40,4),
|
||||||
|
(4,2,24,4), (3,2,23,1), (1,2,40,2), (3,4,17,2),
|
||||||
|
(5,5,65,1), (2,3,70,3), (1,4,35,3), (2,3,25,3),
|
||||||
|
(2,2,40,4), (1,4,55,1), (5,3,72,4), (1,2,70,5);
|
||||||
|
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(1,2,38), (2,3,15), (1,3,40), (1,4,35),
|
||||||
|
(2,2,70), (3,4,23), (5,5,12), (5,4,17),
|
||||||
|
(3,3,17), (4,2,24), (2,5,25), (5,1,65);
|
||||||
|
|
||||||
|
INSERT INTO t3 VALUES
|
||||||
|
(1,25), (1,18), (2,15), (4,24),
|
||||||
|
(1,35), (3,23), (3,17), (2,15);
|
||||||
|
|
||||||
|
CREATE VIEW v1 AS
|
||||||
|
(
|
||||||
|
SELECT t3.x AS v1_x, t3.y AS v1_y FROM t3 WHERE t3.x<=3
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE VIEW v2 AS
|
||||||
|
(
|
||||||
|
SELECT t2.e, t2.f, MAX(t2.g) AS max_g
|
||||||
|
FROM t2
|
||||||
|
GROUP BY t2.e
|
||||||
|
HAVING max_g>25
|
||||||
|
);
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.c<25 AND
|
||||||
|
(t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e);
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted AND formula : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.c>55 AND t1.b<4 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted OR formula : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.c>60 OR t1.c<25) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted AND-OR formula : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # using view IN subquery defINition : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.c>20 AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT v1_x,MAX(v1_y)
|
||||||
|
FROM v1
|
||||||
|
WHERE v1_x>1
|
||||||
|
GROUP BY v1_x
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # using equality : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1,v1
|
||||||
|
WHERE t1.c>20 AND t1.c=v1_y AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.a<2 AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted AND formula : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.a>2 AND t1.a<5 AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted OR formula : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.a<2 OR t1.a>=4) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted AND-OR formula : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e,t2.f
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # extracted AND-OR formula : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e,t2.f
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # using equalities : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.d=1 AND t1.a=t1.d AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # using equality : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.d>1 AND t1.a=t1.d AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # using view IN subquery definition : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.a<3 AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT v1_x,MAX(v1_y)
|
||||||
|
FROM v1
|
||||||
|
WHERE v1_x>1
|
||||||
|
GROUP BY v1_x
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # using equality : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1,v1
|
||||||
|
WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE
|
||||||
|
--echo # extracted OR formula : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using addition : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.a+t1.c>41) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using substitution : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.c-t1.a<35) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using multiplication : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.c*t1.a>100) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using division : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.c/t1.a>30) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using BETWEEN : pushing into HAVING
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.c BETWEEN 50 AND 100) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using addition : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.a+t1.b > 5) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e,t2.f
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using substitution : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.a-t1.b > 0) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e,t2.f
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using multiplication : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.a*t1.b > 6) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e,t2.f
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using division : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.b/t1.a > 2) AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e,t2.f
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula using BETWEEN : pushing into WHERE
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.a BETWEEN 1 AND 3) AND
|
||||||
|
(t1.a,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into HAVING of the IN subquery
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the view from the IN subquery
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.c>3 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT v2.e,MAX(v2.f),v2.max_g
|
||||||
|
FROM v2
|
||||||
|
WHERE v2.e<5
|
||||||
|
GROUP BY v2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the IN subquery
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the view
|
||||||
|
--echo # from the IN subquery
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.a>1 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT v2.e,MAX(v2.f),v2.max_g
|
||||||
|
FROM v2
|
||||||
|
WHERE v2.e<5
|
||||||
|
GROUP BY v2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE and HAVING
|
||||||
|
--echo # of the IN subquery
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the view
|
||||||
|
--echo # from the IN subquery
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.a>1 AND t1.c<100 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT v2.e,MAX(v2.f),v2.max_g
|
||||||
|
FROM v2
|
||||||
|
WHERE v2.e<5
|
||||||
|
GROUP BY v2.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the IN subquery
|
||||||
|
--echo # extracted AND formula : pushing into HAVING of the derived table
|
||||||
|
--echo # from the IN subquery
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE t1.a>1 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT t2.e, t2.f, MAX(t2.g) AS max_g
|
||||||
|
FROM t2
|
||||||
|
GROUP BY t2.f
|
||||||
|
HAVING max_g>25
|
||||||
|
) as d_tab
|
||||||
|
WHERE d_tab.e<5
|
||||||
|
GROUP BY d_tab.e
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into HAVING of the derived table
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the IN subquery from
|
||||||
|
--echo # the derived table
|
||||||
|
SELECT *
|
||||||
|
FROM t3,
|
||||||
|
(
|
||||||
|
SELECT t1.a,t1.b,max(t1.c) as max_c
|
||||||
|
FROM t1
|
||||||
|
WHERE t1.a>1 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
GROUP BY t2.e
|
||||||
|
)
|
||||||
|
GROUP BY t1.a
|
||||||
|
) AS d_tab
|
||||||
|
WHERE d_tab.a=t3.x AND d_tab.b>2;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the derived table
|
||||||
|
--echo # extracted AND formula : pushing into WHERE of the IN subquery from
|
||||||
|
--echo # the derived table
|
||||||
|
SELECT *
|
||||||
|
FROM t3,
|
||||||
|
(
|
||||||
|
SELECT t1.a,t1.b,max(t1.c) as max_c
|
||||||
|
FROM t1
|
||||||
|
WHERE t1.a>1 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
GROUP BY t2.e
|
||||||
|
HAVING t2.f<5
|
||||||
|
)
|
||||||
|
GROUP BY t1.a
|
||||||
|
) AS d_tab
|
||||||
|
WHERE d_tab.a=t3.x AND d_tab.a<5;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE and HAVING
|
||||||
|
--echo # of the derived table
|
||||||
|
--echo # extracted AND formula : pushing into WHERE of the IN subquery
|
||||||
|
--echo # from the derived table
|
||||||
|
LET $query=
|
||||||
|
SELECT *
|
||||||
|
FROM t3,
|
||||||
|
(
|
||||||
|
SELECT t1.a,t1.b,max(t1.c) as max_c
|
||||||
|
FROM t1
|
||||||
|
WHERE t1.a>1 AND
|
||||||
|
(t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
GROUP BY t2.e
|
||||||
|
HAVING t2.f<5
|
||||||
|
)
|
||||||
|
GROUP BY t1.a
|
||||||
|
) AS d_tab
|
||||||
|
WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE of the derived table
|
||||||
|
--echo # conjunctive subformula : pushing into HAVING of the IN subquery from
|
||||||
|
--echo # the derived table
|
||||||
|
SELECT *
|
||||||
|
FROM t3,
|
||||||
|
(
|
||||||
|
SELECT t1.a,t1.b,max(t1.c) as max_c
|
||||||
|
FROM t1
|
||||||
|
WHERE (t1.a,t1.b,t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.e,t2.f,MAX(t2.g)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.f<4
|
||||||
|
GROUP BY t2.f
|
||||||
|
)
|
||||||
|
GROUP BY t1.a
|
||||||
|
HAVING t1.b<5
|
||||||
|
) AS d_tab
|
||||||
|
WHERE d_tab.a=t3.x AND d_tab.a<5;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE
|
||||||
|
--echo # using WINDOW FUNCTIONS : using MAX function
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.b>1) AND
|
||||||
|
(t1.b, t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
--echo # conjunctive subformula : pushing into WHERE
|
||||||
|
--echo # using WINDOW FUNCTIONS : using SUM function
|
||||||
|
LET $query=
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE (t1.b>1) AND
|
||||||
|
(t1.b, t1.c) IN
|
||||||
|
(
|
||||||
|
SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT)
|
||||||
|
FROM t2
|
||||||
|
WHERE t2.e<5
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
EVAL $no_pushdown $query;
|
||||||
|
EVAL $query;
|
||||||
|
EVAL EXPLAIN $query;
|
||||||
|
EVAL EXPLAIN FORMAT=JSON $query;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
DROP VIEW v1,v2;
|
||||||
@@ -665,7 +665,8 @@ The following options may be given as the first argument:
|
|||||||
join_cache_hashed, join_cache_bka,
|
join_cache_hashed, join_cache_bka,
|
||||||
optimize_join_buffer_size, table_elimination,
|
optimize_join_buffer_size, table_elimination,
|
||||||
extended_keys, exists_to_in, orderby_uses_equalities,
|
extended_keys, exists_to_in, orderby_uses_equalities,
|
||||||
condition_pushdown_for_derived, split_materialized
|
condition_pushdown_for_derived, split_materialized,
|
||||||
|
condition_pushdown_for_subquery
|
||||||
--optimizer-use-condition-selectivity=#
|
--optimizer-use-condition-selectivity=#
|
||||||
Controls selectivity of which conditions the optimizer
|
Controls selectivity of which conditions the optimizer
|
||||||
takes into account to calculate cardinality of a partial
|
takes into account to calculate cardinality of a partial
|
||||||
@@ -1514,7 +1515,7 @@ old-style-user-limits FALSE
|
|||||||
optimizer-prune-level 1
|
optimizer-prune-level 1
|
||||||
optimizer-search-depth 62
|
optimizer-search-depth 62
|
||||||
optimizer-selectivity-sampling-limit 100
|
optimizer-selectivity-sampling-limit 100
|
||||||
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
optimizer-use-condition-selectivity 1
|
optimizer-use-condition-selectivity 1
|
||||||
performance-schema FALSE
|
performance-schema FALSE
|
||||||
performance-schema-accounts-size -1
|
performance-schema-accounts-size -1
|
||||||
|
|||||||
@@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
|
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
|
||||||
SELECT * FROM t1
|
SELECT * FROM t1
|
||||||
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
|
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
|
||||||
a b
|
a b
|
||||||
|
|||||||
@@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
|||||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
||||||
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
|
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
|
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
|
||||||
SELECT * FROM t1
|
SELECT * FROM t1
|
||||||
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
|
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
|
||||||
a b
|
a b
|
||||||
|
|||||||
@@ -1,63 +1,63 @@
|
|||||||
SET @start_global_value = @@global.optimizer_switch;
|
SET @start_global_value = @@global.optimizer_switch;
|
||||||
SELECT @start_global_value;
|
SELECT @start_global_value;
|
||||||
@start_global_value
|
@start_global_value
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
select @@global.optimizer_switch;
|
select @@global.optimizer_switch;
|
||||||
@@global.optimizer_switch
|
@@global.optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
select @@session.optimizer_switch;
|
select @@session.optimizer_switch;
|
||||||
@@session.optimizer_switch
|
@@session.optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
show global variables like 'optimizer_switch';
|
show global variables like 'optimizer_switch';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
show session variables like 'optimizer_switch';
|
show session variables like 'optimizer_switch';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
select * from information_schema.global_variables where variable_name='optimizer_switch';
|
select * from information_schema.global_variables where variable_name='optimizer_switch';
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
select * from information_schema.session_variables where variable_name='optimizer_switch';
|
select * from information_schema.session_variables where variable_name='optimizer_switch';
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
set global optimizer_switch=10;
|
set global optimizer_switch=10;
|
||||||
set session optimizer_switch=5;
|
set session optimizer_switch=5;
|
||||||
select @@global.optimizer_switch;
|
select @@global.optimizer_switch;
|
||||||
@@global.optimizer_switch
|
@@global.optimizer_switch
|
||||||
index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
select @@session.optimizer_switch;
|
select @@session.optimizer_switch;
|
||||||
@@session.optimizer_switch
|
@@session.optimizer_switch
|
||||||
index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
set global optimizer_switch="index_merge_sort_union=on";
|
set global optimizer_switch="index_merge_sort_union=on";
|
||||||
set session optimizer_switch="index_merge=off";
|
set session optimizer_switch="index_merge=off";
|
||||||
select @@global.optimizer_switch;
|
select @@global.optimizer_switch;
|
||||||
@@global.optimizer_switch
|
@@global.optimizer_switch
|
||||||
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
select @@session.optimizer_switch;
|
select @@session.optimizer_switch;
|
||||||
@@session.optimizer_switch
|
@@session.optimizer_switch
|
||||||
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
show global variables like 'optimizer_switch';
|
show global variables like 'optimizer_switch';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
show session variables like 'optimizer_switch';
|
show session variables like 'optimizer_switch';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
select * from information_schema.global_variables where variable_name='optimizer_switch';
|
select * from information_schema.global_variables where variable_name='optimizer_switch';
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
select * from information_schema.session_variables where variable_name='optimizer_switch';
|
select * from information_schema.session_variables where variable_name='optimizer_switch';
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
set session optimizer_switch="default";
|
set session optimizer_switch="default";
|
||||||
select @@session.optimizer_switch;
|
select @@session.optimizer_switch;
|
||||||
@@session.optimizer_switch
|
@@session.optimizer_switch
|
||||||
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
|
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
|
||||||
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
|
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
|
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
|
||||||
select @@optimizer_switch;
|
select @@optimizer_switch;
|
||||||
@@optimizer_switch
|
@@optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
set global optimizer_switch=1.1;
|
set global optimizer_switch=1.1;
|
||||||
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
|
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
|
||||||
set global optimizer_switch=1e1;
|
set global optimizer_switch=1e1;
|
||||||
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
|
|||||||
SET @@global.optimizer_switch = @start_global_value;
|
SET @@global.optimizer_switch = @start_global_value;
|
||||||
SELECT @@global.optimizer_switch;
|
SELECT @@global.optimizer_switch;
|
||||||
@@global.optimizer_switch
|
@@global.optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
|
|||||||
@@ -2673,17 +2673,17 @@ ENUM_VALUE_LIST NULL
|
|||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
VARIABLE_NAME OPTIMIZER_SWITCH
|
VARIABLE_NAME OPTIMIZER_SWITCH
|
||||||
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
VARIABLE_SCOPE SESSION
|
VARIABLE_SCOPE SESSION
|
||||||
VARIABLE_TYPE FLAGSET
|
VARIABLE_TYPE FLAGSET
|
||||||
VARIABLE_COMMENT Fine-tune the optimizer behavior
|
VARIABLE_COMMENT Fine-tune the optimizer behavior
|
||||||
NUMERIC_MIN_VALUE NULL
|
NUMERIC_MIN_VALUE NULL
|
||||||
NUMERIC_MAX_VALUE NULL
|
NUMERIC_MAX_VALUE NULL
|
||||||
NUMERIC_BLOCK_SIZE NULL
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default
|
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
|
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
|
||||||
|
|||||||
@@ -2883,17 +2883,17 @@ ENUM_VALUE_LIST NULL
|
|||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
VARIABLE_NAME OPTIMIZER_SWITCH
|
VARIABLE_NAME OPTIMIZER_SWITCH
|
||||||
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
VARIABLE_SCOPE SESSION
|
VARIABLE_SCOPE SESSION
|
||||||
VARIABLE_TYPE FLAGSET
|
VARIABLE_TYPE FLAGSET
|
||||||
VARIABLE_COMMENT Fine-tune the optimizer behavior
|
VARIABLE_COMMENT Fine-tune the optimizer behavior
|
||||||
NUMERIC_MIN_VALUE NULL
|
NUMERIC_MIN_VALUE NULL
|
||||||
NUMERIC_MAX_VALUE NULL
|
NUMERIC_MAX_VALUE NULL
|
||||||
NUMERIC_BLOCK_SIZE NULL
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default
|
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT REQUIRED
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
|
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
|
||||||
|
|||||||
248
sql/item.cc
248
sql/item.cc
@@ -7635,6 +7635,231 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Prepare AND/OR formula for extraction of a pushable condition
|
||||||
|
|
||||||
|
@param checker the checker callback function to be applied to the nodes
|
||||||
|
of the tree of the object
|
||||||
|
@param arg parameter to be passed to the checker
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method recursively traverses this AND/OR condition and for each
|
||||||
|
subformula of the condition it checks whether it can be usable for the
|
||||||
|
extraction of a pushable condition. The criteria of pushability of
|
||||||
|
a subformula is checked by the callback function 'checker' with one
|
||||||
|
parameter arg. The subformulas that are not usable are marked with
|
||||||
|
the flag NO_EXTRACTION_FL.
|
||||||
|
@note
|
||||||
|
This method is called before any call of build_pushable_cond.
|
||||||
|
The flag NO_EXTRACTION_FL set in a subformula allows to avoid building
|
||||||
|
clones for the subformulas that are not used in the pushable condition.
|
||||||
|
@note
|
||||||
|
This method is called for pushdown conditions into materialized
|
||||||
|
derived tables/views optimization.
|
||||||
|
Item::pushable_cond_checker_for_derived() is passed as the actual callback
|
||||||
|
function.
|
||||||
|
Also it is called for pushdown conditions in materialized IN subqueries.
|
||||||
|
Item::pushable_cond_checker_for_subquery is passed as the actual
|
||||||
|
callback function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Item::check_pushable_cond(Pushdown_checker checker, uchar *arg)
|
||||||
|
{
|
||||||
|
clear_extraction_flag();
|
||||||
|
if (type() == Item::COND_ITEM)
|
||||||
|
{
|
||||||
|
bool and_cond= ((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC;
|
||||||
|
List_iterator<Item> li(*((Item_cond*) this)->argument_list());
|
||||||
|
uint count= 0;
|
||||||
|
Item *item;
|
||||||
|
while ((item=li++))
|
||||||
|
{
|
||||||
|
item->check_pushable_cond(checker, arg);
|
||||||
|
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
|
||||||
|
count++;
|
||||||
|
else if (!and_cond)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((and_cond && count == 0) || item)
|
||||||
|
{
|
||||||
|
set_extraction_flag(NO_EXTRACTION_FL);
|
||||||
|
if (and_cond)
|
||||||
|
li.rewind();
|
||||||
|
while ((item= li++))
|
||||||
|
item->clear_extraction_flag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!((this->*checker) (arg)))
|
||||||
|
set_extraction_flag(NO_EXTRACTION_FL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Build condition extractable from this condition for pushdown
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param checker the checker callback function to be applied to the
|
||||||
|
equal items of multiple equality items
|
||||||
|
@param arg parameter to be passed to the checker
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method finds out what condition that can be pushed down can be
|
||||||
|
extracted from this condition. If such condition C exists the
|
||||||
|
method builds the item for it. The method uses the flag NO_EXTRACTION_FL
|
||||||
|
set by the preliminary call of the method check_pushable_cond() to figure
|
||||||
|
out whether a subformula is pushable or not.
|
||||||
|
In the case when this item is a multiple equality a checker method is
|
||||||
|
called to find the equal fields to build a new equality that can be
|
||||||
|
pushed down.
|
||||||
|
@note
|
||||||
|
The built condition C is always implied by the condition cond
|
||||||
|
(cond => C). The method tries to build the most restrictive such
|
||||||
|
condition (i.e. for any other condition C' such that cond => C'
|
||||||
|
we have C => C').
|
||||||
|
@note
|
||||||
|
The build item is not ready for usage: substitution for the field items
|
||||||
|
has to be done and it has to be re-fixed.
|
||||||
|
@note
|
||||||
|
This method is called for pushdown conditions into materialized
|
||||||
|
derived tables/views optimization.
|
||||||
|
Item::pushable_equality_checker_for_derived() is passed as the actual
|
||||||
|
callback function.
|
||||||
|
Also it is called for pushdown conditions into materialized IN subqueries.
|
||||||
|
Item::pushable_equality_checker_for_subquery() is passed as the actual
|
||||||
|
callback function.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
the built condition pushable into if such a condition exists
|
||||||
|
NULL if there is no such a condition
|
||||||
|
*/
|
||||||
|
|
||||||
|
Item *Item::build_pushable_cond(THD *thd,
|
||||||
|
Pushdown_checker checker,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
bool is_multiple_equality= type() == Item::FUNC_ITEM &&
|
||||||
|
((Item_func*) this)->functype() == Item_func::MULT_EQUAL_FUNC;
|
||||||
|
|
||||||
|
if (get_extraction_flag() == NO_EXTRACTION_FL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (type() == Item::COND_ITEM)
|
||||||
|
{
|
||||||
|
bool cond_and= false;
|
||||||
|
Item_cond *new_cond;
|
||||||
|
if (((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC)
|
||||||
|
{
|
||||||
|
cond_and= true;
|
||||||
|
new_cond= new (thd->mem_root) Item_cond_and(thd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
new_cond= new (thd->mem_root) Item_cond_or(thd);
|
||||||
|
if (!new_cond)
|
||||||
|
return 0;
|
||||||
|
List_iterator<Item> li(*((Item_cond*) this)->argument_list());
|
||||||
|
Item *item;
|
||||||
|
bool is_fix_needed= false;
|
||||||
|
|
||||||
|
while ((item=li++))
|
||||||
|
{
|
||||||
|
if (item->get_extraction_flag() == NO_EXTRACTION_FL)
|
||||||
|
{
|
||||||
|
if (!cond_and)
|
||||||
|
return 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Item *fix= item->build_pushable_cond(thd, checker, arg);
|
||||||
|
if (!fix && !cond_and)
|
||||||
|
return 0;
|
||||||
|
if (!fix)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fix->type() == Item::COND_ITEM &&
|
||||||
|
((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
|
||||||
|
is_fix_needed= true;
|
||||||
|
|
||||||
|
if (new_cond->argument_list()->push_back(fix, thd->mem_root))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (is_fix_needed)
|
||||||
|
new_cond->fix_fields(thd, 0);
|
||||||
|
|
||||||
|
switch (new_cond->argument_list()->elements)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
return new_cond->argument_list()->head();
|
||||||
|
default:
|
||||||
|
return new_cond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_multiple_equality)
|
||||||
|
{
|
||||||
|
Item *new_cond= NULL;
|
||||||
|
int i= 0;
|
||||||
|
Item_equal *item_equal= (Item_equal *) this;
|
||||||
|
Item *left_item = item_equal->get_const();
|
||||||
|
Item_equal_fields_iterator it(*item_equal);
|
||||||
|
Item *item;
|
||||||
|
Item *right_item;
|
||||||
|
if (!left_item)
|
||||||
|
{
|
||||||
|
while ((item=it++))
|
||||||
|
{
|
||||||
|
left_item= ((item->*checker) (arg)) ? item : NULL;
|
||||||
|
if (left_item)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!left_item)
|
||||||
|
return 0;
|
||||||
|
while ((item=it++))
|
||||||
|
{
|
||||||
|
right_item= ((item->*checker) (arg)) ? item : NULL;
|
||||||
|
if (!right_item)
|
||||||
|
continue;
|
||||||
|
Item_func_eq *eq= 0;
|
||||||
|
Item *left_item_clone= left_item->build_clone(thd);
|
||||||
|
Item *right_item_clone= item->build_clone(thd);
|
||||||
|
if (left_item_clone && right_item_clone)
|
||||||
|
{
|
||||||
|
left_item_clone->set_item_equal(NULL);
|
||||||
|
right_item_clone->set_item_equal(NULL);
|
||||||
|
eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
|
||||||
|
left_item_clone);
|
||||||
|
}
|
||||||
|
if (eq)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
new_cond= eq;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
|
||||||
|
thd->mem_root))
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (new_cond && new_cond->fix_fields(thd, &new_cond))
|
||||||
|
return 0;
|
||||||
|
return new_cond;
|
||||||
|
}
|
||||||
|
else if (get_extraction_flag() != NO_EXTRACTION_FL)
|
||||||
|
return build_clone(thd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
|
Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
|
||||||
{
|
{
|
||||||
@@ -7754,18 +7979,18 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
Grouping_tmp_field *find_matching_grouping_field(Item *item,
|
Field_pair *find_matching_grouping_field(Item *item,
|
||||||
st_select_lex *sel)
|
st_select_lex *sel)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
|
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
|
||||||
(item->type() == Item::REF_ITEM &&
|
(item->type() == Item::REF_ITEM &&
|
||||||
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
|
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
|
||||||
List_iterator<Grouping_tmp_field> li(sel->grouping_tmp_fields);
|
List_iterator<Field_pair> li(sel->grouping_tmp_fields);
|
||||||
Grouping_tmp_field *gr_field;
|
Field_pair *gr_field;
|
||||||
Item_field *field_item= (Item_field *) (item->real_item());
|
Item_field *field_item= (Item_field *) (item->real_item());
|
||||||
while ((gr_field= li++))
|
while ((gr_field= li++))
|
||||||
{
|
{
|
||||||
if (field_item->field == gr_field->tmp_field)
|
if (field_item->field == gr_field->field)
|
||||||
return gr_field;
|
return gr_field;
|
||||||
}
|
}
|
||||||
Item_equal *item_equal= item->get_item_equal();
|
Item_equal *item_equal= item->get_item_equal();
|
||||||
@@ -7779,7 +8004,7 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item,
|
|||||||
li.rewind();
|
li.rewind();
|
||||||
while ((gr_field= li++))
|
while ((gr_field= li++))
|
||||||
{
|
{
|
||||||
if (field_item->field == gr_field->tmp_field)
|
if (field_item->field == gr_field->field)
|
||||||
return gr_field;
|
return gr_field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7788,26 +8013,25 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
|
Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
uchar *arg)
|
|
||||||
{
|
{
|
||||||
st_select_lex *sel= (st_select_lex *)arg;
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
|
Field_pair *gr_field= find_matching_grouping_field(this, sel);
|
||||||
if (gr_field)
|
if (gr_field)
|
||||||
return gr_field->producing_item->build_clone(thd);
|
return gr_field->corresponding_item->build_clone(thd);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *
|
Item *
|
||||||
Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd,
|
Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
|
||||||
uchar *arg)
|
uchar *arg)
|
||||||
{
|
{
|
||||||
if (!item_equal)
|
if (!item_equal)
|
||||||
return this;
|
return this;
|
||||||
st_select_lex *sel= (st_select_lex *)arg;
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
|
Field_pair *gr_field= find_matching_grouping_field(this, sel);
|
||||||
return gr_field->producing_item->build_clone(thd);
|
return gr_field->corresponding_item->build_clone(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item_field::print(String *str, enum_query_type query_type)
|
void Item_field::print(String *str, enum_query_type query_type)
|
||||||
|
|||||||
77
sql/item.h
77
sql/item.h
@@ -569,6 +569,7 @@ typedef bool (Item::*Item_processor) (void *arg);
|
|||||||
typedef bool (Item::*Item_analyzer) (uchar **argp);
|
typedef bool (Item::*Item_analyzer) (uchar **argp);
|
||||||
typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg);
|
typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg);
|
||||||
typedef void (*Cond_traverser) (const Item *item, void *arg);
|
typedef void (*Cond_traverser) (const Item *item, void *arg);
|
||||||
|
typedef bool (Item::*Pushdown_checker) (uchar *arg);
|
||||||
|
|
||||||
struct st_cond_statistic;
|
struct st_cond_statistic;
|
||||||
|
|
||||||
@@ -601,6 +602,7 @@ public:
|
|||||||
String_copier_for_item(THD *thd): m_thd(thd) { }
|
String_copier_for_item(THD *thd): m_thd(thd) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item: public Value_source,
|
class Item: public Value_source,
|
||||||
public Type_all_attributes
|
public Type_all_attributes
|
||||||
{
|
{
|
||||||
@@ -1647,7 +1649,15 @@ public:
|
|||||||
or can be converted to such an exression using equalities.
|
or can be converted to such an exression using equalities.
|
||||||
Not to be used for AND/OR formulas.
|
Not to be used for AND/OR formulas.
|
||||||
*/
|
*/
|
||||||
virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; }
|
virtual bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
|
{ return false; }
|
||||||
|
/*
|
||||||
|
TRUE if the expression depends only on fields from the left part of
|
||||||
|
IN subquery or can be converted to such an expression using equalities.
|
||||||
|
Not to be used for AND/OR formulas.
|
||||||
|
*/
|
||||||
|
virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
|
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
|
||||||
virtual bool find_function_processor (void *arg) { return 0; }
|
virtual bool find_function_processor (void *arg) { return 0; }
|
||||||
@@ -1825,8 +1835,12 @@ public:
|
|||||||
{ return this; }
|
{ return this; }
|
||||||
virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
|
virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
{ return this; }
|
{ return this; }
|
||||||
virtual Item *derived_grouping_field_transformer_for_where(THD *thd,
|
virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
uchar *arg)
|
{ return this; }
|
||||||
|
/* Now is not used. */
|
||||||
|
virtual Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
|
{ return this; }
|
||||||
|
virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
{ return this; }
|
{ return this; }
|
||||||
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
|
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
|
||||||
{ return this; }
|
{ return this; }
|
||||||
@@ -2023,6 +2037,33 @@ public:
|
|||||||
{
|
{
|
||||||
marker &= ~EXTRACTION_MASK;
|
marker &= ~EXTRACTION_MASK;
|
||||||
}
|
}
|
||||||
|
void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg);
|
||||||
|
bool pushable_cond_checker_for_derived(uchar *arg)
|
||||||
|
{
|
||||||
|
return excl_dep_on_table(*((table_map *)arg));
|
||||||
|
}
|
||||||
|
bool pushable_cond_checker_for_subquery(uchar *arg)
|
||||||
|
{
|
||||||
|
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
|
||||||
|
}
|
||||||
|
Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
|
||||||
|
Item *build_pushable_cond(THD *thd,
|
||||||
|
Pushdown_checker checker,
|
||||||
|
uchar *arg);
|
||||||
|
/*
|
||||||
|
Checks if this item depends only on the arg table
|
||||||
|
*/
|
||||||
|
bool pushable_equality_checker_for_derived(uchar *arg)
|
||||||
|
{
|
||||||
|
return (used_tables() == *((table_map *)arg));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Checks if this item consists in the left part of arg IN subquery predicate
|
||||||
|
*/
|
||||||
|
bool pushable_equality_checker_for_subquery(uchar *arg)
|
||||||
|
{
|
||||||
|
return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MEM_ROOT *get_thd_memroot(THD *thd);
|
MEM_ROOT *get_thd_memroot(THD *thd);
|
||||||
@@ -2151,6 +2192,17 @@ protected:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (args[i]->const_item())
|
||||||
|
continue;
|
||||||
|
if (!args[i]->excl_dep_on_in_subq_left_part(subq_pred))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
Item_args(void)
|
Item_args(void)
|
||||||
:args(NULL), arg_count(0)
|
:args(NULL), arg_count(0)
|
||||||
@@ -3046,10 +3098,13 @@ public:
|
|||||||
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
|
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
|
||||||
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
|
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
|
||||||
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg);
|
Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
|
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
|
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
|
||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
bool excl_dep_on_table(table_map tab_map);
|
bool excl_dep_on_table(table_map tab_map);
|
||||||
bool excl_dep_on_grouping_fields(st_select_lex *sel);
|
bool excl_dep_on_grouping_fields(st_select_lex *sel);
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
|
||||||
bool cleanup_excluding_fields_processor(void *arg)
|
bool cleanup_excluding_fields_processor(void *arg)
|
||||||
{ return field ? 0 : cleanup_processor(arg); }
|
{ return field ? 0 : cleanup_processor(arg); }
|
||||||
bool cleanup_excluding_const_fields_processor(void *arg)
|
bool cleanup_excluding_const_fields_processor(void *arg)
|
||||||
@@ -4874,6 +4929,8 @@ public:
|
|||||||
}
|
}
|
||||||
bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
|
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{ return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }
|
||||||
bool cleanup_excluding_fields_processor(void *arg)
|
bool cleanup_excluding_fields_processor(void *arg)
|
||||||
{
|
{
|
||||||
Item *item= real_item();
|
Item *item= real_item();
|
||||||
@@ -5188,10 +5245,12 @@ public:
|
|||||||
}
|
}
|
||||||
bool excl_dep_on_table(table_map tab_map);
|
bool excl_dep_on_table(table_map tab_map);
|
||||||
bool excl_dep_on_grouping_fields(st_select_lex *sel);
|
bool excl_dep_on_grouping_fields(st_select_lex *sel);
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
|
||||||
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
|
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
|
||||||
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
Item *derived_grouping_field_transformer_for_where(THD *thd,
|
Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
uchar *arg);
|
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
|
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
|
||||||
|
|
||||||
void save_val(Field *to)
|
void save_val(Field *to)
|
||||||
{
|
{
|
||||||
@@ -6110,7 +6169,11 @@ public:
|
|||||||
{ return convert_to_basic_const_item(thd); }
|
{ return convert_to_basic_const_item(thd); }
|
||||||
Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
|
Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
{ return convert_to_basic_const_item(thd); }
|
{ return convert_to_basic_const_item(thd); }
|
||||||
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg)
|
Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
|
{ return convert_to_basic_const_item(thd); }
|
||||||
|
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
|
{ return convert_to_basic_const_item(thd); }
|
||||||
|
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
{ return convert_to_basic_const_item(thd); }
|
{ return convert_to_basic_const_item(thd); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1272,7 +1272,11 @@ public:
|
|||||||
{ reset_first_arg_if_needed(); return this; }
|
{ reset_first_arg_if_needed(); return this; }
|
||||||
Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
|
Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
{ reset_first_arg_if_needed(); return this; }
|
{ reset_first_arg_if_needed(); return this; }
|
||||||
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg)
|
Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
|
{ reset_first_arg_if_needed(); return this; }
|
||||||
|
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
|
{ reset_first_arg_if_needed(); return this; }
|
||||||
|
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
{ reset_first_arg_if_needed(); return this; }
|
{ reset_first_arg_if_needed(); return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3135,6 +3139,8 @@ public:
|
|||||||
{
|
{
|
||||||
return used_tables() & tab_map;
|
return used_tables() & tab_map;
|
||||||
}
|
}
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
|
||||||
|
|
||||||
friend class Item_equal_fields_iterator;
|
friend class Item_equal_fields_iterator;
|
||||||
bool count_sargable_conds(void *arg);
|
bool count_sargable_conds(void *arg);
|
||||||
friend class Item_equal_iterator<List_iterator_fast,Item>;
|
friend class Item_equal_iterator<List_iterator_fast,Item>;
|
||||||
|
|||||||
@@ -326,6 +326,11 @@ public:
|
|||||||
return Item_args::excl_dep_on_grouping_fields(sel);
|
return Item_args::excl_dep_on_grouping_fields(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We assume the result of any function that has a TIMESTAMP argument to be
|
We assume the result of any function that has a TIMESTAMP argument to be
|
||||||
timezone-dependent, since a TIMESTAMP value in both numeric and string
|
timezone-dependent, since a TIMESTAMP value in both numeric and string
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ public:
|
|||||||
return Item_args::excl_dep_on_grouping_fields(sel);
|
return Item_args::excl_dep_on_grouping_fields(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
|
||||||
|
}
|
||||||
|
|
||||||
bool check_vcol_func_processor(void *arg) {return FALSE; }
|
bool check_vcol_func_processor(void *arg) {return FALSE; }
|
||||||
Item *get_copy(THD *thd)
|
Item *get_copy(THD *thd)
|
||||||
{ return get_item_copy<Item_row>(thd, this); }
|
{ return get_item_copy<Item_row>(thd, this); }
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class subselect_hash_sj_engine;
|
|||||||
class Item_bool_func2;
|
class Item_bool_func2;
|
||||||
class Comp_creator;
|
class Comp_creator;
|
||||||
class With_element;
|
class With_element;
|
||||||
|
class Field_pair;
|
||||||
|
|
||||||
typedef class st_select_lex SELECT_LEX;
|
typedef class st_select_lex SELECT_LEX;
|
||||||
|
|
||||||
@@ -570,6 +571,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool is_registered_semijoin;
|
bool is_registered_semijoin;
|
||||||
|
|
||||||
|
List<Field_pair> corresponding_fields;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Used to determine how this subselect item is represented in the item tree,
|
Used to determine how this subselect item is represented in the item tree,
|
||||||
in case there is a need to locate it there and replace with something else.
|
in case there is a need to locate it there and replace with something else.
|
||||||
@@ -741,6 +744,8 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool pushdown_cond_for_in_subquery(THD *thd, Item *cond);
|
||||||
|
|
||||||
friend class Item_ref_null_helper;
|
friend class Item_ref_null_helper;
|
||||||
friend class Item_is_not_null_test;
|
friend class Item_is_not_null_test;
|
||||||
friend class Item_in_optimizer;
|
friend class Item_in_optimizer;
|
||||||
@@ -852,7 +857,6 @@ protected:
|
|||||||
void set_row(List<Item> &item_list, Item_cache **row);
|
void set_row(List<Item> &item_list, Item_cache **row);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class subselect_single_select_engine: public subselect_engine
|
class subselect_single_select_engine: public subselect_engine
|
||||||
{
|
{
|
||||||
bool prepared; /* simple subselect is prepared */
|
bool prepared; /* simple subselect is prepared */
|
||||||
@@ -886,9 +890,10 @@ public:
|
|||||||
|
|
||||||
friend class subselect_hash_sj_engine;
|
friend class subselect_hash_sj_engine;
|
||||||
friend class Item_in_subselect;
|
friend class Item_in_subselect;
|
||||||
friend bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
friend bool execute_degenerate_jtbm_semi_join(THD *thd,
|
||||||
Item **join_where);
|
TABLE_LIST *tbl,
|
||||||
|
Item_in_subselect *subq_pred,
|
||||||
|
List<Item> &eq_list);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5436,12 +5436,435 @@ int select_value_catcher::send_data(List<Item> &items)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Setup JTBM join tabs for execution
|
@brief
|
||||||
|
Conjugate conditions after optimize_cond() call
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param cond the condition where to attach new conditions
|
||||||
|
@param cond_eq IN/OUT the multiple equalities of cond
|
||||||
|
@param new_conds IN/OUT the list of conditions needed to add
|
||||||
|
@param cond_value the returned value of the condition
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method creates new condition through conjunction of cond and
|
||||||
|
the conditions from new_conds list.
|
||||||
|
The method is called after optimize_cond() for cond. The result
|
||||||
|
of the conjunction should be the same as if it was done before the
|
||||||
|
the optimize_cond() call.
|
||||||
|
|
||||||
|
@retval NULL if an error occurs
|
||||||
|
@retval otherwise the created condition
|
||||||
|
*/
|
||||||
|
|
||||||
|
Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
|
||||||
|
COND_EQUAL **cond_eq,
|
||||||
|
List<Item> &new_conds,
|
||||||
|
Item::cond_result *cond_value)
|
||||||
|
{
|
||||||
|
COND_EQUAL new_cond_equal;
|
||||||
|
Item *item;
|
||||||
|
Item_equal *equality;
|
||||||
|
bool is_simplified_cond= false;
|
||||||
|
List_iterator<Item> li(new_conds);
|
||||||
|
List_iterator_fast<Item_equal> it(new_cond_equal.current_level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Creates multiple equalities new_cond_equal from new_conds list
|
||||||
|
equalities. If multiple equality can't be created or the condition
|
||||||
|
from new_conds list isn't an equality the method leaves it in new_conds
|
||||||
|
list.
|
||||||
|
|
||||||
|
The equality can't be converted into the multiple equality if it
|
||||||
|
is a knowingly false or true equality.
|
||||||
|
For example, (3 = 1) equality.
|
||||||
|
*/
|
||||||
|
while ((item=li++))
|
||||||
|
{
|
||||||
|
if (item->type() == Item::FUNC_ITEM &&
|
||||||
|
((Item_func *) item)->functype() == Item_func::EQ_FUNC &&
|
||||||
|
check_simple_equality(thd,
|
||||||
|
Item::Context(Item::ANY_SUBST,
|
||||||
|
((Item_func_equal *)item)->compare_type_handler(),
|
||||||
|
((Item_func_equal *)item)->compare_collation()),
|
||||||
|
((Item_func *)item)->arguments()[0]->real_item(),
|
||||||
|
((Item_func *)item)->arguments()[1]->real_item(),
|
||||||
|
&new_cond_equal))
|
||||||
|
li.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
it.rewind();
|
||||||
|
if (cond && cond->type() == Item::COND_ITEM &&
|
||||||
|
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
cond is an AND-condition.
|
||||||
|
The method conjugates the AND-condition cond, created multiple
|
||||||
|
equalities new_cond_equal and remain conditions from new_conds.
|
||||||
|
|
||||||
|
First, the method disjoins multiple equalities of cond and
|
||||||
|
merges new_cond_equal multiple equalities with these equalities.
|
||||||
|
It checks if after the merge the multiple equalities are knowingly
|
||||||
|
true or false equalities.
|
||||||
|
It attaches to cond the conditions from new_conds list and the result
|
||||||
|
of the merge of multiple equalities. The multiple equalities are
|
||||||
|
attached only to the upper level of AND-condition cond. So they
|
||||||
|
should be pushed down to the inner levels of cond AND-condition
|
||||||
|
if needed. It is done by propagate_new_equalities().
|
||||||
|
*/
|
||||||
|
COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->m_cond_equal;
|
||||||
|
List<Item_equal> *cond_equalities= &cond_equal->current_level;
|
||||||
|
List<Item> *and_args= ((Item_cond_and *)cond)->argument_list();
|
||||||
|
and_args->disjoin((List<Item> *) cond_equalities);
|
||||||
|
and_args->append(&new_conds);
|
||||||
|
|
||||||
|
while ((equality= it++))
|
||||||
|
{
|
||||||
|
equality->upper_levels= 0;
|
||||||
|
equality->merge_into_list(thd, cond_equalities, false, false);
|
||||||
|
}
|
||||||
|
List_iterator_fast<Item_equal> ei(*cond_equalities);
|
||||||
|
while ((equality= ei++))
|
||||||
|
{
|
||||||
|
if (equality->const_item() && !equality->val_int())
|
||||||
|
is_simplified_cond= true;
|
||||||
|
equality->fixed= 0;
|
||||||
|
if (equality->fix_fields(thd, NULL))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
and_args->append((List<Item> *) cond_equalities);
|
||||||
|
*cond_eq= &((Item_cond_and *) cond)->m_cond_equal;
|
||||||
|
|
||||||
|
propagate_new_equalities(thd, cond, cond_equalities,
|
||||||
|
cond_equal->upper_levels,
|
||||||
|
&is_simplified_cond);
|
||||||
|
cond= cond->propagate_equal_fields(thd,
|
||||||
|
Item::Context_boolean(),
|
||||||
|
cond_equal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
cond isn't AND-condition or is NULL.
|
||||||
|
There can be several cases:
|
||||||
|
|
||||||
|
1. cond is a multiple equality.
|
||||||
|
In this case cond is merged with the multiple equalities of
|
||||||
|
new_cond_equal.
|
||||||
|
The new condition is created with the conjunction of new_conds
|
||||||
|
list conditions and the result of merge of multiple equalities.
|
||||||
|
2. cond is NULL
|
||||||
|
The new condition is created from the conditions of new_conds
|
||||||
|
list and multiple equalities from new_cond_equal.
|
||||||
|
3. Otherwise
|
||||||
|
In this case the new condition is created from cond, remain conditions
|
||||||
|
from new_conds list and created multiple equalities from
|
||||||
|
new_cond_equal.
|
||||||
|
*/
|
||||||
|
List<Item> new_conds_list;
|
||||||
|
/* Flag is set to true if cond is a multiple equality */
|
||||||
|
bool is_mult_eq= (cond && cond->type() == Item::FUNC_ITEM &&
|
||||||
|
((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC);
|
||||||
|
|
||||||
|
if (cond && !is_mult_eq &&
|
||||||
|
new_conds_list.push_back(cond, thd->mem_root))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (new_conds.elements > 0)
|
||||||
|
{
|
||||||
|
li.rewind();
|
||||||
|
while ((item=li++))
|
||||||
|
{
|
||||||
|
if (!item->fixed && item->fix_fields(thd, NULL))
|
||||||
|
return NULL;
|
||||||
|
if (item->const_item() && !item->val_int())
|
||||||
|
is_simplified_cond= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_conds.elements > 1)
|
||||||
|
new_conds_list.append(&new_conds);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
li.rewind();
|
||||||
|
item= li++;
|
||||||
|
if (new_conds_list.push_back(item, thd->mem_root))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_cond_equal.current_level.elements > 0)
|
||||||
|
{
|
||||||
|
if (is_mult_eq)
|
||||||
|
{
|
||||||
|
Item_equal *eq_cond= (Item_equal *)cond;
|
||||||
|
eq_cond->upper_levels= 0;
|
||||||
|
eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
|
||||||
|
false, false);
|
||||||
|
|
||||||
|
while ((equality= it++))
|
||||||
|
{
|
||||||
|
if (equality->const_item() && !equality->val_int())
|
||||||
|
is_simplified_cond= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_cond_equal.current_level.elements +
|
||||||
|
new_conds_list.elements == 1)
|
||||||
|
{
|
||||||
|
it.rewind();
|
||||||
|
equality= it++;
|
||||||
|
equality->fixed= 0;
|
||||||
|
if (equality->fix_fields(thd, NULL))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*cond_eq= &new_cond_equal;
|
||||||
|
}
|
||||||
|
new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_conds_list.elements > 1)
|
||||||
|
{
|
||||||
|
Item_cond_and *and_cond=
|
||||||
|
new (thd->mem_root) Item_cond_and(thd, new_conds_list);
|
||||||
|
|
||||||
|
and_cond->m_cond_equal.copy(new_cond_equal);
|
||||||
|
cond= (Item *)and_cond;
|
||||||
|
*cond_eq= &((Item_cond_and *)cond)->m_cond_equal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> iter(new_conds_list);
|
||||||
|
cond= iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cond->fixed && cond->fix_fields(thd, NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (new_cond_equal.current_level.elements > 0)
|
||||||
|
cond= cond->propagate_equal_fields(thd,
|
||||||
|
Item::Context_boolean(),
|
||||||
|
&new_cond_equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If it was found that some of the created condition parts are knowingly
|
||||||
|
true or false equalities the method calls removes_eq_cond() to remove them
|
||||||
|
from cond and set the cond_value to the appropriate value.
|
||||||
|
*/
|
||||||
|
if (is_simplified_cond)
|
||||||
|
cond= cond->remove_eq_conds(thd, cond_value, true);
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Materialize a degenerate jtbm semi join
|
||||||
|
|
||||||
|
@param thd thread handler
|
||||||
|
@param tbl table list for the target jtbm semi join table
|
||||||
|
@param subq_pred IN subquery predicate with the degenerate jtbm semi join
|
||||||
|
@param eq_list IN/OUT the list where to add produced equalities
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method materializes the degenerate jtbm semi join for the
|
||||||
|
subquery from the IN subquery predicate subq_pred taking table
|
||||||
|
as the target for materialization.
|
||||||
|
Any degenerate table is guaranteed to produce 0 or 1 record.
|
||||||
|
Examples of both cases:
|
||||||
|
|
||||||
|
select * from ot where col in (select ... from it where 2>3)
|
||||||
|
select * from ot where col in (select MY_MIN(it.key) from it)
|
||||||
|
|
||||||
|
in this case, there is no necessity to create a temp.table for
|
||||||
|
materialization.
|
||||||
|
We now just need to
|
||||||
|
1. Check whether 1 or 0 records are produced, setup this as a
|
||||||
|
constant join tab.
|
||||||
|
2. Create a dummy temporary table, because all of the join
|
||||||
|
optimization code relies on TABLE object being present.
|
||||||
|
|
||||||
|
In the case when materialization produces one row the function
|
||||||
|
additionally creates equalities between the expressions from the
|
||||||
|
left part of the IN subquery predicate and the corresponding
|
||||||
|
columns of the produced row. These equalities are added to the
|
||||||
|
list eq_list. They are supposed to be conjuncted with the condition
|
||||||
|
of the WHERE clause.
|
||||||
|
|
||||||
|
@retval TRUE if an error occurs
|
||||||
|
@retval FALSE otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool execute_degenerate_jtbm_semi_join(THD *thd,
|
||||||
|
TABLE_LIST *tbl,
|
||||||
|
Item_in_subselect *subq_pred,
|
||||||
|
List<Item> &eq_list)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("execute_degenerate_jtbm_semi_join");
|
||||||
|
select_value_catcher *new_sink;
|
||||||
|
|
||||||
|
DBUG_ASSERT(subq_pred->engine->engine_type() ==
|
||||||
|
subselect_engine::SINGLE_SELECT_ENGINE);
|
||||||
|
subselect_single_select_engine *engine=
|
||||||
|
(subselect_single_select_engine*)subq_pred->engine;
|
||||||
|
if (!(new_sink= new (thd->mem_root) select_value_catcher(thd, subq_pred)))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
|
||||||
|
engine->select_lex->join->change_result(new_sink, NULL) ||
|
||||||
|
engine->exec())
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
subq_pred->is_jtbm_const_tab= TRUE;
|
||||||
|
|
||||||
|
if (new_sink->assigned)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Subselect produced one row, which is saved in new_sink->row.
|
||||||
|
Save "left_expr[i] == row[i]" equalities into the eq_list.
|
||||||
|
*/
|
||||||
|
subq_pred->jtbm_const_row_found= TRUE;
|
||||||
|
|
||||||
|
Item *eq_cond;
|
||||||
|
for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
|
||||||
|
{
|
||||||
|
eq_cond=
|
||||||
|
new (thd->mem_root) Item_func_eq(thd,
|
||||||
|
subq_pred->left_expr->element_index(i),
|
||||||
|
new_sink->row[i]);
|
||||||
|
if (!eq_cond || eq_list.push_back(eq_cond, thd->mem_root))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Subselect produced no rows. Just set the flag */
|
||||||
|
subq_pred->jtbm_const_row_found= FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TABLE *dummy_table;
|
||||||
|
if (!(dummy_table= create_dummy_tmp_table(thd)))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
tbl->table= dummy_table;
|
||||||
|
tbl->table->pos_in_table_list= tbl;
|
||||||
|
/*
|
||||||
|
Note: the table created above may be freed by:
|
||||||
|
1. JOIN_TAB::cleanup(), when the parent join is a regular join.
|
||||||
|
2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
|
||||||
|
degenerate join (e.g. one with "Impossible where").
|
||||||
|
*/
|
||||||
|
setup_table_map(tbl->table, tbl, tbl->jtbm_table_no);
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Execute degenerate jtbm semi joins before optimize_cond() for parent
|
||||||
|
|
||||||
|
@param join the parent join for jtbm semi joins
|
||||||
|
@param join_list the list of tables where jtbm semi joins are processed
|
||||||
|
@param eq_list IN/OUT the list where to add equalities produced after
|
||||||
|
materialization of single-row degenerate jtbm semi joins
|
||||||
|
|
||||||
|
@details
|
||||||
|
The method traverses join_list trying to find any degenerate jtbm semi
|
||||||
|
joins for subqueries of IN predicates. For each degenerate jtbm
|
||||||
|
semi join execute_degenerate_jtbm_semi_join() is called. As a result
|
||||||
|
of this call new equalities that substitute for single-row materialized
|
||||||
|
jtbm semi join are added to eq_list.
|
||||||
|
|
||||||
|
In the case when a table is nested in another table 'nested_join' the
|
||||||
|
method is recursively called for the join_list of the 'nested_join' trying
|
||||||
|
to find in the list any degenerate jtbm semi joins. Currently a jtbm semi
|
||||||
|
join may occur in a mergeable semi join nest.
|
||||||
|
|
||||||
|
@retval TRUE if an error occurs
|
||||||
|
@retval FALSE otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
|
||||||
|
List<TABLE_LIST> *join_list,
|
||||||
|
List<Item> &eq_list)
|
||||||
|
{
|
||||||
|
TABLE_LIST *table;
|
||||||
|
NESTED_JOIN *nested_join;
|
||||||
|
List_iterator<TABLE_LIST> li(*join_list);
|
||||||
|
THD *thd= join->thd;
|
||||||
|
DBUG_ENTER("setup_degenerate_jtbm_semi_joins");
|
||||||
|
|
||||||
|
while ((table= li++))
|
||||||
|
{
|
||||||
|
Item_in_subselect *subq_pred;
|
||||||
|
|
||||||
|
if ((subq_pred= table->jtbm_subselect))
|
||||||
|
{
|
||||||
|
JOIN *subq_join= subq_pred->unit->first_select()->join;
|
||||||
|
|
||||||
|
if (!subq_join->tables_list || !subq_join->table_count)
|
||||||
|
{
|
||||||
|
if (execute_degenerate_jtbm_semi_join(thd,
|
||||||
|
table,
|
||||||
|
subq_pred,
|
||||||
|
eq_list))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
join->is_orig_degenerated= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((nested_join= table->nested_join))
|
||||||
|
{
|
||||||
|
if (setup_degenerate_jtbm_semi_joins(join,
|
||||||
|
&nested_join->join_list,
|
||||||
|
eq_list))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Optimize jtbm semi joins for materialization
|
||||||
|
|
||||||
|
@param join the parent join for jtbm semi joins
|
||||||
|
@param join_list the list of TABLE_LIST objects where jtbm semi join
|
||||||
|
can occur
|
||||||
|
@param eq_list IN/OUT the list where to add produced equalities
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method is called by the optimizer after the call of
|
||||||
|
optimize_cond() for parent select.
|
||||||
|
The method traverses join_list trying to find any jtbm semi joins for
|
||||||
|
subqueries from IN predicates and optimizes them.
|
||||||
|
After the optimization some of jtbm semi joins may become degenerate.
|
||||||
|
For example the subquery 'SELECT MAX(b) FROM t2' from the query
|
||||||
|
|
||||||
|
SELECT * FROM t1 WHERE 4 IN (SELECT MAX(b) FROM t2);
|
||||||
|
|
||||||
|
will become degenerate if there is an index on t2.b.
|
||||||
|
If a subquery becomes degenerate it is handled by the function
|
||||||
|
execute_degenerate_jtbm_semi_join().
|
||||||
|
|
||||||
|
Otherwise the method creates a temporary table in which the subquery
|
||||||
|
of the jtbm semi join will be materialied.
|
||||||
|
|
||||||
|
The function saves the equalities between all pairs of the expressions
|
||||||
|
from the left part of the IN subquery predicate and the corresponding
|
||||||
|
columns of the subquery from the predicate in eq_list appending them
|
||||||
|
to the list. The equalities of eq_list will be later conjucted with the
|
||||||
|
condition of the WHERE clause.
|
||||||
|
|
||||||
|
In the case when a table is nested in another table 'nested_join' the
|
||||||
|
method is recursively called for the join_list of the 'nested_join' trying
|
||||||
|
to find in the list any degenerate jtbm semi joins. Currently a jtbm semi
|
||||||
|
join may occur in a mergeable semi join nest.
|
||||||
|
|
||||||
|
@retval TRUE if an error occurs
|
||||||
|
@retval FALSE otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
||||||
Item **join_where)
|
List<Item> &eq_list)
|
||||||
{
|
{
|
||||||
TABLE_LIST *table;
|
TABLE_LIST *table;
|
||||||
NESTED_JOIN *nested_join;
|
NESTED_JOIN *nested_join;
|
||||||
@@ -5451,16 +5874,15 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
|||||||
|
|
||||||
while ((table= li++))
|
while ((table= li++))
|
||||||
{
|
{
|
||||||
Item_in_subselect *item;
|
Item_in_subselect *subq_pred;
|
||||||
|
|
||||||
if ((item= table->jtbm_subselect))
|
if ((subq_pred= table->jtbm_subselect))
|
||||||
{
|
{
|
||||||
Item_in_subselect *subq_pred= item;
|
|
||||||
double rows;
|
double rows;
|
||||||
double read_time;
|
double read_time;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Perform optimization of the subquery, so that we know estmated
|
Perform optimization of the subquery, so that we know estimated
|
||||||
- cost of materialization process
|
- cost of materialization process
|
||||||
- how many records will be in the materialized temp.table
|
- how many records will be in the materialized temp.table
|
||||||
*/
|
*/
|
||||||
@@ -5473,103 +5895,36 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
|||||||
|
|
||||||
if (!subq_join->tables_list || !subq_join->table_count)
|
if (!subq_join->tables_list || !subq_join->table_count)
|
||||||
{
|
{
|
||||||
/*
|
if (!join->is_orig_degenerated &&
|
||||||
A special case; subquery's join is degenerate, and it either produces
|
execute_degenerate_jtbm_semi_join(thd, table, subq_pred,
|
||||||
0 or 1 record. Examples of both cases:
|
eq_list))
|
||||||
|
|
||||||
select * from ot where col in (select ... from it where 2>3)
|
|
||||||
select * from ot where col in (select MY_MIN(it.key) from it)
|
|
||||||
|
|
||||||
in this case, the subquery predicate has not been setup for
|
|
||||||
materialization. In particular, there is no materialized temp.table.
|
|
||||||
We'll now need to
|
|
||||||
1. Check whether 1 or 0 records are produced, setup this as a
|
|
||||||
constant join tab.
|
|
||||||
2. Create a dummy temporary table, because all of the join
|
|
||||||
optimization code relies on TABLE object being present (here we
|
|
||||||
follow a bad tradition started by derived tables)
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(subq_pred->engine->engine_type() ==
|
|
||||||
subselect_engine::SINGLE_SELECT_ENGINE);
|
|
||||||
subselect_single_select_engine *engine=
|
|
||||||
(subselect_single_select_engine*)subq_pred->engine;
|
|
||||||
select_value_catcher *new_sink;
|
|
||||||
if (!(new_sink=
|
|
||||||
new (thd->mem_root) select_value_catcher(thd, subq_pred)))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
|
|
||||||
engine->select_lex->join->change_result(new_sink, NULL) ||
|
|
||||||
engine->exec())
|
|
||||||
{
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
subq_pred->is_jtbm_const_tab= TRUE;
|
|
||||||
|
|
||||||
if (new_sink->assigned)
|
|
||||||
{
|
|
||||||
subq_pred->jtbm_const_row_found= TRUE;
|
|
||||||
/*
|
|
||||||
Subselect produced one row, which is saved in new_sink->row.
|
|
||||||
Inject "left_expr[i] == row[i] equalities into parent's WHERE.
|
|
||||||
*/
|
|
||||||
Item *eq_cond;
|
|
||||||
for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
|
|
||||||
{
|
|
||||||
eq_cond= new (thd->mem_root)
|
|
||||||
Item_func_eq(thd, subq_pred->left_expr->element_index(i),
|
|
||||||
new_sink->row[i]);
|
|
||||||
if (!eq_cond)
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
|
|
||||||
if (!((*join_where)= and_items(thd, *join_where, eq_cond)) ||
|
|
||||||
(*join_where)->fix_fields(thd, join_where))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Subselect produced no rows. Just set the flag, */
|
|
||||||
subq_pred->jtbm_const_row_found= FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up a dummy TABLE*, optimizer code needs JOIN_TABs to have TABLE */
|
|
||||||
TABLE *dummy_table;
|
|
||||||
if (!(dummy_table= create_dummy_tmp_table(thd)))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
table->table= dummy_table;
|
|
||||||
table->table->pos_in_table_list= table;
|
|
||||||
/*
|
|
||||||
Note: the table created above may be freed by:
|
|
||||||
1. JOIN_TAB::cleanup(), when the parent join is a regular join.
|
|
||||||
2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
|
|
||||||
degenerate join (e.g. one with "Impossible where").
|
|
||||||
*/
|
|
||||||
setup_table_map(table->table, table, table->jtbm_table_no);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
|
DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
|
||||||
subq_pred->is_jtbm_const_tab= FALSE;
|
subq_pred->is_jtbm_const_tab= FALSE;
|
||||||
subselect_hash_sj_engine *hash_sj_engine=
|
subselect_hash_sj_engine *hash_sj_engine=
|
||||||
((subselect_hash_sj_engine*)item->engine);
|
((subselect_hash_sj_engine*)subq_pred->engine);
|
||||||
|
|
||||||
table->table= hash_sj_engine->tmp_table;
|
table->table= hash_sj_engine->tmp_table;
|
||||||
table->table->pos_in_table_list= table;
|
table->table->pos_in_table_list= table;
|
||||||
|
|
||||||
setup_table_map(table->table, table, table->jtbm_table_no);
|
setup_table_map(table->table, table, table->jtbm_table_no);
|
||||||
|
|
||||||
Item *sj_conds= hash_sj_engine->semi_join_conds;
|
List_iterator<Item> li(*hash_sj_engine->semi_join_conds->argument_list());
|
||||||
|
Item *item;
|
||||||
(*join_where)= and_items(thd, *join_where, sj_conds);
|
while ((item=li++))
|
||||||
if (!(*join_where)->fixed)
|
{
|
||||||
(*join_where)->fix_fields(thd, join_where);
|
if (eq_list.push_back(item, thd->mem_root))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping);
|
table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nested_join= table->nested_join))
|
if ((nested_join= table->nested_join))
|
||||||
{
|
{
|
||||||
if (setup_jtbm_semi_joins(join, &nested_join->join_list, join_where))
|
if (setup_jtbm_semi_joins(join, &nested_join->join_list, eq_list))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5963,3 +6318,418 @@ bool JOIN::choose_tableless_subquery_plan()
|
|||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if the item exists in the fields list of the left part of
|
||||||
|
the IN subquery predicate subq_pred and returns its corresponding
|
||||||
|
item from the select of the right part of subq_pred.
|
||||||
|
*/
|
||||||
|
Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(type() == Item::FIELD_ITEM ||
|
||||||
|
(type() == Item::REF_ITEM &&
|
||||||
|
((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF));
|
||||||
|
|
||||||
|
List_iterator<Field_pair> it(subq_pred->corresponding_fields);
|
||||||
|
Field_pair *ret;
|
||||||
|
Item_field *field_item= (Item_field *) (real_item());
|
||||||
|
while ((ret= it++))
|
||||||
|
{
|
||||||
|
if (field_item->field == ret->field)
|
||||||
|
return ret->corresponding_item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
|
||||||
|
return true;
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
Item_equal_fields_iterator it(*item_equal);
|
||||||
|
Item *equal_item;
|
||||||
|
while ((equal_item= it++))
|
||||||
|
{
|
||||||
|
if (equal_item->const_item())
|
||||||
|
continue;
|
||||||
|
if (equal_item->get_corresponding_field_in_insubq(subq_pred))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
|
||||||
|
if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (*ref)->excl_dep_on_in_subq_left_part(subq_pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_equal::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
Item *left_item = get_const();
|
||||||
|
Item_equal_fields_iterator it(*this);
|
||||||
|
Item *item;
|
||||||
|
if (!left_item)
|
||||||
|
{
|
||||||
|
while ((item=it++))
|
||||||
|
{
|
||||||
|
if (item->excl_dep_on_in_subq_left_part(subq_pred))
|
||||||
|
{
|
||||||
|
left_item= item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!left_item)
|
||||||
|
return false;
|
||||||
|
while ((item=it++))
|
||||||
|
{
|
||||||
|
if (item->excl_dep_on_in_subq_left_part(subq_pred))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Get corresponding item from the select of the right part of IN subquery
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param item the item from the left part of subq_pred for which
|
||||||
|
corresponding item should be found
|
||||||
|
@param subq_pred the IN subquery predicate
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method looks through the fields of the select of the right part of
|
||||||
|
the IN subquery predicate subq_pred trying to find the corresponding
|
||||||
|
item 'new_item' for item. If item has equal items it looks through
|
||||||
|
the fields of the select of the right part of subq_pred for each equal
|
||||||
|
item trying to find the corresponding item.
|
||||||
|
The method assumes that the given item is either a field item or
|
||||||
|
a reference to a field item.
|
||||||
|
|
||||||
|
@retval <item*> reference to the corresponding item
|
||||||
|
@retval NULL if item was not found
|
||||||
|
*/
|
||||||
|
|
||||||
|
static
|
||||||
|
Item *get_corresponding_item(THD *thd, Item *item,
|
||||||
|
Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
|
||||||
|
(item->type() == Item::REF_ITEM &&
|
||||||
|
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
|
||||||
|
|
||||||
|
Item *corresonding_item;
|
||||||
|
Item_equal *item_equal= item->get_item_equal();
|
||||||
|
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
Item_equal_fields_iterator it(*item_equal);
|
||||||
|
Item *equal_item;
|
||||||
|
while ((equal_item= it++))
|
||||||
|
{
|
||||||
|
corresonding_item=
|
||||||
|
equal_item->get_corresponding_field_in_insubq(subq_pred);
|
||||||
|
if (corresonding_item)
|
||||||
|
return corresonding_item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return item->get_corresponding_field_in_insubq(subq_pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_field::in_subq_field_transformer_for_where(THD *thd, uchar *arg)
|
||||||
|
{
|
||||||
|
Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
|
||||||
|
Item *producing_item= get_corresponding_item(thd, this, subq_pred);
|
||||||
|
if (producing_item)
|
||||||
|
return producing_item->build_clone(thd);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_direct_view_ref::in_subq_field_transformer_for_where(THD *thd,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
|
||||||
|
Item *producing_item= get_corresponding_item(thd, this, subq_pred);
|
||||||
|
DBUG_ASSERT (producing_item != NULL);
|
||||||
|
return producing_item->build_clone(thd);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Transforms item so it can be pushed into the IN subquery HAVING clause
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param in_item the item for which pushable item should be created
|
||||||
|
@param subq_pred the IN subquery predicate
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method finds for in_item that is a field from the left part of the
|
||||||
|
IN subquery predicate subq_pred its corresponding item from the right part
|
||||||
|
of subq_pred.
|
||||||
|
If corresponding item is found, a shell for this item is created.
|
||||||
|
This shell can be pushed into the HAVING part of subq_pred select.
|
||||||
|
|
||||||
|
@retval <item*> reference to the created corresponding item shell for in_item
|
||||||
|
@retval NULL if mistake occurs
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Item*
|
||||||
|
get_corresponding_item_for_in_subq_having(THD *thd, Item *in_item,
|
||||||
|
Item_in_subselect *subq_pred)
|
||||||
|
{
|
||||||
|
Item *new_item= get_corresponding_item(thd, in_item, subq_pred);
|
||||||
|
|
||||||
|
if (new_item)
|
||||||
|
{
|
||||||
|
Item_ref *ref=
|
||||||
|
new (thd->mem_root) Item_ref(thd,
|
||||||
|
&subq_pred->unit->first_select()->context,
|
||||||
|
NullS, NullS,
|
||||||
|
&new_item->name);
|
||||||
|
if (!ref)
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
return new_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
|
{
|
||||||
|
return get_corresponding_item_for_in_subq_having(thd, this,
|
||||||
|
(Item_in_subselect *)arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_direct_view_ref::in_subq_field_transformer_for_having(THD *thd,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
if (!item_equal)
|
||||||
|
return this;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Item *new_item= get_corresponding_item_for_in_subq_having(thd, this,
|
||||||
|
(Item_in_subselect *)arg);
|
||||||
|
if (!new_item)
|
||||||
|
return this;
|
||||||
|
return new_item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Find fields that are used in the GROUP BY of the select
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param sel the select of the IN subquery predicate
|
||||||
|
@param fields fields of the left part of the IN subquery predicate
|
||||||
|
@param grouping_list GROUP BY clause
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method traverses fields which are used in the GROUP BY of
|
||||||
|
sel and saves them with their corresponding items from fields.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool grouping_fields_in_the_in_subq_left_part(THD *thd,
|
||||||
|
st_select_lex *sel,
|
||||||
|
List<Field_pair> *fields,
|
||||||
|
ORDER *grouping_list)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("grouping_fields_in_the_in_subq_left_part");
|
||||||
|
sel->grouping_tmp_fields.empty();
|
||||||
|
List_iterator<Field_pair> it(*fields);
|
||||||
|
Field_pair *item;
|
||||||
|
while ((item= it++))
|
||||||
|
{
|
||||||
|
for (ORDER *ord= grouping_list; ord; ord= ord->next)
|
||||||
|
{
|
||||||
|
if ((*ord->item)->eq(item->corresponding_item, 0))
|
||||||
|
{
|
||||||
|
if (sel->grouping_tmp_fields.push_back(item, thd->mem_root))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Extract condition that can be pushed into select of this IN subquery
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param cond current condition
|
||||||
|
|
||||||
|
@details
|
||||||
|
This function builds the most restrictive condition depending only on
|
||||||
|
the list of fields of the left part of this IN subquery predicate
|
||||||
|
(directly or indirectly through equality) that can be extracted from the
|
||||||
|
given condition cond and pushes it into this IN subquery.
|
||||||
|
|
||||||
|
Example of the transformation:
|
||||||
|
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE a>3 AND b>10 AND
|
||||||
|
(a,b) IN (SELECT x,MAX(y) FROM t2 GROUP BY x);
|
||||||
|
|
||||||
|
=>
|
||||||
|
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE a>3 AND b>10 AND
|
||||||
|
(a,b) IN (SELECT x,max(y)
|
||||||
|
FROM t2
|
||||||
|
WHERE x>3
|
||||||
|
GROUP BY x
|
||||||
|
HAVING MAX(y)>10);
|
||||||
|
|
||||||
|
|
||||||
|
In details:
|
||||||
|
1. Check what pushable formula can be extracted from cond
|
||||||
|
2. Build a clone PC of the formula that can be extracted
|
||||||
|
(the clone is built only if the extracted formula is a AND subformula
|
||||||
|
of cond or conjunction of such subformulas)
|
||||||
|
3. If there is no HAVING clause prepare PC to be conjuncted with
|
||||||
|
WHERE clause of this subquery. Otherwise do 4-7.
|
||||||
|
4. Check what formula PC_where can be extracted from PC to be pushed
|
||||||
|
into the WHERE clause of the subquery
|
||||||
|
5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC
|
||||||
|
getting PC_having
|
||||||
|
6. Prepare PC_where to be conjuncted with the WHERE clause of
|
||||||
|
the IN subquery
|
||||||
|
7. Prepare PC_having to be conjuncted with the HAVING clause of
|
||||||
|
the IN subquery
|
||||||
|
|
||||||
|
@note
|
||||||
|
This method is similar to pushdown_cond_for_derived()
|
||||||
|
|
||||||
|
@retval TRUE if an error occurs
|
||||||
|
@retval FALSE otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_in_subselect::pushdown_cond_for_in_subquery");
|
||||||
|
Item *remaining_cond= NULL;
|
||||||
|
|
||||||
|
if (!cond)
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
st_select_lex *sel = unit->first_select();
|
||||||
|
|
||||||
|
if (is_jtbm_const_tab)
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
if (!sel->cond_pushdown_is_allowed())
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a list of Field_pair items for this IN subquery.
|
||||||
|
It consists of the pairs of fields from the left part of this IN subquery
|
||||||
|
predicate 'left_part' and the respective fields from the select of the
|
||||||
|
right part of the IN subquery 'sel' (the field from left_part with the
|
||||||
|
corresponding field from the sel projection list).
|
||||||
|
Attach this list to the IN subquery.
|
||||||
|
*/
|
||||||
|
corresponding_fields.empty();
|
||||||
|
List_iterator_fast<Item> it(sel->join->fields_list);
|
||||||
|
Item *item;
|
||||||
|
for (uint i= 0; i < left_expr->cols(); i++)
|
||||||
|
{
|
||||||
|
item= it++;
|
||||||
|
Item *elem= left_expr->element_index(i);
|
||||||
|
|
||||||
|
if (elem->real_item()->type() != Item::FIELD_ITEM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (corresponding_fields.push_back(
|
||||||
|
new Field_pair(((Item_field *)(elem->real_item()))->field,
|
||||||
|
item)))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1. Check what pushable formula can be extracted from cond */
|
||||||
|
Item *extracted_cond;
|
||||||
|
cond->check_pushable_cond(&Item::pushable_cond_checker_for_subquery,
|
||||||
|
(uchar *)this);
|
||||||
|
/* 2. Build a clone PC of the formula that can be extracted */
|
||||||
|
extracted_cond=
|
||||||
|
cond->build_pushable_cond(thd,
|
||||||
|
&Item::pushable_equality_checker_for_subquery,
|
||||||
|
(uchar *)this);
|
||||||
|
/* Nothing to push */
|
||||||
|
if (!extracted_cond)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect fields that are used in the GROUP BY of sel */
|
||||||
|
st_select_lex *save_curr_select= thd->lex->current_select;
|
||||||
|
if (sel->have_window_funcs())
|
||||||
|
{
|
||||||
|
if (sel->group_list.first || sel->join->implicit_grouping)
|
||||||
|
goto exit;
|
||||||
|
ORDER *common_partition_fields=
|
||||||
|
sel->find_common_window_func_partition_fields(thd);
|
||||||
|
if (!common_partition_fields)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (grouping_fields_in_the_in_subq_left_part(thd, sel, &corresponding_fields,
|
||||||
|
common_partition_fields))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
else if (grouping_fields_in_the_in_subq_left_part(thd, sel,
|
||||||
|
&corresponding_fields,
|
||||||
|
sel->group_list.first))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
/* Do 4-6 */
|
||||||
|
sel->pushdown_cond_into_where_clause(thd, extracted_cond,
|
||||||
|
&remaining_cond,
|
||||||
|
&Item::in_subq_field_transformer_for_where,
|
||||||
|
(uchar *) this);
|
||||||
|
if (!remaining_cond)
|
||||||
|
goto exit;
|
||||||
|
/*
|
||||||
|
7. Prepare PC_having to be conjuncted with the HAVING clause of
|
||||||
|
the IN subquery
|
||||||
|
*/
|
||||||
|
remaining_cond=
|
||||||
|
remaining_cond->transform(thd,
|
||||||
|
&Item::in_subq_field_transformer_for_having,
|
||||||
|
(uchar *)this);
|
||||||
|
if (!remaining_cond)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
|
||||||
|
0, 0);
|
||||||
|
sel->cond_pushed_into_having= remaining_cond;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
thd->lex->current_select= save_curr_select;
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,8 +26,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
|
|||||||
bool convert_join_subqueries_to_semijoins(JOIN *join);
|
bool convert_join_subqueries_to_semijoins(JOIN *join);
|
||||||
int pull_out_semijoin_tables(JOIN *join);
|
int pull_out_semijoin_tables(JOIN *join);
|
||||||
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
|
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
|
||||||
|
Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
|
||||||
|
COND_EQUAL **cond_eq,
|
||||||
|
List<Item> &new_conds,
|
||||||
|
Item::cond_result *cond_value);
|
||||||
|
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
|
||||||
|
List<TABLE_LIST> *join_list,
|
||||||
|
List<Item> &eq_list);
|
||||||
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
||||||
Item **join_where);
|
List<Item> &eq_list);
|
||||||
void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list);
|
void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list);
|
||||||
|
|
||||||
// used by Loose_scan_opt
|
// used by Loose_scan_opt
|
||||||
|
|||||||
@@ -1242,25 +1242,61 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
@brief
|
@brief
|
||||||
Extract the condition depended on derived table/view and pushed it there
|
Extract condition that can be pushed into a derived table/view
|
||||||
|
|
||||||
@param thd The thread handle
|
@param thd the thread handle
|
||||||
@param cond The condition from which to extract the pushed condition
|
@param cond current condition
|
||||||
@param derived The reference to the derived table/view
|
@param derived the reference to the derived table/view
|
||||||
|
|
||||||
@details
|
@details
|
||||||
This functiom builds the most restrictive condition depending only on
|
This function builds the most restrictive condition depending only on
|
||||||
the derived table/view that can be extracted from the condition cond.
|
the derived table/view (directly or indirectly through equality) that
|
||||||
The built condition is pushed into the having clauses of the
|
can be extracted from the given condition cond and pushes it into the
|
||||||
selects contained in the query specifying the derived table/view.
|
derived table/view.
|
||||||
The function also checks for each select whether any condition depending
|
|
||||||
only on grouping fields can be extracted from the pushed condition.
|
|
||||||
If so, it pushes the condition over grouping fields into the where
|
|
||||||
clause of the select.
|
|
||||||
|
|
||||||
@retval
|
Example of the transformation:
|
||||||
true if an error is reported
|
|
||||||
false otherwise
|
SELECT *
|
||||||
|
FROM t1,
|
||||||
|
(
|
||||||
|
SELECT x,MAX(y) AS max_y
|
||||||
|
FROM t2
|
||||||
|
GROUP BY x
|
||||||
|
) AS d_tab
|
||||||
|
WHERE d_tab.x>1 AND d_tab.max_y<30;
|
||||||
|
|
||||||
|
=>
|
||||||
|
|
||||||
|
SELECT *
|
||||||
|
FROM t1,
|
||||||
|
(
|
||||||
|
SELECT x,z,MAX(y) AS max_y
|
||||||
|
FROM t2
|
||||||
|
WHERE x>1
|
||||||
|
HAVING max_y<30
|
||||||
|
GROUP BY x
|
||||||
|
) AS d_tab
|
||||||
|
WHERE d_tab.x>1 AND d_tab.max_y<30;
|
||||||
|
|
||||||
|
In details:
|
||||||
|
1. Check what pushable formula can be extracted from cond
|
||||||
|
2. Build a clone PC of the formula that can be extracted
|
||||||
|
(the clone is built only if the extracted formula is a AND subformula
|
||||||
|
of cond or conjunction of such subformulas)
|
||||||
|
Do for every select specifying derived table/view:
|
||||||
|
3. If there is no HAVING clause prepare PC to be conjuncted with
|
||||||
|
WHERE clause of the select. Otherwise do 4-7.
|
||||||
|
4. Check what formula PC_where can be extracted from PC to be pushed
|
||||||
|
into the WHERE clause of the select
|
||||||
|
5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC
|
||||||
|
getting PC_having
|
||||||
|
6. Prepare PC_where to be conjuncted with the WHERE clause of the select
|
||||||
|
7. Prepare PC_having to be conjuncted with the HAVING clause of the select
|
||||||
|
@note
|
||||||
|
This method is similar to pushdown_cond_for_in_subquery()
|
||||||
|
|
||||||
|
@retval TRUE if an error occurs
|
||||||
|
@retval FALSE otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
||||||
@@ -1300,63 +1336,25 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
|||||||
if (!some_select_allows_cond_pushdown)
|
if (!some_select_allows_cond_pushdown)
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
/*
|
/* 1. Check what pushable formula can be extracted from cond */
|
||||||
Build the most restrictive condition extractable from 'cond'
|
|
||||||
that can be pushed into the derived table 'derived'.
|
|
||||||
All subexpressions of this condition are cloned from the
|
|
||||||
subexpressions of 'cond'.
|
|
||||||
This condition has to be fixed yet.
|
|
||||||
*/
|
|
||||||
Item *extracted_cond;
|
Item *extracted_cond;
|
||||||
derived->check_pushable_cond_for_table(cond);
|
cond->check_pushable_cond(&Item::pushable_cond_checker_for_derived,
|
||||||
extracted_cond= derived->build_pushable_cond_for_table(thd, cond);
|
(uchar *)(&derived->table->map));
|
||||||
|
/* 2. Build a clone PC of the formula that can be extracted */
|
||||||
|
extracted_cond=
|
||||||
|
cond->build_pushable_cond(thd,
|
||||||
|
&Item::pushable_equality_checker_for_derived,
|
||||||
|
((uchar *)&derived->table->map));
|
||||||
if (!extracted_cond)
|
if (!extracted_cond)
|
||||||
{
|
{
|
||||||
/* Nothing can be pushed into the derived table */
|
/* Nothing can be pushed into the derived table */
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
/* Push extracted_cond into every select of the unit specifying 'derived' */
|
|
||||||
st_select_lex *save_curr_select= thd->lex->current_select;
|
st_select_lex *save_curr_select= thd->lex->current_select;
|
||||||
for (; sl; sl= sl->next_select())
|
for (; sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
Item *extracted_cond_copy;
|
Item *extracted_cond_copy;
|
||||||
if (!sl->cond_pushdown_is_allowed())
|
|
||||||
continue;
|
|
||||||
thd->lex->current_select= sl;
|
|
||||||
if (sl->have_window_funcs())
|
|
||||||
{
|
|
||||||
if (sl->join->group_list || sl->join->implicit_grouping)
|
|
||||||
continue;
|
|
||||||
ORDER *common_partition_fields=
|
|
||||||
sl->find_common_window_func_partition_fields(thd);
|
|
||||||
if (!common_partition_fields)
|
|
||||||
continue;
|
|
||||||
extracted_cond_copy= !sl->next_select() ?
|
|
||||||
extracted_cond :
|
|
||||||
extracted_cond->build_clone(thd);
|
|
||||||
if (!extracted_cond_copy)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Item *cond_over_partition_fields;;
|
|
||||||
sl->collect_grouping_fields(thd, common_partition_fields);
|
|
||||||
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
|
|
||||||
derived);
|
|
||||||
cond_over_partition_fields=
|
|
||||||
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
|
|
||||||
if (cond_over_partition_fields)
|
|
||||||
cond_over_partition_fields= cond_over_partition_fields->transform(thd,
|
|
||||||
&Item::derived_grouping_field_transformer_for_where,
|
|
||||||
(uchar*) sl);
|
|
||||||
if (cond_over_partition_fields)
|
|
||||||
{
|
|
||||||
cond_over_partition_fields->walk(
|
|
||||||
&Item::cleanup_excluding_const_fields_processor, 0, 0);
|
|
||||||
sl->cond_pushed_into_where= cond_over_partition_fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For each select of the unit except the last one
|
For each select of the unit except the last one
|
||||||
create a clone of extracted_cond
|
create a clone of extracted_cond
|
||||||
@@ -1367,73 +1365,44 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
|||||||
if (!extracted_cond_copy)
|
if (!extracted_cond_copy)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!sl->join->group_list && !sl->with_sum_func)
|
/* Collect fields that are used in the GROUP BY of sl */
|
||||||
|
if (sl->have_window_funcs())
|
||||||
{
|
{
|
||||||
/* extracted_cond_copy is pushed into where of sl */
|
if (sl->group_list.first || sl->join->implicit_grouping)
|
||||||
extracted_cond_copy= extracted_cond_copy->transform(thd,
|
continue;
|
||||||
|
ORDER *common_partition_fields=
|
||||||
|
sl->find_common_window_func_partition_fields(thd);
|
||||||
|
if (!common_partition_fields)
|
||||||
|
continue;
|
||||||
|
sl->collect_grouping_fields(thd, common_partition_fields);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sl->collect_grouping_fields(thd, sl->group_list.first);
|
||||||
|
|
||||||
|
Item *remaining_cond= NULL;
|
||||||
|
/* Do 4-6 */
|
||||||
|
sl->pushdown_cond_into_where_clause(thd, extracted_cond_copy,
|
||||||
|
&remaining_cond,
|
||||||
&Item::derived_field_transformer_for_where,
|
&Item::derived_field_transformer_for_where,
|
||||||
(uchar*) sl);
|
(uchar *) sl);
|
||||||
if (extracted_cond_copy)
|
|
||||||
{
|
|
||||||
extracted_cond_copy->walk(
|
|
||||||
&Item::cleanup_excluding_const_fields_processor, 0, 0);
|
|
||||||
sl->cond_pushed_into_where= extracted_cond_copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!remaining_cond)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Figure out what can be extracted from the pushed condition
|
7. Prepare PC_having to be conjuncted with the HAVING clause of
|
||||||
that could be pushed into the where clause of sl
|
the select
|
||||||
*/
|
*/
|
||||||
Item *cond_over_grouping_fields;
|
remaining_cond=
|
||||||
sl->collect_grouping_fields(thd, sl->join->group_list);
|
remaining_cond->transform(thd,
|
||||||
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
|
|
||||||
derived);
|
|
||||||
cond_over_grouping_fields=
|
|
||||||
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Transform the references to the 'derived' columns from the condition
|
|
||||||
pushed into the where clause of sl to make them usable in the new context
|
|
||||||
*/
|
|
||||||
if (cond_over_grouping_fields)
|
|
||||||
cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
|
|
||||||
&Item::derived_grouping_field_transformer_for_where,
|
|
||||||
(uchar*) sl);
|
|
||||||
|
|
||||||
if (cond_over_grouping_fields)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
In extracted_cond_copy remove top conjuncts that
|
|
||||||
has been pushed into the where clause of sl
|
|
||||||
*/
|
|
||||||
extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
|
|
||||||
|
|
||||||
cond_over_grouping_fields->walk(
|
|
||||||
&Item::cleanup_excluding_const_fields_processor, 0, 0);
|
|
||||||
sl->cond_pushed_into_where= cond_over_grouping_fields;
|
|
||||||
|
|
||||||
if (!extracted_cond_copy)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Transform the references to the 'derived' columns from the condition
|
|
||||||
pushed into the having clause of sl to make them usable in the new context
|
|
||||||
*/
|
|
||||||
extracted_cond_copy= extracted_cond_copy->transform(thd,
|
|
||||||
&Item::derived_field_transformer_for_having,
|
&Item::derived_field_transformer_for_having,
|
||||||
(uchar*) sl);
|
(uchar *) sl);
|
||||||
if (!extracted_cond_copy)
|
if (!remaining_cond)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
extracted_cond_copy->walk(&Item::cleanup_excluding_const_fields_processor,
|
remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
|
||||||
0, 0);
|
0, 0);
|
||||||
sl->cond_pushed_into_having= extracted_cond_copy;
|
sl->cond_pushed_into_having= remaining_cond;
|
||||||
}
|
}
|
||||||
thd->lex->current_select= save_curr_select;
|
thd->lex->current_select= save_curr_select;
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
136
sql/sql_lex.cc
136
sql/sql_lex.cc
@@ -7245,8 +7245,8 @@ void st_select_lex::collect_grouping_fields(THD *thd,
|
|||||||
{
|
{
|
||||||
if ((*ord->item)->eq((Item*)item, 0))
|
if ((*ord->item)->eq((Item*)item, 0))
|
||||||
{
|
{
|
||||||
Grouping_tmp_field *grouping_tmp_field=
|
Field_pair *grouping_tmp_field=
|
||||||
new Grouping_tmp_field(master_unit()->derived->table->field[i], item);
|
new Field_pair(master_unit()->derived->table->field[i], item);
|
||||||
grouping_tmp_fields.push_back(grouping_tmp_field);
|
grouping_tmp_fields.push_back(grouping_tmp_field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7277,8 +7277,7 @@ void st_select_lex::collect_grouping_fields(THD *thd,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
|
||||||
TABLE_LIST *derived)
|
|
||||||
{
|
{
|
||||||
cond->clear_extraction_flag();
|
cond->clear_extraction_flag();
|
||||||
if (cond->type() == Item::COND_ITEM)
|
if (cond->type() == Item::COND_ITEM)
|
||||||
@@ -7291,7 +7290,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
|||||||
Item *item;
|
Item *item;
|
||||||
while ((item=li++))
|
while ((item=li++))
|
||||||
{
|
{
|
||||||
check_cond_extraction_for_grouping_fields(item, derived);
|
check_cond_extraction_for_grouping_fields(item);
|
||||||
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
|
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
@@ -7340,7 +7339,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
|||||||
to figure out whether a subformula depends only on these fields or not.
|
to figure out whether a subformula depends only on these fields or not.
|
||||||
@note
|
@note
|
||||||
The built condition C is always implied by the condition cond
|
The built condition C is always implied by the condition cond
|
||||||
(cond => C). The method tries to build the most restictive such
|
(cond => C). The method tries to build the least restictive such
|
||||||
condition (i.e. for any other condition C' such that cond => C'
|
condition (i.e. for any other condition C' such that cond => C'
|
||||||
we have C => C').
|
we have C => C').
|
||||||
@note
|
@note
|
||||||
@@ -7757,3 +7756,128 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const
|
|||||||
make_item_func_trim_oracle(thd) :
|
make_item_func_trim_oracle(thd) :
|
||||||
make_item_func_trim_std(thd);
|
make_item_func_trim_std(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Extract from given item a condition pushable into WHERE clause
|
||||||
|
|
||||||
|
@param thd the thread handle
|
||||||
|
@param cond the item to extract a condition to be pushed
|
||||||
|
into WHERE
|
||||||
|
@param remaining_cond the condition that will remain of cond after
|
||||||
|
the pushdown of its parts into the WHERE clause
|
||||||
|
@param transformer the transformer callback function to be
|
||||||
|
applied to the condition so it can be pushed
|
||||||
|
down into the WHERE clause of this select
|
||||||
|
@param arg parameter to be passed to the transformer
|
||||||
|
|
||||||
|
@details
|
||||||
|
This method checks if cond entirely or its parts can be
|
||||||
|
pushed into the WHERE clause of this select and prepares it for pushing.
|
||||||
|
|
||||||
|
First it checks wherever this select doesn't have any aggregation function
|
||||||
|
in its projection and GROUP BY clause. If so cond can be entirely
|
||||||
|
pushed into the WHERE clause of this select but before its fields should
|
||||||
|
be transformed with transformer_for_where to make it pushable.
|
||||||
|
|
||||||
|
Otherwise the method checks wherever any condition depending only on
|
||||||
|
grouping fields can be extracted from cond. If there is any it prepares it
|
||||||
|
for pushing using grouping_field_transformer_for_where and if it happens to
|
||||||
|
be a conjunct of cond it removes it from cond. It saves the result of
|
||||||
|
removal in remaining_cond.
|
||||||
|
The extracted condition is saved in cond_pushed_into_where of this select.
|
||||||
|
|
||||||
|
@note
|
||||||
|
When looking for pushable condition the method considers only the grouping
|
||||||
|
fields from the list grouping_tmp_fields whose elements are of the type
|
||||||
|
Field_pair. This list must be prepared before the call of the
|
||||||
|
function.
|
||||||
|
|
||||||
|
@note
|
||||||
|
This method is called for pushdown conditions into materialized
|
||||||
|
derived tables/views optimization.
|
||||||
|
Item::derived_field_transformer_for_where is passed as the actual
|
||||||
|
callback function.
|
||||||
|
Also it is called for pushdown conditions into materialized IN subqueries.
|
||||||
|
Item::in_subq_field_transformer_for_where is passed as the actual
|
||||||
|
callback function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
|
||||||
|
Item **remaining_cond,
|
||||||
|
Item_transformer transformer,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
if (!cond_pushdown_is_allowed())
|
||||||
|
return;
|
||||||
|
thd->lex->current_select= this;
|
||||||
|
if (have_window_funcs())
|
||||||
|
{
|
||||||
|
Item *cond_over_partition_fields;
|
||||||
|
check_cond_extraction_for_grouping_fields(cond);
|
||||||
|
cond_over_partition_fields=
|
||||||
|
build_cond_for_grouping_fields(thd, cond, true);
|
||||||
|
if (cond_over_partition_fields)
|
||||||
|
cond_over_partition_fields= cond_over_partition_fields->transform(thd,
|
||||||
|
&Item::grouping_field_transformer_for_where,
|
||||||
|
(uchar*) this);
|
||||||
|
if (cond_over_partition_fields)
|
||||||
|
{
|
||||||
|
cond_over_partition_fields->walk(
|
||||||
|
&Item::cleanup_excluding_const_fields_processor, 0, 0);
|
||||||
|
cond_pushed_into_where= cond_over_partition_fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!join->group_list && !with_sum_func)
|
||||||
|
{
|
||||||
|
cond=
|
||||||
|
cond->transform(thd, transformer, arg);
|
||||||
|
if (cond)
|
||||||
|
{
|
||||||
|
cond->walk(
|
||||||
|
&Item::cleanup_excluding_const_fields_processor, 0, 0);
|
||||||
|
cond_pushed_into_where= cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Figure out what can be extracted from cond
|
||||||
|
that could be pushed into the WHERE clause of this select
|
||||||
|
*/
|
||||||
|
Item *cond_over_grouping_fields;
|
||||||
|
check_cond_extraction_for_grouping_fields(cond);
|
||||||
|
cond_over_grouping_fields=
|
||||||
|
build_cond_for_grouping_fields(thd, cond, true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Transform the references to the columns from the cond
|
||||||
|
pushed into the WHERE clause of this select to make them usable in
|
||||||
|
the new context
|
||||||
|
*/
|
||||||
|
if (cond_over_grouping_fields)
|
||||||
|
cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
|
||||||
|
&Item::grouping_field_transformer_for_where,
|
||||||
|
(uchar*) this);
|
||||||
|
|
||||||
|
if (cond_over_grouping_fields)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
In cond remove top conjuncts that has been pushed into the WHERE
|
||||||
|
clause of this select
|
||||||
|
*/
|
||||||
|
cond= remove_pushed_top_conjuncts(thd, cond);
|
||||||
|
|
||||||
|
cond_over_grouping_fields->walk(
|
||||||
|
&Item::cleanup_excluding_const_fields_processor, 0, 0);
|
||||||
|
cond_pushed_into_where= cond_over_grouping_fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
*remaining_cond= cond;
|
||||||
|
}
|
||||||
|
|||||||
@@ -808,19 +808,19 @@ typedef Bounds_checked_array<Item*> Ref_ptr_array;
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Structure which consists of the field and the item which
|
Structure which consists of the field and the item that
|
||||||
produces this field.
|
corresponds to this field.
|
||||||
*/
|
*/
|
||||||
|
class Field_pair :public Sql_alloc
|
||||||
class Grouping_tmp_field :public Sql_alloc
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Field *tmp_field;
|
Field *field;
|
||||||
Item *producing_item;
|
Item *corresponding_item;
|
||||||
Grouping_tmp_field(Field *fld, Item *item)
|
Field_pair(Field *fld, Item *item)
|
||||||
:tmp_field(fld), producing_item(item) {}
|
:field(fld), corresponding_item(item) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SELECT_LEX - store information of parsed SELECT statment
|
SELECT_LEX - store information of parsed SELECT statment
|
||||||
*/
|
*/
|
||||||
@@ -1033,7 +1033,8 @@ public:
|
|||||||
nesting_map name_visibility_map;
|
nesting_map name_visibility_map;
|
||||||
|
|
||||||
table_map with_dep;
|
table_map with_dep;
|
||||||
List<Grouping_tmp_field> grouping_tmp_fields;
|
/* the structure to store fields that are used in the GROUP BY of this select */
|
||||||
|
List<Field_pair> grouping_tmp_fields;
|
||||||
|
|
||||||
/* it is for correct printing SELECT options */
|
/* it is for correct printing SELECT options */
|
||||||
thr_lock_type lock_type;
|
thr_lock_type lock_type;
|
||||||
@@ -1239,8 +1240,7 @@ public:
|
|||||||
bool check_unrestricted_recursive(bool only_standard_compliant);
|
bool check_unrestricted_recursive(bool only_standard_compliant);
|
||||||
bool check_subqueries_with_recursive_references();
|
bool check_subqueries_with_recursive_references();
|
||||||
void collect_grouping_fields(THD *thd, ORDER *grouping_list);
|
void collect_grouping_fields(THD *thd, ORDER *grouping_list);
|
||||||
void check_cond_extraction_for_grouping_fields(Item *cond,
|
void check_cond_extraction_for_grouping_fields(Item *cond);
|
||||||
TABLE_LIST *derived);
|
|
||||||
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
|
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
|
||||||
bool no_to_clones);
|
bool no_to_clones);
|
||||||
|
|
||||||
@@ -1266,6 +1266,11 @@ public:
|
|||||||
bool cond_pushdown_is_allowed() const
|
bool cond_pushdown_is_allowed() const
|
||||||
{ return !olap && !explicit_limit && !tvc; }
|
{ return !olap && !explicit_limit && !tvc; }
|
||||||
|
|
||||||
|
void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond,
|
||||||
|
Item **remaining_cond,
|
||||||
|
Item_transformer transformer,
|
||||||
|
uchar *arg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_non_agg_field_used;
|
bool m_non_agg_field_used;
|
||||||
bool m_agg_func_used;
|
bool m_agg_func_used;
|
||||||
|
|||||||
@@ -228,6 +228,7 @@
|
|||||||
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
|
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
|
||||||
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
|
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
|
||||||
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
|
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
|
||||||
|
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
|
||||||
|
|
||||||
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
|
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
|
||||||
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
|
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
|
||||||
@@ -254,7 +255,8 @@
|
|||||||
OPTIMIZER_SWITCH_EXISTS_TO_IN | \
|
OPTIMIZER_SWITCH_EXISTS_TO_IN | \
|
||||||
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
|
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
|
||||||
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
|
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
|
||||||
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED)
|
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
|
||||||
|
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
|
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
|
||||||
|
|||||||
@@ -1617,9 +1617,28 @@ JOIN::optimize_inner()
|
|||||||
thd->restore_active_arena(arena, &backup);
|
thd->restore_active_arena(arena, &backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setup_jtbm_semi_joins(this, join_list, &conds))
|
List<Item> eq_list;
|
||||||
|
|
||||||
|
if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
if (eq_list.elements != 0)
|
||||||
|
{
|
||||||
|
Item *new_cond;
|
||||||
|
|
||||||
|
if (eq_list.elements == 1)
|
||||||
|
new_cond= eq_list.pop();
|
||||||
|
else
|
||||||
|
new_cond= new (thd->mem_root) Item_cond_and(thd, eq_list);
|
||||||
|
|
||||||
|
if (new_cond &&
|
||||||
|
((new_cond->fix_fields(thd, &new_cond) ||
|
||||||
|
!(conds= and_items(thd, conds, new_cond)) ||
|
||||||
|
conds->fix_fields(thd, &conds))))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
eq_list.empty();
|
||||||
|
|
||||||
if (select_lex->cond_pushed_into_where)
|
if (select_lex->cond_pushed_into_where)
|
||||||
{
|
{
|
||||||
conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
|
conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
|
||||||
@@ -1641,6 +1660,32 @@ JOIN::optimize_inner()
|
|||||||
conds= optimize_cond(this, conds, join_list, FALSE,
|
conds= optimize_cond(this, conds, join_list, FALSE,
|
||||||
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
|
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
|
||||||
|
|
||||||
|
if (thd->lex->sql_command == SQLCOM_SELECT &&
|
||||||
|
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
|
||||||
|
{
|
||||||
|
TABLE_LIST *tbl;
|
||||||
|
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
|
||||||
|
while ((tbl= li++))
|
||||||
|
if (tbl->jtbm_subselect)
|
||||||
|
{
|
||||||
|
if (tbl->jtbm_subselect->pushdown_cond_for_in_subquery(thd, conds))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setup_jtbm_semi_joins(this, join_list, eq_list))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
if (eq_list.elements != 0)
|
||||||
|
{
|
||||||
|
conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
|
||||||
|
eq_list, &cond_value);
|
||||||
|
|
||||||
|
if (!conds &&
|
||||||
|
cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (thd->lex->sql_command == SQLCOM_SELECT &&
|
if (thd->lex->sql_command == SQLCOM_SELECT &&
|
||||||
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
|
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
|
||||||
{
|
{
|
||||||
@@ -1679,7 +1724,6 @@ JOIN::optimize_inner()
|
|||||||
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
|
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thd->is_error())
|
if (thd->is_error())
|
||||||
{
|
{
|
||||||
error= 1;
|
error= 1;
|
||||||
@@ -13382,7 +13426,7 @@ finish:
|
|||||||
FALSE otherwise
|
FALSE otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool check_simple_equality(THD *thd, const Item::Context &ctx,
|
bool check_simple_equality(THD *thd, const Item::Context &ctx,
|
||||||
Item *left_item, Item *right_item,
|
Item *left_item, Item *right_item,
|
||||||
COND_EQUAL *cond_equal)
|
COND_EQUAL *cond_equal)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1470,6 +1470,11 @@ public:
|
|||||||
Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting;
|
Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting;
|
||||||
|
|
||||||
JOIN_TAB *sort_and_group_aggr_tab;
|
JOIN_TAB *sort_and_group_aggr_tab;
|
||||||
|
/*
|
||||||
|
Flag is set to true if select_lex was found to be degenerated before
|
||||||
|
the optimize_cond() call in JOIN::optimize_inner() method.
|
||||||
|
*/
|
||||||
|
bool is_orig_degenerated;
|
||||||
|
|
||||||
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
|
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
|
||||||
select_result *result_arg)
|
select_result *result_arg)
|
||||||
@@ -1564,6 +1569,7 @@ public:
|
|||||||
emb_sjm_nest= NULL;
|
emb_sjm_nest= NULL;
|
||||||
sjm_lookup_tables= 0;
|
sjm_lookup_tables= 0;
|
||||||
sjm_scan_tables= 0;
|
sjm_scan_tables= 0;
|
||||||
|
is_orig_degenerated= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* True if the plan guarantees that it will be returned zero or one row */
|
/* True if the plan guarantees that it will be returned zero or one row */
|
||||||
@@ -1734,6 +1740,7 @@ public:
|
|||||||
bool fix_all_splittings_in_plan();
|
bool fix_all_splittings_in_plan();
|
||||||
|
|
||||||
bool transform_in_predicates_into_in_subq(THD *thd);
|
bool transform_in_predicates_into_in_subq(THD *thd);
|
||||||
|
bool add_equalities_to_where_condition(THD *thd, List<Item> &eq_list);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Create a temporary table to be used for processing DISTINCT/ORDER
|
Create a temporary table to be used for processing DISTINCT/ORDER
|
||||||
@@ -2325,7 +2332,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
|
|||||||
extern bool test_if_ref(Item *,
|
extern bool test_if_ref(Item *,
|
||||||
Item_field *left_item,Item *right_item);
|
Item_field *left_item,Item *right_item);
|
||||||
|
|
||||||
inline bool optimizer_flag(THD *thd, uint flag)
|
inline bool optimizer_flag(THD *thd, ulonglong flag)
|
||||||
{
|
{
|
||||||
return (thd->variables.optimizer_switch & flag);
|
return (thd->variables.optimizer_switch & flag);
|
||||||
}
|
}
|
||||||
@@ -2440,4 +2447,13 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort);
|
|||||||
JOIN_TAB *first_explain_order_tab(JOIN* join);
|
JOIN_TAB *first_explain_order_tab(JOIN* join);
|
||||||
JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab);
|
JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab);
|
||||||
|
|
||||||
|
bool check_simple_equality(THD *thd, const Item::Context &ctx,
|
||||||
|
Item *left_item, Item *right_item,
|
||||||
|
COND_EQUAL *cond_equal);
|
||||||
|
|
||||||
|
void propagate_new_equalities(THD *thd, Item *cond,
|
||||||
|
List<Item_equal> *new_equalities,
|
||||||
|
COND_EQUAL *inherited,
|
||||||
|
bool *is_simplifiable_cond);
|
||||||
|
|
||||||
#endif /* SQL_SELECT_INCLUDED */
|
#endif /* SQL_SELECT_INCLUDED */
|
||||||
|
|||||||
@@ -2472,6 +2472,7 @@ export const char *optimizer_switch_names[]=
|
|||||||
"orderby_uses_equalities",
|
"orderby_uses_equalities",
|
||||||
"condition_pushdown_for_derived",
|
"condition_pushdown_for_derived",
|
||||||
"split_materialized",
|
"split_materialized",
|
||||||
|
"condition_pushdown_for_subquery",
|
||||||
"default",
|
"default",
|
||||||
NullS
|
NullS
|
||||||
};
|
};
|
||||||
|
|||||||
194
sql/table.cc
194
sql/table.cc
@@ -8315,200 +8315,6 @@ double KEY::actual_rec_per_key(uint i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief
|
|
||||||
Mark subformulas of a condition unusable for the condition pushed into table
|
|
||||||
|
|
||||||
@param cond The condition whose subformulas are to be marked
|
|
||||||
|
|
||||||
@details
|
|
||||||
This method recursively traverses the AND-OR condition cond and for each subformula
|
|
||||||
of the codition it checks whether it can be usable for the extraction of a condition
|
|
||||||
that can be pushed into this table. The subformulas that are not usable are
|
|
||||||
marked with the flag NO_EXTRACTION_FL.
|
|
||||||
@note
|
|
||||||
This method is called before any call of TABLE_LIST::build_pushable_cond_for_table.
|
|
||||||
The flag NO_EXTRACTION_FL set in a subformula allows to avoid building clone
|
|
||||||
for the subformula when extracting the pushable condition.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void TABLE_LIST::check_pushable_cond_for_table(Item *cond)
|
|
||||||
{
|
|
||||||
table_map tab_map= table->map;
|
|
||||||
cond->clear_extraction_flag();
|
|
||||||
if (cond->type() == Item::COND_ITEM)
|
|
||||||
{
|
|
||||||
bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
|
|
||||||
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
|
||||||
uint count= 0;
|
|
||||||
Item *item;
|
|
||||||
while ((item=li++))
|
|
||||||
{
|
|
||||||
check_pushable_cond_for_table(item);
|
|
||||||
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
|
|
||||||
count++;
|
|
||||||
else if (!and_cond)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((and_cond && count == 0) || item)
|
|
||||||
{
|
|
||||||
cond->set_extraction_flag(NO_EXTRACTION_FL);
|
|
||||||
if (and_cond)
|
|
||||||
li.rewind();
|
|
||||||
while ((item= li++))
|
|
||||||
item->clear_extraction_flag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!cond->excl_dep_on_table(tab_map))
|
|
||||||
cond->set_extraction_flag(NO_EXTRACTION_FL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief
|
|
||||||
Build condition extractable from the given one depended only on this table
|
|
||||||
|
|
||||||
@param thd The thread handle
|
|
||||||
@param cond The condition from which the pushable one is to be extracted
|
|
||||||
|
|
||||||
@details
|
|
||||||
For the given condition cond this method finds out what condition depended
|
|
||||||
only on this table can be extracted from cond. If such condition C exists
|
|
||||||
the method builds the item for it.
|
|
||||||
The method uses the flag NO_EXTRACTION_FL set by the preliminary call of
|
|
||||||
the method TABLE_LIST::check_pushable_cond_for_table to figure out whether
|
|
||||||
a subformula depends only on this table or not.
|
|
||||||
@note
|
|
||||||
The built condition C is always implied by the condition cond
|
|
||||||
(cond => C). The method tries to build the most restictive such
|
|
||||||
condition (i.e. for any other condition C' such that cond => C'
|
|
||||||
we have C => C').
|
|
||||||
@note
|
|
||||||
The build item is not ready for usage: substitution for the field items
|
|
||||||
has to be done and it has to be re-fixed.
|
|
||||||
|
|
||||||
@retval
|
|
||||||
the built condition pushable into this table if such a condition exists
|
|
||||||
NULL if there is no such a condition
|
|
||||||
*/
|
|
||||||
|
|
||||||
Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond)
|
|
||||||
{
|
|
||||||
table_map tab_map= table->map;
|
|
||||||
bool is_multiple_equality= cond->type() == Item::FUNC_ITEM &&
|
|
||||||
((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC;
|
|
||||||
if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
|
|
||||||
return 0;
|
|
||||||
if (cond->type() == Item::COND_ITEM)
|
|
||||||
{
|
|
||||||
bool cond_and= false;
|
|
||||||
Item_cond *new_cond;
|
|
||||||
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
|
|
||||||
{
|
|
||||||
cond_and= true;
|
|
||||||
new_cond=new (thd->mem_root) Item_cond_and(thd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
new_cond= new (thd->mem_root) Item_cond_or(thd);
|
|
||||||
if (!new_cond)
|
|
||||||
return 0;
|
|
||||||
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
|
||||||
Item *item;
|
|
||||||
bool is_fix_needed= false;
|
|
||||||
while ((item=li++))
|
|
||||||
{
|
|
||||||
if (item->get_extraction_flag() == NO_EXTRACTION_FL)
|
|
||||||
{
|
|
||||||
if (!cond_and)
|
|
||||||
return 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Item *fix= build_pushable_cond_for_table(thd, item);
|
|
||||||
if (!fix && !cond_and)
|
|
||||||
return 0;
|
|
||||||
if (!fix)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fix->type() == Item::COND_ITEM &&
|
|
||||||
((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
|
|
||||||
is_fix_needed= true;
|
|
||||||
|
|
||||||
new_cond->argument_list()->push_back(fix, thd->mem_root);
|
|
||||||
}
|
|
||||||
if (is_fix_needed)
|
|
||||||
new_cond->fix_fields(thd, 0);
|
|
||||||
|
|
||||||
switch (new_cond->argument_list()->elements)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
return new_cond->argument_list()->head();
|
|
||||||
default:
|
|
||||||
return new_cond;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (is_multiple_equality)
|
|
||||||
{
|
|
||||||
if (!(cond->used_tables() & tab_map))
|
|
||||||
return 0;
|
|
||||||
Item *new_cond= NULL;
|
|
||||||
int i= 0;
|
|
||||||
Item_equal *item_equal= (Item_equal *) cond;
|
|
||||||
Item *left_item = item_equal->get_const();
|
|
||||||
Item_equal_fields_iterator it(*item_equal);
|
|
||||||
Item *item;
|
|
||||||
if (!left_item)
|
|
||||||
{
|
|
||||||
while ((item=it++))
|
|
||||||
if (item->used_tables() == tab_map)
|
|
||||||
{
|
|
||||||
left_item= item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!left_item)
|
|
||||||
return 0;
|
|
||||||
while ((item=it++))
|
|
||||||
{
|
|
||||||
if (!(item->used_tables() == tab_map))
|
|
||||||
continue;
|
|
||||||
Item_func_eq *eq= 0;
|
|
||||||
Item *left_item_clone= left_item->build_clone(thd);
|
|
||||||
Item *right_item_clone= item->build_clone(thd);
|
|
||||||
if (left_item_clone && right_item_clone)
|
|
||||||
{
|
|
||||||
left_item_clone->set_item_equal(NULL);
|
|
||||||
right_item_clone->set_item_equal(NULL);
|
|
||||||
eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
|
|
||||||
left_item_clone);
|
|
||||||
}
|
|
||||||
if (eq)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
new_cond= eq;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
|
|
||||||
thd->mem_root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (new_cond)
|
|
||||||
new_cond->fix_fields(thd, &new_cond);
|
|
||||||
return new_cond;
|
|
||||||
}
|
|
||||||
else if (cond->get_extraction_flag() != NO_EXTRACTION_FL)
|
|
||||||
return cond->build_clone(thd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LEX_CSTRING *fk_option_name(enum_fk_option opt)
|
LEX_CSTRING *fk_option_name(enum_fk_option opt)
|
||||||
{
|
{
|
||||||
static LEX_CSTRING names[]=
|
static LEX_CSTRING names[]=
|
||||||
|
|||||||
@@ -2595,8 +2595,6 @@ struct TABLE_LIST
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void set_lock_type(THD* thd, enum thr_lock_type lock);
|
void set_lock_type(THD* thd, enum thr_lock_type lock);
|
||||||
void check_pushable_cond_for_table(Item *cond);
|
|
||||||
Item *build_pushable_cond_for_table(THD *thd, Item *cond);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
drop table if exists t;
|
drop table if exists t;
|
||||||
select @@optimizer_switch;
|
select @@optimizer_switch;
|
||||||
@@optimizer_switch
|
@@optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
|
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
|
||||||
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
|
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
|
||||||
explain select x,id from t force index (x) where x=0 and id=0;
|
explain select x,id from t force index (x) where x=0 and id=0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
drop table if exists t;
|
drop table if exists t;
|
||||||
select @@optimizer_switch;
|
select @@optimizer_switch;
|
||||||
@@optimizer_switch
|
@@optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
|
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
|
||||||
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
|
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
|
||||||
explain select x,id from t force index (x) where x=0 and id=0;
|
explain select x,id from t force index (x) where x=0 and id=0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
drop table if exists t;
|
drop table if exists t;
|
||||||
select @@optimizer_switch;
|
select @@optimizer_switch;
|
||||||
@@optimizer_switch
|
@@optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
|
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
|
||||||
insert into t values (0,0,0,0),(0,1,0,1);
|
insert into t values (0,0,0,0),(0,1,0,1);
|
||||||
explain select c,a,b from t where c=0 and a=0 and b=1;
|
explain select c,a,b from t where c=0 and a=0 and b=1;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
drop table if exists t;
|
drop table if exists t;
|
||||||
select @@optimizer_switch;
|
select @@optimizer_switch;
|
||||||
@@optimizer_switch
|
@@optimizer_switch
|
||||||
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
|
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
|
||||||
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
|
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
|
||||||
insert into t values (0,0,0,0),(0,1,0,1);
|
insert into t values (0,0,0,0),(0,1,0,1);
|
||||||
explain select c,a,b from t where c=0 and a=0 and b=1;
|
explain select c,a,b from t where c=0 and a=0 and b=1;
|
||||||
|
|||||||
Reference in New Issue
Block a user