Commit f5955f87 authored by Igor Babaev's avatar Igor Babaev

Fixed LP bug #874006.

This bug manifested itself with queries containing non-correlated
IN subqueries over materialized views/derived tables.  
The bug happened because the code of the function generate_derived_keys did
not take into account that the function could be called twice when the
optimizer was deciding whether in-exist transformation should be applied.
parent 5e4a381c
...@@ -781,7 +781,7 @@ SELECT * FROM t3 ...@@ -781,7 +781,7 @@ SELECT * FROM t3
WHERE t3.a IN (SELECT v1.a FROM v1, t2 WHERE t2.a = v1.b); WHERE t3.a IN (SELECT v1.a FROM v1, t2 WHERE t2.a = v1.b);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where 1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
2 DEPENDENT SUBQUERY <derived3> ref key0 key0 5 func 2 100.00 2 DEPENDENT SUBQUERY <derived3> ref key1 key1 5 func 2 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
3 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using temporary; Using filesort 3 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using temporary; Using filesort
Warnings: Warnings:
...@@ -1462,4 +1462,46 @@ b a ...@@ -1462,4 +1462,46 @@ b a
9 2 9 2
7 2 7 2
DROP TABLE t1,t2,t3; DROP TABLE t1,t2,t3;
#
# LP bug #874006: materialized view used in IN subquery
#
CREATE TABLE t3 (a int NOT NULL, b varchar(1), c varchar(1));
INSERT INTO t3 VALUES (19,NULL,NULL), (20,'r','r');
CREATE TABLE t1 (a int, b varchar(1) , c varchar(1));
INSERT INTO t1 VALUES (1,NULL,NULL), (5,'r','r'), (7,'y','y');
CREATE TABLE t2 (a int NOT NULL , b int, c varchar(1));
INSERT INTO t2 VALUES (4,3,'r');
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
SET SESSION optimizer_switch='derived_with_keys=off';
EXPLAIN
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 3 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 3
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
a b c
20 r r
SET SESSION optimizer_switch='derived_with_keys=on';
EXPLAIN
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY <derived3> ref key1 key1 10 const,const 0 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 3
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
a b c
20 r r
DROP VIEW v1;
DROP TABLE t1,t2,t3;
set optimizer_switch=@exit_optimizer_switch; set optimizer_switch=@exit_optimizer_switch;
...@@ -910,5 +910,42 @@ SELECT * FROM t1 , t2 ...@@ -910,5 +910,42 @@ SELECT * FROM t1 , t2
DROP TABLE t1,t2,t3; DROP TABLE t1,t2,t3;
--echo #
--echo # LP bug #874006: materialized view used in IN subquery
--echo #
CREATE TABLE t3 (a int NOT NULL, b varchar(1), c varchar(1));
INSERT INTO t3 VALUES (19,NULL,NULL), (20,'r','r');
CREATE TABLE t1 (a int, b varchar(1) , c varchar(1));
INSERT INTO t1 VALUES (1,NULL,NULL), (5,'r','r'), (7,'y','y');
CREATE TABLE t2 (a int NOT NULL , b int, c varchar(1));
INSERT INTO t2 VALUES (4,3,'r');
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
SET SESSION optimizer_switch='derived_with_keys=off';
EXPLAIN
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
SET SESSION optimizer_switch='derived_with_keys=on';
EXPLAIN
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
SELECT * FROM t3
WHERE t3.b IN (SELECT v1.b FROM v1, t2
WHERE t2.c = v1.c AND t2.c = v1.b AND v1.b = t3.c);
DROP VIEW v1;
DROP TABLE t1,t2,t3;
# The following command must be the last one the file # The following command must be the last one the file
set optimizer_switch=@exit_optimizer_switch; set optimizer_switch=@exit_optimizer_switch;
...@@ -8413,17 +8413,17 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys) ...@@ -8413,17 +8413,17 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys)
TABLE *table= keyuse->table; TABLE *table= keyuse->table;
if (table->alloc_keys(keys)) if (table->alloc_keys(keys))
return TRUE; return TRUE;
uint keyno= 0; uint key_count= 0;
KEYUSE *first_keyuse= keyuse; KEYUSE *first_keyuse= keyuse;
uint prev_part= keyuse->keypart; uint prev_part= keyuse->keypart;
uint parts= 0; uint parts= 0;
uint i= 0; uint i= 0;
for ( ; i < count && keyno < keys; ) for ( ; i < count && key_count < keys; )
{ {
do do
{ {
keyuse->key= keyno; keyuse->key= table->s->keys;
keyuse->keypart_map= (key_part_map) (1 << parts); keyuse->keypart_map= (key_part_map) (1 << parts);
keyuse++; keyuse++;
i++; i++;
...@@ -8437,14 +8437,14 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys) ...@@ -8437,14 +8437,14 @@ bool generate_derived_keys_for_table(KEYUSE *keyuse, uint count, uint keys)
} }
else else
{ {
if (table->add_tmp_key(keyno, parts, if (table->add_tmp_key(table->s->keys, parts,
get_next_field_for_derived_key, get_next_field_for_derived_key,
(uchar *) &first_keyuse, (uchar *) &first_keyuse,
FALSE)) FALSE))
return TRUE; return TRUE;
table->reginfo.join_tab->keys.set_bit(keyno); table->reginfo.join_tab->keys.set_bit(table->s->keys);
first_keyuse= keyuse; first_keyuse= keyuse;
keyno++; key_count++;
parts= 0; parts= 0;
prev_part= keyuse->keypart; prev_part= keyuse->keypart;
} }
...@@ -8471,12 +8471,23 @@ bool generate_derived_keys(DYNAMIC_ARRAY *keyuse_array) ...@@ -8471,12 +8471,23 @@ bool generate_derived_keys(DYNAMIC_ARRAY *keyuse_array)
TABLE_LIST *derived= NULL; TABLE_LIST *derived= NULL;
if (keyuse->table != prev_table) if (keyuse->table != prev_table)
derived= keyuse->table->pos_in_table_list; derived= keyuse->table->pos_in_table_list;
while (derived && derived->is_materialized_derived() && while (derived && derived->is_materialized_derived())
keyuse->key == MAX_KEY)
{ {
if (keyuse->table != prev_table) if (keyuse->table != prev_table)
{ {
prev_table= keyuse->table; prev_table= keyuse->table;
while (keyuse->table == prev_table && keyuse->key != MAX_KEY)
{
keyuse++;
i++;
}
if (keyuse->table != prev_table)
{
keyuse--;
i--;
derived= NULL;
continue;
}
first_table_keyuse= keyuse; first_table_keyuse= keyuse;
last_used_tables= keyuse->used_tables; last_used_tables= keyuse->used_tables;
count= 0; count= 0;
...@@ -8489,11 +8500,13 @@ bool generate_derived_keys(DYNAMIC_ARRAY *keyuse_array) ...@@ -8489,11 +8500,13 @@ bool generate_derived_keys(DYNAMIC_ARRAY *keyuse_array)
} }
count++; count++;
keyuse++; keyuse++;
i++;
if (keyuse->table != prev_table) if (keyuse->table != prev_table)
{ {
if (generate_derived_keys_for_table(first_table_keyuse, count, ++keys)) if (generate_derived_keys_for_table(first_table_keyuse, count, ++keys))
return TRUE; return TRUE;
keyuse--; keyuse--;
i--;
derived= NULL; derived= NULL;
} }
} }
...@@ -8524,12 +8537,13 @@ void JOIN::drop_unused_derived_keys() ...@@ -8524,12 +8537,13 @@ void JOIN::drop_unused_derived_keys()
TABLE *table=tab->table; TABLE *table=tab->table;
if (!table) if (!table)
continue; continue;
if (!table->pos_in_table_list->is_materialized_derived() || if (!table->pos_in_table_list->is_materialized_derived())
table->max_keys <= 1)
continue; continue;
if (table->max_keys > 1)
table->use_index(tab->ref.key); table->use_index(tab->ref.key);
if (table->s->keys) if (table->s->keys)
tab->ref.key= 0; tab->ref.key= 0;
tab->keys= (key_map) (table->s->keys ? 1 : 0);
} }
} }
......
...@@ -5220,10 +5220,11 @@ void st_table::mark_virtual_columns_for_write(bool insert_fl) ...@@ -5220,10 +5220,11 @@ void st_table::mark_virtual_columns_for_write(bool insert_fl)
@brief @brief
Allocate space for keys Allocate space for keys
@param key_count number of keys to allocate @param key_count number of keys to allocate additionally
@details @details
The function allocates memory to fit 'key_count' keys for this table. The function allocates memory to fit additionally 'key_count' keys
for this table.
@return FALSE space was successfully allocated @return FALSE space was successfully allocated
@return TRUE an error occur @return TRUE an error occur
...@@ -5231,9 +5232,11 @@ void st_table::mark_virtual_columns_for_write(bool insert_fl) ...@@ -5231,9 +5232,11 @@ void st_table::mark_virtual_columns_for_write(bool insert_fl)
bool TABLE::alloc_keys(uint key_count) bool TABLE::alloc_keys(uint key_count)
{ {
key_info= s->key_info= (KEY*) alloc_root(&mem_root, sizeof(KEY)*key_count); key_info= (KEY*) alloc_root(&mem_root, sizeof(KEY)*(s->keys+key_count));
s->keys= 0; if (s->keys)
max_keys= key_count; memmove(key_info, s->key_info, sizeof(KEY)*s->keys);
s->key_info= key_info;
max_keys= s->keys+key_count;
return !(key_info); return !(key_info);
} }
......
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