Commit 2e7ba70a authored by Igor Babaev's avatar Igor Babaev

Fixed the bug mdev-10693.

The code that chooses between materialization of a non-correlated
IN subquery and its transformation into an EXISTS correlated
subquery assumes that the execution plan for the outer select
has been already built. However it was not always so if subqueries
occurred in the expressions used for ref access to tables of
the outer select. A call of the function create_ref_for_key() in
get_best_combination() could trigger a premature execution of
the above mentioned code when the execution plan structures for
the outer select were not fully built. This could cause a crash
of the server.

The fix postpones the calls of create_ref_for_key() until the
structures for the execution plan is fully built.
parent c6ee3fe9
......@@ -469,3 +469,17 @@ f1 f2
set join_cache_level = default;
drop view v1;
drop table t1,t2;
#
# MDEV-10693: cost-based choice between materialization and in-to-exists
# for a subquery from the expression used in ref access
#
CREATE TABLE t1 (i1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (i2 INT) ENGINE=InnoDB;
CREATE TABLE t3 (i3 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t3 VALUES (3);
SELECT * FROM t1
WHERE NULL IN ( SELECT i2 FROM t2
WHERE i1 IN ( i2 IN ( SELECT i3 FROM t3 ) ) AND i2 = 2 );
i1
DROP TABLE t1,t2,t3;
......@@ -453,3 +453,25 @@ SELECT * FROM v1, t2 WHERE ( f1, f2 ) IN ( SELECT f1, f1 FROM t1 );
set join_cache_level = default;
drop view v1;
drop table t1,t2;
--echo #
--echo # MDEV-10693: cost-based choice between materialization and in-to-exists
--echo # for a subquery from the expression used in ref access
--echo #
--source include/have_innodb.inc
CREATE TABLE t1 (i1 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (i2 INT) ENGINE=InnoDB;
CREATE TABLE t3 (i3 INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t3 VALUES (3);
SELECT * FROM t1
WHERE NULL IN ( SELECT i2 FROM t2
WHERE i1 IN ( i2 IN ( SELECT i3 FROM t3 ) ) AND i2 = 2 );
DROP TABLE t1,t2,t3;
......@@ -7728,8 +7728,6 @@ get_best_combination(JOIN *join)
join->full_join=0;
join->hash_join= FALSE;
used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
fix_semijoin_strategies_for_picked_join_order(join);
JOIN_TAB_RANGE *root_range;
......@@ -7791,7 +7789,6 @@ get_best_combination(JOIN *join)
j->bush_root_tab= sjm_nest_root;
form=join->table[tablenr]=j->table;
used_tables|= form->map;
form->reginfo.join_tab=j;
DBUG_PRINT("info",("type: %d", j->type));
if (j->type == JT_CONST)
......@@ -7818,9 +7815,6 @@ get_best_combination(JOIN *join)
join->best_positions[tablenr].loosescan_picker.loosescan_key);
j->index= join->best_positions[tablenr].loosescan_picker.loosescan_key;
}*/
if (keyuse && create_ref_for_key(join, j, keyuse, TRUE, used_tables))
DBUG_RETURN(TRUE); // Something went wrong
if ((j->type == JT_REF || j->type == JT_EQ_REF) &&
is_hash_join_key_no(j->ref.key))
......@@ -7845,6 +7839,21 @@ get_best_combination(JOIN *join)
}
root_range->end= j;
used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++)
{
if (j->bush_children)
j= j->bush_children->start;
used_tables|= j->table->map;
if ((keyuse= join->best_positions[tablenr].key) &&
create_ref_for_key(join, j, keyuse, TRUE, used_tables))
DBUG_RETURN(TRUE); // Something went wrong
if (j->last_leaf_in_bush)
j= j->bush_root_tab;
}
join->top_join_tab_count= join->join_tab_ranges.head()->end -
join->join_tab_ranges.head()->start;
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment