mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Fix LP BUG#611622
Fix MySQL BUG#52344 - Subquery materialization: Assertion if subquery in on-clause of outer join Original fix and comments from Oysten, adjusted for the different subquery optimization in MariaDB. " Problem: If tables of an outer join are constant tables, the associated on-clause will be evaluated in the optimization phase. If the on-clause contains a query that is to be executed with subquery materialization, this will not work since the infrastructure for such execution is not yet set up. Solution: Do not evaluate on-clause in optimization phase if is_expensive() returns true for this clause. This is how the problem is currently avoided for where-clauses. This works because, Item_in_subselect::is_expensive_processor returns true if query is to be executed with subquery materialization. " In addition, after MWL#89, in MariaDB if the IN-EXISTS strategy is chosen, the in-to-exists predicates are insterted after join_read_const_table() is called, resulting in evaluation of the subquery without the in-to-exists predicates.
This commit is contained in:
@@ -1297,3 +1297,50 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum;
|
||||
c1_sum
|
||||
drop table t1, t2;
|
||||
#
|
||||
# BUG#52344 - Subquery materialization:
|
||||
# Assertion if subquery in on-clause of outer join
|
||||
#
|
||||
set @@optimizer_switch='semijoin=off';
|
||||
CREATE TABLE t1 (i INTEGER);
|
||||
INSERT INTO t1 VALUES (10);
|
||||
CREATE TABLE t2 (j INTEGER);
|
||||
INSERT INTO t2 VALUES (5);
|
||||
CREATE TABLE t3 (k INTEGER);
|
||||
EXPLAIN
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT k FROM t3);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
1 PRIMARY t2 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY t3 system NULL NULL NULL NULL 0 const row not found
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT k FROM t3);
|
||||
i
|
||||
10
|
||||
EXPLAIN
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT max(k) FROM t3);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
1 PRIMARY t2 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY t3 system NULL NULL NULL NULL 0 const row not found
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT max(k) FROM t3);
|
||||
i
|
||||
10
|
||||
DROP TABLE t1, t2, t3;
|
||||
#
|
||||
# LPBUG#609121: RQG: wrong result on aggregate + NOT IN + HAVING and
|
||||
# partial_match_table_scan=on
|
||||
#
|
||||
CREATE TABLE t1 (c1 int);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TABLE t2 (c2 int);
|
||||
INSERT INTO t2 VALUES (10);
|
||||
PREPARE st1 FROM "
|
||||
SELECT *
|
||||
FROM t2 LEFT JOIN (SELECT * FROM t2) t3 ON (8, 4) IN (SELECT c1, c1 FROM t1)";
|
||||
EXECUTE st1;
|
||||
c2 c2
|
||||
10 10
|
||||
EXECUTE st1;
|
||||
c2 c2
|
||||
10 10
|
||||
DROP TABLE t1, t2;
|
||||
|
@@ -943,3 +943,48 @@ SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum;
|
||||
SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum;
|
||||
|
||||
drop table t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # BUG#52344 - Subquery materialization:
|
||||
--echo # Assertion if subquery in on-clause of outer join
|
||||
--echo #
|
||||
|
||||
set @@optimizer_switch='semijoin=off';
|
||||
|
||||
CREATE TABLE t1 (i INTEGER);
|
||||
INSERT INTO t1 VALUES (10);
|
||||
|
||||
CREATE TABLE t2 (j INTEGER);
|
||||
INSERT INTO t2 VALUES (5);
|
||||
|
||||
CREATE TABLE t3 (k INTEGER);
|
||||
|
||||
EXPLAIN
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT k FROM t3);
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT k FROM t3);
|
||||
|
||||
EXPLAIN
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT max(k) FROM t3);
|
||||
SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT max(k) FROM t3);
|
||||
|
||||
DROP TABLE t1, t2, t3;
|
||||
|
||||
--echo #
|
||||
--echo # LPBUG#609121: RQG: wrong result on aggregate + NOT IN + HAVING and
|
||||
--echo # partial_match_table_scan=on
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (c1 int);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
|
||||
CREATE TABLE t2 (c2 int);
|
||||
INSERT INTO t2 VALUES (10);
|
||||
|
||||
PREPARE st1 FROM "
|
||||
SELECT *
|
||||
FROM t2 LEFT JOIN (SELECT * FROM t2) t3 ON (8, 4) IN (SELECT c1, c1 FROM t1)";
|
||||
|
||||
EXECUTE st1;
|
||||
EXECUTE st1;
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
@@ -10599,16 +10599,6 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
}
|
||||
}
|
||||
else if (cond->const_item() && !cond->is_expensive())
|
||||
/*
|
||||
DontEvaluateMaterializedSubqueryTooEarly:
|
||||
TODO:
|
||||
Excluding all expensive functions is too restritive we should exclude only
|
||||
materialized IN subquery predicates because they can't yet be evaluated
|
||||
here (they need additional initialization that is done later on).
|
||||
|
||||
The proper way to exclude the subqueries would be to walk the cond tree and
|
||||
check for materialized subqueries there.
|
||||
*/
|
||||
{
|
||||
*cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
|
||||
return (COND*) 0;
|
||||
@@ -13527,7 +13517,14 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
}
|
||||
if (*tab->on_expr_ref && !table->null_row)
|
||||
/*
|
||||
Evaluate an on-expression only if it is not considered expensive.
|
||||
This mainly prevents executing subqueries in optimization phase.
|
||||
This is necessary since proper setup for such execution has not been
|
||||
done at this stage.
|
||||
*/
|
||||
if (*tab->on_expr_ref && !table->null_row &&
|
||||
!(*tab->on_expr_ref)->is_expensive())
|
||||
{
|
||||
#if !defined(DBUG_OFF) && defined(NOT_USING_ITEM_EQUAL)
|
||||
/*
|
||||
|
Reference in New Issue
Block a user