mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
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.
This commit is contained in:
parent
c6ee3fe9d4
commit
2e7ba70a94
3 changed files with 51 additions and 6 deletions
|
@ -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;
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue