diff options
author | unknown <sanja@askmonty.org> | 2013-11-11 16:40:46 +0200 |
---|---|---|
committer | unknown <sanja@askmonty.org> | 2013-11-11 16:40:46 +0200 |
commit | c85db2c4943b644c34cc4c67a95cfb5e5f0a09a4 (patch) | |
tree | 31a00735fded4bba3b8a833c4a7925a607f48559 /sql | |
parent | 542ce5a068f2139c5b57ace8ba15b425fb570703 (diff) | |
download | mariadb-git-c85db2c4943b644c34cc4c67a95cfb5e5f0a09a4.tar.gz |
MDEV-5103: server crashed on singular Item_equal
Singular Item_equal support added.
The problem was that during constant table substitution Item_equal become containing only one constant which was not supported internally.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_cmpfunc.cc | 22 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 |
2 files changed, 22 insertions, 1 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d1075c3c47f..22554c71d90 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5564,6 +5564,12 @@ void Item_equal::add_const(Item *c, Item *f) func->quick_fix_field(); cond_false= !func->val_int(); } + /* + TODO: also support the case where Item_equal becomes singular with + this->is_cond_true()=1. When I attempted to mark the item as constant, + the optimizer attempted to remove it, however it is still referenced from + COND_EQUAL and I got a crash. + */ if (cond_false) const_item_cache= 1; } @@ -5768,7 +5774,8 @@ void Item_equal::merge_into_list(List<Item_equal> *list, void Item_equal::sort(Item_field_cmpfunc compare, void *arg) { - bubble_sort<Item>(&equal_items, compare, arg); + if (equal_items.elements > 1) + bubble_sort<Item>(&equal_items, compare, arg); } @@ -5868,6 +5875,12 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) void Item_equal::update_used_tables() { not_null_tables_cache= used_tables_cache= 0; + /* + TODO: also support the case where Item_equal becomes singular with + this->is_cond_true()=1. When I attempted to mark the item as constant, + the optimizer attempted to remove it, however it is still referenced from + COND_EQUAL and I got a crash. + */ if ((const_item_cache= cond_false)) return; Item_equal_fields_iterator it(*this); @@ -5916,6 +5929,8 @@ longlong Item_equal::val_int() { if (cond_false) return 0; + if (is_cond_true()) + return 1; Item *item= get_const(); Item_equal_fields_iterator it(*this); if (!item) @@ -5940,6 +5955,11 @@ longlong Item_equal::val_int() void Item_equal::fix_length_and_dec() { Item *item= get_first(NO_PARTICULAR_TAB, NULL); + if (!item) + { + DBUG_ASSERT(is_cond_true()); // it should be the only constant + item= equal_items.head(); + } eval_item= cmp_item::get_comparator(item->cmp_type(), item, item->collation.collation); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c1ef680f3ee..cdb4963e857 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1725,6 +1725,7 @@ public: Item_equal(Item_equal *item_equal); /* Currently the const item is always the first in the list of equal items */ inline Item* get_const() { return with_const ? equal_items.head() : NULL; } + inline bool is_cond_true() { return equal_items.elements == 1; } void add_const(Item *c, Item *f = NULL); /** Add a non-constant item to the multiple equality */ void add(Item *f) { equal_items.push_back(f); } |