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;
|
SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum;
|
||||||
c1_sum
|
c1_sum
|
||||||
drop table t1, t2;
|
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;
|
SELECT SUM(c1) c1_sum FROM t1 WHERE c1 IN (SELECT c2 FROM t2) HAVING c1_sum;
|
||||||
|
|
||||||
drop table t1, t2;
|
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())
|
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;
|
*cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
|
||||||
return (COND*) 0;
|
return (COND*) 0;
|
||||||
@@ -13527,7 +13517,14 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
|
|||||||
DBUG_RETURN(error);
|
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)
|
#if !defined(DBUG_OFF) && defined(NOT_USING_ITEM_EQUAL)
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user