diff options
-rw-r--r-- | mysql-test/r/func_equal.result | 44 | ||||
-rw-r--r-- | mysql-test/t/func_equal.test | 52 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 22 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 |
4 files changed, 117 insertions, 2 deletions
diff --git a/mysql-test/r/func_equal.result b/mysql-test/r/func_equal.result index 4750af6e8d8..02593529a91 100644 --- a/mysql-test/r/func_equal.result +++ b/mysql-test/r/func_equal.result @@ -42,3 +42,47 @@ select * from t1 where a in ('4828532208463511553'); a 4828532208463511553 drop table t1; +#End of 4.1 tests +# +# MDEV-5103: server crashed on singular Item_equal +# +CREATE TABLE `t1` ( +`tipo` enum('p','r') NOT NULL DEFAULT 'r', +`arquivo_id` bigint(20) unsigned NOT NULL DEFAULT '0', +`arquivo_md5` char(32) NOT NULL, +`conteudo` longblob NOT NULL, +`usuario` varchar(15) NOT NULL, +`datahora_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', +`tipo_arquivo` varchar(255) NOT NULL, +`nome_arquivo` varchar(255) NOT NULL, +`tamanho_arquivo` bigint(20) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (`tipo`,`arquivo_id`), +UNIQUE KEY `tipo` (`tipo`,`arquivo_md5`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1; +INSERT INTO `t1` (`tipo`, `arquivo_id`, `arquivo_md5`, `conteudo`, `usuario`, `datahora_gmt`, `tipo_arquivo`, `nome_arquivo`, `tamanho_arquivo`) VALUES +('r', 1, 'ad18832202b199728921807033a8a515', '', 'rspadim', '2013-10-05 13:55:50', '001_cbr643', 'CBR6431677410201314132.ret', 21306); +CREATE TABLE `t2` ( +`tipo` enum('p','r') NOT NULL DEFAULT 'p', +`arquivo_id` bigint(20) NOT NULL DEFAULT '0', +`usuario` varchar(25) NOT NULL, +`datahora` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', +`erros` longblob NOT NULL, +`importados` bigint(20) unsigned NOT NULL DEFAULT '0', +`n_importados` bigint(20) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (`tipo`,`arquivo_id`,`datahora`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1; +INSERT INTO `t2` (`tipo`, `arquivo_id`, `usuario`, `datahora`, `erros`, `importados`, `n_importados`) VALUES +('r', 1, 'rspadim', '2013-10-05 14:25:30', '', 32, 0); +SELECT +arquivo_id,usuario,datahora_gmt,tipo_arquivo,nome_arquivo,tamanho_arquivo +FROM t1 AS a +WHERE datahora_gmt>='0000-00-00 00:00:00' AND +datahora_gmt<='2013-10-07 02:59:59' AND tipo='r' AND +(tipo_arquivo,arquivo_id) NOT IN +(SELECT tipo_arquivo,arquivo_id +FROM t2 +WHERE (tipo_arquivo,arquivo_id)=(a.tipo_arquivo,a.arquivo_id)) +ORDER BY arquivo_id DESC; +arquivo_id usuario datahora_gmt tipo_arquivo nome_arquivo tamanho_arquivo +drop table t2, t1; +#End of 5.3 tests diff --git a/mysql-test/t/func_equal.test b/mysql-test/t/func_equal.test index 1c219af0254..990b6d8e74e 100644 --- a/mysql-test/t/func_equal.test +++ b/mysql-test/t/func_equal.test @@ -43,4 +43,54 @@ select * from t1 where a = '4828532208463511553'; select * from t1 where a in ('4828532208463511553'); drop table t1; -# End of 4.1 tests +--echo #End of 4.1 tests + +--echo # +--echo # MDEV-5103: server crashed on singular Item_equal +--echo # + +CREATE TABLE `t1` ( + `tipo` enum('p','r') NOT NULL DEFAULT 'r', + `arquivo_id` bigint(20) unsigned NOT NULL DEFAULT '0', + `arquivo_md5` char(32) NOT NULL, + `conteudo` longblob NOT NULL, + `usuario` varchar(15) NOT NULL, + `datahora_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `tipo_arquivo` varchar(255) NOT NULL, + `nome_arquivo` varchar(255) NOT NULL, + `tamanho_arquivo` bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`tipo`,`arquivo_id`), + UNIQUE KEY `tipo` (`tipo`,`arquivo_md5`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1; + +INSERT INTO `t1` (`tipo`, `arquivo_id`, `arquivo_md5`, `conteudo`, `usuario`, `datahora_gmt`, `tipo_arquivo`, `nome_arquivo`, `tamanho_arquivo`) VALUES + ('r', 1, 'ad18832202b199728921807033a8a515', '', 'rspadim', '2013-10-05 13:55:50', '001_cbr643', 'CBR6431677410201314132.ret', 21306); + + +CREATE TABLE `t2` ( + `tipo` enum('p','r') NOT NULL DEFAULT 'p', + `arquivo_id` bigint(20) NOT NULL DEFAULT '0', + `usuario` varchar(25) NOT NULL, + `datahora` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `erros` longblob NOT NULL, + `importados` bigint(20) unsigned NOT NULL DEFAULT '0', + `n_importados` bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`tipo`,`arquivo_id`,`datahora`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1; + +INSERT INTO `t2` (`tipo`, `arquivo_id`, `usuario`, `datahora`, `erros`, `importados`, `n_importados`) VALUES + ('r', 1, 'rspadim', '2013-10-05 14:25:30', '', 32, 0); + +SELECT +arquivo_id,usuario,datahora_gmt,tipo_arquivo,nome_arquivo,tamanho_arquivo + FROM t1 AS a + WHERE datahora_gmt>='0000-00-00 00:00:00' AND + datahora_gmt<='2013-10-07 02:59:59' AND tipo='r' AND + (tipo_arquivo,arquivo_id) NOT IN + (SELECT tipo_arquivo,arquivo_id + FROM t2 + WHERE (tipo_arquivo,arquivo_id)=(a.tipo_arquivo,a.arquivo_id)) + ORDER BY arquivo_id DESC; + +drop table t2, t1; +--echo #End of 5.3 tests 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); } |