From 1ec86b21f9328b6ef472fcae1b78c2e3757f73e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Tue, 6 Oct 2009 13:04:51 +0200 Subject: [PATCH 01/20] Bug#47857 strip_sp function in mysys/mf_strip.c never used and cause name clash - Remove mf_strip.c and the declaration of 'strip_sp' --- include/my_sys.h | 1 - mysys/CMakeLists.txt | 2 +- mysys/Makefile.am | 2 +- mysys/mf_strip.c | 45 -------------------------------------------- sql/mysql_priv.h.pp | 1 - 5 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 mysys/mf_strip.c diff --git a/include/my_sys.h b/include/my_sys.h index 166133251bc..b4aac3a17bd 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -720,7 +720,6 @@ extern int wild_compare(const char *str,const char *wildstr, extern WF_PACK *wf_comp(char * str); extern int wf_test(struct wild_file_pack *wf_pack,const char *name); extern void wf_end(struct wild_file_pack *buffer); -extern size_t strip_sp(char * str); extern my_bool array_append_string_unique(const char *str, const char **array, size_t size); extern void get_date(char * to,int timeflag,time_t use_time); diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 545278485d1..7afb800643c 100755 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -29,7 +29,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_ errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c - mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_arr_appstr.c mf_tempdir.c + mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_arr_appstr.c mf_tempdir.c mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 16f0e1a9759..19017330654 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -35,7 +35,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ my_symlink.c my_symlink2.c \ - mf_pack.c mf_unixpath.c mf_strip.c mf_arr_appstr.c \ + mf_pack.c mf_unixpath.c mf_arr_appstr.c \ mf_wcomp.c mf_wfile.c my_gethwaddr.c \ mf_qsort.c mf_qsort2.c mf_sort.c \ ptr_cmp.c mf_radix.c queues.c my_getncpus.c \ diff --git a/mysys/mf_strip.c b/mysys/mf_strip.c deleted file mode 100644 index b33620b1b2d..00000000000 --- a/mysys/mf_strip.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* T|mmer en str{ng p{ slut_space */ - -#include "mysys_priv.h" - -/* - strip_sp(char * str) - Strips end-space from string and returns new length. -*/ - -size_t strip_sp(register char * str) -{ - reg2 char * found; - reg3 char * start; - - start=found=str; - - while (*str) - { - if (*str != ' ') - { - while (*++str && *str != ' ') {}; - if (!*str) - return (size_t) (str-start); /* Return stringlength */ - } - found=str; - while (*++str == ' ') {}; - } - *found= '\0'; /* Stripp at first space */ - return (size_t) (found-start); -} /* strip_sp */ diff --git a/sql/mysql_priv.h.pp b/sql/mysql_priv.h.pp index 8bb31f64587..d874a2591d1 100644 --- a/sql/mysql_priv.h.pp +++ b/sql/mysql_priv.h.pp @@ -773,7 +773,6 @@ extern int wild_compare(const char *str,const char *wildstr, extern WF_PACK *wf_comp(char * str); extern int wf_test(struct wild_file_pack *wf_pack,const char *name); extern void wf_end(struct wild_file_pack *buffer); -extern size_t strip_sp(char * str); extern my_bool array_append_string_unique(const char *str, const char **array, size_t size); extern void get_date(char * to,int timeflag,time_t use_time); From 1a48dd4e2bf0c6353bbf76b1f9b768620e0aa090 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 7 Oct 2009 18:03:42 +0300 Subject: [PATCH 02/20] Bug #43029: FORCE INDEX FOR ORDER BY is ignored when join buffering is used FORCE INDEX FOR ORDER BY now prevents the optimizer from using join buffering. As a result the optimizer can use indexed access on the first table and doesn't need to sort the complete resultset at the end of the statement. --- mysql-test/r/order_by.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/order_by.test | 32 ++++++++++++++++++++++++++++++++ sql/sql_base.cc | 6 ++++-- sql/sql_parse.cc | 1 + sql/sql_select.cc | 19 ++++++++++++++----- sql/sql_select.h | 2 ++ sql/table.cc | 25 ++++++++++++++++++++----- sql/table.h | 12 ++++++++++++ 8 files changed, 116 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 306fce1f3c2..0c72f816c21 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1557,3 +1557,34 @@ a 2001 1991 DROP TABLE t1; +# +# Bug #43029: FORCE INDEX FOR ORDER BY is ignored when join buffering +# is used +# +CREATE TABLE t1 (a INT, b INT, KEY (a)); +INSERT INTO t1 VALUES (0, NULL), (1, NULL), (2, NULL), (3, NULL); +INSERT INTO t1 SELECT a+4, b FROM t1; +INSERT INTO t1 SELECT a+8, b FROM t1; +CREATE TABLE t2 (a INT, b INT); +INSERT INTO t2 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL), (4,NULL); +INSERT INTO t2 SELECT a+4, b FROM t2; +# shouldn't have "using filesort" +EXPLAIN +SELECT * FROM t1 FORCE INDEX FOR ORDER BY (a), t2 WHERE t1.a < 2 ORDER BY t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 2 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 +# should have "using filesort" +EXPLAIN +SELECT * FROM t1 USE INDEX FOR ORDER BY (a), t2 WHERE t1.a < 2 ORDER BY t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 2 Using where; Using temporary; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using join buffer +# should have "using filesort" +EXPLAIN +SELECT * FROM t1 FORCE INDEX FOR JOIN (a), t2 WHERE t1.a < 2 ORDER BY t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 2 Using where; Using temporary; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using join buffer +DROP TABLE t1, t2; +End of 5.1 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index cca1e3209cc..ac2bbaaeeac 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -1402,3 +1402,35 @@ SELECT DISTINCT a FROM t1 WHERE b = 1 ORDER BY c DESC LIMIT 0, 9; SELECT DISTINCT a FROM t1 WHERE b = 1 ORDER BY c DESC LIMIT 0, 9; DROP TABLE t1; + +--echo # +--echo # Bug #43029: FORCE INDEX FOR ORDER BY is ignored when join buffering +--echo # is used +--echo # + +CREATE TABLE t1 (a INT, b INT, KEY (a)); + +INSERT INTO t1 VALUES (0, NULL), (1, NULL), (2, NULL), (3, NULL); +INSERT INTO t1 SELECT a+4, b FROM t1; +INSERT INTO t1 SELECT a+8, b FROM t1; + +CREATE TABLE t2 (a INT, b INT); + +INSERT INTO t2 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL), (4,NULL); +INSERT INTO t2 SELECT a+4, b FROM t2; + +--echo # shouldn't have "using filesort" +EXPLAIN +SELECT * FROM t1 FORCE INDEX FOR ORDER BY (a), t2 WHERE t1.a < 2 ORDER BY t1.a; + +--echo # should have "using filesort" +EXPLAIN +SELECT * FROM t1 USE INDEX FOR ORDER BY (a), t2 WHERE t1.a < 2 ORDER BY t1.a; + +--echo # should have "using filesort" +EXPLAIN +SELECT * FROM t1 FORCE INDEX FOR JOIN (a), t2 WHERE t1.a < 2 ORDER BY t1.a; + +DROP TABLE t1, t2; + +--echo End of 5.1 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d1e96fcdbb3..e706bd04ea6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2305,7 +2305,8 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in) table->tablenr=thd->current_tablenr++; table->used_fields=0; table->const_table=0; - table->null_row= table->maybe_null= table->force_index= 0; + table->null_row= table->maybe_null= 0; + table->force_index= table->force_index_order= table->force_index_group= 0; table->status=STATUS_NO_RECORD; DBUG_RETURN(FALSE); } @@ -2963,7 +2964,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->tablenr=thd->current_tablenr++; table->used_fields=0; table->const_table=0; - table->null_row= table->maybe_null= table->force_index= 0; + table->null_row= table->maybe_null= 0; + table->force_index= table->force_index_order= table->force_index_group= 0; table->status=STATUS_NO_RECORD; table->insert_values= 0; table->fulltext_searched= 0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 83ef525e3eb..27688e41d4f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6258,6 +6258,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->table_name_length=table->table.length; ptr->lock_type= lock_type; ptr->updating= test(table_options & TL_OPTION_UPDATING); + /* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */ ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); ptr->derived= table->sel; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3f1432914a0..9dacb2c2ce4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1231,13 +1231,22 @@ JOIN::optimize() (!group_list && tmp_table_param.sum_func_count)) order=0; - // Can't use sort on head table if using row cache + // Can't use sort on head table if using join buffering if (full_join) { - if (group_list) - simple_group=0; - if (order) - simple_order=0; + TABLE *stable= (sort_by_table == (TABLE *) 1 ? + join_tab[const_tables].table : sort_by_table); + /* + FORCE INDEX FOR ORDER BY can be used to prevent join buffering when + sorting on the first table. + */ + if (!stable || !stable->force_index_order) + { + if (group_list) + simple_group= 0; + if (order) + simple_order= 0; + } } /* diff --git a/sql/sql_select.h b/sql/sql_select.h index a0366d47149..3f06b402638 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -357,6 +357,8 @@ public: simple_xxxxx is set if ORDER/GROUP BY doesn't include any references to other tables than the first non-constant table in the JOIN. It's also set if ORDER/GROUP BY is empty. + Used for deciding for or against using a temporary table to compute + GROUP/ORDER BY. */ bool simple_order, simple_group; /** diff --git a/sql/table.cc b/sql/table.cc index 04f2a3fbcf8..d2538eb4d59 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4637,7 +4637,8 @@ Item_subselect *TABLE_LIST::containing_subselect() (TABLE_LIST::index_hints). Using the information in this tagged list this function sets the members st_table::keys_in_use_for_query, st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by, - st_table::force_index and st_table::covering_keys. + st_table::force_index, st_table::force_index_order, + st_table::force_index_group and st_table::covering_keys. Current implementation of the runtime does not allow mixing FORCE INDEX and USE INDEX, so this is checked here. Then the FORCE INDEX list @@ -4765,14 +4766,28 @@ bool TABLE_LIST::process_index_hints(TABLE *tbl) } /* process FORCE INDEX as USE INDEX with a flag */ + if (!index_order[INDEX_HINT_FORCE].is_clear_all()) + { + tbl->force_index_order= TRUE; + index_order[INDEX_HINT_USE].merge(index_order[INDEX_HINT_FORCE]); + } + + if (!index_group[INDEX_HINT_FORCE].is_clear_all()) + { + tbl->force_index_group= TRUE; + index_group[INDEX_HINT_USE].merge(index_group[INDEX_HINT_FORCE]); + } + + /* + TODO: get rid of tbl->force_index (on if any FORCE INDEX is specified) and + create tbl->force_index_join instead. + Then use the correct force_index_XX instead of the global one. + */ if (!index_join[INDEX_HINT_FORCE].is_clear_all() || - !index_order[INDEX_HINT_FORCE].is_clear_all() || - !index_group[INDEX_HINT_FORCE].is_clear_all()) + tbl->force_index_group || tbl->force_index_order) { tbl->force_index= TRUE; index_join[INDEX_HINT_USE].merge(index_join[INDEX_HINT_FORCE]); - index_order[INDEX_HINT_USE].merge(index_order[INDEX_HINT_FORCE]); - index_group[INDEX_HINT_USE].merge(index_group[INDEX_HINT_FORCE]); } /* apply USE INDEX */ diff --git a/sql/table.h b/sql/table.h index 40372fa91cf..e4a382c799f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -752,6 +752,18 @@ struct st_table { bytes, it would take up 4. */ my_bool force_index; + + /** + Flag set when the statement contains FORCE INDEX FOR ORDER BY + See TABLE_LIST::process_index_hints(). + */ + my_bool force_index_order; + + /** + Flag set when the statement contains FORCE INDEX FOR GROUP BY + See TABLE_LIST::process_index_hints(). + */ + my_bool force_index_group; my_bool distinct,const_table,no_rows; /** From 8f7f8b5a7450d9de486bb12b041bb5d3e7412720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Thu, 8 Oct 2009 13:25:11 +0200 Subject: [PATCH 03/20] Merge --- .../suite/binlog/t/binlog_stm_unsafe_warning.test | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test index a5472952f08..656eaae5721 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test @@ -94,15 +94,24 @@ DROP TABLE t1; SET GLOBAL log_warnings = @old_log_warnings; -let LOG_ERROR= `SELECT @@GLOBAL.log_error`; +let $log_error= `SELECT @@GLOBAL.log_error`; +if(!$log_error) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error = $MYSQLTEST_VARDIR/log/mysqld.1.err; +} +# Assign env variable LOG_ERROR +let LOG_ERROR=$log_error; --echo # Count the number of times the "Unsafe" message was printed --echo # to the error log. perl; - $log_error= $ENV{'LOG_ERROR'}; + use strict; + my $log_error= $ENV{'LOG_ERROR'} || die "LOG_ERROR not set"; open(FILE, "$log_error") or die("Unable to open $log_error: $!\n"); - $count = () = grep(/Bug#46265/g,); + my $count = () = grep(/Bug#46265/g,); print "Occurrences: $count\n"; close(FILE); EOF From 3185118e1a8d7599b7b5238b4b320f1a97a47bd5 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 8 Oct 2009 16:56:31 +0500 Subject: [PATCH 04/20] Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access Problem: Field_bit is the only field which returns INT_RESULT and doesn't have unsigned flag. As it's not a descendant of the Field_num, so using ((Field_num *) field_bit)->unsigned_flag may lead to unpredictable results. Fix: check the field type before casting. mysql-test/r/type_bit.result: Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access - test result. mysql-test/t/type_bit.test: Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access - test case. sql/opt_range.cc: Fix for bug #42803: Field_bit does not have unsigned_flag field, can lead to bad memory access - don't cast to (Field_num *) Field_bit, as it's not a Field_num descendant and is always unsigned by nature. --- mysql-test/r/type_bit.result | 10 ++++++++++ mysql-test/t/type_bit.test | 11 +++++++++++ sql/opt_range.cc | 5 ++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 63dec0297d0..252f8165aec 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -749,4 +749,14 @@ bin(a1) 110000111111111 110001011111111 drop table t1bit7, t2bit7; +# +# Bug42803: Field_bit does not have unsigned_flag field, +# can lead to bad memory access +# +CREATE TABLE t1 (a BIT(7), b BIT(9), KEY(a, b)); +INSERT INTO t1 VALUES(0, 0), (5, 3), (5, 6), (6, 4), (7, 0); +EXPLAIN SELECT a+0, b+0 FROM t1 WHERE a > 4 and b < 7 ORDER BY 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 2 NULL 4 Using where; Using index; Using filesort +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index bdc678688f1..7ec0649cbdd 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -397,4 +397,15 @@ insert into t2bit7 values (b'110011011111111'); select bin(a1) from t1bit7, t2bit7 where t1bit7.a1=t2bit7.b1; drop table t1bit7, t2bit7; + +--echo # +--echo # Bug42803: Field_bit does not have unsigned_flag field, +--echo # can lead to bad memory access +--echo # +CREATE TABLE t1 (a BIT(7), b BIT(9), KEY(a, b)); +INSERT INTO t1 VALUES(0, 0), (5, 3), (5, 6), (6, 4), (7, 0); +EXPLAIN SELECT a+0, b+0 FROM t1 WHERE a > 4 and b < 7 ORDER BY 2; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index fdf6cc03a44..355317fe280 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -4536,6 +4536,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, if (type == Item_func::LT_FUNC && (value->val_int() > 0)) type = Item_func::LE_FUNC; else if (type == Item_func::GT_FUNC && + (field->type() != FIELD_TYPE_BIT) && !((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag && (value->val_int() < 0)) @@ -4572,7 +4573,9 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, */ if (field->result_type() == INT_RESULT && value->result_type() == INT_RESULT && - ((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag) + ((field->type() == FIELD_TYPE_BIT || + ((Field_num *) field)->unsigned_flag) && + !((Item_int*) value)->unsigned_flag)) { longlong item_val= value->val_int(); if (item_val < 0) From 0b1fdf0bd8782757a07efca2c0fc231734e362c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Thu, 8 Oct 2009 14:00:43 +0200 Subject: [PATCH 05/20] BUG#47129 fix small bug in test --- .../suite/binlog/t/binlog_stm_unsafe_warning.test | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test index 656eaae5721..21c11d5a3df 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test @@ -94,22 +94,22 @@ DROP TABLE t1; SET GLOBAL log_warnings = @old_log_warnings; -let $log_error= `SELECT @@GLOBAL.log_error`; -if(!$log_error) +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!`select LENGTH('$log_error_')`) { # MySQL Server on windows is started with --console and thus # does not know the location of its .err log, use default location - let $log_error = $MYSQLTEST_VARDIR/log/mysqld.1.err; + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; } # Assign env variable LOG_ERROR -let LOG_ERROR=$log_error; +let LOG_ERROR=$log_error_; --echo # Count the number of times the "Unsafe" message was printed --echo # to the error log. perl; use strict; - my $log_error= $ENV{'LOG_ERROR'} || die "LOG_ERROR not set"; + my $log_error= $ENV{'LOG_ERROR'} or die "LOG_ERROR not set"; open(FILE, "$log_error") or die("Unable to open $log_error: $!\n"); my $count = () = grep(/Bug#46265/g,); print "Occurrences: $count\n"; From 805136fd2ba0599de4718b465c4c53f30469d857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Thu, 8 Oct 2009 14:54:11 +0200 Subject: [PATCH 06/20] Bug #47797 CMake, engine can't specify additional libraries to link with - Make it possible for the CmakeLists.txt files in an engine to use ${engine}_LIBS to set additional libraries to link with Example: NDBCLUSTER_LIBS = ndbclient --- storage/mysql_storage_engine.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake index bb368494898..af8c3a85cd1 100644 --- a/storage/mysql_storage_engine.cmake +++ b/storage/mysql_storage_engine.cmake @@ -7,6 +7,8 @@ # Remarks: # ${engine}_SOURCES variable containing source files to produce the library must set before # calling this macro +# ${engine}_LIBS variable containing extra libraries to link with may be set + MACRO(MYSQL_STORAGE_ENGINE engine) IF(NOT SOURCE_SUBLIBS) @@ -22,6 +24,9 @@ IF(NOT SOURCE_SUBLIBS) #Create static library. The name of the library is .lib ADD_LIBRARY(${libname} ${${engine}_SOURCES}) ADD_DEPENDENCIES(${libname} GenError) + IF(${engine}_LIBS) + TARGET_LINK_LIBRARIES(${libname} ${${engine}_LIBS}) + ENDIF(${engine}_LIBS) MESSAGE("build ${engine} as static library") ELSEIF(${ENGINE_BUILD_TYPE} STREQUAL "DYNAMIC") ADD_DEFINITIONS(-DMYSQL_DYNAMIC_PLUGIN) @@ -30,6 +35,9 @@ IF(NOT SOURCE_SUBLIBS) SET(dyn_libname ha_${libname}) ADD_LIBRARY(${dyn_libname} SHARED ${${engine}_SOURCES}) TARGET_LINK_LIBRARIES (${dyn_libname} mysqld) + IF(${engine}_LIBS) + TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS}) + ENDIF(${engine}_LIBS) MESSAGE("build ${engine} as DLL") ENDIF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC") ENDIF(NOT SOURCE_SUBLIBS) From 28bdd6e69d4e0b8d98e7725a421165c5d23951e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Thu, 8 Oct 2009 15:19:24 +0200 Subject: [PATCH 07/20] Bug #47795 CMake, storage engine name different from directory name - Read plug.in to fid the name of the engine to link with, does not have to be same as engine dir - Use engine dir when figuring out which libraries to build limbysqld with --- CMakeLists.txt | 9 +++++++-- libmysqld/CMakeLists.txt | 13 +++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c40312e32b..7da3bd05cef 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,12 +217,16 @@ ENDIF(WITHOUT_DYNAMIC_PLUGINS) FILE(GLOB STORAGE_SUBDIRS storage/*) FOREACH(SUBDIR ${STORAGE_SUBDIRS}) FILE(RELATIVE_PATH DIRNAME ${PROJECT_SOURCE_DIR}/storage ${SUBDIR}) - STRING(TOUPPER ${DIRNAME} ENGINE) - STRING(TOLOWER ${DIRNAME} ENGINE_LOWER) IF (EXISTS ${SUBDIR}/CMakeLists.txt) # Check MYSQL_STORAGE_ENGINE macro is present FILE(STRINGS ${SUBDIR}/CMakeLists.txt HAVE_STORAGE_ENGINE REGEX MYSQL_STORAGE_ENGINE) IF(HAVE_STORAGE_ENGINE) + # Extract name of engine from HAVE_STORAGE_ENGINE + STRING(REGEX REPLACE ".*MYSQL_STORAGE_ENGINE\\((.*\)\\).*" + "\\1" ENGINE_NAME ${HAVE_STORAGE_ENGINE}) + STRING(TOUPPER ${ENGINE_NAME} ENGINE) + STRING(TOLOWER ${ENGINE_NAME} ENGINE_LOWER) + SET(ENGINE_BUILD_TYPE "DYNAMIC") # Read plug.in to find out if a plugin is mandatory and whether it supports # build as shared library (dynamic). @@ -248,6 +252,7 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS}) SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${ENGINE_LOWER}) SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE") SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE) + SET (${ENGINE}_DIR ${DIRNAME}) ENDIF (ENGINE_BUILD_TYPE STREQUAL "STATIC") ENDIF(EXISTS ${SUBDIR}/plug.in) diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index bea6f6c0e1f..db398258b69 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -90,10 +90,11 @@ ENDFOREACH(rpath) FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS}) - INCLUDE(${CMAKE_SOURCE_DIR}/storage/${ENGINE_LIB}/CMakeLists.txt) STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER) + SET(ENGINE_DIR ${${ENGINE_LIB_UPPER}_DIR}) + INCLUDE(${CMAKE_SOURCE_DIR}/storage/${ENGINE_DIR}/CMakeLists.txt) FOREACH(rpath ${${ENGINE_LIB_UPPER}_SOURCES}) - SET(LIB_SOURCES ${LIB_SOURCES} ${CMAKE_SOURCE_DIR}/storage/${ENGINE_LIB}/${rpath}) + SET(LIB_SOURCES ${LIB_SOURCES} ${CMAKE_SOURCE_DIR}/storage/${ENGINE_DIR}/${rpath}) ENDFOREACH(rpath) ENDFOREACH(ENGINE_LIB) @@ -155,6 +156,14 @@ ADD_LIBRARY(mysqlserver STATIC ${LIBMYSQLD_SOURCES}) ADD_DEPENDENCIES(mysqlserver GenServerSource GenError) TARGET_LINK_LIBRARIES(mysqlserver) +# Add any additional libraries requested by engine(s) +FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS}) + STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER) + IF(${ENGINE_LIB_UPPER}_LIBS) + TARGET_LINK_LIBRARIES(mysqlserver ${${ENGINE_LIB_UPPER}_LIBS}) + ENDIF(${ENGINE_LIB_UPPER}_LIBS) +ENDFOREACH(ENGINE_LIB) + ADD_LIBRARY(libmysqld SHARED cmake_dummy.c libmysqld.def) ADD_DEPENDENCIES(libmysqld mysqlserver) TARGET_LINK_LIBRARIES(libmysqld mysqlserver wsock32) From ec42ccfdfb8c7f5c8c2ef13183690279566bc3c3 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 8 Oct 2009 16:21:07 +0300 Subject: [PATCH 08/20] Addendum to the fix for bug 43029 --- sql/mysql_priv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6fde16d3049..c04b1f5ae38 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2433,6 +2433,7 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr) table->tablenr= tablenr; table->map= (table_map) 1 << tablenr; table->force_index= table_list->force_index; + table->force_index_order= table->force_index_group= 0; table->covering_keys= table->s->keys_for_keyread; table->merge_keys.clear_all(); } From 0186334ae86380935124c4e71f5887ce6dab59e9 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 8 Oct 2009 15:36:43 +0200 Subject: [PATCH 09/20] Bug#46922: crash when adding partitions and open_files_limit is reached Problem was bad error handling, leaving some new temporary partitions locked and initialized and some not yet initialized and locked, leading to a crash when trying to unlock the not yet initialized and locked partitions Solution was to unlock the already locked partitions, and not include any of the new temporary partitions in later unlocks mysql-test/r/partition_open_files_limit.result: Bug#46922: crash when adding partitions and open_files_limit is reached New test result mysql-test/t/partition_open_files_limit-master.opt: Bug#46922: crash when adding partitions and open_files_limit is reached New test opt-file for testing when open_files_limit is reached mysql-test/t/partition_open_files_limit.test: Bug#46922: crash when adding partitions and open_files_limit is reached New test case testing when open_files_limit is reached sql/ha_partition.cc: Bug#46922: crash when adding partitions and open_files_limit is reached When cleaning up the partitions already locked need to be unlocked, and not be unlocked/closed after cleaning up. --- .../r/partition_open_files_limit.result | 22 +++++++++++++++++++ .../t/partition_open_files_limit-master.opt | 1 + mysql-test/t/partition_open_files_limit.test | 19 ++++++++++++++++ sql/ha_partition.cc | 2 +- 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/partition_open_files_limit.result create mode 100644 mysql-test/t/partition_open_files_limit-master.opt create mode 100644 mysql-test/t/partition_open_files_limit.test diff --git a/mysql-test/r/partition_open_files_limit.result b/mysql-test/r/partition_open_files_limit.result new file mode 100644 index 00000000000..1441ba4e78e --- /dev/null +++ b/mysql-test/r/partition_open_files_limit.result @@ -0,0 +1,22 @@ +DROP TABLE IF EXISTS `t1`; +# Bug#46922: crash when adding partitions and open_files_limit is reached +CREATE TABLE t1 (a INT PRIMARY KEY) +ENGINE=MyISAM PARTITION BY KEY () PARTITIONS 1; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); +# if the bug exists, then crash will happen here +ALTER TABLE t1 ADD PARTITION PARTITIONS 511; +ERROR HY000: Out of resources when opening file '' (Errcode: 24) +SELECT * FROM t1; +a +1 +10 +11 +2 +3 +4 +5 +6 +7 +8 +9 +DROP TABLE t1; diff --git a/mysql-test/t/partition_open_files_limit-master.opt b/mysql-test/t/partition_open_files_limit-master.opt new file mode 100644 index 00000000000..4c1ed0c3da3 --- /dev/null +++ b/mysql-test/t/partition_open_files_limit-master.opt @@ -0,0 +1 @@ +--open-files-limit=5 --max_connections=2 --table_open_cache=1 diff --git a/mysql-test/t/partition_open_files_limit.test b/mysql-test/t/partition_open_files_limit.test new file mode 100644 index 00000000000..92a9b18b573 --- /dev/null +++ b/mysql-test/t/partition_open_files_limit.test @@ -0,0 +1,19 @@ +--source include/have_partition.inc + +--disable_warnings +DROP TABLE IF EXISTS `t1`; +--enable_warnings + +# +--echo # Bug#46922: crash when adding partitions and open_files_limit is reached +# +CREATE TABLE t1 (a INT PRIMARY KEY) +ENGINE=MyISAM PARTITION BY KEY () PARTITIONS 1; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); +--echo # if the bug exists, then crash will happen here +--replace_regex /file '.*'/file ''/ +--error 23 +ALTER TABLE t1 ADD PARTITION PARTITIONS 511; +--sorted_result +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5b053ab9cac..6b5350a82cd 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1280,10 +1280,10 @@ void ha_partition::cleanup_new_partition(uint part_count) m_file= m_added_file; m_added_file= NULL; + external_lock(ha_thd(), F_UNLCK); /* delete_table also needed, a bit more complex */ close(); - m_added_file= m_file; m_file= save_m_file; } DBUG_VOID_RETURN; From 62395e6ffa34316ebe4b5297459f8742361f9143 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 8 Oct 2009 15:58:17 +0200 Subject: [PATCH 10/20] Bug#44059: Incorrect cardinality of indexes on a partitioned table backport for bug#44059 from mysql-pe to mysql-5.1-bugteam Using the partition with most rows instead of first partition to estimate the cardinality of indexes. mysql-test/r/partition.result: Bug#44059: Incorrect cardinality of indexes on a partitioned table Added test result mysql-test/t/partition.test: Bug#44059: Incorrect cardinality of indexes on a partitioned table Added test case sql/ha_partition.cc: Bug#44059: Incorrect cardinality of indexes on a partitioned table Checking which partition that has the most rows, and using that partition for HA_STATUS_CONST instead of first partition --- mysql-test/r/partition.result | 15 +++++++++++++++ mysql-test/t/partition.test | 13 +++++++++++++ sql/ha_partition.cc | 34 +++++++++++++++++++++++++++------- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 2d54a66fe11..6611d39628f 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -50,6 +50,21 @@ t1 CREATE TABLE `t1` ( PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ DROP TABLE t1; +create table t1 (a int, b int, key(a)) +partition by list (a) +( partition p0 values in (1), +partition p1 values in (2)); +insert into t1 values (1,1),(2,1),(2,2),(2,3); +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A 1 NULL NULL YES BTREE +drop table t1; CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a)) ENGINE=MyISAM PARTITION BY HASH (a); diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index c5ed098b678..1dfc53c6232 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -61,6 +61,19 @@ SELECT * FROM t1; SHOW CREATE TABLE t1; DROP TABLE t1; +# +# Bug#44059: rec_per_key on empty partition gives weird optimiser results +# +create table t1 (a int, b int, key(a)) +partition by list (a) +( partition p0 values in (1), + partition p1 values in (2)); +insert into t1 values (1,1),(2,1),(2,2),(2,3); +show indexes from t1; +analyze table t1; +show indexes from t1; +drop table t1; + # # Bug#36001: Partitions: spelling and using some error messages # diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index df5badccb1e..ac55c4e718e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5011,8 +5011,9 @@ int ha_partition::info(uint flag) If the handler doesn't support statistics, it should set all of the above to 0. - We will allow the first handler to set the rec_per_key and use - this as an estimate on the total table. + We first scans through all partitions to get the one holding most rows. + We will then allow the handler with the most rows to set + the rec_per_key and use this as an estimate on the total table. max_data_file_length: Maximum data file length We ignore it, is only used in @@ -5024,14 +5025,33 @@ int ha_partition::info(uint flag) ref_length: We set this to the value calculated and stored in local object create_time: Creation time of table - Set by first handler - So we calculate these constants by using the variables on the first - handler. + So we calculate these constants by using the variables from the + handler with most rows. */ - handler *file; + handler *file, **file_array; + ulonglong max_records= 0; + uint32 i= 0; + uint32 handler_instance= 0; - file= m_file[0]; + file_array= m_file; + do + { + file= *file_array; + /* Get variables if not already done */ + if (!(flag & HA_STATUS_VARIABLE) || + !bitmap_is_set(&(m_part_info->used_partitions), + (file_array - m_file))) + file->info(HA_STATUS_VARIABLE); + if (file->stats.records > max_records) + { + max_records= file->stats.records; + handler_instance= i; + } + i++; + } while (*(++file_array)); + + file= m_file[handler_instance]; file->info(HA_STATUS_CONST); stats.create_time= file->stats.create_time; ref_length= m_ref_length; From fd04391340e9480857e0a31426cdefea21b5a036 Mon Sep 17 00:00:00 2001 From: Frazer Clement Date: Thu, 8 Oct 2009 16:23:15 +0100 Subject: [PATCH 11/20] Fix compile break from bug#39663 fix --- client/mysqltest.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index fb33d30da81..442b2020a56 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -6214,8 +6214,10 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, MYSQL_STMT *stmt; DYNAMIC_STRING ds_prepare_warnings; DYNAMIC_STRING ds_execute_warnings; + ulonglong affected_rows; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); + LINT_INIT(affected_rows); /* Init a new stmt if it's not already one created for this connection @@ -6350,9 +6352,6 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, Need to grab affected rows information before getting warnings here */ - ulonglong affected_rows; - LINT_INIT(affected_rows); - if (!disable_info) affected_rows= mysql_affected_rows(mysql); From 23d31a15d3f81e240990a85a6e4c1dac162d43b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Fri, 9 Oct 2009 09:53:29 +0200 Subject: [PATCH 12/20] BUG#47850: too many files built in regex/ - Don't build split.c or debug.c since they are not part of the actual regex library --- regex/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regex/CMakeLists.txt b/regex/CMakeLists.txt index a3088c00357..2e3b18c7bb0 100755 --- a/regex/CMakeLists.txt +++ b/regex/CMakeLists.txt @@ -18,7 +18,7 @@ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUT INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) -SET(REGEX_SOURCES debug.c regcomp.c regerror.c regexec.c regfree.c reginit.c split.c) +SET(REGEX_SOURCES regcomp.c regerror.c regexec.c regfree.c reginit.c) IF(NOT SOURCE_SUBLIBS) ADD_LIBRARY(regex ${REGEX_SOURCES}) From fa4006bc8ac7c2c773be2acb1303840c372c3e11 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 9 Oct 2009 16:54:48 +0800 Subject: [PATCH 13/20] Bug#47323 : mysqlbinlog --verbose displays bad output when events contain subset of columns Commit the non-NDB specific part (originated by frazer) to 5.1 mainline. --- .../r/binlog_row_mysqlbinlog_verbose.result | 161 ++++++++++++++++++ .../binlog/std_data/update-full-row.binlog | Bin 0 -> 614 bytes .../binlog/std_data/update-partial-row.binlog | Bin 0 -> 606 bytes .../binlog/std_data/write-full-row.binlog | Bin 0 -> 571 bytes .../binlog/std_data/write-partial-row.binlog | Bin 0 -> 596 bytes .../t/binlog_row_mysqlbinlog_verbose.test | 82 +++++++++ sql/log_event.cc | 6 +- 7 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_verbose.result create mode 100644 mysql-test/suite/binlog/std_data/update-full-row.binlog create mode 100644 mysql-test/suite/binlog/std_data/update-partial-row.binlog create mode 100644 mysql-test/suite/binlog/std_data/write-full-row.binlog create mode 100644 mysql-test/suite/binlog/std_data/write-partial-row.binlog create mode 100644 mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test diff --git a/mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_verbose.result b/mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_verbose.result new file mode 100644 index 00000000000..f1a3fafc498 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_verbose.result @@ -0,0 +1,161 @@ +Verbose statements from : write-partial-row.binlog +select txt from raw_binlog_rows where txt like '###%'; +txt +### INSERT INTO mysql.ndb_apply_status +### SET +### @1=1 +### @2=25769803786 +### @3='' +### @4=0 +### @5=0 +### INSERT INTO test.ba +### SET +### @1=3 +### @2=3 +### @3=3 +### INSERT INTO test.ba +### SET +### @1=1 +### @2=1 +### @3=1 +### INSERT INTO test.ba +### SET +### @1=2 +### @2=2 +### @3=2 +### INSERT INTO test.ba +### SET +### @1=4 +### @2=4 +### @3=4 +### INSERT INTO test.ba +### SET +### @1=4 +### @3=40 +### DELETE FROM test.ba +### WHERE +### @1=2 +drop table raw_binlog_rows; +Verbose statements from : write-full-row.binlog +select txt from raw_binlog_rows where txt like '###%'; +txt +### INSERT INTO mysql.ndb_apply_status +### SET +### @1=2 +### @2=25769803786 +### @3='' +### @4=0 +### @5=0 +### INSERT INTO test.ba +### SET +### @1=3 +### @2=3 +### @3=3 +### INSERT INTO test.ba +### SET +### @1=1 +### @2=1 +### @3=1 +### INSERT INTO test.ba +### SET +### @1=2 +### @2=2 +### @3=2 +### INSERT INTO test.ba +### SET +### @1=4 +### @2=4 +### @3=4 +### INSERT INTO test.ba +### SET +### @1=4 +### @2=4 +### @3=40 +### DELETE FROM test.ba +### WHERE +### @1=2 +drop table raw_binlog_rows; +Verbose statements from : update-partial-row.binlog +select txt from raw_binlog_rows where txt like '###%'; +txt +### INSERT INTO mysql.ndb_apply_status +### SET +### @1=3 +### @2=25769803786 +### @3='' +### @4=0 +### @5=0 +### INSERT INTO test.ba +### SET +### @1=3 +### @2=3 +### @3=3 +### INSERT INTO test.ba +### SET +### @1=1 +### @2=1 +### @3=1 +### INSERT INTO test.ba +### SET +### @1=2 +### @2=2 +### @3=2 +### INSERT INTO test.ba +### SET +### @1=4 +### @2=4 +### @3=4 +### UPDATE test.ba +### WHERE +### @1=4 +### @3=4 +### SET +### @1=4 +### @3=40 +### DELETE FROM test.ba +### WHERE +### @1=2 +drop table raw_binlog_rows; +Verbose statements from : update-full-row.binlog +select txt from raw_binlog_rows where txt like '###%'; +txt +### INSERT INTO mysql.ndb_apply_status +### SET +### @1=4 +### @2=25769803786 +### @3='' +### @4=0 +### @5=0 +### INSERT INTO test.ba +### SET +### @1=3 +### @2=3 +### @3=3 +### INSERT INTO test.ba +### SET +### @1=1 +### @2=1 +### @3=1 +### INSERT INTO test.ba +### SET +### @1=2 +### @2=2 +### @3=2 +### INSERT INTO test.ba +### SET +### @1=4 +### @2=4 +### @3=4 +### UPDATE test.ba +### WHERE +### @1=4 +### @2=4 +### @3=4 +### SET +### @1=4 +### @2=4 +### @3=40 +### DELETE FROM test.ba +### WHERE +### @1=2 +drop table raw_binlog_rows; diff --git a/mysql-test/suite/binlog/std_data/update-full-row.binlog b/mysql-test/suite/binlog/std_data/update-full-row.binlog new file mode 100644 index 0000000000000000000000000000000000000000..866a351033e5fd95cd96736f7575cf1278cba11c GIT binary patch literal 614 zcma)4!Ab&A6g|#7^$~=ki_A^XDySLKsH`BYh%nHI+Ka=e6sFdU3%{gg`@W&yh_-#k zw9(FeF$3bJ3uk8Tz2}^JXWq=bhvE43<2t7R^oU0SP}p}X?%ts@^gZXmt-6&X$M1TR zzB3s04P*HtHpSX1Gzw6R0&oXa)?{j}EooaarB1v{kw~J;@q$uLGNbOhP?nvuHd^h6tperor<7dA?V>Gae77?I7%glK^R3 z=eXq@5cQf2Iw4w%>Wyz{tPmMuDH7=|TW>}h?`Y2>o5dKBG-E^-lNgaqh#`h0NovH` zqG2|>KuwY@Qbo5ex=rGTx;*|CNx@FdWRx(>ahx$ZX666KadFdZHtt_&pk%}j(GyFv QwcO1&_8tCO?yf}j7fK*a0{{R3 literal 0 HcmV?d00001 diff --git a/mysql-test/suite/binlog/std_data/update-partial-row.binlog b/mysql-test/suite/binlog/std_data/update-partial-row.binlog new file mode 100644 index 0000000000000000000000000000000000000000..67e3611aa3a5d8dd2bd9b1b0bd6a590b0562cdce GIT binary patch literal 606 zcma))%}T>S6opTdNf`ubX&2UR1XqG4v=#plq$(l`t%$BI4XH(`wI%7IPvX+O&)_?_ za_=j+%R*Yu9hpMu#tUDPnS0K?HNaXkmq}~+JixF+=`QS zGK%53I>#xefVfwr(IIKhyVt%Xu|%?DA!gQVre2NJ&gf24v073|T2hA#ORBiANWqeL zD&%9npy&NqnR(ctMD(koUnk$x=kYf{25x2|Ekt3C;h2jWcm972r&o=}#qE#BBq4l6=OG0Wzei zc=PUK}DQ3598U#ZP6y8C-4G@BprJ-@95MWhJkzH)xBE7 z4g0}l;6|f?R;)hQrgFAUipnGrWukkMRRyI|%I31otF*uyCqW)nj9NsNNjM@&L#ZHw z?DG1i-PQKozYo5&ZhNVgX+KHH4tx>_a&qZ81QqSMxs(=Or^z^?627bF$8j|6C8?iI z5-JE)#4Z;^+`YjIH9_}p_s%yL)_?<6B5!>}>0P&)J&HvpkThgmG-PaQ$Rs9)e6oim zyKk{<7kr|*M8ED932V*;R_HUnz=W^#|7U!4*Xgt$#xRiVbO4$>&|BfRKDf}u|Kc5T G)PDdA3P>dY literal 0 HcmV?d00001 diff --git a/mysql-test/suite/binlog/std_data/write-partial-row.binlog b/mysql-test/suite/binlog/std_data/write-partial-row.binlog new file mode 100644 index 0000000000000000000000000000000000000000..7424ec4e940b5bd3b3d261e5be16f685d883c241 GIT binary patch literal 596 zcmaJ?=e}h+l zf_HEJg&ef?&1xc2@WI>c%)I%?uru#=IC^-#C|E>v1Kxo|l6G}X?=+mD?>T$Au4@O5 z-}fd1Cm0QkV)5WI<^5$+R3ZtKh^|Ri6qHISJ4D##E=}->onVFvZcQSN8{|b4`%*y! z*~!^?tHb$aj&FjmMx@P&Y2$trlkK@A0Lo|5BM3|mRez+p`)M=|sEGgSxnUSgdr|Dh zlZbLc6)@$Th_hF?(IMC|6J^J>tdCN-T=%o71;%7lX{6B|a#M8Zg! z72JUH $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +select txt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; + +--disable_query_log +--let $binlog_file=write-full-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +select txt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; + +--disable_query_log +--let $binlog_file=update-partial-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +select txt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; + +--disable_query_log +--let $binlog_file=update-full-row.binlog +--exec $MYSQL_BINLOG --verbose suite/binlog/std_data/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +create table raw_binlog_rows (txt varchar(1000)); +--eval load data local infile '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql' into table raw_binlog_rows columns terminated by '\n'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_verbose.sql +--enable_query_log +--echo Verbose statements from : $binlog_file +select txt from raw_binlog_rows where txt like '###%'; +drop table raw_binlog_rows; diff --git a/sql/log_event.cc b/sql/log_event.cc index d7921ad3c27..ae7c4335f59 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1852,6 +1852,7 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, { const uchar *value0= value; const uchar *null_bits= value; + uint null_bit_index= 0; char typestr[64]= ""; value+= (m_width + 7) / 8; @@ -1860,7 +1861,8 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, for (size_t i= 0; i < td->size(); i ++) { - int is_null= (null_bits[i / 8] >> (i % 8)) & 0x01; + int is_null= (null_bits[null_bit_index / 8] + >> (null_bit_index % 8)) & 0x01; if (bitmap_is_set(cols_bitmap, i) == 0) continue; @@ -1897,6 +1899,8 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, } my_b_printf(file, "\n"); + + null_bit_index++; } return value - value0; } From 5ef9ec9d9e8457bbc850a1b66f41445a5a4adb44 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Fri, 9 Oct 2009 11:30:40 +0200 Subject: [PATCH 14/20] Bug#42846: wrong result returned for range scan when using covering index When two range predicates were combined under an OR predicate, the algorithm tried to merge overlapping ranges into one. But the case when a range overlapped several other ranges was not handled. This lead to 1) ranges overlapping, which gave repeated results and 2) a range that overlapped several other ranges was cut off. Fixed by 1) Making sure that a range got an upper bound equal to the next range with a greater minimum. 2) Removing a continue statement mysql-test/r/group_min_max.result: Bug#42846: Changed query plans mysql-test/r/range.result: Bug#42846: Test result. mysql-test/t/range.test: Bug#42846: Test case. sql/opt_range.cc: Bug#42846: The fix. Part1: Previously, both endpoints from key2 were copied, which is not safe. Since ranges are processed in ascending order of minimum endpoints, it is safe to copy the minimum endpoint from key2 but not the maximum. The maximum may only be copied if there is no other range or the other range's minimum is greater than key2's maximum. --- mysql-test/r/group_min_max.result | 6 +- mysql-test/r/range.result | 179 ++++++++++++++++++++++++++++++ mysql-test/t/range.test | 125 +++++++++++++++++++++ sql/opt_range.cc | 75 ++++++++++++- 4 files changed, 379 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index ac9a53ca238..620f5dc19ec 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -876,10 +876,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by explain select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by +1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by +1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by @@ -924,7 +924,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by explain select a1,a2,b, max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by +1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index cc5e8d2be96..c98a7696ea6 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1219,3 +1219,182 @@ explain select * from t2 where a=1000 and b<11; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 5 const 502 Using where drop table t1, t2; +CREATE TABLE t1( a INT, b INT, KEY( a, b ) ); +CREATE TABLE t2( a INT, b INT, KEY( a, b ) ); +CREATE TABLE t3( a INT, b INT, KEY( a, b ) ); +INSERT INTO t1( a, b ) +VALUES (0, 1), (1, 2), (1, 4), (2, 3), (5, 0), (9, 7); +INSERT INTO t2( a, b ) +VALUES ( 1, 1), ( 2, 1), ( 3, 1), ( 4, 1), ( 5, 1), +( 6, 1), ( 7, 1), ( 8, 1), ( 9, 1), (10, 1), +(11, 1), (12, 1), (13, 1), (14, 1), (15, 1), +(16, 1), (17, 1), (18, 1), (19, 1), (20, 1); +INSERT INTO t2 SELECT a, 2 FROM t2 WHERE b = 1; +INSERT INTO t2 SELECT a, 3 FROM t2 WHERE b = 1; +INSERT INTO t2 SELECT -1, -1 FROM t2; +INSERT INTO t2 SELECT -1, -1 FROM t2; +INSERT INTO t2 SELECT -1, -1 FROM t2; +INSERT INTO t3 +VALUES (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), +(6, 0), (7, 0), (8, 0), (9, 0), (10, 0); +INSERT INTO t3 SELECT * FROM t3 WHERE a = 10; +INSERT INTO t3 SELECT * FROM t3 WHERE a = 10; +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 < a AND b = 3 OR +3 <= a; +a b +5 0 +9 7 +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 < a AND b = 3 OR +3 <= a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 <= a AND b = 3 OR +3 <= a; +a b +5 0 +9 7 +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 <= a AND b = 3 OR +3 <= a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 4 Using where; Using index +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +5 <= a AND b = 3 OR +3 <= a; +a b +5 0 +9 7 +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +5 <= a AND b = 3 OR +3 <= a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +3 <= a; +a b +5 0 +9 7 +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +3 <= a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 3 Using where; Using index +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 1 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; +a b +1 1 +2 1 +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +15 3 +16 1 +16 3 +17 1 +17 3 +18 1 +18 3 +19 1 +19 3 +20 1 +EXPLAIN +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 1 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range a a 10 NULL 50 Using where; Using index +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 2 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; +a b +1 1 +2 1 +3 1 +4 1 +5 1 +5 2 +6 1 +6 2 +7 1 +7 2 +8 1 +8 2 +9 1 +9 2 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +15 3 +16 1 +16 3 +17 1 +17 3 +18 1 +18 3 +19 1 +19 3 +20 1 +EXPLAIN +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 2 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range a a 10 NULL 50 Using where; Using index +SELECT * FROM t3 WHERE +5 <= a AND a < 10 AND b = 3 OR +a < 5 OR +a < 10; +a b +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +EXPLAIN +SELECT * FROM t3 WHERE +5 <= a AND a < 10 AND b = 3 OR +a < 5 OR +a < 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 range a a 5 NULL 8 Using where; Using index +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index e1411e7fd46..dc119b6a77e 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1046,3 +1046,128 @@ explain select * from t2 where a=1000 and b<11; drop table t1, t2; +# +# Bug#42846: wrong result returned for range scan when using covering index +# +CREATE TABLE t1( a INT, b INT, KEY( a, b ) ); + +CREATE TABLE t2( a INT, b INT, KEY( a, b ) ); + +CREATE TABLE t3( a INT, b INT, KEY( a, b ) ); + +INSERT INTO t1( a, b ) +VALUES (0, 1), (1, 2), (1, 4), (2, 3), (5, 0), (9, 7); + +INSERT INTO t2( a, b ) +VALUES ( 1, 1), ( 2, 1), ( 3, 1), ( 4, 1), ( 5, 1), + ( 6, 1), ( 7, 1), ( 8, 1), ( 9, 1), (10, 1), + (11, 1), (12, 1), (13, 1), (14, 1), (15, 1), + (16, 1), (17, 1), (18, 1), (19, 1), (20, 1); + +INSERT INTO t2 SELECT a, 2 FROM t2 WHERE b = 1; +INSERT INTO t2 SELECT a, 3 FROM t2 WHERE b = 1; + +# To make range scan compelling to the optimizer +INSERT INTO t2 SELECT -1, -1 FROM t2; +INSERT INTO t2 SELECT -1, -1 FROM t2; +INSERT INTO t2 SELECT -1, -1 FROM t2; + +INSERT INTO t3 +VALUES (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), + (6, 0), (7, 0), (8, 0), (9, 0), (10, 0); + +# To make range scan compelling to the optimizer +INSERT INTO t3 SELECT * FROM t3 WHERE a = 10; +INSERT INTO t3 SELECT * FROM t3 WHERE a = 10; + + +# +# Problem#1 Test queries. Will give missing results unless Problem#1 is fixed. +# With one exception, they are independent of Problem#2. +# +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 < a AND b = 3 OR +3 <= a; + +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 < a AND b = 3 OR +3 <= a; + +# Query below: Tests both Problem#1 and Problem#2 (EXPLAIN differs as well) +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 <= a AND b = 3 OR +3 <= a; + +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a < 5 OR +5 <= a AND b = 3 OR +3 <= a; + +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +5 <= a AND b = 3 OR +3 <= a; + +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +5 <= a AND b = 3 OR +3 <= a; + +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +3 <= a; + +EXPLAIN +SELECT * FROM t1 WHERE +3 <= a AND a <= 5 OR +3 <= a; + +# +# Problem#2 Test queries. +# These queries will give missing results if Problem#1 is fixed. +# But Problem#1 also hides this bug. +# +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 1 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; + +EXPLAIN +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 1 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; + +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 2 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; + +EXPLAIN +SELECT * FROM t2 WHERE +5 <= a AND a < 10 AND b = 2 OR +15 <= a AND a < 20 AND b = 3 +OR +1 <= a AND b = 1; + +SELECT * FROM t3 WHERE +5 <= a AND a < 10 AND b = 3 OR +a < 5 OR +a < 10; + +EXPLAIN +SELECT * FROM t3 WHERE +5 <= a AND a < 10 AND b = 3 OR +a < 5 OR +a < 10; + +DROP TABLE t1, t2, t3; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1b1d948b3b9..119f90bc97a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6512,6 +6512,63 @@ get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1) } +/** + Combine two range expression under a common OR. On a logical level, the + transformation is key_or( expr1, expr2 ) => expr1 OR expr2. + + Both expressions are assumed to be in the SEL_ARG format. In a logic sense, + theformat is reminiscent of DNF, since an expression such as the following + + ( 1 < kp1 < 10 AND p1 ) OR ( 10 <= kp2 < 20 AND p2 ) + + where there is a key consisting of keyparts ( kp1, kp2, ..., kpn ) and p1 + and p2 are valid SEL_ARG expressions over keyparts kp2 ... kpn, is a valid + SEL_ARG condition. The disjuncts appear ordered by the minimum endpoint of + the first range and ranges must not overlap. It follows that they are also + ordered by maximum endpoints. Thus + + ( 1 < kp1 <= 2 AND ( kp2 = 2 OR kp2 = 3 ) ) OR kp1 = 3 + + Is a a valid SER_ARG expression for a key of at least 2 keyparts. + + For simplicity, we will assume that expr2 is a single range predicate, + i.e. on the form ( a < x < b AND ... ). It is easy to generalize to a + disjunction of several predicates by subsequently call key_or for each + disjunct. + + The algorithm iterates over each disjunct of expr1, and for each disjunct + where the first keypart's range overlaps with the first keypart's range in + expr2: + + If the predicates are equal for the rest of the keyparts, or if there are + no more, the range in expr2 has its endpoints copied in, and the SEL_ARG + node in expr2 is deallocated. If more ranges became connected in expr1, the + surplus is also dealocated. If they differ, two ranges are created. + + - The range leading up to the overlap. Empty if endpoints are equal. + + - The overlapping sub-range. May be the entire range if they are equal. + + Finally, there may be one more range if expr2's first keypart's range has a + greater maximum endpoint than the last range in expr1. + + For the overlapping sub-range, we recursively call key_or. Thus in order to + compute key_or of + + (1) ( 1 < kp1 < 10 AND 1 < kp2 < 10 ) + + (2) ( 2 < kp1 < 20 AND 4 < kp2 < 20 ) + + We create the ranges 1 < kp <= 2, 2 < kp1 < 10, 10 <= kp1 < 20. For the + first one, we simply hook on the condition for the second keypart from (1) + : 1 < kp2 < 10. For the second range 2 < kp1 < 10, key_or( 1 < kp2 < 10, 4 + < kp2 < 20 ) is called, yielding 1 < kp2 < 20. For the last range, we reuse + the range 4 < kp2 < 20 from (2) for the second keypart. The result is thus + + ( 1 < kp1 <= 2 AND 1 < kp2 < 10 ) OR + ( 2 < kp1 < 10 AND 1 < kp2 < 20 ) OR + ( 10 <= kp1 < 20 AND 4 < kp2 < 20 ) +*/ static SEL_ARG * key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) { @@ -6663,7 +6720,21 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) key1=key1->tree_delete(save); } last->copy_min(tmp); - if (last->copy_min(key2) || last->copy_max(key2)) + bool full_range= last->copy_min(key2); + if (!full_range) + { + if (last->next && key2->cmp_max_to_min(last->next) >= 0) + { + last->max_value= last->next->min_value; + if (last->next->min_flag & NEAR_MIN) + last->max_flag&= ~NEAR_MAX; + else + last->max_flag|= NEAR_MAX; + } + else + full_range= last->copy_max(key2); + } + if (full_range) { // Full range key1->free_tree(); for (; key2 ; key2=key2->next) @@ -6673,8 +6744,6 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) return 0; } } - key2=key2->next; - continue; } if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0) From 38448521702340ebc96f070e594ce409cd5aa1a4 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 9 Oct 2009 16:12:01 +0200 Subject: [PATCH 15/20] Bug#46922 post push update Disable the test when it will not hit the open_files_limit --- mysql-test/t/partition_open_files_limit.test | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mysql-test/t/partition_open_files_limit.test b/mysql-test/t/partition_open_files_limit.test index 92a9b18b573..e62ebd0ade7 100644 --- a/mysql-test/t/partition_open_files_limit.test +++ b/mysql-test/t/partition_open_files_limit.test @@ -4,6 +4,13 @@ DROP TABLE IF EXISTS `t1`; --enable_warnings +# On some platforms the lowest possible open_files_limit is too high... +let $max_open_files_limit= `SELECT @@open_files_limit > 511`; +if ($max_open_files_limit) +{ + skip Need open_files_limit to be lower than 512; +} + # --echo # Bug#46922: crash when adding partitions and open_files_limit is reached # From adbd70aa12b513e3fe15afdc283830a4df52a8c8 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 9 Oct 2009 21:16:29 +0500 Subject: [PATCH 16/20] BUG#47073 - valgrind errs, corruption,failed repair of partition, low myisam_sort_buffer_size Repair by sort (default) or parallel repair of a MyISAM table (doesn't matter partitioned or not) as well as bulk inserts and enable indexes some times didn't failover to repair with key cache. The problem was that after unsuccessful attempt, data file was closed. Whereas repair with key cache requires open data file. Fixed by reopening data file. Also fixed a valgrind warning, which may appear during repair by sort or parallel repair with certain myisam_sort_buffer_size number of rows and length of an index entry (very dependent). mysql-test/r/myisam.result: A test case for BUG#47073. mysql-test/t/myisam.test: A test case for BUG#47073. storage/myisam/ha_myisam.cc: Reverted fix for BUG25289. Not needed anymore. storage/myisam/mi_check.c: Reopen data file, when repair by sort or parallel repair fails. When repair by sort is requested to rebuild data file, data file gets rebuilt while fixing first index. When rebuild is completed, info->dfile is pointing to temporary data file, original data file is closed. It may happen that repair has successfully fixed first index and rebuilt data file, but failed to fix second index. E.g. myisam_sort_buffer_size was big enough to fix first shorter index, but not enough to fix subsequent longer index. In this case we end up with info->dfile pointing to temporary file, which is removed and info->dfile is set to -1. Though repair by sort failed, the upper layer may still want to try repair with key cache. But it needs info->dfile pointing to valid data file. storage/myisam/sort.c: When performing a copy of IO_CACHE structure, current_pos and current_end must be updated separatly to point to memory we're copying to (not to memory we're copying from). As t_file2 is always WRITE cache, proper members are write_pos and write_end accordingly. --- mysql-test/r/myisam.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/myisam.test | 28 ++++++++++++++++++++++++++++ storage/myisam/ha_myisam.cc | 16 ---------------- storage/myisam/mi_check.c | 10 ++++++---- storage/myisam/sort.c | 4 ++++ 5 files changed, 66 insertions(+), 20 deletions(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 58e2e451a0d..df97e96c334 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2271,4 +2271,32 @@ checksum table t3; Table Checksum test.t3 326284887 drop table t1,t2,t3; +CREATE TABLE t1(a INT, b CHAR(10), KEY(a), KEY(b)); +INSERT INTO t1 VALUES(1,'0'),(2,'0'),(3,'0'),(4,'0'),(5,'0'), +(6,'0'),(7,'0'); +INSERT INTO t1 SELECT a+10,b FROM t1; +INSERT INTO t1 SELECT a+20,b FROM t1; +INSERT INTO t1 SELECT a+40,b FROM t1; +INSERT INTO t1 SELECT a+80,b FROM t1; +INSERT INTO t1 SELECT a+160,b FROM t1; +INSERT INTO t1 SELECT a+320,b FROM t1; +INSERT INTO t1 SELECT a+640,b FROM t1; +INSERT INTO t1 SELECT a+1280,b FROM t1; +INSERT INTO t1 SELECT a+2560,b FROM t1; +INSERT INTO t1 SELECT a+5120,b FROM t1; +SET myisam_sort_buffer_size=4; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair error myisam_sort_buffer_size is too small +test.t1 repair warning Number of rows changed from 0 to 7168 +test.t1 repair status OK +SET myisam_repair_threads=2; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair error myisam_sort_buffer_size is too small +test.t1 repair warning Number of rows changed from # to 7168 +test.t1 repair status OK +SET myisam_repair_threads=@@global.myisam_repair_threads; +SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 5de7c997a24..faeb5ee686a 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1518,5 +1518,33 @@ CREATE TABLE t3 select * from t1; checksum table t3; drop table t1,t2,t3; + +# +# BUG#47073 - valgrind errs, corruption,failed repair of partition, +# low myisam_sort_buffer_size +# +CREATE TABLE t1(a INT, b CHAR(10), KEY(a), KEY(b)); +INSERT INTO t1 VALUES(1,'0'),(2,'0'),(3,'0'),(4,'0'),(5,'0'), + (6,'0'),(7,'0'); +INSERT INTO t1 SELECT a+10,b FROM t1; +INSERT INTO t1 SELECT a+20,b FROM t1; +INSERT INTO t1 SELECT a+40,b FROM t1; +INSERT INTO t1 SELECT a+80,b FROM t1; +INSERT INTO t1 SELECT a+160,b FROM t1; +INSERT INTO t1 SELECT a+320,b FROM t1; +INSERT INTO t1 SELECT a+640,b FROM t1; +INSERT INTO t1 SELECT a+1280,b FROM t1; +INSERT INTO t1 SELECT a+2560,b FROM t1; +INSERT INTO t1 SELECT a+5120,b FROM t1; +SET myisam_sort_buffer_size=4; +REPAIR TABLE t1; +SET myisam_repair_threads=2; +# May report different values depending on threads activity. +--replace_regex /changed from [0-9]+/changed from #/ +REPAIR TABLE t1; +SET myisam_repair_threads=@@global.myisam_repair_threads; +SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 5198e685817..aa9a2eeb77a 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1087,22 +1087,6 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) ha_rows rows= file->state->records; DBUG_ENTER("ha_myisam::repair"); - /* - Normally this method is entered with a properly opened table. If the - repair fails, it can be repeated with more elaborate options. Under - special circumstances it can happen that a repair fails so that it - closed the data file and cannot re-open it. In this case file->dfile - is set to -1. We must not try another repair without an open data - file. (Bug #25289) - */ - if (file->dfile == -1) - { - sql_print_information("Retrying repair of: '%s' failed. " - "Please try REPAIR EXTENDED or myisamchk", - table->s->path.str); - DBUG_RETURN(HA_ADMIN_FAILED); - } - param.db_name= table->s->db.str; param.table_name= table->alias; param.tmpfile_createflag = O_RDWR | O_TRUNC; diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 1c33ffa90f5..8f7b1399aa2 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2561,8 +2561,9 @@ err: VOID(my_close(new_file,MYF(0))); VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, MYF(MY_WME))); - if (info->dfile == new_file) - info->dfile= -1; + if (info->dfile == new_file) /* Retry with key cache */ + if (unlikely(mi_open_datafile(info, share, name, -1))) + param->retry_repair= 0; /* Safety */ } mi_mark_crashed_on_repair(info); } @@ -3095,8 +3096,9 @@ err: VOID(my_close(new_file,MYF(0))); VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, MYF(MY_WME))); - if (info->dfile == new_file) - info->dfile= -1; + if (info->dfile == new_file) /* Retry with key cache */ + if (unlikely(mi_open_datafile(info, share, name, -1))) + param->retry_repair= 0; /* Safety */ } mi_mark_crashed_on_repair(info); } diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index f31edbe1249..fb16af9cddf 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -788,7 +788,11 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, cleanup: close_cached_file(to_file); /* This holds old result */ if (to_file == t_file) + { *t_file=t_file2; /* Copy result file */ + t_file->current_pos= &t_file->write_pos; + t_file->current_end= &t_file->write_end; + } DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */ } /* merge_many_buff */ From 64e89a7ed276d04c699f97186ea8f689a45c6922 Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Mon, 12 Oct 2009 13:13:15 +0530 Subject: [PATCH 17/20] Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 In MySQL when the mapping for space is changed to something other than 0x20 by defining a different collation, then space is not ignored when comparing two strings. This was happening because the function that performs the comparison of two strings while ignoring ending spaces, was comparing the collation value of a space with the ascii value of the ' ' character. This should be changed to do comparison between the collated values. mysql-test/r/ctype_ldml.result: Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 Result file for test case. mysql-test/std_data/Index.xml: Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 Added entry for new test collation in the index file. mysql-test/std_data/latin1.xml: Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 Added support for new collation for test. mysql-test/t/ctype_ldml.test: Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 Added test case to ensure trailing spaces are not ignored. strings/ctype-simple.c: Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 change my_strnncollsp_simple to compare collated values when checking for trailing spaces. Currently the comparison happens between a collated value and the ascii value. --- mysql-test/r/ctype_ldml.result | 8 ++ mysql-test/std_data/Index.xml | 13 ++++ mysql-test/std_data/latin1.xml | 135 +++++++++++++++++++++++++++++++++ mysql-test/t/ctype_ldml.test | 5 ++ strings/ctype-simple.c | 4 +- 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 mysql-test/std_data/latin1.xml diff --git a/mysql-test/r/ctype_ldml.result b/mysql-test/r/ctype_ldml.result index 711921eb526..fe870f82743 100644 --- a/mysql-test/r/ctype_ldml.result +++ b/mysql-test/r/ctype_ldml.result @@ -321,3 +321,11 @@ Vv Xx YyÝýỲỳỴỵỶỷỸỹ drop table t1; +Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 +set names latin1; +show collation like 'latin1_test'; +Collation Charset Id Default Compiled Sortlen +latin1_test latin1 99 Yes 1 +select "foo" = "foo " collate latin1_test; +"foo" = "foo " collate latin1_test +1 diff --git a/mysql-test/std_data/Index.xml b/mysql-test/std_data/Index.xml index 988dddcc68a..3dc647d8195 100644 --- a/mysql-test/std_data/Index.xml +++ b/mysql-test/std_data/Index.xml @@ -68,4 +68,17 @@ + + Western + cp1252 West European + csisolatin1 + iso-8859-1 + iso-ir-100 + iso_8859-1 + iso_8859-1:1987 + l1 + latin1 + + + diff --git a/mysql-test/std_data/latin1.xml b/mysql-test/std_data/latin1.xml new file mode 100644 index 00000000000..42b4342c1ae --- /dev/null +++ b/mysql-test/std_data/latin1.xml @@ -0,0 +1,135 @@ + + + + + + Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + + + + + 00 + 20 20 20 20 20 20 20 20 20 28 28 28 28 28 20 20 + 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 + 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 + 84 84 84 84 84 84 84 84 84 84 10 10 10 10 10 10 + 10 81 81 81 81 81 81 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 10 10 10 10 10 + 10 82 82 82 82 82 82 02 02 02 02 02 02 02 02 02 + 02 02 02 02 02 02 02 02 02 02 02 10 10 10 10 20 + 10 00 10 02 10 10 10 10 10 10 01 10 01 00 01 00 + 00 10 10 10 10 10 10 10 10 10 02 10 02 00 02 01 + 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 + 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 10 01 01 01 01 01 01 01 02 + 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 + 02 02 02 02 02 02 02 10 02 02 02 02 02 02 02 02 + + + + + + + 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F + 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F + 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F + 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F + 40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F + 70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F + 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F + 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F + 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F + 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F + A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF + B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF + E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF + F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF + E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF + F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF + + + + + + + 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F + 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F + 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F + 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F + 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F + 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F + 60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F + 50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F + 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F + 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F + A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF + B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF + C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF + D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF + C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF + D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF + + + + + + + 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F + 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 001A 001B 001C 001D 001E 001F + 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 002A 002B 002C 002D 002E 002F + 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 003A 003B 003C 003D 003E 003F + 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F + 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F + 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F + 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F + 20AC 0081 201A 0192 201E 2026 2020 2021 02C6 2030 0160 2039 0152 008D 017D 008F + 0090 2018 2019 201C 201D 2022 2013 2014 02DC 2122 0161 203A 0153 009D 017E 0178 + 00A0 00A1 00A2 00A3 00A4 00A5 00A6 00A7 00A8 00A9 00AA 00AB 00AC 00AD 00AE 00AF + 00B0 00B1 00B2 00B3 00B4 00B5 00B6 00B7 00B8 00B9 00BA 00BB 00BC 00BD 00BE 00BF + 00C0 00C1 00C2 00C3 00C4 00C5 00C6 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF + 00D0 00D1 00D2 00D3 00D4 00D5 00D6 00D7 00D8 00D9 00DA 00DB 00DC 00DD 00DE 00DF + 00E0 00E1 00E2 00E3 00E4 00E5 00E6 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF + 00F0 00F1 00F2 00F3 00F4 00F5 00F6 00F7 00F8 00F9 00FA 00FB 00FC 00FD 00FE 00FF + + + + + + 00 01 02 03 37 2D 2E 2F 16 05 25 0B 0C 0D 0E 0F + 10 11 12 13 3C 3D 32 26 18 19 3F 27 1C 1D 1E 1F + 40 4F 7F 7B 5B 6C 50 7D 4D 5D 5C 4E 6B 60 4B 61 + F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 7A 5E 4C 7E 6E 6F + 7C C1 C2 C3 C4 C5 C6 C7 C8 C9 D1 D2 D3 D4 D5 D6 + D7 D8 D9 E2 E3 E4 E5 E6 E7 E8 E9 4A E0 5A 5F 6D + 79 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 + 97 98 99 A2 A3 A4 A5 A6 A7 A8 A9 C0 6A D0 A1 07 + 20 21 22 23 24 15 06 17 28 29 2A 2B 2C 09 0A 1B + 30 31 1A 33 34 35 36 08 38 39 3A 3B 04 14 3E E1 + 41 42 43 44 45 46 47 48 49 51 52 53 54 55 56 57 + 58 59 62 63 64 65 66 67 68 69 70 71 72 73 74 75 + 76 77 78 80 8A 8B 8C 8D 8E 8F 90 9A 9B 9C 9D 9E + 9F A0 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 + B8 B9 BA BB BC BD BE BF CA CB CC CD CE CF DA DB + DC DD DE DF EA EB EC ED EE EF FA FB FC FD FE FF + + + + + + diff --git a/mysql-test/t/ctype_ldml.test b/mysql-test/t/ctype_ldml.test index db9461bfbf7..bc04b93a935 100644 --- a/mysql-test/t/ctype_ldml.test +++ b/mysql-test/t/ctype_ldml.test @@ -86,3 +86,8 @@ select hex(c1) as h, c1 from t1 order by c1, h; select group_concat(hex(c1) order by hex(c1)) from t1 group by c1; select group_concat(c1 order by hex(c1) SEPARATOR '') from t1 group by c1; drop table t1; + +--echo Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 +set names latin1; +show collation like 'latin1_test'; +select "foo" = "foo " collate latin1_test; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 7de00025eda..4f3aaa6f668 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -185,8 +185,8 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, size_t a_length, } for (end= a + a_length-length; a < end ; a++) { - if (map[*a] != ' ') - return (map[*a] < ' ') ? -swap : swap; + if (map[*a] != map[' ']) + return (map[*a] < map[' ']) ? -swap : swap; } } return res; From 409773e8070eed68ba3767cd9b6fe391a5017dfb Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Mon, 12 Oct 2009 15:05:40 +0530 Subject: [PATCH 18/20] Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 Fixing copyright header in test collation file. mysql-test/std_data/latin1.xml: Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 Fixing copy right header in test collation file. --- mysql-test/std_data/latin1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/std_data/latin1.xml b/mysql-test/std_data/latin1.xml index 42b4342c1ae..a2dab731656 100644 --- a/mysql-test/std_data/latin1.xml +++ b/mysql-test/std_data/latin1.xml @@ -3,7 +3,7 @@ - Copyright (C) 2003 MySQL AB + Copyright (C) 2008 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From c2c12c240269eafc21c6d3fc6a9f0a41c4eaed20 Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Mon, 12 Oct 2009 15:25:59 +0530 Subject: [PATCH 19/20] Bug#46448 trailing spaces are not ignored when user collation maps space != 0x20 changing year in copyright header to 2009. --- mysql-test/std_data/latin1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/std_data/latin1.xml b/mysql-test/std_data/latin1.xml index a2dab731656..458b1c34da1 100644 --- a/mysql-test/std_data/latin1.xml +++ b/mysql-test/std_data/latin1.xml @@ -3,7 +3,7 @@ - Copyright (C) 2008 Sun Microsystems, Inc + Copyright (C) 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 1994d2c11e0d1c57ffedfe026e080d6b4c16d322 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2009 10:26:15 +0800 Subject: [PATCH 20/20] Bug#45578: Test binlog_tmp_table fails ramdonly on PB2: Unknown table 't2' The bug has been closed. --- mysql-test/collections/default.experimental | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 50c5a71e252..214b732e5cb 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -1,6 +1,5 @@ funcs_1.charset_collation_1 # depends on compile-time decisions main.plugin_load @solaris # Bug#42144 -binlog.binlog_tmp_table* # Bug#45578: Test binlog_tmp_table fails ramdonly on PB2: Unknown table 't2' main.ctype_gbk_binlog @solaris # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists rpl.rpl_row_create_table* # Bug#45576: rpl_row_create_table fails on PB2 rpl_ndb.rpl_ndb_log # Bug#38998