From 60561ae6133cf40f4fc445e1d6e8f395a20b2573 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Jun 2012 18:47:13 +0300 Subject: [PATCH 1/4] Fix for LP bug#1001505 and LP bug#1001510 We set correct cmp_context during preparation to avoid changing it later by Item_field::equal_fields_propagator. (see mysql bugs #57135 #57692 during merging) --- mysql-test/r/case.result | 4 ++++ mysql-test/r/compare.result | 4 ++++ mysql-test/t/case.test | 10 ++++++++++ mysql-test/t/compare.test | 8 ++++++++ sql/item_cmpfunc.cc | 19 +++++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 0c0e2d623c8..811bbee1d91 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -218,3 +218,7 @@ a d 3 11120436154190595086 drop table t1, t2; End of 5.0 tests +CREATE TABLE t1(a YEAR); +SELECT 1 FROM t1 WHERE a=1 AND CASE 1 WHEN a THEN 1 ELSE 1 END; +1 +DROP TABLE t1; diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result index 796821a87bd..5168eb38586 100644 --- a/mysql-test/r/compare.result +++ b/mysql-test/r/compare.result @@ -96,3 +96,7 @@ SELECT * FROM t1 WHERE a > '2008-01-01' AND a = '0000-00-00'; a DROP TABLE t1; End of 5.0 tests +CREATE TABLE t1(a INT ZEROFILL); +SELECT 1 FROM t1 WHERE t1.a IN (1, t1.a) AND t1.a=2; +1 +DROP TABLE t1; diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index 028c64d6de7..81855dfc97f 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -170,3 +170,13 @@ select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 drop table t1, t2; --echo End of 5.0 tests + +# +# LP BUG#1001510 +# Bug #11764313 57135: CRASH IN ITEM_FUNC_CASE::FIND_ITEM WITH CASE WHEN +# ELSE CLAUSE +# + +CREATE TABLE t1(a YEAR); +SELECT 1 FROM t1 WHERE a=1 AND CASE 1 WHEN a THEN 1 ELSE 1 END; +DROP TABLE t1; diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test index 103244eb2f7..d2b2a7e5523 100644 --- a/mysql-test/t/compare.test +++ b/mysql-test/t/compare.test @@ -86,3 +86,11 @@ SELECT * FROM t1 WHERE a > '2008-01-01' AND a = '0000-00-00'; DROP TABLE t1; --echo End of 5.0 tests + +# +# Bug #11764818 57692: Crash in item_func_in::val_int() with ZEROFILL +# + +CREATE TABLE t1(a INT ZEROFILL); +SELECT 1 FROM t1 WHERE t1.a IN (1, t1.a) AND t1.a=2; +DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 61554bdf420..847c51b8a5e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3095,6 +3095,15 @@ void Item_func_case::fix_length_and_dec() return; } } + /* + Set cmp_context of all WHEN arguments. This prevents + Item_field::equal_fields_propagator() from transforming a + zerofill argument into a string constant. Such a change would + require rebuilding cmp_items. + */ + for (i= 0; i < ncases; i+= 2) + args[i]->cmp_context= item_cmp_type(left_result_type, + args[i]->result_type()); } if (else_expr_num == -1 || args[else_expr_num]->maybe_null) @@ -4081,6 +4090,16 @@ void Item_func_in::fix_length_and_dec() } } } + /* + Set cmp_context of all arguments. This prevents + Item_field::equal_fields_propagator() from transforming a zerofill integer + argument into a string constant. Such a change would require rebuilding + cmp_itmes. + */ + for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++) + { + arg[0]->cmp_context= item_cmp_type(left_result_type, arg[0]->result_type()); + } max_length= 1; } From d07b179fd2397bd78dd4f9ba7c54dda38fc1ce8c Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 13 Aug 2012 21:13:14 -0700 Subject: [PATCH 2/4] Fixed bug mdev-449. The bug could caused a crash when the server executed a query with ORDER by and sort_buffer_size was set to a small enough number. It happened because the small sort buffer did not allow to allocate all merge buffers in it. Made sure that the allocated sort buffer would be big enough to contain all possible merge buffers. --- mysql-test/r/order_by.result | 132 +++++++++++++++++++++++++++++++++++ mysql-test/t/order_by.test | 39 +++++++++++ sql/filesort.cc | 12 ++-- 3 files changed, 178 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index c0a54817b4c..8fa1006b8fc 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1783,3 +1783,135 @@ Warnings: Note 1003 select `test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`a` = `test`.`t1`.`b`) group by `test`.`t2`.`b` order by `test`.`t1`.`b` drop table t1,t2; End of 5.2 tests +# +# Bug mdev-449: ORDER BY with small sort_buffer_size +# +CREATE TABLE t1(f0 int auto_increment primary key, f1 int, f2 varchar(200)); +INSERT INTO t1(f1, f2) VALUES +(0,"0"),(1,"1"),(2,"2"),(3,"3"),(4,"4"),(5,"5"), +(6,"6"),(7,"7"),(8,"8"),(9,"9"),(10,"10"), +(11,"11"),(12,"12"),(13,"13"),(14,"14"),(15,"15"), +(16,"16"),(17,"17"),(18,"18"),(19,"19"),(20,"20"), +(21,"21"),(22,"22"),(23,"23"),(24,"24"),(25,"25"), +(26,"26"),(27,"27"),(28,"28"),(29,"29"),(30,"30"), +(31,"31"),(32,"32"),(33,"33"),(34,"34"),(35,"35"), +(36,"36"),(37,"37"),(38,"38"),(39,"39"),(40,"40"), +(41,"41"),(42,"42"),(43,"43"),(44,"44"),(45,"45"), +(46,"46"),(47,"47"),(48,"48"),(49,"49"),(50,"50"), +(51,"51"),(52,"52"),(53,"53"),(54,"54"),(55,"55"), +(56,"56"),(57,"57"),(58,"58"),(59,"59"),(60,"60"), +(61,"61"),(62,"62"),(63,"63"),(64,"64"),(65,"65"), +(66,"66"),(67,"67"),(68,"68"),(69,"69"),(70,"70"), +(71,"71"),(72,"72"),(73,"73"),(74,"74"),(75,"75"), +(76,"76"),(77,"77"),(78,"78"),(79,"79"),(80,"80"), +(81,"81"),(82,"82"),(83,"83"),(84,"84"),(85,"85"), +(86,"86"),(87,"87"),(88,"88"),(89,"89"),(90,"90"), +(91,"91"),(92,"92"),(93,"93"),(94,"94"),(95,"95"), +(96,"96"),(97,"97"),(98,"98"),(99,"99"); +set @save_sort_buffer_size= @@sort_buffer_size; +set sort_buffer_size= 2000; +SELECT * FROM t1 ORDER BY f1 DESC, f0; +f0 f1 f2 +100 99 99 +99 98 98 +98 97 97 +97 96 96 +96 95 95 +95 94 94 +94 93 93 +93 92 92 +92 91 91 +91 90 90 +90 89 89 +89 88 88 +88 87 87 +87 86 86 +86 85 85 +85 84 84 +84 83 83 +83 82 82 +82 81 81 +81 80 80 +80 79 79 +79 78 78 +78 77 77 +77 76 76 +76 75 75 +75 74 74 +74 73 73 +73 72 72 +72 71 71 +71 70 70 +70 69 69 +69 68 68 +68 67 67 +67 66 66 +66 65 65 +65 64 64 +64 63 63 +63 62 62 +62 61 61 +61 60 60 +60 59 59 +59 58 58 +58 57 57 +57 56 56 +56 55 55 +55 54 54 +54 53 53 +53 52 52 +52 51 51 +51 50 50 +50 49 49 +49 48 48 +48 47 47 +47 46 46 +46 45 45 +45 44 44 +44 43 43 +43 42 42 +42 41 41 +41 40 40 +40 39 39 +39 38 38 +38 37 37 +37 36 36 +36 35 35 +35 34 34 +34 33 33 +33 32 32 +32 31 31 +31 30 30 +30 29 29 +29 28 28 +28 27 27 +27 26 26 +26 25 25 +25 24 24 +24 23 23 +23 22 22 +22 21 21 +21 20 20 +20 19 19 +19 18 18 +18 17 17 +17 16 16 +16 15 15 +15 14 14 +14 13 13 +13 12 12 +12 11 11 +11 10 10 +10 9 9 +9 8 8 +8 7 7 +7 6 6 +6 5 5 +5 4 4 +4 3 3 +3 2 2 +2 1 1 +1 0 0 +set sort_buffer_size= @save_sort_buffer_size; +DROP TABLE t1; +End of 5.3 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 425bef6c679..1d81248b81e 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -1589,3 +1589,42 @@ SELECT t2.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; drop table t1,t2; --echo End of 5.2 tests + +--echo # +--echo # Bug mdev-449: ORDER BY with small sort_buffer_size +--echo # + +CREATE TABLE t1(f0 int auto_increment primary key, f1 int, f2 varchar(200)); +INSERT INTO t1(f1, f2) VALUES +(0,"0"),(1,"1"),(2,"2"),(3,"3"),(4,"4"),(5,"5"), +(6,"6"),(7,"7"),(8,"8"),(9,"9"),(10,"10"), +(11,"11"),(12,"12"),(13,"13"),(14,"14"),(15,"15"), +(16,"16"),(17,"17"),(18,"18"),(19,"19"),(20,"20"), +(21,"21"),(22,"22"),(23,"23"),(24,"24"),(25,"25"), +(26,"26"),(27,"27"),(28,"28"),(29,"29"),(30,"30"), +(31,"31"),(32,"32"),(33,"33"),(34,"34"),(35,"35"), +(36,"36"),(37,"37"),(38,"38"),(39,"39"),(40,"40"), +(41,"41"),(42,"42"),(43,"43"),(44,"44"),(45,"45"), +(46,"46"),(47,"47"),(48,"48"),(49,"49"),(50,"50"), +(51,"51"),(52,"52"),(53,"53"),(54,"54"),(55,"55"), +(56,"56"),(57,"57"),(58,"58"),(59,"59"),(60,"60"), +(61,"61"),(62,"62"),(63,"63"),(64,"64"),(65,"65"), +(66,"66"),(67,"67"),(68,"68"),(69,"69"),(70,"70"), +(71,"71"),(72,"72"),(73,"73"),(74,"74"),(75,"75"), +(76,"76"),(77,"77"),(78,"78"),(79,"79"),(80,"80"), +(81,"81"),(82,"82"),(83,"83"),(84,"84"),(85,"85"), +(86,"86"),(87,"87"),(88,"88"),(89,"89"),(90,"90"), +(91,"91"),(92,"92"),(93,"93"),(94,"94"),(95,"95"), +(96,"96"),(97,"97"),(98,"98"),(99,"99"); + +set @save_sort_buffer_size= @@sort_buffer_size; +set sort_buffer_size= 2000; + +SELECT * FROM t1 ORDER BY f1 DESC, f0; + +set sort_buffer_size= @save_sort_buffer_size; + +DROP TABLE t1; + +--echo End of 5.3 tests + diff --git a/sql/filesort.cc b/sql/filesort.cc index 772698c6e1a..4d06317447a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -102,6 +102,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, { int error; ulong memavl, min_sort_memory; + ulong sort_buff_sz; uint maxbuffer; BUFFPEK *buffpek; ha_rows records= HA_POS_ERROR; @@ -210,6 +211,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, memavl= thd->variables.sortbuff_size; min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2); + set_if_bigger(min_sort_memory, sizeof(BUFFPEK*)*MERGEBUFF2); if (!table_sort.sort_keys) { while (memavl >= min_sort_memory) @@ -217,9 +219,10 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ulong old_memavl; ulong keys= memavl/(param.rec_length+sizeof(char*)); table_sort.keys= (uint) min(records+1, keys); + sort_buff_sz= table_sort.keys*(param.rec_length+sizeof(char*)); + set_if_bigger(sort_buff_sz, param.rec_length * MERGEBUFF2); if ((table_sort.sort_keys= - (uchar**) my_malloc(table_sort.keys*(param.rec_length+sizeof(char*)), - MYF(0)))) + (uchar**) my_malloc(sort_buff_sz, MYF(0)))) break; old_memavl=memavl; if ((memavl=memavl/4*3) < min_sort_memory && @@ -282,8 +285,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, Use also the space previously used by string pointers in sort_buffer for temporary key storage. */ - param.keys=((param.keys*(param.rec_length+sizeof(char*))) / - param.rec_length-1); + param.keys= sort_buff_sz / param.rec_length; maxbuffer--; // Offset from 0 if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer, &tempfile)) @@ -1257,7 +1259,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, to_start_filepos= my_b_tell(to_file); strpos= sort_buffer; org_max_rows=max_rows= param->max_rows; - + /* The following will fire if there is not enough space in sort_buffer */ DBUG_ASSERT(maxcount!=0); From fbee9f5b6e25e60c7e6785b3125a277426eb78b5 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 14 Aug 2012 14:25:56 -0700 Subject: [PATCH 3/4] Corrected the pactch for mdev-449 to fix valgrind failures. --- sql/filesort.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index 4d06317447a..46348f91bb4 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -285,7 +285,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, Use also the space previously used by string pointers in sort_buffer for temporary key storage. */ - param.keys= sort_buff_sz / param.rec_length; + param.keys=((param.keys*(param.rec_length+sizeof(char*))) / + param.rec_length-1); maxbuffer--; // Offset from 0 if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer, &tempfile)) @@ -1260,8 +1261,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, strpos= sort_buffer; org_max_rows=max_rows= param->max_rows; - /* The following will fire if there is not enough space in sort_buffer */ - DBUG_ASSERT(maxcount!=0); + set_if_bigger(maxcount, 1); if (unique_buff) { From ed06ba3492d55c9e9dde231b55352f854e5e4b50 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Tue, 21 Aug 2012 22:24:34 +0400 Subject: [PATCH 4/4] Better comments --- sql/opt_subselect.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 0273c947ef6..4591888307e 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -143,18 +143,18 @@ 3.2.1 Non-merged semi-joins and join optimization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For join optimization purposes, non-merged semi-join nests are similar to - base tables - they've got one JOIN_TAB, which can be accessed with one of - two methods: + base tables. Each such nest is represented by one one JOIN_TAB, which has + two possible access strategies: - full table scan (representing SJ-Materialization-Scan strategy) - eq_ref-like table lookup (representing SJ-Materialization-Lookup) Unlike regular base tables, non-merged semi-joins have: - non-zero JOIN_TAB::startup_cost, and - join_tab->table->is_filled_at_execution()==TRUE, which means one - cannot do const table detection or range analysis or other table data- - dependent inferences - // instead, get_delayed_table_estimates() runs optimization on the nest so that - // we get an idea about temptable size + cannot do const table detection, range analysis or other dataset-dependent + optimizations. + Instead, get_delayed_table_estimates() will run optimization for the + subquery and produce an E(materialized table size). 3.2.2 Merged semi-joins and join optimization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~