Commit 8bd47162 authored by Sergei Petrunia's avatar Sergei Petrunia

Merge ../10.1-orderby-fixes into 10.1

parents 26e048ff f8f8a59c
...@@ -74,7 +74,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -74,7 +74,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 17 Using sort_union(i1,i2); Using where 1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 17 Using sort_union(i1,i2); Using where
explain select * from t0 where key2 = 45 or key1 <=> null; explain select * from t0 where key2 = 45 or key1 <=> null;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 range i1,i2 i2 4 NULL 1 Using where 1 SIMPLE t0 range i1,i2 i2 4 NULL 1 Using index condition
explain select * from t0 where key2 = 45 or key1 is not null; explain select * from t0 where key2 = 45 or key1 is not null;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where 1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where
......
...@@ -1002,7 +1002,7 @@ insert into t2 (b) values (null), (null), (null); ...@@ -1002,7 +1002,7 @@ insert into t2 (b) values (null), (null), (null);
set optimizer_switch='extended_keys=on'; set optimizer_switch='extended_keys=on';
explain select a from t1 where b is null order by a desc limit 2; explain select a from t1 where b is null order by a desc limit 2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref b b 9 const 2 Using where; Using filesort 1 SIMPLE t1 index b PRIMARY 8 NULL 3 Using where
select a from t1 where b is null order by a desc limit 2; select a from t1 where b is null order by a desc limit 2;
a a
3 3
......
...@@ -2090,10 +2090,10 @@ SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a ...@@ -2090,10 +2090,10 @@ SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a
WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5 WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5
ORDER BY t1.b; ORDER BY t1.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 SIMPLE t1 ref PRIMARY,idx idx 4 const 2 100.00 Using where; Using filesort 1 SIMPLE t1 ref PRIMARY,idx idx 4 const 2 100.00 Using where
1 SIMPLE t2 ref c c 5 test.t1.a 2 100.00 1 SIMPLE t2 ref c c 5 test.t1.a 2 100.00
Warnings: Warnings:
Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` join `test`.`t1` where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (((`test`.`t1`.`pk` between 5 and 6) and isnull(`test`.`t1`.`b`)) or (`test`.`t1`.`b` = 5))) order by `test`.`t1`.`b` Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` join `test`.`t1` where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t1`.`b` = 5)) order by `test`.`t1`.`b`
SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a
WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5 WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5
ORDER BY t1.b; ORDER BY t1.b;
......
...@@ -2101,10 +2101,10 @@ SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a ...@@ -2101,10 +2101,10 @@ SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a
WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5 WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5
ORDER BY t1.b; ORDER BY t1.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 SIMPLE t1 ref PRIMARY,idx idx 4 const 2 100.00 Using where; Using filesort 1 SIMPLE t1 ref PRIMARY,idx idx 4 const 2 100.00 Using where
1 SIMPLE t2 ref c c 5 test.t1.a 2 100.00 1 SIMPLE t2 ref c c 5 test.t1.a 2 100.00
Warnings: Warnings:
Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` join `test`.`t1` where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (((`test`.`t1`.`pk` between 5 and 6) and isnull(`test`.`t1`.`b`)) or (`test`.`t1`.`b` = 5))) order by `test`.`t1`.`b` Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` join `test`.`t1` where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t1`.`b` = 5)) order by `test`.`t1`.`b`
SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a SELECT t1.b, t2.c, t2.d FROM t2 LEFT JOIN t1 ON t2.c = t1.a
WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5 WHERE t1.pk BETWEEN 5 AND 6 AND t1.b IS NULL OR t1.b = 5
ORDER BY t1.b; ORDER BY t1.b;
......
...@@ -2196,3 +2196,48 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -2196,3 +2196,48 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1 1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range a a 5 NULL 1 Using where; Using index 1 SIMPLE t2 range a a 5 NULL 1 Using where; Using index
drop table t1,t2,t3; drop table t1,t2,t3;
#
# MDEV-6480: Remove conditions for which range optimizer returned SEL_ARG::IMPOSSIBLE.
#
create table t1(a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t2 (a int, b int, c int, key(a), key(b));
insert into t2
select
A.a + B.a* 10 + C.a * 100,
A.a + B.a* 10 + C.a * 100,
12345
from
t1 A, t1 B, t1 C;
# EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where (b > 25 and b < 15) or a<44;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 range a,b a 5 NULL 43 100.00 Using index condition
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`a` < 44)
# EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where a < 44 or (b > 25 and b < 15);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 range a,b a 5 NULL 43 100.00 Using index condition
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`a` < 44)
# Here, conditions b will not be removed, because "c<44" is not sargable
# and hence (b.. and .. b) part is not analyzed at all:
explain extended select * from t2 where c < 44 or (b > 25 and b < 15);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL b NULL NULL NULL 1000 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`c` < 44) or ((`test`.`t2`.`b` > 25) and (`test`.`t2`.`b` < 15)))
# EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where (b > 25 and b < 15) or c < 44;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL b NULL NULL NULL 1000 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`c` < 44))
# Try a case where both OR parts produce SEL_ARG::IMPOSSIBLE:
explain extended select * from t2 where (b > 25 and b < 15) or (a>55 and a<44);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where 0
drop table t1,t2;
...@@ -2198,4 +2198,49 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -2198,4 +2198,49 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1 1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range a a 5 NULL 1 Using where; Using index 1 SIMPLE t2 range a a 5 NULL 1 Using where; Using index
drop table t1,t2,t3; drop table t1,t2,t3;
#
# MDEV-6480: Remove conditions for which range optimizer returned SEL_ARG::IMPOSSIBLE.
#
create table t1(a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t2 (a int, b int, c int, key(a), key(b));
insert into t2
select
A.a + B.a* 10 + C.a * 100,
A.a + B.a* 10 + C.a * 100,
12345
from
t1 A, t1 B, t1 C;
# EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where (b > 25 and b < 15) or a<44;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 range a,b a 5 NULL 43 100.00 Using index condition; Rowid-ordered scan
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`a` < 44)
# EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where a < 44 or (b > 25 and b < 15);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 range a,b a 5 NULL 43 100.00 Using index condition; Rowid-ordered scan
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`a` < 44)
# Here, conditions b will not be removed, because "c<44" is not sargable
# and hence (b.. and .. b) part is not analyzed at all:
explain extended select * from t2 where c < 44 or (b > 25 and b < 15);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL b NULL NULL NULL 1000 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`c` < 44) or ((`test`.`t2`.`b` > 25) and (`test`.`t2`.`b` < 15)))
# EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where (b > 25 and b < 15) or c < 44;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL b NULL NULL NULL 1000 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`c` < 44))
# Try a case where both OR parts produce SEL_ARG::IMPOSSIBLE:
explain extended select * from t2 where (b > 25 and b < 15) or (a>55 and a<44);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where 0
drop table t1,t2;
set optimizer_switch=@mrr_icp_extra_tmp; set optimizer_switch=@mrr_icp_extra_tmp;
...@@ -1745,3 +1745,35 @@ explain select * from t3, t2 where t2.a < t3.b and t3.a=1; ...@@ -1745,3 +1745,35 @@ explain select * from t3, t2 where t2.a < t3.b and t3.a=1;
--echo # The second table should use 'range': --echo # The second table should use 'range':
explain select * from t3, t2 where t3.b > t2.a and t3.a=1; explain select * from t3, t2 where t3.b > t2.a and t3.a=1;
drop table t1,t2,t3; drop table t1,t2,t3;
--echo #
--echo # MDEV-6480: Remove conditions for which range optimizer returned SEL_ARG::IMPOSSIBLE.
--echo #
create table t1(a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t2 (a int, b int, c int, key(a), key(b));
insert into t2
select
A.a + B.a* 10 + C.a * 100,
A.a + B.a* 10 + C.a * 100,
12345
from
t1 A, t1 B, t1 C;
--echo # EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where (b > 25 and b < 15) or a<44;
--echo # EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where a < 44 or (b > 25 and b < 15);
--echo # Here, conditions b will not be removed, because "c<44" is not sargable
--echo # and hence (b.. and .. b) part is not analyzed at all:
explain extended select * from t2 where c < 44 or (b > 25 and b < 15);
--echo # EXPLAIN EXTENDED should show that 'b > 25 and b < 15' is removed from the WHERE:
explain extended select * from t2 where (b > 25 and b < 15) or c < 44;
--echo # Try a case where both OR parts produce SEL_ARG::IMPOSSIBLE:
explain extended select * from t2 where (b > 25 and b < 15) or (a>55 and a<44);
drop table t1,t2;
...@@ -829,6 +829,12 @@ public: ...@@ -829,6 +829,12 @@ public:
*/ */
bool remove_jump_scans; bool remove_jump_scans;
/*
TRUE <=> Range analyzer should remove parts of condition that are found
to be always FALSE.
*/
bool remove_false_where_parts;
/* /*
used_key_no -> table_key_no translation table. Only makes sense if used_key_no -> table_key_no translation table. Only makes sense if
using_real_indexes==TRUE using_real_indexes==TRUE
...@@ -908,7 +914,7 @@ static SEL_TREE * get_mm_parts(RANGE_OPT_PARAM *param,COND *cond_func,Field *fie ...@@ -908,7 +914,7 @@ static SEL_TREE * get_mm_parts(RANGE_OPT_PARAM *param,COND *cond_func,Field *fie
static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field, static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field,
KEY_PART *key_part, KEY_PART *key_part,
Item_func::Functype type,Item *value); Item_func::Functype type,Item *value);
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond); static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond);
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts); static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
...@@ -2941,7 +2947,8 @@ static int fill_used_fields_bitmap(PARAM *param) ...@@ -2941,7 +2947,8 @@ static int fill_used_fields_bitmap(PARAM *param)
int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
table_map prev_tables, table_map prev_tables,
ha_rows limit, bool force_quick_range, ha_rows limit, bool force_quick_range,
bool ordered_output) bool ordered_output,
bool remove_false_parts_of_where)
{ {
uint idx; uint idx;
double scan_time; double scan_time;
...@@ -3000,6 +3007,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -3000,6 +3007,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.imerge_cost_buff_size= 0; param.imerge_cost_buff_size= 0;
param.using_real_indexes= TRUE; param.using_real_indexes= TRUE;
param.remove_jump_scans= TRUE; param.remove_jump_scans= TRUE;
param.remove_false_where_parts= remove_false_parts_of_where;
param.force_default_mrr= ordered_output; param.force_default_mrr= ordered_output;
param.possible_keys.clear_all(); param.possible_keys.clear_all();
...@@ -3073,7 +3081,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -3073,7 +3081,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (cond) if (cond)
{ {
if ((tree= get_mm_tree(&param,cond))) if ((tree= get_mm_tree(&param, &cond)))
{ {
if (tree->type == SEL_TREE::IMPOSSIBLE) if (tree->type == SEL_TREE::IMPOSSIBLE)
{ {
...@@ -3415,7 +3423,7 @@ double records_in_column_ranges(PARAM *param, uint idx, ...@@ -3415,7 +3423,7 @@ double records_in_column_ranges(PARAM *param, uint idx,
TRUE otherwise TRUE otherwise
*/ */
bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
{ {
uint keynr; uint keynr;
uint max_quick_key_parts= 0; uint max_quick_key_parts= 0;
...@@ -3425,7 +3433,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) ...@@ -3425,7 +3433,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond)
table->cond_selectivity= 1.0; table->cond_selectivity= 1.0;
if (!cond || table_records == 0) if (!*cond || table_records == 0)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (table->pos_in_table_list->schema_table) if (table->pos_in_table_list->schema_table)
...@@ -3529,6 +3537,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) ...@@ -3529,6 +3537,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond)
param.old_root= thd->mem_root; param.old_root= thd->mem_root;
param.table= table; param.table= table;
param.is_ror_scan= FALSE; param.is_ror_scan= FALSE;
param.remove_false_where_parts= true;
if (create_key_parts_for_pseudo_indexes(&param, used_fields)) if (create_key_parts_for_pseudo_indexes(&param, used_fields))
goto free_alloc; goto free_alloc;
...@@ -3606,7 +3615,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) ...@@ -3606,7 +3615,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond)
ulong check_rows= ulong check_rows=
MY_MIN(thd->variables.optimizer_selectivity_sampling_limit, MY_MIN(thd->variables.optimizer_selectivity_sampling_limit,
(ulong) (table_records * SELECTIVITY_SAMPLING_SHARE)); (ulong) (table_records * SELECTIVITY_SAMPLING_SHARE));
if (cond && check_rows > SELECTIVITY_SAMPLING_THRESHOLD && if (*cond && check_rows > SELECTIVITY_SAMPLING_THRESHOLD &&
thd->variables.optimizer_use_condition_selectivity > 4) thd->variables.optimizer_use_condition_selectivity > 4)
{ {
find_selective_predicates_list_processor_data *dt= find_selective_predicates_list_processor_data *dt=
...@@ -3617,8 +3626,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) ...@@ -3617,8 +3626,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
dt->list.empty(); dt->list.empty();
dt->table= table; dt->table= table;
if (cond->walk(&Item::find_selective_predicates_list_processor, 0, if ((*cond)->walk(&Item::find_selective_predicates_list_processor, 0,
(uchar*) dt)) (uchar*) dt))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (dt->list.elements > 0) if (dt->list.elements > 0)
{ {
...@@ -3951,6 +3960,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) ...@@ -3951,6 +3960,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
/* range_par->cond doesn't need initialization */ /* range_par->cond doesn't need initialization */
range_par->prev_tables= range_par->read_tables= 0; range_par->prev_tables= range_par->read_tables= 0;
range_par->current_table= table->map; range_par->current_table= table->map;
/* It should be possible to switch the following ON: */
range_par->remove_false_where_parts= false;
range_par->keys= 1; // one index range_par->keys= 1; // one index
range_par->using_real_indexes= FALSE; range_par->using_real_indexes= FALSE;
...@@ -3967,7 +3978,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) ...@@ -3967,7 +3978,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
SEL_TREE *tree; SEL_TREE *tree;
int res; int res;
tree= get_mm_tree(range_par, pprune_cond); tree= get_mm_tree(range_par, &pprune_cond);
if (!tree) if (!tree)
goto all_used; goto all_used;
...@@ -7855,15 +7866,33 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, ...@@ -7855,15 +7866,33 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
DBUG_RETURN(ftree); DBUG_RETURN(ftree);
} }
/* make a select tree of all keys in condition */ /*
make a select tree of all keys in condition
@param param Context
@param cond INOUT condition to perform range analysis on.
@detail
Range analysis may infer that some conditions are never true.
- If the condition is never true, SEL_TREE(type=IMPOSSIBLE) is returned
- if parts of condition are never true, the function may remove these parts
from the condition 'cond'. Sometimes, this will cause the condition to
be substituted for something else.
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond) @return
NULL - Could not infer anything from condition cond.
SEL_TREE with type=IMPOSSIBLE - condition can never be true.
*/
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
{ {
SEL_TREE *tree=0; SEL_TREE *tree=0;
SEL_TREE *ftree= 0; SEL_TREE *ftree= 0;
Item_field *field_item= 0; Item_field *field_item= 0;
bool inv= FALSE; bool inv= FALSE;
Item *value= 0; Item *value= 0;
Item *cond= *cond_ptr;
DBUG_ENTER("get_mm_tree"); DBUG_ENTER("get_mm_tree");
if (cond->type() == Item::COND_ITEM) if (cond->type() == Item::COND_ITEM)
...@@ -7876,31 +7905,75 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond) ...@@ -7876,31 +7905,75 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
Item *item; Item *item;
while ((item=li++)) while ((item=li++))
{ {
SEL_TREE *new_tree= get_mm_tree(param,item); SEL_TREE *new_tree= get_mm_tree(param,li.ref());
if (param->statement_should_be_aborted()) if (param->statement_should_be_aborted())
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
tree= tree_and(param,tree,new_tree); tree= tree_and(param,tree,new_tree);
if (tree && tree->type == SEL_TREE::IMPOSSIBLE) if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
{
/*
Do not remove 'item' from 'cond'. We return a SEL_TREE::IMPOSSIBLE
and that is sufficient for the caller to see that the whole
condition is never true.
*/
break; break;
}
} }
} }
else else
{ // COND OR { // COND OR
tree= get_mm_tree(param,li++); bool replace_cond= false;
Item *replacement_item= li++;
tree= get_mm_tree(param, li.ref());
if (param->statement_should_be_aborted()) if (param->statement_should_be_aborted())
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
if (tree) if (tree)
{ {
if (tree->type == SEL_TREE::IMPOSSIBLE &&
param->remove_false_where_parts)
{
/* See the other li.remove() call below */
li.remove();
if (((Item_cond*)cond)->argument_list()->elements <= 1)
replace_cond= true;
}
Item *item; Item *item;
while ((item=li++)) while ((item=li++))
{ {
SEL_TREE *new_tree=get_mm_tree(param,item); SEL_TREE *new_tree=get_mm_tree(param,li.ref());
if (new_tree == NULL || param->statement_should_be_aborted()) if (new_tree == NULL || param->statement_should_be_aborted())
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
tree= tree_or(param,tree,new_tree); tree= tree_or(param,tree,new_tree);
if (tree == NULL || tree->type == SEL_TREE::ALWAYS) if (tree == NULL || tree->type == SEL_TREE::ALWAYS)
{
replacement_item= *li.ref();
break; break;
}
if (new_tree && new_tree->type == SEL_TREE::IMPOSSIBLE &&
param->remove_false_where_parts)
{
/*
This is a condition in form
cond = item1 OR ... OR item_i OR ... itemN
and item_i produces SEL_TREE(IMPOSSIBLE). We should remove item_i
from cond. This may cause 'cond' to become a degenerate,
one-way OR. In that case, we replace 'cond' with the remaining
item_i.
*/
li.remove();
if (((Item_cond*)cond)->argument_list()->elements <= 1)
replace_cond= true;
}
else
replacement_item= *li.ref();
} }
if (replace_cond)
*cond_ptr= replacement_item;
} }
} }
DBUG_RETURN(tree); DBUG_RETURN(tree);
...@@ -10617,6 +10690,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, ...@@ -10617,6 +10690,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
param->table->quick_condition_rows= param->table->quick_condition_rows=
MY_MIN(param->table->quick_condition_rows, rows); MY_MIN(param->table->quick_condition_rows, rows);
param->table->quick_rows[keynr]= rows; param->table->quick_rows[keynr]= rows;
param->table->quick_costs[keynr]= cost->total_cost();
} }
} }
/* Figure out if the key scan is ROR (returns rows in ROWID order) or not */ /* Figure out if the key scan is ROR (returns rows in ROWID order) or not */
......
...@@ -994,7 +994,7 @@ class SQL_SELECT :public Sql_alloc { ...@@ -994,7 +994,7 @@ class SQL_SELECT :public Sql_alloc {
{ {
key_map tmp; key_map tmp;
tmp.set_all(); tmp.set_all();
return test_quick_select(thd, tmp, 0, limit, force_quick_range, FALSE) < 0; return test_quick_select(thd, tmp, 0, limit, force_quick_range, FALSE, FALSE) < 0;
} }
/* /*
RETURN RETURN
...@@ -1011,7 +1011,7 @@ class SQL_SELECT :public Sql_alloc { ...@@ -1011,7 +1011,7 @@ class SQL_SELECT :public Sql_alloc {
} }
int test_quick_select(THD *thd, key_map keys, table_map prev_tables, int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
ha_rows limit, bool force_quick_range, ha_rows limit, bool force_quick_range,
bool ordered_output); bool ordered_output, bool remove_false_parts_of_where);
}; };
...@@ -1036,7 +1036,7 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, ...@@ -1036,7 +1036,7 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, table_map read_tables, COND *conds,
bool allow_null_cond, int *error); bool allow_null_cond, int *error);
bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond); bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond);
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond); bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
......
This diff is collapsed.
...@@ -1113,6 +1113,7 @@ public: ...@@ -1113,6 +1113,7 @@ public:
and max #key parts that range access would use. and max #key parts that range access would use.
*/ */
ha_rows quick_rows[MAX_KEY]; ha_rows quick_rows[MAX_KEY];
double quick_costs[MAX_KEY];
/* /*
Bitmaps of key parts that =const for the duration of join execution. If Bitmaps of key parts that =const for the duration of join execution. If
......
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