mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Fixed LP bug #946055.
The function create_hj_key_for_table() that builds the descriptor of the hash join key to access a table of a materialized subquery must ignore any equi-join predicate depending on the tables not belonging to the subquery.
This commit is contained in:
parent
8a5940c477
commit
04ee30e75a
4 changed files with 153 additions and 4 deletions
|
@ -1913,6 +1913,57 @@ WHERE a IN (SELECT MAX(c) FROM t2 WHERE c < 4) AND b=7 AND (a IS NULL OR a=b);
|
|||
a b
|
||||
SET optimizer_switch=@save_optimizer_switch;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# BUG#946055: Crash with semijoin IN subquery when hash join is used
|
||||
#
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (7);
|
||||
CREATE TABLE t2 (b int, c int, d varchar(1), e varchar(1), KEY (c), KEY (d, c));
|
||||
INSERT INTO t2 VALUES
|
||||
(4,2,'v','v'), (6,1,'v','v'), (0,5,'x','x'), (7,1,'x','x'),
|
||||
(7,3,'i','i'), (7,1,'e','e'), (1,4,'p','p'), (1,2,'j','j');
|
||||
SET @save_optimizer_switch=@@optimizer_switch;
|
||||
SET @save_join_cache_level=@@join_cache_level;
|
||||
SET join_cache_level=2;
|
||||
EXPLAIN
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
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 index NULL c 5 NULL 8 Using where; Using index
|
||||
2 MATERIALIZED s2 ref d d 4 const 1 Using where; Using index
|
||||
2 MATERIALIZED s1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
|
||||
3 SUBQUERY t2 ALL NULL NULL NULL NULL 8
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
a c
|
||||
7 1
|
||||
7 1
|
||||
7 1
|
||||
SET optimizer_switch='join_cache_hashed=on';
|
||||
SET join_cache_level=4;
|
||||
EXPLAIN
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
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 index NULL c 5 NULL 8 Using where; Using index
|
||||
2 MATERIALIZED s2 ref d d 4 const 1 Using where; Using index
|
||||
2 MATERIALIZED s1 hash_ALL NULL #hash#$hj 5 test.s2.d 8 Using where; Using join buffer (flat, BNLH join)
|
||||
3 SUBQUERY t2 ALL NULL NULL NULL NULL 8
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
a c
|
||||
7 1
|
||||
7 1
|
||||
7 1
|
||||
SET optimizer_switch=@save_optimizer_switch;
|
||||
SET join_cache_level=@save_join_cache_level;
|
||||
DROP TABLE t1,t2;
|
||||
# This must be at the end:
|
||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||
set join_cache_level=@save_join_cache_level;
|
||||
|
|
|
@ -1951,6 +1951,59 @@ WHERE a IN (SELECT MAX(c) FROM t2 WHERE c < 4) AND b=7 AND (a IS NULL OR a=b);
|
|||
a b
|
||||
SET optimizer_switch=@save_optimizer_switch;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# BUG#946055: Crash with semijoin IN subquery when hash join is used
|
||||
#
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (7);
|
||||
CREATE TABLE t2 (b int, c int, d varchar(1), e varchar(1), KEY (c), KEY (d, c));
|
||||
INSERT INTO t2 VALUES
|
||||
(4,2,'v','v'), (6,1,'v','v'), (0,5,'x','x'), (7,1,'x','x'),
|
||||
(7,3,'i','i'), (7,1,'e','e'), (1,4,'p','p'), (1,2,'j','j');
|
||||
SET @save_optimizer_switch=@@optimizer_switch;
|
||||
SET @save_join_cache_level=@@join_cache_level;
|
||||
SET join_cache_level=2;
|
||||
EXPLAIN
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
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 index c c 5 NULL 8 Using index
|
||||
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
|
||||
2 MATERIALIZED s2 ref d d 4 const 1 Using where; Using index
|
||||
2 MATERIALIZED s1 ALL c NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
|
||||
3 SUBQUERY t2 ALL NULL NULL NULL NULL 8
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
a c
|
||||
7 1
|
||||
7 1
|
||||
7 1
|
||||
SET optimizer_switch='join_cache_hashed=on';
|
||||
SET join_cache_level=4;
|
||||
EXPLAIN
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
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 index c c 5 NULL 8 Using index
|
||||
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
|
||||
2 MATERIALIZED s2 ref d d 4 const 1 Using where; Using index
|
||||
2 MATERIALIZED s1 hash_ALL c #hash#$hj 10 const,test.s2.d 8 Using where; Using join buffer (flat, BNLH join)
|
||||
3 SUBQUERY t2 ALL NULL NULL NULL NULL 8
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
a c
|
||||
7 1
|
||||
7 1
|
||||
7 1
|
||||
SET optimizer_switch=@save_optimizer_switch;
|
||||
SET join_cache_level=@save_join_cache_level;
|
||||
DROP TABLE t1,t2;
|
||||
# This must be at the end:
|
||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||
set join_cache_level=@save_join_cache_level;
|
||||
|
|
|
@ -1602,6 +1602,46 @@ SET optimizer_switch=@save_optimizer_switch;
|
|||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # BUG#946055: Crash with semijoin IN subquery when hash join is used
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (7);
|
||||
|
||||
CREATE TABLE t2 (b int, c int, d varchar(1), e varchar(1), KEY (c), KEY (d, c));
|
||||
|
||||
INSERT INTO t2 VALUES
|
||||
(4,2,'v','v'), (6,1,'v','v'), (0,5,'x','x'), (7,1,'x','x'),
|
||||
(7,3,'i','i'), (7,1,'e','e'), (1,4,'p','p'), (1,2,'j','j');
|
||||
|
||||
SET @save_optimizer_switch=@@optimizer_switch;
|
||||
SET @save_join_cache_level=@@join_cache_level;
|
||||
|
||||
SET join_cache_level=2;
|
||||
EXPLAIN
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
|
||||
SET optimizer_switch='join_cache_hashed=on';
|
||||
SET join_cache_level=4;
|
||||
EXPLAIN
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
SELECT a, c FROM t1, t2
|
||||
WHERE (a, c) IN (SELECT s1.b, s1.c FROM t2 AS s1, t2 AS s2
|
||||
WHERE s2.d = s1.e AND s1.e = (SELECT MAX(e) FROM t2));
|
||||
|
||||
SET optimizer_switch=@save_optimizer_switch;
|
||||
SET join_cache_level=@save_join_cache_level;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo # This must be at the end:
|
||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||
set join_cache_level=@save_join_cache_level;
|
||||
|
|
|
@ -60,6 +60,7 @@ static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
|
|||
static bool sort_and_filter_keyuse(THD *thd, DYNAMIC_ARRAY *keyuse,
|
||||
bool skip_unprefixed_keyparts);
|
||||
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
|
||||
static bool are_tables_local(JOIN_TAB *jtab, table_map used_tables);
|
||||
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
|
||||
bool allow_full_scan, table_map used_tables);
|
||||
void best_access_path(JOIN *join, JOIN_TAB *s,
|
||||
|
@ -7262,7 +7263,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
|
|||
|
||||
do
|
||||
{
|
||||
if (!(~used_tables & keyuse->used_tables))
|
||||
if (!(~used_tables & keyuse->used_tables) &&
|
||||
are_tables_local(join_tab, keyuse->used_tables))
|
||||
{
|
||||
if (first_keyuse)
|
||||
{
|
||||
|
@ -7275,7 +7277,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
|
|||
for( ; curr < keyuse; curr++)
|
||||
{
|
||||
if (curr->keypart == keyuse->keypart &&
|
||||
!(~used_tables & curr->used_tables))
|
||||
!(~used_tables & curr->used_tables) &&
|
||||
are_tables_local(join_tab, curr->used_tables))
|
||||
break;
|
||||
}
|
||||
if (curr == keyuse)
|
||||
|
@ -7306,7 +7309,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
|
|||
keyuse= org_keyuse;
|
||||
do
|
||||
{
|
||||
if (!(~used_tables & keyuse->used_tables))
|
||||
if (!(~used_tables & keyuse->used_tables) &&
|
||||
are_tables_local(join_tab, keyuse->used_tables))
|
||||
{
|
||||
bool add_key_part= TRUE;
|
||||
if (!first_keyuse)
|
||||
|
@ -7314,7 +7318,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
|
|||
for(KEYUSE *curr= org_keyuse; curr < keyuse; curr++)
|
||||
{
|
||||
if (curr->keypart == keyuse->keypart &&
|
||||
!(~used_tables & curr->used_tables))
|
||||
!(~used_tables & curr->used_tables) &&
|
||||
are_tables_local(join_tab, curr->used_tables))
|
||||
{
|
||||
keyuse->keypart= NO_KEYPART;
|
||||
add_key_part= FALSE;
|
||||
|
|
Loading…
Reference in a new issue