diff options
author | unknown <timour@askmonty.org> | 2011-08-17 14:10:32 +0300 |
---|---|---|
committer | unknown <timour@askmonty.org> | 2011-08-17 14:10:32 +0300 |
commit | 6b70cc538b91afa31bf1d90d1c75714092cba815 (patch) | |
tree | de648491442cdad0085489e312ce6a431531f803 /sql | |
parent | f240aa4cbfc50de1f2cb83ebce658bd331091f61 (diff) | |
download | mariadb-git-6b70cc538b91afa31bf1d90d1c75714092cba815.tar.gz |
Fix bug lp:813473
The bug is a duplicate of MySQL's Bug#11764086,
however MySQL's fix is incomplete for MariaDB, so
this fix is slightly different.
In addition, this patch renames
Item_func_not_all::top_level() to is_top_level_item()
to make it in line with the analogous methods of
Item_in_optimizer, and Item_subselect.
Analysis:
It is possible to determine whether a predicate is
NULL-rejecting only if it is a top-level one. However,
this was not taken into account for Item_in_optimizer.
As a result, a NOT IN predicate was erroneously
considered as NULL-rejecting, and the NULL-complemented
rows generated by the outer join were rejected before
being checked by the NOT IN predicate.
Solution:
Change Item_in_optimizer to be considered as
NULL-rejecting only if it a top-level predicate.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_cmpfunc.cc | 23 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 4 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 |
3 files changed, 25 insertions, 4 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 721c9b6a5f7..446d5f18c7f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1399,6 +1399,26 @@ longlong Item_func_truth::val_int() } +bool Item_in_optimizer::is_top_level_item() +{ + return ((Item_in_subselect *)args[1])->is_top_level_item(); +} + + +bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg) +{ + not_null_tables_cache= 0; + if (is_top_level_item()) + { + /* + It is possible to determine NULL-rejectedness of the left arguments + of IN only if it is a top-level predicate. + */ + not_null_tables_cache= args[0]->not_null_tables(); + } + return FALSE; +} + bool Item_in_optimizer::fix_left(THD *thd, Item **ref) { if ((!args[0]->fixed && args[0]->fix_fields(thd, args)) || @@ -1425,7 +1445,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref) } used_tables_cache= args[0]->used_tables(); } - not_null_tables_cache= args[0]->not_null_tables(); + eval_not_null_tables(NULL); with_sum_func= args[0]->with_sum_func; with_field= args[0]->with_field; if ((const_item_cache= args[0]->const_item())) @@ -1458,7 +1478,6 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) with_sum_func= with_sum_func || args[1]->with_sum_func; with_field= with_field || args[1]->with_field; used_tables_cache|= args[1]->used_tables(); - not_null_tables_cache|= args[1]->not_null_tables(); const_item_cache&= args[1]->const_item(); fixed= 1; return FALSE; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 6ae7309b241..e70e7d80391 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -260,6 +260,8 @@ public: void set_join_tab_idx(uint join_tab_idx_arg) { args[1]->set_join_tab_idx(join_tab_idx_arg); } virtual void get_cache_parameters(List<Item> ¶meters); + bool is_top_level_item(); + bool eval_not_null_tables(uchar *opt_arg); }; class Comp_creator @@ -494,7 +496,7 @@ public: show(0) {} virtual void top_level_item() { abort_on_null= 1; } - bool top_level() { return abort_on_null; } + bool is_top_level_item() { return abort_on_null; } longlong val_int(); enum Functype functype() const { return NOT_ALL_FUNC; } const char *func_name() const { return "<not>"; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 9281ebb22bb..12f6c26b57f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1701,7 +1701,7 @@ bool Item_allany_subselect::is_maxmin_applicable(JOIN *join) Check if max/min optimization applicable: It is top item of WHERE condition. */ - return (abort_on_null || (upper_item && upper_item->top_level())) && + return (abort_on_null || (upper_item && upper_item->is_top_level_item())) && !join->select_lex->master_unit()->uncacheable && !func->eqne_op(); } |