summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <timour@askmonty.org>2011-08-17 14:10:32 +0300
committerunknown <timour@askmonty.org>2011-08-17 14:10:32 +0300
commit6b70cc538b91afa31bf1d90d1c75714092cba815 (patch)
treede648491442cdad0085489e312ce6a431531f803 /sql
parentf240aa4cbfc50de1f2cb83ebce658bd331091f61 (diff)
downloadmariadb-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.cc23
-rw-r--r--sql/item_cmpfunc.h4
-rw-r--r--sql/item_subselect.cc2
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> &parameters);
+ 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();
}