mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fixed mdev-14845 Server crashes in st_join_table::is_inner_table_of_outer_join
Do not try to apply the splitting optimization to a materialized derived if it's specified by a select with impossible where or if all joined tables of this select are constant.
This commit is contained in:
@ -14772,3 +14772,19 @@ SELECT * FROM v3 JOIN t1 ON (bmax = b);
|
|||||||
a bmax a b
|
a bmax a b
|
||||||
DROP VIEW v1,v2,v3;
|
DROP VIEW v1,v2,v3;
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
#
|
||||||
|
# MDEV-14845: Impossible where for derived with GROUP BY
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (pk INT PRIMARY KEY);
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
WITH cte AS ( SELECT pk FROM t1 WHERE pk IS NULL GROUP BY pk )
|
||||||
|
SELECT * FROM cte;
|
||||||
|
pk
|
||||||
|
EXPLAIN EXTENDED WITH cte AS ( SELECT pk FROM t1 WHERE pk IS NULL GROUP BY pk )
|
||||||
|
SELECT * FROM cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 Const row not found
|
||||||
|
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with cte as (/* select#2 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where 0 group by `test`.`t1`.`pk`)/* select#1 */ select NULL AS `pk` from `cte`
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -2519,3 +2519,19 @@ SELECT * FROM v3 JOIN t1 ON (bmax = b);
|
|||||||
DROP VIEW v1,v2,v3;
|
DROP VIEW v1,v2,v3;
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-14845: Impossible where for derived with GROUP BY
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (pk INT PRIMARY KEY);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
let $q=
|
||||||
|
WITH cte AS ( SELECT pk FROM t1 WHERE pk IS NULL GROUP BY pk )
|
||||||
|
SELECT * FROM cte;
|
||||||
|
|
||||||
|
eval $q;
|
||||||
|
eval EXPLAIN EXTENDED $q;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -291,14 +291,15 @@ struct SplM_field_ext_info: public SplM_field_info
|
|||||||
3. this is the only select in the specification of T
|
3. this is the only select in the specification of T
|
||||||
4. condition pushdown is not prohibited into T
|
4. condition pushdown is not prohibited into T
|
||||||
5. T is not recursive
|
5. T is not recursive
|
||||||
6. T is either
|
6. not all of this join are constant or optimized away
|
||||||
6.1. a grouping table with GROUP BY list P
|
7. T is either
|
||||||
|
7.1. a grouping table with GROUP BY list P
|
||||||
or
|
or
|
||||||
6.2. a non-grouping table with window functions over the same non-empty
|
7.2. a non-grouping table with window functions over the same non-empty
|
||||||
partition specified by the PARTITION BY list P
|
partition specified by the PARTITION BY list P
|
||||||
7. P contains some references on the columns of the joined tables C
|
8. P contains some references on the columns of the joined tables C
|
||||||
occurred also in the select list of this join
|
occurred also in the select list of this join
|
||||||
8. There are defined some keys usable for ref access of fields from C
|
9. There are defined some keys usable for ref access of fields from C
|
||||||
with available statistics.
|
with available statistics.
|
||||||
|
|
||||||
@retval
|
@retval
|
||||||
@ -315,15 +316,16 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
!(derived && derived->is_materialized_derived()) || // !(2)
|
!(derived && derived->is_materialized_derived()) || // !(2)
|
||||||
(unit->first_select()->next_select()) || // !(3)
|
(unit->first_select()->next_select()) || // !(3)
|
||||||
(derived->prohibit_cond_pushdown) || // !(4)
|
(derived->prohibit_cond_pushdown) || // !(4)
|
||||||
(derived->is_recursive_with_table())) // !(5)
|
(derived->is_recursive_with_table()) || // !(5)
|
||||||
|
(table_count == 0 || const_tables == top_join_tab_count)) // !(6)
|
||||||
return false;
|
return false;
|
||||||
if (group_list) // (6.1)
|
if (group_list) // (7.1)
|
||||||
{
|
{
|
||||||
if (!select_lex->have_window_funcs())
|
if (!select_lex->have_window_funcs())
|
||||||
partition_list= group_list;
|
partition_list= group_list;
|
||||||
}
|
}
|
||||||
else if (select_lex->have_window_funcs() &&
|
else if (select_lex->have_window_funcs() &&
|
||||||
select_lex->window_specs.elements == 1) // (6.2)
|
select_lex->window_specs.elements == 1) // (7.2)
|
||||||
{
|
{
|
||||||
partition_list=
|
partition_list=
|
||||||
select_lex->window_specs.head()->partition_list->first;
|
select_lex->window_specs.head()->partition_list->first;
|
||||||
@ -337,15 +339,15 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
/*
|
/*
|
||||||
Select from partition_list all candidates for splitting.
|
Select from partition_list all candidates for splitting.
|
||||||
A candidate must be
|
A candidate must be
|
||||||
- field item or refer to such (7.1)
|
- field item or refer to such (8.1)
|
||||||
- item mentioned in the select list (7.2)
|
- item mentioned in the select list (8.2)
|
||||||
Put info about such candidates into the array candidates
|
Put info about such candidates into the array candidates
|
||||||
*/
|
*/
|
||||||
table_map usable_tables= 0; // tables that contains the candidate
|
table_map usable_tables= 0; // tables that contains the candidate
|
||||||
for (ord= partition_list; ord; ord= ord->next)
|
for (ord= partition_list; ord; ord= ord->next)
|
||||||
{
|
{
|
||||||
Item *ord_item= *ord->item;
|
Item *ord_item= *ord->item;
|
||||||
if (ord_item->real_item()->type() != Item::FIELD_ITEM) // !(7.1)
|
if (ord_item->real_item()->type() != Item::FIELD_ITEM) // !(8.1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Field *ord_field= ((Item_field *) (ord_item->real_item()))->field;
|
Field *ord_field= ((Item_field *) (ord_item->real_item()))->field;
|
||||||
@ -359,7 +361,7 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
uint item_no= 0;
|
uint item_no= 0;
|
||||||
while ((item= li++))
|
while ((item= li++))
|
||||||
{
|
{
|
||||||
if ((*ord->item)->eq(item, 0)) // (7.2)
|
if ((*ord->item)->eq(item, 0)) // (8.2)
|
||||||
{
|
{
|
||||||
SplM_field_ext_info new_elem;
|
SplM_field_ext_info new_elem;
|
||||||
new_elem.producing_item= item;
|
new_elem.producing_item= item;
|
||||||
@ -374,7 +376,7 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
item_no++;
|
item_no++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (candidates.elements() == 0) // no candidates satisfying (7.1) && (7.2)
|
if (candidates.elements() == 0) // no candidates satisfying (8.1) && (8.2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -432,7 +434,7 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
spl_field_cnt--;
|
spl_field_cnt--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spl_field_cnt) // No candidate field can be accessed by ref => !(8)
|
if (!spl_field_cnt) // No candidate field can be accessed by ref => !(9)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user