diff --git a/cmake/os/FreeBSD.cmake b/cmake/os/FreeBSD.cmake index be7af778e93..e09592942c1 100644 --- a/cmake/os/FreeBSD.cmake +++ b/cmake/os/FreeBSD.cmake @@ -20,4 +20,5 @@ # #Legacy option, maybe not needed anymore , taken as is from autotools build # ADD_DEFINITIONS(-DNET_RETRY_COUNT=1000000) -ADD_DEFINITIONS(-DHAVE_BROKEN_REALPATH) +# The below was used for really old versions of FreeBSD, roughly: before 5.1.9 +# ADD_DEFINITIONS(-DHAVE_BROKEN_REALPATH) diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index 3be739d3122..aac7e484f26 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -110,6 +110,10 @@ IF(MSVC) ADD_DEFINITIONS(/wd4996) ENDIF() + # Make class/struct definition mismatch an error (overseen too often, + # adds tons of new warnings) + ADD_DEFINITIONS(/we4099) + IF(CMAKE_SIZEOF_VOID_P MATCHES 8) # _WIN64 is defined by the compiler itself. # Yet, we define it here again to work around a bug with Intellisense diff --git a/configure.in b/configure.in index 78138ac284e..3467d2d852d 100644 --- a/configure.in +++ b/configure.in @@ -1301,9 +1301,7 @@ case $SYSTEM_TYPE in if test "$OSVERSION" -gt "600000" then # Post user-level threads, MYSQLD_NET_RETRY_COUNT is not needed any more - AC_MSG_WARN([Adding fix for broken realpath]) - CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH" - CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_REALPATH" + : elif test "$OSVERSION" -gt "480100" && \ test "$OSVERSION" -lt "500000" || \ test "$OSVERSION" -gt "500109" diff --git a/mysql-test/collections/default.daily b/mysql-test/collections/default.daily index a95e5f4657d..d23ae8a6d51 100644 --- a/mysql-test/collections/default.daily +++ b/mysql-test/collections/default.daily @@ -3,3 +3,4 @@ perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collection perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --vardir=var-emebbed --embedded perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_ndb_row --vardir=var-rpl_ndb_row --mysqld=--binlog-format=row --suite=rpl_ndb,ndb +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog --skip-ndb diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index e58953c9e73..47167f0bf96 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -24,9 +24,10 @@ main.sp @solaris # Bug#47791 2010-01-20 alik Several tes main.type_float @freebsd # Bug#38965 2010-05-04 alik test cases gis-rtree, type_float, type_newdecimal fail in embedded server main.wait_timeout @solaris # Bug#51244 2010-04-26 alik wait_timeout fails on OpenSolaris +parts.partition_alter4_innodb # Bug#45299 2010-06-28 alik Test "partition_alter4_innodb" is taking too long, timeout perfschema.pfs_upgrade # Bug#53102 2010-06-15 alik perfschema.pfs_upgrade fails on sol10 sparc64 max in parallel mode -rpl.rpl_heartbeat_basic # BUG#43828 2009-10-22 luis fails sporadically +rpl.rpl_heartbeat_basic # BUG#54820 2010-06-26 alik rpl.rpl_heartbeat_basic fails sporadically again rpl.rpl_heartbeat_2slaves # BUG#43828 2009-10-22 luis fails sporadically rpl.rpl_innodb_bug28430* # Bug#46029 rpl.rpl_innodb_bug30888* @solaris # Bug#47646 2009-09-25 alik rpl.rpl_innodb_bug30888 fails sporadically on Solaris @@ -35,6 +36,7 @@ rpl.rpl_plugin_load* @solaris # Bug#47146 rpl.rpl_row_sp011* @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun +sys_vars.slow_query_log_func @solaris # Bug#54819 2010-06-26 alik sys_vars.slow_query_log_func fails sporadically on Solaris 10 sys_vars.wait_timeout_func # Bug#41255 2010-04-26 alik wait_timeout_func fails # Declare all NDB-tests in ndb and rpl_ndb test suites experimental. diff --git a/mysql-test/collections/default.push b/mysql-test/collections/default.push index 77dc9a586db..a213706498e 100644 --- a/mysql-test/collections/default.push +++ b/mysql-test/collections/default.push @@ -1,5 +1,5 @@ -perl mysql-test-run.pl --timer --force --parallel=auto --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --experimental=collections/default.experimental --skip-ndb -perl mysql-test-run.pl --timer --force --parallel=auto --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --experimental=collections/default.experimental --skip-ndb +perl mysql-test-run.pl --timer --force --parallel=auto --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --experimental=collections/default.experimental --skip-ndb --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --experimental=collections/default.experimental --skip-ndb --skip-test-list=collections/disabled-per-push.list perl mysql-test-run.pl --timer --force --parallel=auto --comment=embedded --vardir=var-emebbed --embedded --experimental=collections/default.experimental --skip-ndb -perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --suite=rpl,binlog --mysqld=--binlog-format=row --experimental=collections/default.experimental --skip-ndb +perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --suite=rpl,binlog --mysqld=--binlog-format=row --experimental=collections/default.experimental --skip-ndb --skip-test-list=collections/disabled-per-push.list perl mysql-test-run.pl --timer --force --parallel=auto --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 --experimental=collections/default.experimental --skip-ndb diff --git a/mysql-test/collections/disabled-per-push.list b/mysql-test/collections/disabled-per-push.list new file mode 100644 index 00000000000..32177fcb98d --- /dev/null +++ b/mysql-test/collections/disabled-per-push.list @@ -0,0 +1,186 @@ +rpl.rpl000010 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl000011 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl000013 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_000015 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_alter_db : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_auto_increment_11932 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_auto_increment_update_failure : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_begin_commit_rollback : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_binlog_grant : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_binlog_query_filter_rules : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_bit : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_bit_npk : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_blackhole : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_bug31076 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_bug33931 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_bug38694 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_bug41902 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_charset : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_concurrency_error : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_create_if_not_exists : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_create_tmp_table_if_not_exists : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_cross_version : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_do_grant : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_drop_if_exists : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_EE_err : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_empty_master_host : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_extraColmaster_myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_extraCol_myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_filter_tables_not_exist : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_flushlog_loop : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_flush_logs : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_foreign_key_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_free_items : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_get_lock : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_grant : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_heartbeat : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_idempotency : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ignore_revoke : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ignore_table_update : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_incident : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_init_slave_errors : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_init_slave : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_innodb_bug30888 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_innodb_mixed_ddl : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_insert_id_pk : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_insert_ignore : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_insert_select : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ip_mix2 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ip_mix : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ipv4_as_ipv6 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ipv6 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_known_bugs_detection : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata_charset : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata_fatal : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddatalocal : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata_map : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata_simple : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata_s : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_loaddata_symlink : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_log_pos : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_master_pos_wait : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_misc_functions : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mixed_binlog_max_cache_size : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mixed_bit_pk : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mixed_ddl_dml : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mixed_implicit_commit_binlog : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mixed_mixing_engines : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mixed_row_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mix_found_rows : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_delete2 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_delete : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_engine : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_update2 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_update3 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_update4 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_multi_update : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_mysql_upgrade : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_name_const : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_nondeterministic_functions : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_non_direct_mixed_mixing_engines : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_non_direct_row_mixing_engines : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_non_direct_stm_mixing_engines : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_not_null_myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_optimize : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_ps : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_relayrotate : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_relay_space_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_relayspace : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_relay_space_myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_replicate_ignore_db : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_rewrt_db : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_4_bytes : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_basic_2myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_basic_3innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_basic_8partition : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_colSize : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_disabled_slave_key : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_drop : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_flsh_tbls : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_func001 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_func002 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_func003 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_idempotency : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_implicit_commit_binlog : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_inexist_tbl : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_loaddata_concurrent : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_max_relay_size : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_mixing_engines : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_reset_slave : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_show_relaylog_events : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp001 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp002_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp005 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp006_InnoDB : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp007_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp008 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp009 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_sp012 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_tabledefs_2myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_tabledefs_3innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_trig001 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_trig002 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_trig003 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_trig004 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_trunc_temp : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_unsafe_funcs : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_until : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_USER : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_utf16 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_utf32 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_view01 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_row_wide_table : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_server_id1 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_server_id2 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_server_id_ignore : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_server_id : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_set_charset : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_set_null_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_set_null_myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_sf : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_skip_error : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_slave_grp_exec : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_slave_load_in : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_slave_load_tmpdir_not_exist : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_slave_status : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_slow_query_log : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_sp004 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_sporadic_master : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_000001 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_auto_increment_bug33029 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_binlog_max_cache_size : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_conflicts : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_EE_err2 : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_flsh_tbls : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_found_rows : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_insert_delayed : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_loaddata_concurrent : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_loadfile : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_log : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_max_relay_size : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_mixing_engines : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_mix_show_relaylog_events : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_multi_query : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_no_op : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_reset_slave : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_sql_mode : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_start_stop_slave : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_stop_middle_group : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_until : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_stm_user_variables : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_temporary_errors : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_temporary : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_temp_table : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_temp_table_mix_row : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_temp_temporary : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_truncate_2myisam : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_truncate_3innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_trunc_temp : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_typeconv_innodb : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_typeconv : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_user : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_user_variables : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_variables : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. +rpl.rpl_variables_stm : lsoares 2010-05-26 WL#5408 Reduce Pushbuild2 turnaround times for rpl suite. diff --git a/mysql-test/collections/mysql-next-mr.push b/mysql-test/collections/mysql-next-mr.push index b84f43eea7c..b87cc4b801f 100644 --- a/mysql-test/collections/mysql-next-mr.push +++ b/mysql-test/collections/mysql-next-mr.push @@ -1,5 +1,5 @@ -perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema -perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema --skip-test-list=collections/disabled-per-push.list perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --vardir=var-emebbed --embedded --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema -perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog --skip-test-list=collections/disabled-per-push.list perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 diff --git a/mysql-test/collections/mysql-trunk.push b/mysql-test/collections/mysql-trunk.push index b84f43eea7c..b87cc4b801f 100644 --- a/mysql-test/collections/mysql-trunk.push +++ b/mysql-test/collections/mysql-trunk.push @@ -1,5 +1,5 @@ -perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema -perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema --skip-test-list=collections/disabled-per-push.list perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --vardir=var-emebbed --embedded --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema -perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog --skip-test-list=collections/disabled-per-push.list perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 29626e38396..f7a23ab34e7 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -104,10 +104,11 @@ sub init_pattern { # ############################################################################## -sub collect_test_cases ($$$) { +sub collect_test_cases ($$$$) { my $opt_reorder= shift; # True if we're reordering tests my $suites= shift; # Semicolon separated list of test suites my $opt_cases= shift; + my $opt_skip_test_list= shift; my $cases= []; # Array of hash(one hash for each testcase) $do_test_reg= init_pattern($do_test, "--do-test"); @@ -131,7 +132,7 @@ sub collect_test_cases ($$$) { { foreach my $suite (split(",", $suites)) { - push(@$cases, collect_one_suite($suite, $opt_cases)); + push(@$cases, collect_one_suite($suite, $opt_cases, $opt_skip_test_list)); last if $some_test_found; } } @@ -256,6 +257,7 @@ sub collect_one_suite($) { my $suite= shift; # Test suite name my $opt_cases= shift; + my $opt_skip_test_list= shift; my @cases; # Array of hash mtr_verbose("Collecting: $suite"); @@ -317,18 +319,23 @@ sub collect_one_suite($) # Build a hash of disabled testcases for this suite # ---------------------------------------------------------------------- my %disabled; - if ( open(DISABLED, "$testdir/disabled.def" ) ) - { - while ( ) + my @disabled_collection= @{$opt_skip_test_list} if defined @{$opt_skip_test_list}; + unshift (@disabled_collection, "$testdir/disabled.def"); + for my $skip (@disabled_collection) + { + if ( open(DISABLED, $skip ) ) { - chomp; - if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ ) + while ( ) { - $disabled{$1}= $2; + chomp; + if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ ) + { + $disabled{$1}= $2 if not exists $disabled{$1}; + } } + close DISABLED; } - close DISABLED; - } + } # Read suite.opt file my $suite_opt_file= "$testdir/suite.opt"; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index acb5fa3ed0f..c5cc3c5c295 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -165,6 +165,7 @@ our @opt_extra_mysqld_opt; my $opt_compress; my $opt_ssl; my $opt_skip_ssl; +my @opt_skip_test_list; our $opt_ssl_supported; my $opt_ps_protocol; my $opt_sp_protocol; @@ -326,7 +327,7 @@ sub main { } mtr_report("Collecting tests..."); - my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases); + my $tests= collect_test_cases($opt_reorder, $opt_suites, \@opt_cases, \@opt_skip_test_list); if ( $opt_report_features ) { # Put "report features" as the first test to run @@ -948,6 +949,7 @@ sub command_line_setup { 'help|h' => \$opt_usage, 'list-options' => \$opt_list_options, + 'skip-test-list=s' => \@opt_skip_test_list ); GetOptions(%options) or usage("Can't read options"); @@ -5440,6 +5442,9 @@ Options to control what test suites or cases to run enable-disabled Run also tests marked as disabled print-testcases Don't run the tests but print details about all the selected tests, in the order they would be run. + skip-test-list=FILE Skip the tests listed in FILE. Each line in the file + is an entry and should be formatted as: + : Options that specify ports diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 714a14c1f4f..4c54f12b34f 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -333,7 +333,7 @@ rows_examined sql_text 2 INSERT INTO t1 SELECT b+sleep(.01) from t2 4 UPDATE t1 SET a=a+sleep(.01) WHERE a>2 8 UPDATE t1 SET a=a+sleep(.01) ORDER BY a DESC -2 UPDATE t2 set b=b+sleep(.01) limit 1 +1 UPDATE t2 set b=b+sleep(.01) limit 1 4 UPDATE t1 SET a=a+sleep(.01) WHERE a in (SELECT b from t2) 6 DELETE FROM t1 WHERE a=a+sleep(.01) ORDER BY a LIMIT 2 DROP TABLE t1,t2; diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result index b621a466a29..26a151b55aa 100644 --- a/mysql-test/r/lowercase_table2.result +++ b/mysql-test/r/lowercase_table2.result @@ -2,7 +2,7 @@ DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; DROP DATABASE IF EXISTS mysqltest_LC2; -CREATE TABLE T1 (a int); +CREATE TABLE T1 (a int) ENGINE=MyISAM; INSERT INTO T1 VALUES (1); SHOW TABLES LIKE "T1"; Tables_in_test (T1) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 63b957e7a3f..43f456a6d95 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -1191,6 +1191,9 @@ SHOW CREATE TABLE t4; ERROR HY000: Table 't4' was not locked with LOCK TABLES INSERT INTO t4 VALUES (4); ERROR HY000: Table 't4' was not locked with LOCK TABLES +# Temporary tables can be created in spite of LOCK TABLES. +# If the temporary MERGE table uses the locked children only, +# it can even be used. CREATE TEMPORARY TABLE t4 LIKE t3; SHOW CREATE TABLE t4; ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist @@ -1672,6 +1675,7 @@ c1 33 DELETE FROM t4 WHERE c1 = 33; DROP TRIGGER t3_ai; +UNLOCK TABLES; # # Trigger with table use on child DELETE FROM t4 WHERE c1 = 4; @@ -1854,9 +1858,9 @@ ALTER TABLE t2 UNION=(t3,t1); SELECT * FROM t2; ERROR HY000: Table 't3' is differently defined or of non-MyISAM type or doesn't exist DROP TABLE t1, t2, t3; -CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; -CREATE TABLE t2 (c1 INT) ENGINE= MyISAM; -CREATE TABLE t3 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1, t2); +CREATE TABLE t1 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t2 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2); INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (2); SELECT * FROM t3; @@ -2635,6 +2639,17 @@ DROP TRIGGER t2_au; DROP FUNCTION f1; DROP TABLE tm1, t1, t2, t3, t4, t5; # +# Bug#47633 - assert in ha_myisammrg::info during OPTIMIZE +# +CREATE TEMPORARY TABLE t1 (c1 INT); +ALTER TABLE t1 ENGINE=MERGE UNION(t_not_exists,t1); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize Error Table 'test.t_not_exists' doesn't exist +test.t1 optimize Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +test.t1 optimize note The storage engine for the table doesn't support optimize +DROP TABLE t1; +# # Bug47098 assert in MDL_context::destroy on HANDLER # OPEN # @@ -2700,6 +2715,18 @@ ALTER TABLE m1 ADD INDEX (c1); UNLOCK TABLES; DROP TABLE m1, t1; # +# If children are to be altered, they need an explicit lock. +# +CREATE TABLE t1 (c1 INT); +CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1); +LOCK TABLE m1 WRITE; +ALTER TABLE t1 ADD INDEX (c1); +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +LOCK TABLE m1 WRITE, t1 WRITE; +ALTER TABLE t1 ADD INDEX (c1); +UNLOCK TABLES; +DROP TABLE m1, t1; +# # Test for bug #37371 "CREATE TABLE LIKE merge loses UNION parameter" # drop tables if exists t1, m1, m2; diff --git a/mysql-test/r/single_delete_update.result b/mysql-test/r/single_delete_update.result new file mode 100644 index 00000000000..921d308097c --- /dev/null +++ b/mysql-test/r/single_delete_update.result @@ -0,0 +1,1074 @@ +# +# Bug #30584: delete with order by and limit clauses does not use +# limit efficiently +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25); +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +a i +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; +a i +NULL 16 +NULL 17 +NULL 18 +DROP TABLE t2; +# +# index on field prefix: +# +CREATE TABLE t2(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t2 (i) SELECT i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +a i +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 5 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 8 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 5 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; +a i +NULL 16 +NULL 17 +NULL 18 +DROP TABLE t2; +# +# constant inside ORDER BY list, should use filesort +# on a small table +# +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +## should be 5 (previous LIMIT) +SELECT 1 - COUNT(*) FROM t2 WHERE b = 10; +1 - COUNT(*) +1 +DROP TABLE t2; +# +# same test as above (constant inside ORDER BY list), but with +# a larger table - should not use filesort +# +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; +INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 NULL +10 10 10 NULL +10 10 10 NULL +10 10 10 NULL +10 10 10 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 1 +Handler_read_key 0 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 1 +Handler_read_key 0 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +## should be 5 (previous LIMIT) +SELECT 257 - COUNT(*) FROM t2 WHERE b = 10; +257 - COUNT(*) +5 +DROP TABLE t2; +# +# as above + partial index, should use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b(1),c)); +INSERT INTO t2 SELECT i, i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 10 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; +a b c d +DROP TABLE t2; +# +# as above but index is without HA_READ_ORDER flag, should use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b,c)) ENGINE=HEAP; +INSERT INTO t2 SELECT i, i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 10 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; +a b c d +DROP TABLE t2; +# +# quick select is Index Merge, should use filesort +# +CREATE TABLE t2 (i INT, key1 INT, key2 INT, INDEX (key1), INDEX (key2)); +INSERT INTO t2 (key1, key2) SELECT i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +i key1 key2 +NULL 10 10 +NULL 11 11 +NULL 12 12 +NULL 13 13 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 1 +Sort_rows 4 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_next 7 +Handler_read_prev 0 +Handler_read_rnd 4 +Handler_read_rnd_next 0 +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +id select_type table type possible_keys key key_len ref rows filtered Extra +x x x x x x x x x x Using sort_union(key1,key2); Using where; Using filesort +Warnings: +x x x +FLUSH STATUS; +DELETE FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 1 +Sort_rows 4 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_next 7 +Handler_read_prev 0 +Handler_read_rnd 8 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +i key1 key2 +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +id select_type table type possible_keys key key_len ref rows filtered Extra +x x x x x x x x x x Using sort_union(key1,key2); Using where; Using filesort +Warnings: +x x x +DROP TABLE t2; +# +# reverse quick select, should not use filesort +# +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +a i +NULL 18 +NULL 17 +NULL 16 +NULL 15 +NULL 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; +a i +NULL 11 +NULL 12 +NULL 13 +DROP TABLE t2; +# +# mixed sorting direction, should use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 SELECT i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5; +a b c +10 10 10 +11 11 11 +12 12 12 +13 13 13 +14 14 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 5 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +DELETE FROM t2 ORDER BY a, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 16 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 5 +Handler_read_rnd_next 17 +SELECT * FROM t2 ORDER BY a, b DESC; +a b c +15 15 15 +16 16 16 +17 17 17 +18 18 18 +19 19 19 +20 20 20 +21 21 21 +22 22 22 +23 23 23 +24 24 24 +25 25 25 +DROP TABLE t2; +# +# LIMIT with no WHERE and DESC direction, should not use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 (a, b) SELECT i, i FROM t1; +INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2; +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b LIMIT 5; +a b c +10 10 NULL +10 10 NULL +10 10 NULL +10 10 NULL +10 10 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 1 +Handler_read_key 0 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; +a b c +25 25 NULL +25 25 NULL +25 25 NULL +25 25 NULL +25 25 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC; +a b c +DROP TABLE t1, t2; +# +# Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a filesort +# even if not required +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25); +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +a i +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 5 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; +a i +10 11 +10 12 +10 13 +10 14 +10 15 +NULL 16 +NULL 17 +NULL 18 +DROP TABLE t2; +# +# index on field prefix: +# +CREATE TABLE t2(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t2 (i) SELECT i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +a i +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 5 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 5 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 5 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; +a i +10 11 +10 12 +10 13 +10 14 +10 15 +NULL 16 +NULL 17 +NULL 18 +DROP TABLE t2; +# +# constant inside ORDER BY list, should use filesort +# on a small table +# +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +## should be 5 (previous LIMIT) +SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c; +COUNT(*) +1 +DROP TABLE t2; +# +# same test as above (constant inside ORDER BY list), but with +# a larger table - should not use filesort +# +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; +INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 NULL +10 10 10 NULL +10 10 10 NULL +10 10 10 NULL +10 10 10 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 1 +Handler_read_key 0 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 1 +Handler_read_key 0 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 5 +Handler_read_rnd_next 0 +## should be 5 (previous LIMIT) +SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c; +COUNT(*) +5 +DROP TABLE t2; +# +# as above + partial index, should use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b(1),c)); +INSERT INTO t2 SELECT i, i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 10 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; +a b c d +10 10 10 10 +DROP TABLE t2; +# +# as above but index is without HA_READ_ORDER flag, should use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b,c)) ENGINE=HEAP; +INSERT INTO t2 SELECT i, i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +a b c d +10 10 10 10 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; +a b c d +10 10 10 10 +DROP TABLE t2; +# +# quick select is Index Merge, should use filesort +# +CREATE TABLE t2 (i INT, key1 INT, key2 INT, INDEX (key1), INDEX (key2)); +INSERT INTO t2 (key1, key2) SELECT i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +i key1 key2 +NULL 10 10 +NULL 11 11 +NULL 12 12 +NULL 13 13 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 1 +Sort_rows 4 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_next 7 +Handler_read_prev 0 +Handler_read_rnd 4 +Handler_read_rnd_next 0 +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +id select_type table type possible_keys key key_len ref rows filtered Extra +x x x x x x x x x x Using sort_union(key1,key2); Using where; Using filesort +Warnings: +x x x +FLUSH STATUS; +UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 1 +Sort_rows 4 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_next 7 +Handler_read_prev 0 +Handler_read_rnd 8 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +i key1 key2 +123 10 10 +123 11 11 +123 12 12 +123 13 13 +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +id select_type table type possible_keys key key_len ref rows filtered Extra +x x x x x x x x x x Using sort_union(key1,key2); Using where; Using filesort +Warnings: +x x x +DROP TABLE t2; +# +# reverse quick select, should not use filesort +# +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +a i +NULL 18 +NULL 17 +NULL 16 +NULL 15 +NULL 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 5 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; +a i +NULL 11 +NULL 12 +NULL 13 +10 14 +10 15 +10 16 +10 17 +10 18 +DROP TABLE t2; +# +# mixed sorting direction, should use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 SELECT i, i, i FROM t1; +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5; +a b c +10 10 10 +11 11 11 +12 12 12 +13 13 13 +14 14 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 5 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 17 +FLUSH STATUS; +UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 5 +Sort_scan 1 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 5 +Handler_read_rnd_next 17 +SELECT * FROM t2 WHERE c = 10 ORDER BY a, b DESC; +a b c +10 10 10 +11 11 10 +12 12 10 +13 13 10 +14 14 10 +DROP TABLE t2; +# +# LIMIT with no WHERE and DESC direction, should not use filesort +# +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 (a, b) SELECT i, i FROM t1; +INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2; +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b LIMIT 5; +a b c +10 10 NULL +10 10 NULL +10 10 NULL +10 10 NULL +10 10 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 1 +Handler_read_key 0 +Handler_read_next 4 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; +a b c +25 25 NULL +25 25 NULL +25 25 NULL +25 25 NULL +25 25 NULL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_range 0 +Sort_rows 0 +Sort_scan 0 +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 4 +Handler_read_rnd 5 +Handler_read_rnd_next 0 +SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC; +a b c +25 25 10 +25 25 10 +25 25 10 +25 25 10 +25 25 10 +DROP TABLE t1, t2; +# +# Bug #53742: UPDATEs have no effect after applying patch for bug 36569 +# +CREATE TABLE t1 ( +pk INT NOT NULL AUTO_INCREMENT, +c1_idx CHAR(1) DEFAULT 'y', +c2 INT, +PRIMARY KEY (pk), +INDEX c1_idx (c1_idx) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (), (), (), (); +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +pk c1_idx c2 +4 y NULL +3 y NULL +UPDATE t1 SET c2 = 0 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +pk c1_idx c2 +4 y 0 +3 y 0 +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC; +pk c1_idx c2 +4 y 0 +3 y 0 +2 y NULL +1 y NULL +DELETE FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC; +pk c1_idx c2 +2 y NULL +1 y NULL +DROP TABLE t1; diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 482e0045840..dd4bf599ad0 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -59,3 +59,28 @@ FROM t3 WHERE 1 = 0 GROUP BY 1; (SELECT 1 FROM t1,t2 WHERE t2.b > t3.b) DROP TABLE t1,t2,t3; End of 5.0 tests. +# +# Bug#53236 Segfault in DTCollation::set(DTCollation&) +# +CREATE TABLE t1 ( +pk INTEGER AUTO_INCREMENT, +col_varchar VARCHAR(1), +PRIMARY KEY (pk) +) +; +INSERT INTO t1 (col_varchar) +VALUES +('w'), +('m') +; +SELECT table1.pk +FROM ( t1 AS table1 JOIN t1 AS table2 ON (table1.col_varchar = +table2.col_varchar) ) +WHERE ( 1, 2 ) IN ( SELECT SUBQUERY1_t1.pk AS SUBQUERY1_field1, +SUBQUERY1_t1.pk AS SUBQUERY1_field2 +FROM ( t1 AS SUBQUERY1_t1 JOIN t1 AS SUBQUERY1_t2 +ON (SUBQUERY1_t2.col_varchar = +SUBQUERY1_t1.col_varchar) ) ) +; +pk +drop table t1; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 006eaba4e69..6c3f54fca38 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -306,8 +306,8 @@ Handler_read_first 0 Handler_read_key 0 Handler_read_next 0 Handler_read_prev 0 -Handler_read_rnd 1 -Handler_read_rnd_next 9 +Handler_read_rnd 0 +Handler_read_rnd_next 0 alter table t1 disable keys; flush status; delete from t1 order by a limit 1; diff --git a/mysql-test/suite/rpl/r/rpl_savepoint.result b/mysql-test/suite/rpl/r/rpl_savepoint.result new file mode 100644 index 00000000000..e1462f435a3 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_savepoint.result @@ -0,0 +1,32 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +# +# Bug#50124 Rpl failure on DROP table with concurrent txn/non-txn +# DML flow and SAVEPOINT +# +# Connection master +DROP TABLE IF EXISTS tt, nt; +CREATE TABLE tt (i INT) ENGINE = InnoDB; +CREATE TABLE nt (i INT) ENGINE = MyISAM; +FLUSH LOGS; +START TRANSACTION; +INSERT INTO nt VALUES (1); +SAVEPOINT insert_statement; +INSERT INTO tt VALUES (1); +# Connection master1 +# Sending: +DROP TABLE tt; +# Connection master +ROLLBACK TO SAVEPOINT insert_statement; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +COMMIT; +# Connection master1 +# Reaping: DROP TABLE tt +FLUSH LOGS; +# Connection master +DROP TABLE nt; diff --git a/mysql-test/suite/rpl/t/rpl_savepoint.test b/mysql-test/suite/rpl/t/rpl_savepoint.test new file mode 100644 index 00000000000..c3d1f44d162 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_savepoint.test @@ -0,0 +1,47 @@ +--source include/master-slave.inc +--source include/have_innodb.inc + +--echo # +--echo # Bug#50124 Rpl failure on DROP table with concurrent txn/non-txn +--echo # DML flow and SAVEPOINT +--echo # + +--echo # Connection master +connection master; + +--disable_warnings +DROP TABLE IF EXISTS tt, nt; +--enable_warnings + +CREATE TABLE tt (i INT) ENGINE = InnoDB; +CREATE TABLE nt (i INT) ENGINE = MyISAM; +FLUSH LOGS; +START TRANSACTION; +INSERT INTO nt VALUES (1); +SAVEPOINT insert_statement; +INSERT INTO tt VALUES (1); + +--echo # Connection master1 +connection master1; +--echo # Sending: +--send DROP TABLE tt + +--echo # Connection master +connection master; +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table" AND info = "DROP TABLE tt"; +--source include/wait_condition.inc +ROLLBACK TO SAVEPOINT insert_statement; +COMMIT; + +--echo # Connection master1 +connection master1; +--echo # Reaping: DROP TABLE tt +--reap +FLUSH LOGS; + +--echo # Connection master +connection master; +DROP TABLE nt; +--source include/master-slave-end.inc diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test index b8c7f532cde..d8aa4e97fb3 100644 --- a/mysql-test/t/lowercase_table2.test +++ b/mysql-test/t/lowercase_table2.test @@ -16,7 +16,7 @@ DROP DATABASE IF EXISTS `test_$1`; DROP DATABASE IF EXISTS mysqltest_LC2; --enable_warnings -CREATE TABLE T1 (a int); +CREATE TABLE T1 (a int) ENGINE=MyISAM; INSERT INTO T1 VALUES (1); SHOW TABLES LIKE "T1"; SHOW TABLES LIKE "t1"; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index d7026011055..252495cc1be 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -457,7 +457,7 @@ CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); SELECT * FROM t2; DROP TABLE t1, t2; CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); ---error 1168 +--error ER_WRONG_MRG_TABLE SELECT * FROM t2; DROP TABLE t2; @@ -549,11 +549,11 @@ drop table t1; # CREATE TABLE fails # CREATE TABLE tm1(a INT) ENGINE=MERGE UNION=(t1, t2); ---error 1168 +--error ER_WRONG_MRG_TABLE SELECT * FROM tm1; CHECK TABLE tm1; CREATE TABLE t1(a INT); ---error 1168 +--error ER_WRONG_MRG_TABLE SELECT * FROM tm1; CHECK TABLE tm1; CREATE TABLE t2(a BLOB); @@ -887,6 +887,9 @@ CREATE TABLE t4 LIKE t3; SHOW CREATE TABLE t4; --error ER_TABLE_NOT_LOCKED INSERT INTO t4 VALUES (4); +--echo # Temporary tables can be created in spite of LOCK TABLES. +--echo # If the temporary MERGE table uses the locked children only, +--echo # it can even be used. CREATE TEMPORARY TABLE t4 LIKE t3; --error ER_WRONG_MRG_TABLE SHOW CREATE TABLE t4; @@ -913,7 +916,7 @@ DROP TABLE t4; --echo # 2. Normal rename. SELECT * FROM t3 ORDER BY c1; RENAME TABLE t2 TO t5; ---error 1168 +--error ER_WRONG_MRG_TABLE SELECT * FROM t3 ORDER BY c1; RENAME TABLE t5 TO t2; SELECT * FROM t3 ORDER BY c1; @@ -931,7 +934,7 @@ UNLOCK TABLES; --echo # --echo # 4. Alter table rename. ALTER TABLE t2 RENAME TO t5; ---error 1168 +--error ER_WRONG_MRG_TABLE SELECT * FROM t3 ORDER BY c1; ALTER TABLE t5 RENAME TO t2; SELECT * FROM t3 ORDER BY c1; @@ -1170,6 +1173,7 @@ SELECT @a; SELECT * FROM t4 ORDER BY c1; DELETE FROM t4 WHERE c1 = 33; DROP TRIGGER t3_ai; +UNLOCK TABLES; --echo # --echo # Trigger with table use on child DELETE FROM t4 WHERE c1 = 4; @@ -1273,11 +1277,12 @@ DROP TABLE t1, t2, t3; # # Bug#25038 - Waiting TRUNCATE +# Truncate failed with error message when table was in use by MERGE. # # Show that truncate of child table after use of parent table works. -CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; -CREATE TABLE t2 (c1 INT) ENGINE= MyISAM; -CREATE TABLE t3 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1, t2); +CREATE TABLE t1 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t2 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2); INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (2); SELECT * FROM t3; @@ -1429,7 +1434,6 @@ FLUSH TABLES m1, t1; UNLOCK TABLES; DROP TABLE t1, m1; - # # Bug#35068 - Assertion fails when reading from i_s.tables # and there is incorrect merge table @@ -1816,7 +1820,7 @@ CREATE TABLE m1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,mysql_test1.t2) INSERT INTO t1 VALUES (1); INSERT INTO mysql_test1.t2 VALUES (2); SELECT * FROM m1; -#--copy_file $MYSQLTEST_VARDIR/master-data/test/m1.MRG /tmp/mysql-test-m1.MRG +#--copy_file $MYSQLTEST_DATADIR/test/m1.MRG /tmp/mysql-test-m1.MRG DROP TABLE t1, mysql_test1.t2, m1; DROP DATABASE mysql_test1; # @@ -2104,6 +2108,14 @@ DROP TRIGGER t2_au; DROP FUNCTION f1; DROP TABLE tm1, t1, t2, t3, t4, t5; +--echo # +--echo # Bug#47633 - assert in ha_myisammrg::info during OPTIMIZE +--echo # +CREATE TEMPORARY TABLE t1 (c1 INT); +ALTER TABLE t1 ENGINE=MERGE UNION(t_not_exists,t1); +OPTIMIZE TABLE t1; +DROP TABLE t1; + --echo # --echo # Bug47098 assert in MDL_context::destroy on HANDLER --echo # OPEN @@ -2186,6 +2198,18 @@ ALTER TABLE m1 ADD INDEX (c1); UNLOCK TABLES; DROP TABLE m1, t1; +--echo # +--echo # If children are to be altered, they need an explicit lock. +--echo # +CREATE TABLE t1 (c1 INT); +CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1); +LOCK TABLE m1 WRITE; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +ALTER TABLE t1 ADD INDEX (c1); +LOCK TABLE m1 WRITE, t1 WRITE; +ALTER TABLE t1 ADD INDEX (c1); +UNLOCK TABLES; +DROP TABLE m1, t1; --echo # --echo # Test for bug #37371 "CREATE TABLE LIKE merge loses UNION parameter" diff --git a/mysql-test/t/single_delete_update.test b/mysql-test/t/single_delete_update.test new file mode 100644 index 00000000000..e3ee13f891c --- /dev/null +++ b/mysql-test/t/single_delete_update.test @@ -0,0 +1,481 @@ +# +# Single table specific update/delete tests (mysql_update and mysql_delete) +# + +--echo # +--echo # Bug #30584: delete with order by and limit clauses does not use +--echo # limit efficiently +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), + (20),(21),(22),(23),(24),(25); + +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; + +DROP TABLE t2; + +--echo # +--echo # index on field prefix: +--echo # + +CREATE TABLE t2(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t2 (i) SELECT i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; + +DROP TABLE t2; + +--echo # +--echo # constant inside ORDER BY list, should use filesort +--echo # on a small table +--echo # + +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`; + +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +--echo ## should be 5 (previous LIMIT) +eval SELECT $cnt - COUNT(*) FROM t2 WHERE b = 10; + +DROP TABLE t2; + +--echo # +--echo # same test as above (constant inside ORDER BY list), but with +--echo # a larger table - should not use filesort +--echo # + +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; + +INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`; + +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +--echo ## should be 5 (previous LIMIT) +eval SELECT $cnt - COUNT(*) FROM t2 WHERE b = 10; + +DROP TABLE t2; + +--echo # +--echo # as above + partial index, should use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b(1),c)); +INSERT INTO t2 SELECT i, i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; + +DROP TABLE t2; + +--echo # +--echo # as above but index is without HA_READ_ORDER flag, should use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b,c)) ENGINE=HEAP; +INSERT INTO t2 SELECT i, i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; + +DROP TABLE t2; + +--echo # +--echo # quick select is Index Merge, should use filesort +--echo # + +CREATE TABLE t2 (i INT, key1 INT, key2 INT, INDEX (key1), INDEX (key2)); +INSERT INTO t2 (key1, key2) SELECT i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; + +FLUSH STATUS; +DELETE FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +DROP TABLE t2; + +--echo # +--echo # reverse quick select, should not use filesort +--echo # + +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; + +DROP TABLE t2; + +--echo # +--echo # mixed sorting direction, should use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 SELECT i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 ORDER BY a, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 ORDER BY a, b DESC; + +DROP TABLE t2; + +--echo # +--echo # LIMIT with no WHERE and DESC direction, should not use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 (a, b) SELECT i, i FROM t1; +INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2; + +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC; + +DROP TABLE t1, t2; + + +--echo # +--echo # Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a filesort +--echo # even if not required +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), + (20),(21),(22),(23),(24),(25); + +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; + +DROP TABLE t2; + +--echo # +--echo # index on field prefix: +--echo # + +CREATE TABLE t2(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t2 (i) SELECT i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; + +DROP TABLE t2; + +--echo # +--echo # constant inside ORDER BY list, should use filesort +--echo # on a small table +--echo # + +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`; + +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +--echo ## should be 5 (previous LIMIT) +SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c; + +DROP TABLE t2; + +--echo # +--echo # same test as above (constant inside ORDER BY list), but with +--echo # a larger table - should not use filesort +--echo # + +CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c)); +INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; + +INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`; + +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +--echo ## should be 5 (previous LIMIT) +SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c; + +DROP TABLE t2; + +--echo # +--echo # as above + partial index, should use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b(1),c)); +INSERT INTO t2 SELECT i, i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; + +DROP TABLE t2; + +--echo # +--echo # as above but index is without HA_READ_ORDER flag, should use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b,c)) ENGINE=HEAP; +INSERT INTO t2 SELECT i, i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; + +DROP TABLE t2; + +--echo # +--echo # quick select is Index Merge, should use filesort +--echo # + +CREATE TABLE t2 (i INT, key1 INT, key2 INT, INDEX (key1), INDEX (key2)); +INSERT INTO t2 (key1, key2) SELECT i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; + +FLUSH STATUS; +UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; +--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; + +DROP TABLE t2; + +--echo # +--echo # reverse quick select, should not use filesort +--echo # + +CREATE TABLE t2(a INT, i INT PRIMARY KEY); +INSERT INTO t2 (i) SELECT i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; + +DROP TABLE t2; + +--echo # +--echo # mixed sorting direction, should use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 SELECT i, i, i FROM t1; + +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE c = 10 ORDER BY a, b DESC; + +DROP TABLE t2; + +--echo # +--echo # LIMIT with no WHERE and DESC direction, should not use filesort +--echo # + +CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b)); +INSERT INTO t2 (a, b) SELECT i, i FROM t1; +INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2; + +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a, b LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; + +FLUSH STATUS; +UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5; +SHOW SESSION STATUS LIKE 'Sort%'; +SHOW STATUS LIKE 'Handler_read_%'; +SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC; + +DROP TABLE t1, t2; + + +--echo # +--echo # Bug #53742: UPDATEs have no effect after applying patch for bug 36569 +--echo # + +--disable_warnings +CREATE TABLE t1 ( + pk INT NOT NULL AUTO_INCREMENT, + c1_idx CHAR(1) DEFAULT 'y', + c2 INT, + PRIMARY KEY (pk), + INDEX c1_idx (c1_idx) +) ENGINE=InnoDB; +--enable_warnings + +INSERT INTO t1 VALUES (), (), (), (); + +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +UPDATE t1 SET c2 = 0 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC; + +DELETE FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; +SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC; + +DROP TABLE t1; + diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 440eca22828..fb0f58bf804 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -62,3 +62,32 @@ FROM t3 WHERE 1 = 0 GROUP BY 1; DROP TABLE t1,t2,t3; --echo End of 5.0 tests. + +--echo # +--echo # Bug#53236 Segfault in DTCollation::set(DTCollation&) +--echo # + +CREATE TABLE t1 ( + pk INTEGER AUTO_INCREMENT, + col_varchar VARCHAR(1), + PRIMARY KEY (pk) +) +; + +INSERT INTO t1 (col_varchar) +VALUES +('w'), +('m') +; + +SELECT table1.pk +FROM ( t1 AS table1 JOIN t1 AS table2 ON (table1.col_varchar = + table2.col_varchar) ) +WHERE ( 1, 2 ) IN ( SELECT SUBQUERY1_t1.pk AS SUBQUERY1_field1, + SUBQUERY1_t1.pk AS SUBQUERY1_field2 + FROM ( t1 AS SUBQUERY1_t1 JOIN t1 AS SUBQUERY1_t2 + ON (SUBQUERY1_t2.col_varchar = + SUBQUERY1_t1.col_varchar) ) ) +; + +drop table t1; diff --git a/mysys/my_delete.c b/mysys/my_delete.c index edee1c4e875..4a23fedb5ab 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -93,23 +93,33 @@ int nt_share_delete(const char *name, myf MyFlags) name, buf, errno)); break; } - + if (errno == ERROR_FILE_NOT_FOUND) { - my_errno= ENOENT; // marking, that `name' doesn't exist + my_errno= ENOENT; // marking, that `name' doesn't exist } else if (errno == 0) { - if (DeleteFile(buf)) - DBUG_RETURN(0); - else if ((my_errno= GetLastError()) == 0) - my_errno= ENOENT; // marking, that `buf' doesn't exist - } else - my_errno= errno; - + if (DeleteFile(buf)) + DBUG_RETURN(0); + /* + The below is more complicated than necessary. For some reason, the + assignment to my_errno clears the error number, which is retrieved + by GetLastError() (VC2005EE). Assigning to errno first, allows to + retrieve the correct value. + */ + errno= GetLastError(); + if (errno == 0) + my_errno= ENOENT; // marking, that `buf' doesn't exist + else + my_errno= errno; + } + else + my_errno= errno; + if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_DELETE, MYF(ME_BELL + ME_WAITTANG + (MyFlags & ME_NOINPUT)), - name, my_errno); + my_error(EE_DELETE, MYF(ME_BELL + ME_WAITTANG + (MyFlags & ME_NOINPUT)), + name, my_errno); DBUG_RETURN(-1); } #endif diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 303d8efaf30..82ee1562bc2 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -38,13 +38,16 @@ void *my_mmap(void *addr, size_t len, int prot, HANDLE hFileMap; LPVOID ptr; HANDLE hFile= (HANDLE)my_get_osfhandle(fd); + DBUG_ENTER("my_mmap"); + DBUG_PRINT("mysys", ("map fd: %d", fd)); + if (hFile == INVALID_HANDLE_VALUE) - return MAP_FAILED; + DBUG_RETURN(MAP_FAILED); hFileMap=CreateFileMapping(hFile, &mmap_security_attributes, PAGE_READWRITE, 0, (DWORD) len, NULL); if (hFileMap == 0) - return MAP_FAILED; + DBUG_RETURN(MAP_FAILED); ptr=MapViewOfFile(hFileMap, prot & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, @@ -59,14 +62,19 @@ void *my_mmap(void *addr, size_t len, int prot, CloseHandle(hFileMap); if (ptr) - return ptr; + { + DBUG_PRINT("mysys", ("mapped addr: %p", ptr)); + DBUG_RETURN(ptr); + } - return MAP_FAILED; + DBUG_RETURN(MAP_FAILED); } int my_munmap(void *addr, size_t len) { - return UnmapViewOfFile(addr) ? 0 : -1; + DBUG_ENTER("my_munmap"); + DBUG_PRINT("mysys", ("unmap addr: %p", addr)); + DBUG_RETURN(UnmapViewOfFile(addr) ? 0 : -1); } int my_msync(int fd, void *addr, size_t len, int flags) diff --git a/sql/item_func.cc b/sql/item_func.cc index 26c802b8057..efa14c8498b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -51,6 +51,7 @@ #include "sp_rcontext.h" #include "sp.h" #include "set_var.h" +#include "debug_sync.h" #ifdef NO_EMBEDDED_ACCESS_CHECKS #define sp_restore_security_context(A,B) while (0) {} @@ -1941,6 +1942,8 @@ double Item_func_pow::val_real() double Item_func_acos::val_real() { DBUG_ASSERT(fixed == 1); + /* One can use this to defer SELECT processing. */ + DEBUG_SYNC(current_thd, "before_acos_function"); // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug) volatile double value= args[0]->val_real(); if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0)))) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9363b637862..995582fc6ee 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1841,96 +1841,6 @@ SEL_ARG *SEL_ARG::clone_tree(RANGE_OPT_PARAM *param) } -/* - Find the best index to retrieve first N records in given order - - SYNOPSIS - get_index_for_order() - table Table to be accessed - order Required ordering - limit Number of records that will be retrieved - - DESCRIPTION - Find the best index that allows to retrieve first #limit records in the - given order cheaper then one would retrieve them using full table scan. - - IMPLEMENTATION - Run through all table indexes and find the shortest index that allows - records to be retrieved in given order. We look for the shortest index - as we will have fewer index pages to read with it. - - This function is used only by UPDATE/DELETE, so we take into account how - the UPDATE/DELETE code will work: - * index can only be scanned in forward direction - * HA_EXTRA_KEYREAD will not be used - Perhaps these assumptions could be relaxed. - - RETURN - Number of the index that produces the required ordering in the cheapest way - MAX_KEY if no such index was found. -*/ - -uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit) -{ - uint idx; - uint match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1; - ORDER *ord; - - for (ord= order; ord; ord= ord->next) - if (!ord->asc) - return MAX_KEY; - - for (idx= 0; idx < table->s->keys; idx++) - { - if (!(table->keys_in_use_for_query.is_set(idx))) - continue; - KEY_PART_INFO *keyinfo= table->key_info[idx].key_part; - uint n_parts= table->key_info[idx].key_parts; - uint partno= 0; - - /* - The below check is sufficient considering we now have either BTREE - indexes (records are returned in order for any index prefix) or HASH - indexes (records are not returned in order for any index prefix). - */ - if (!(table->file->index_flags(idx, 0, 1) & HA_READ_ORDER)) - continue; - for (ord= order; ord && partno < n_parts; ord= ord->next, partno++) - { - Item *item= order->item[0]; - if (!(item->type() == Item::FIELD_ITEM && - ((Item_field*)item)->field->eq(keyinfo[partno].field))) - break; - } - - if (!ord && table->key_info[idx].key_length < match_key_len) - { - /* - Ok, the ordering is compatible and this key is shorter then - previous match (we want shorter keys as we'll have to read fewer - index pages for the same number of records) - */ - match_key= idx; - match_key_len= table->key_info[idx].key_length; - } - } - - if (match_key != MAX_KEY) - { - /* - Found an index that allows records to be retrieved in the requested - order. Now we'll check if using the index is cheaper then doing a table - scan. - */ - double full_scan_time= table->file->scan_time(); - double index_scan_time= table->file->read_time(match_key, 1, limit); - if (index_scan_time > full_scan_time) - match_key= MAX_KEY; - } - return match_key; -} - - /* Table rows retrieval plan. Range optimizer creates QUICK_SELECT_I-derived objects from table read plans. @@ -8977,7 +8887,6 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, } rev_it.rewind(); q->dont_free=1; // Don't free shared mem - delete q; } @@ -9067,6 +8976,27 @@ int QUICK_SELECT_DESC::get_next() } +/** + Create a compatible quick select with the result ordered in an opposite way + + @param used_key_parts_arg Number of used key parts + + @retval NULL in case of errors (OOM etc) + @retval pointer to a newly created QUICK_SELECT_DESC if success +*/ + +QUICK_SELECT_I *QUICK_RANGE_SELECT::make_reverse(uint used_key_parts_arg) +{ + QUICK_SELECT_DESC *new_quick= new QUICK_SELECT_DESC(this, used_key_parts_arg); + if (new_quick == NULL || new_quick->error != 0) + { + delete new_quick; + return NULL; + } + return new_quick; +} + + /* Compare if found key is over max-value Returns 0 if key <= range->max_key @@ -11673,6 +11603,7 @@ void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose) /* purecov: end */ } + void QUICK_INDEX_MERGE_SELECT::dbug_dump(int indent, bool verbose) { List_iterator_fast it(quick_selects); @@ -11761,7 +11692,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose) } -#endif /* NOT_USED */ +#endif /* !DBUG_OFF */ /***************************************************************************** ** Instantiate templates diff --git a/sql/opt_range.h b/sql/opt_range.h index 72f2eb4b51d..7f05bdb64f0 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -352,6 +352,11 @@ public: */ virtual void dbug_dump(int indent, bool verbose)= 0; #endif + + /* + Returns a QUICK_SELECT with reverse order of to the index. + */ + virtual QUICK_SELECT_I *make_reverse(uint used_key_parts_arg) { return NULL; } }; @@ -437,6 +442,7 @@ public: #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif + QUICK_SELECT_I *make_reverse(uint used_key_parts_arg); private: /* Default copy ctor used by QUICK_SELECT_DESC */ }; @@ -782,6 +788,10 @@ public: int get_next(); bool reverse_sorted() { return 1; } int get_type() { return QS_TYPE_RANGE_DESC; } + QUICK_SELECT_I *make_reverse(uint used_key_parts_arg) + { + return this; // is already reverse sorted + } private: bool range_reads_after_key(QUICK_RANGE *range); int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); } @@ -807,6 +817,7 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); void cleanup(); + void set_quick(QUICK_SELECT_I *new_quick) { delete quick; quick= new_quick; } bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) { key_map tmp; @@ -833,7 +844,6 @@ public: QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, struct st_table_ref *ref, ha_rows records); -uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit); SQL_SELECT *make_select(TABLE *head, table_map const_tables, table_map read_tables, COND *conds, bool allow_null_cond, int *error); diff --git a/sql/records.cc b/sql/records.cc index d85cb49e013..70b7cedb0a5 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -42,12 +42,14 @@ static int rr_from_cache(READ_RECORD *info); static int init_rr_cache(THD *thd, READ_RECORD *info); static int rr_cmp(uchar *a,uchar *b); static int rr_index_first(READ_RECORD *info); +static int rr_index_last(READ_RECORD *info); static int rr_index(READ_RECORD *info); +static int rr_index_desc(READ_RECORD *info); /** - Initialize READ_RECORD structure to perform full index scan (in forward - direction) using read_record.read_record() interface. + Initialize READ_RECORD structure to perform full index scan in desired + direction using read_record.read_record() interface This function has been added at late stage and is used only by UPDATE/DELETE. Other statements perform index scans using @@ -59,10 +61,11 @@ static int rr_index(READ_RECORD *info); @param print_error If true, call table->file->print_error() if an error occurs (except for end-of-records error) @param idx index to scan + @param reverse Scan in the reverse direction */ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, - bool print_error, uint idx) + bool print_error, uint idx, bool reverse) { empty_record(table); bzero((char*) info,sizeof(*info)); @@ -77,7 +80,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, if (!table->file->inited) table->file->ha_index_init(idx, 1); /* read_record will be changed to rr_index in rr_index_first */ - info->read_record= rr_index_first; + info->read_record= reverse ? rr_index_last : rr_index_first; } @@ -364,6 +367,29 @@ static int rr_index_first(READ_RECORD *info) } +/** + Reads last row in an index scan. + + @param info Scan info + + @retval + 0 Ok + @retval + -1 End of records + @retval + 1 Error +*/ + +static int rr_index_last(READ_RECORD *info) +{ + int tmp= info->file->index_last(info->record); + info->read_record= rr_index_desc; + if (tmp) + tmp= rr_handle_error(info, tmp); + return tmp; +} + + /** Reads index sequentially after first row. @@ -389,6 +415,31 @@ static int rr_index(READ_RECORD *info) } +/** + Reads index sequentially from the last row to the first. + + Read the prev index record (in backward direction) and translate return + value. + + @param info Scan info + + @retval + 0 Ok + @retval + -1 End of records + @retval + 1 Error +*/ + +static int rr_index_desc(READ_RECORD *info) +{ + int tmp= info->file->index_prev(info->record); + if (tmp) + tmp= rr_handle_error(info, tmp); + return tmp; +} + + int rr_sequential(READ_RECORD *info) { int tmp; diff --git a/sql/records.h b/sql/records.h index ae81a31ee1a..95464a11b4b 100644 --- a/sql/records.h +++ b/sql/records.h @@ -71,7 +71,7 @@ void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors, bool disable_rr_cache); void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, - bool print_error, uint idx); + bool print_error, uint idx, bool reverse); void end_read_record(READ_RECORD *info); void rr_unlock_row(st_join_table *tab); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index c4a773fee9c..c94ea1302c8 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -47,7 +47,7 @@ */ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_I_List *order, ha_rows limit, ulonglong options) + SQL_I_List *order_list, ha_rows limit, ulonglong options) { bool will_batch; int error, loc_error; @@ -58,6 +58,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, bool transactional_table, safe_update, const_cond; bool const_cond_result; ha_rows deleted= 0; + bool reverse= FALSE; + ORDER *order= (ORDER *) ((order_list && order_list->elements) ? + order_list->first : NULL); uint usable_index= MAX_KEY; SELECT_LEX *select_lex= &thd->lex->select_lex; THD::killed_state killed_status= THD::NOT_KILLED; @@ -79,7 +82,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_RETURN(TRUE); /* check ORDER BY even if it can be ignored */ - if (order && order->elements) + if (order) { TABLE_LIST tables; List fields; @@ -89,9 +92,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, tables.table = table; tables.alias = table_list->alias; - if (select_lex->setup_ref_array(thd, order->elements) || + if (select_lex->setup_ref_array(thd, order_list->elements) || setup_order(thd, select_lex->ref_pointer_array, &tables, - fields, all_fields, order->first)) + fields, all_fields, order)) { delete select; free_underlaid_joins(thd, &thd->lex->select_lex); @@ -182,6 +185,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->covering_keys.clear_all(); table->quick_keys.clear_all(); // Can't use 'only index' + select=make_select(table, 0, 0, conds, 0, &error); if (error) DBUG_RETURN(TRUE); @@ -217,22 +221,25 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (options & OPTION_QUICK) (void) table->file->extra(HA_EXTRA_QUICK); - if (order && order->elements) + if (order) { uint length= 0; SORT_FIELD *sortorder; ha_rows examined_rows; - if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR) - usable_index= get_index_for_order(table, order->first, limit); + table->update_const_key_parts(conds); + order= simple_remove_const(order, conds); - if (usable_index == MAX_KEY) + bool need_sort; + usable_index= get_index_for_order(order, table, select, limit, + &need_sort, &reverse); + if (need_sort) { + DBUG_ASSERT(usable_index == MAX_KEY); table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL)); - if (!(sortorder= make_unireg_sortorder(order->first, - &length, NULL)) || + if (!(sortorder= make_unireg_sortorder(order, &length, NULL)) || (table->sort.found_records = filesort(thd, table, sortorder, length, select, HA_POS_ERROR, 1, &examined_rows)) @@ -263,7 +270,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (usable_index==MAX_KEY || (select && select->quick)) init_read_record(&info, thd, table, select, 1, 1, FALSE); else - init_read_record_idx(&info, thd, table, 1, usable_index); + init_read_record_idx(&info, thd, table, 1, usable_index, reverse); init_ftfuncs(thd, select_lex, 1); thd_proc_info(thd, "updating"); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 05af1237be8..b8bf3b220c9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -998,7 +998,7 @@ extern const LEX_STRING null_lex_str; extern const LEX_STRING empty_lex_str; -struct Sroutine_hash_entry; +class Sroutine_hash_entry; /* Class representing list of all tables used by statement and other diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 992fa8f6212..22190eeefed 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -137,7 +137,6 @@ static uint build_bitmap_for_nested_joins(List *join_list, static COND *optimize_cond(JOIN *join, COND *conds, List *join_list, Item::cond_result *cond_value); -static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); static bool create_myisam_tmp_table(TABLE *,TMP_TABLE_PARAM *, ulonglong, my_bool); static int do_select(JOIN *join,List *fields,TABLE *tmp_table, @@ -190,6 +189,13 @@ static COND *make_cond_for_table(COND *cond,table_map table, table_map used_table); static Item* part_of_refkey(TABLE *form,Field *field); uint find_shortest_key(TABLE *table, const key_map *usable_keys); +static bool test_if_cheaper_ordering(const JOIN_TAB *tab, + ORDER *order, TABLE *table, + key_map usable_keys, int key, + ha_rows select_limit, + int *new_key, int *new_key_direction, + ha_rows *new_select_limit, + uint *new_used_key_parts= NULL); static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order, ha_rows select_limit, bool no_changes, key_map *map); @@ -7361,8 +7367,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, *simple_order=0; else { - Item *comp_item=0; - if (cond && const_expression_in_where(cond,order->item[0], &comp_item)) + if (cond && const_expression_in_where(cond,order->item[0])) { DBUG_PRINT("info",("removing: %s", order->item[0]->full_name())); continue; @@ -7392,6 +7397,46 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, } +/** + Filter out ORDER items those are equal to constants in WHERE + + This function is a limited version of remove_const() for use + with non-JOIN statements (i.e. single-table UPDATE and DELETE). + + + @param order Linked list of ORDER BY arguments + @param cond WHERE expression + + @return pointer to new filtered ORDER list or NULL if whole list eliminated + + @note + This function overwrites input order list. +*/ + +ORDER *simple_remove_const(ORDER *order, COND *where) +{ + if (!order || !where) + return order; + + ORDER *first= NULL, *prev= NULL; + for (; order; order= order->next) + { + DBUG_ASSERT(!order->item[0]->with_sum_func); // should never happen + if (!const_expression_in_where(where, order->item[0])) + { + if (!first) + first= order; + if (prev) + prev->next= order; + prev= order; + } + } + if (prev) + prev->next= NULL; + return first; +} + + static int return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, List &fields, bool send_row, ulonglong select_options, @@ -8584,10 +8629,9 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, left_item->collation.collation == value->collation.collation)) { Item *tmp=value->clone_item(); - tmp->collation.set(right_item->collation); - if (tmp) { + tmp->collation.set(right_item->collation); thd->change_item_tree(args + 1, tmp); func->update_used_tables(); if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC) @@ -8608,10 +8652,9 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, right_item->collation.collation == value->collation.collation)) { Item *tmp= value->clone_item(); - tmp->collation.set(left_item->collation); - if (tmp) { + tmp->collation.set(left_item->collation); thd->change_item_tree(args, tmp); value= tmp; func->update_used_tables(); @@ -9593,13 +9636,50 @@ test_if_equality_guarantees_uniqueness(Item *l, Item *r) l->collation.collation == r->collation.collation))); } -/** - Return TRUE if the item is a const value in all the WHERE clause. + +/* + Return TRUE if i1 and i2 (if any) are equal items, + or if i1 is a wrapper item around the f2 field. */ -static bool -const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) +static bool equal(Item *i1, Item *i2, Field *f2) { + DBUG_ASSERT((i2 == NULL) ^ (f2 == NULL)); + + if (i2 != NULL) + return i1->eq(i2, 1); + else if (i1->type() == Item::FIELD_ITEM) + return f2->eq(((Item_field *) i1)->field); + else + return FALSE; +} + + +/** + Test if a field or an item is equal to a constant value in WHERE + + @param cond WHERE clause expression + @param comp_item Item to find in WHERE expression + (if comp_field != NULL) + @param comp_field Field to find in WHERE expression + (if comp_item != NULL) + @param[out] const_item intermediate arg, set to Item pointer to NULL + + @return TRUE if the field is a constant value in WHERE + + @note + comp_item and comp_field parameters are mutually exclusive. +*/ +bool +const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field, + Item **const_item) +{ + DBUG_ASSERT((comp_item == NULL) ^ (comp_field == NULL)); + + Item *intermediate= NULL; + if (const_item == NULL) + const_item= &intermediate; + if (cond->type() == Item::COND_ITEM) { bool and_level= (((Item_cond*) cond)->functype() @@ -9608,7 +9688,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) Item *item; while ((item=li++)) { - bool res=const_expression_in_where(item, comp_item, const_item); + bool res=const_expression_in_where(item, comp_item, comp_field, + const_item); if (res) // Is a const value { if (and_level) @@ -9620,14 +9701,14 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) return and_level ? 0 : 1; } else if (cond->eq_cmp_result() != Item::COND_OK) - { // boolan compare function + { // boolean compare function Item_func* func= (Item_func*) cond; if (func->functype() != Item_func::EQUAL_FUNC && func->functype() != Item_func::EQ_FUNC) return 0; Item *left_item= ((Item_func*) cond)->arguments()[0]; Item *right_item= ((Item_func*) cond)->arguments()[1]; - if (left_item->eq(comp_item,1)) + if (equal(left_item, comp_item, comp_field)) { if (test_if_equality_guarantees_uniqueness (left_item, right_item)) { @@ -9637,7 +9718,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) return 1; } } - else if (right_item->eq(comp_item,1)) + else if (equal(right_item, comp_item, comp_field)) { if (test_if_equality_guarantees_uniqueness (right_item, left_item)) { @@ -9651,6 +9732,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) return 0; } + /**************************************************************************** Create internal temporary table ****************************************************************************/ @@ -13104,7 +13186,8 @@ part_of_refkey(TABLE *table,Field *field) @param order Sort order @param table Table to sort @param idx Index to check - @param used_key_parts Return value for used key parts. + @param used_key_parts [out] NULL by default, otherwise return value for + used key parts. @note @@ -13123,13 +13206,14 @@ part_of_refkey(TABLE *table,Field *field) */ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, - uint *used_key_parts) + uint *used_key_parts= NULL) { KEY_PART_INFO *key_part,*key_part_end; key_part=table->key_info[idx].key_part; key_part_end=key_part+table->key_info[idx].key_parts; key_part_map const_key_parts=table->const_key_parts[idx]; int reverse=0; + uint key_parts; my_bool on_pk_suffix= FALSE; DBUG_ENTER("test_if_order_by_key"); @@ -13170,8 +13254,9 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, */ if (key_part == key_part_end && reverse == 0) { - *used_key_parts= 0; - DBUG_RETURN(1); + key_parts= 0; + reverse= 1; + goto ok; } } else @@ -13194,7 +13279,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, uint used_key_parts_secondary= table->key_info[idx].key_parts; uint used_key_parts_pk= (uint) (key_part - table->key_info[table->s->primary_key].key_part); - *used_key_parts= used_key_parts_pk + used_key_parts_secondary; + key_parts= used_key_parts_pk + used_key_parts_secondary; if (reverse == -1 && (!(table->file->index_flags(idx, used_key_parts_secondary - 1, 1) & @@ -13205,11 +13290,14 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, } else { - *used_key_parts= (uint) (key_part - table->key_info[idx].key_part); + key_parts= (uint) (key_part - table->key_info[idx].key_part); if (reverse == -1 && - !(table->file->index_flags(idx, *used_key_parts-1, 1) & HA_READ_PREV)) + !(table->file->index_flags(idx, key_parts-1, 1) & HA_READ_PREV)) reverse= 0; // Index can't be used } +ok: + if (used_key_parts != NULL) + *used_key_parts= key_parts; DBUG_RETURN(reverse); } @@ -13303,7 +13391,6 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, uint nr; uint min_length= (uint) ~0; uint best= MAX_KEY; - uint not_used; KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part; KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts; @@ -13314,7 +13401,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, table->key_info[nr].key_parts >= ref_key_parts && is_subkey(table->key_info[nr].key_part, ref_key_part, ref_key_part_end) && - test_if_order_by_key(order, table, nr, ¬_used)) + test_if_order_by_key(order, table, nr)) { min_length= table->key_info[nr].key_length; best= nr; @@ -13606,183 +13693,16 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, goto check_reverse_order; } { - /* - Check whether there is an index compatible with the given order - usage of which is cheaper than usage of the ref_key index (ref_key>=0) - or a table scan. - It may be the case if ORDER/GROUP BY is used with LIMIT. - */ - uint nr; - key_map keys; uint best_key_parts= 0; int best_key_direction= 0; - ha_rows best_records= 0; - double read_time; int best_key= -1; - bool is_best_covering= FALSE; - double fanout= 1; JOIN *join= tab->join; - uint tablenr= tab - join->join_tab; ha_rows table_records= table->file->stats.records; - bool group= join->group && order == join->group_list; - ha_rows ref_key_quick_rows= HA_POS_ERROR; - /* - If not used with LIMIT, only use keys if the whole query can be - resolved with a key; This is because filesort() is usually faster than - retrieving all rows through an index. - */ - if (select_limit >= table_records) - { - keys= *table->file->keys_to_use_for_scanning(); - keys.merge(table->covering_keys); - - /* - We are adding here also the index specified in FORCE INDEX clause, - if any. - This is to allow users to use index in ORDER BY. - */ - if (table->force_index) - keys.merge(group ? table->keys_in_use_for_group_by : - table->keys_in_use_for_order_by); - keys.intersect(usable_keys); - } - else - keys= usable_keys; - - if (ref_key >= 0 && table->covering_keys.is_set(ref_key)) - ref_key_quick_rows= table->quick_rows[ref_key]; - - read_time= join->best_positions[tablenr].read_time; - for (uint i= tablenr+1; i < join->tables; i++) - fanout*= join->best_positions[i].records_read; // fanout is always >= 1 - - for (nr=0; nr < table->s->keys ; nr++) - { - int direction; - - if (keys.is_set(nr) && - (direction= test_if_order_by_key(order, table, nr, &used_key_parts))) - { - /* - At this point we are sure that ref_key is a non-ordering - key (where "ordering key" is a key that will return rows - in the order required by ORDER BY). - */ - DBUG_ASSERT (ref_key != (int) nr); - - bool is_covering= table->covering_keys.is_set(nr) || - (nr == table->s->primary_key && - table->file->primary_key_is_clustered()); - - /* - Don't use an index scan with ORDER BY without limit. - For GROUP BY without limit always use index scan - if there is a suitable index. - Why we hold to this asymmetry hardly can be explained - rationally. It's easy to demonstrate that using - temporary table + filesort could be cheaper for grouping - queries too. - */ - if (is_covering || - select_limit != HA_POS_ERROR || - (ref_key < 0 && (group || table->force_index))) - { - double rec_per_key; - double index_scan_time; - KEY *keyinfo= tab->table->key_info+nr; - if (select_limit == HA_POS_ERROR) - select_limit= table_records; - if (group) - { - /* - Used_key_parts can be larger than keyinfo->key_parts - when using a secondary index clustered with a primary - key (e.g. as in Innodb). - See Bug #28591 for details. - */ - rec_per_key= used_key_parts && - used_key_parts <= keyinfo->key_parts ? - keyinfo->rec_per_key[used_key_parts-1] : 1; - set_if_bigger(rec_per_key, 1); - /* - With a grouping query each group containing on average - rec_per_key records produces only one row that will - be included into the result set. - */ - if (select_limit > table_records/rec_per_key) - select_limit= table_records; - else - select_limit= (ha_rows) (select_limit*rec_per_key); - } - /* - If tab=tk is not the last joined table tn then to get first - L records from the result set we can expect to retrieve - only L/fanout(tk,tn) where fanout(tk,tn) says how many - rows in the record set on average will match each row tk. - Usually our estimates for fanouts are too pessimistic. - So the estimate for L/fanout(tk,tn) will be too optimistic - and as result we'll choose an index scan when using ref/range - access + filesort will be cheaper. - */ - select_limit= (ha_rows) (select_limit < fanout ? - 1 : select_limit/fanout); - /* - We assume that each of the tested indexes is not correlated - with ref_key. Thus, to select first N records we have to scan - N/selectivity(ref_key) index entries. - selectivity(ref_key) = #scanned_records/#table_records = - table->quick_condition_rows/table_records. - In any case we can't select more than #table_records. - N/(table->quick_condition_rows/table_records) > table_records - <=> N > table->quick_condition_rows. - */ - if (select_limit > table->quick_condition_rows) - select_limit= table_records; - else - select_limit= (ha_rows) (select_limit * - (double) table_records / - table->quick_condition_rows); - rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1]; - set_if_bigger(rec_per_key, 1); - /* - Here we take into account the fact that rows are - accessed in sequences rec_per_key records in each. - Rows in such a sequence are supposed to be ordered - by rowid/primary key. When reading the data - in a sequence we'll touch not more pages than the - table file contains. - TODO. Use the formula for a disk sweep sequential access - to calculate the cost of accessing data rows for one - index entry. - */ - index_scan_time= select_limit/rec_per_key * - min(rec_per_key, table->file->scan_time()); - if ((ref_key < 0 && is_covering) || - (ref_key < 0 && (group || table->force_index)) || - index_scan_time < read_time) - { - ha_rows quick_records= table_records; - if ((is_best_covering && !is_covering) || - (is_covering && ref_key_quick_rows < select_limit)) - continue; - if (table->quick_keys.is_set(nr)) - quick_records= table->quick_rows[nr]; - if (best_key < 0 || - (select_limit <= min(quick_records,best_records) ? - keyinfo->key_parts < best_key_parts : - quick_records < best_records)) - { - best_key= nr; - best_key_parts= keyinfo->key_parts; - best_records= quick_records; - is_best_covering= is_covering; - best_key_direction= direction; - } - } - } - } - } + test_if_cheaper_ordering(tab, order, table, usable_keys, + ref_key, select_limit, + &best_key, &best_key_direction, + &select_limit, &best_key_parts); /* filesort() and join cache are usually faster than reading in @@ -13879,7 +13799,7 @@ check_reverse_order: */ if (!select->quick->reverse_sorted()) { - QUICK_SELECT_DESC *tmp; + QUICK_SELECT_I *tmp; int quick_type= select->quick->get_type(); if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || @@ -13892,16 +13812,14 @@ check_reverse_order: } /* ORDER BY range_key DESC */ - tmp= new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick), - used_key_parts); - if (!tmp || tmp->error) + tmp= select->quick->make_reverse(used_key_parts); + if (!tmp) { - delete tmp; select->quick= save_quick; tab->limit= 0; DBUG_RETURN(0); // Reverse sort not supported } - select->quick=tmp; + select->set_quick(tmp); } } else if (tab->type != JT_NEXT && tab->type != JT_REF_OR_NULL && @@ -17438,6 +17356,353 @@ void JOIN::cache_const_exprs() } +/** + Find a cheaper access key than a given @a key + + @param tab NULL or JOIN_TAB of the accessed table + @param order Linked list of ORDER BY arguments + @param table Table if tab == NULL or tab->table + @param usable_keys Key map to find a cheaper key in + @param ref_key + * 0 <= key < MAX_KEY - key number (hint) to start the search + * -1 - no key number provided + @param select_limit LIMIT value + @param [out] new_key Key number if success, otherwise undefined + @param [out] new_key_direction Return -1 (reverse) or +1 if success, + otherwise undefined + @param [out] new_select_limit Return adjusted LIMIT + @param [out] new_used_key_parts NULL by default, otherwise return number + of new_key prefix columns if success + or undefined if the function fails + + @note + This function takes into account table->quick_condition_rows statistic + (that is calculated by the make_join_statistics function). + However, single table procedures such as mysql_update() and mysql_delete() + never call make_join_statistics, so they have to update it manually + (@see get_index_for_order()). +*/ + +static bool +test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, + key_map usable_keys, int ref_key, + ha_rows select_limit, + int *new_key, int *new_key_direction, + ha_rows *new_select_limit, uint *new_used_key_parts) +{ + DBUG_ENTER("test_if_cheaper_ordering"); + /* + Check whether there is an index compatible with the given order + usage of which is cheaper than usage of the ref_key index (ref_key>=0) + or a table scan. + It may be the case if ORDER/GROUP BY is used with LIMIT. + */ + ha_rows best_select_limit= HA_POS_ERROR; + JOIN *join= tab ? tab->join : NULL; + uint nr; + key_map keys; + uint best_key_parts= 0; + int best_key_direction= 0; + ha_rows best_records= 0; + double read_time; + int best_key= -1; + bool is_best_covering= FALSE; + double fanout= 1; + ha_rows table_records= table->file->stats.records; + bool group= join && join->group && order == join->group_list; + ha_rows ref_key_quick_rows= HA_POS_ERROR; + + /* + If not used with LIMIT, only use keys if the whole query can be + resolved with a key; This is because filesort() is usually faster than + retrieving all rows through an index. + */ + if (select_limit >= table_records) + { + keys= *table->file->keys_to_use_for_scanning(); + keys.merge(table->covering_keys); + + /* + We are adding here also the index specified in FORCE INDEX clause, + if any. + This is to allow users to use index in ORDER BY. + */ + if (table->force_index) + keys.merge(group ? table->keys_in_use_for_group_by : + table->keys_in_use_for_order_by); + keys.intersect(usable_keys); + } + else + keys= usable_keys; + + if (ref_key >= 0 && table->covering_keys.is_set(ref_key)) + ref_key_quick_rows= table->quick_rows[ref_key]; + + if (join) + { + uint tablenr= tab - join->join_tab; + read_time= join->best_positions[tablenr].read_time; + for (uint i= tablenr+1; i < join->tables; i++) + fanout*= join->best_positions[i].records_read; // fanout is always >= 1 + } + else + read_time= table->file->scan_time(); + + for (nr=0; nr < table->s->keys ; nr++) + { + int direction; + uint used_key_parts; + + if (keys.is_set(nr) && + (direction= test_if_order_by_key(order, table, nr, &used_key_parts))) + { + /* + At this point we are sure that ref_key is a non-ordering + key (where "ordering key" is a key that will return rows + in the order required by ORDER BY). + */ + DBUG_ASSERT (ref_key != (int) nr); + + bool is_covering= table->covering_keys.is_set(nr) || + (nr == table->s->primary_key && + table->file->primary_key_is_clustered()); + + /* + Don't use an index scan with ORDER BY without limit. + For GROUP BY without limit always use index scan + if there is a suitable index. + Why we hold to this asymmetry hardly can be explained + rationally. It's easy to demonstrate that using + temporary table + filesort could be cheaper for grouping + queries too. + */ + if (is_covering || + select_limit != HA_POS_ERROR || + (ref_key < 0 && (group || table->force_index))) + { + double rec_per_key; + double index_scan_time; + KEY *keyinfo= table->key_info+nr; + if (select_limit == HA_POS_ERROR) + select_limit= table_records; + if (group) + { + /* + Used_key_parts can be larger than keyinfo->key_parts + when using a secondary index clustered with a primary + key (e.g. as in Innodb). + See Bug #28591 for details. + */ + rec_per_key= used_key_parts && + used_key_parts <= keyinfo->key_parts ? + keyinfo->rec_per_key[used_key_parts-1] : 1; + set_if_bigger(rec_per_key, 1); + /* + With a grouping query each group containing on average + rec_per_key records produces only one row that will + be included into the result set. + */ + if (select_limit > table_records/rec_per_key) + select_limit= table_records; + else + select_limit= (ha_rows) (select_limit*rec_per_key); + } + /* + If tab=tk is not the last joined table tn then to get first + L records from the result set we can expect to retrieve + only L/fanout(tk,tn) where fanout(tk,tn) says how many + rows in the record set on average will match each row tk. + Usually our estimates for fanouts are too pessimistic. + So the estimate for L/fanout(tk,tn) will be too optimistic + and as result we'll choose an index scan when using ref/range + access + filesort will be cheaper. + */ + select_limit= (ha_rows) (select_limit < fanout ? + 1 : select_limit/fanout); + /* + We assume that each of the tested indexes is not correlated + with ref_key. Thus, to select first N records we have to scan + N/selectivity(ref_key) index entries. + selectivity(ref_key) = #scanned_records/#table_records = + table->quick_condition_rows/table_records. + In any case we can't select more than #table_records. + N/(table->quick_condition_rows/table_records) > table_records + <=> N > table->quick_condition_rows. + */ + if (select_limit > table->quick_condition_rows) + select_limit= table_records; + else + select_limit= (ha_rows) (select_limit * + (double) table_records / + table->quick_condition_rows); + rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1]; + set_if_bigger(rec_per_key, 1); + /* + Here we take into account the fact that rows are + accessed in sequences rec_per_key records in each. + Rows in such a sequence are supposed to be ordered + by rowid/primary key. When reading the data + in a sequence we'll touch not more pages than the + table file contains. + TODO. Use the formula for a disk sweep sequential access + to calculate the cost of accessing data rows for one + index entry. + */ + index_scan_time= select_limit/rec_per_key * + min(rec_per_key, table->file->scan_time()); + if ((ref_key < 0 && is_covering) || + (ref_key < 0 && (group || table->force_index)) || + index_scan_time < read_time) + { + ha_rows quick_records= table_records; + if ((is_best_covering && !is_covering) || + (is_covering && ref_key_quick_rows < select_limit)) + continue; + if (table->quick_keys.is_set(nr)) + quick_records= table->quick_rows[nr]; + if (best_key < 0 || + (select_limit <= min(quick_records,best_records) ? + keyinfo->key_parts < best_key_parts : + quick_records < best_records)) + { + best_key= nr; + best_key_parts= keyinfo->key_parts; + best_records= quick_records; + is_best_covering= is_covering; + best_key_direction= direction; + best_select_limit= select_limit; + } + } + } + } + } + + if (best_key < 0 || best_key == ref_key) + DBUG_RETURN(FALSE); + + *new_key= best_key; + *new_key_direction= best_key_direction; + *new_select_limit= best_select_limit; + if (new_used_key_parts != NULL) + *new_used_key_parts= best_key_parts; + + DBUG_RETURN(TRUE); +} + + +/** + Find a key to apply single table UPDATE/DELETE by a given ORDER + + @param order Linked list of ORDER BY arguments + @param table Table to find a key + @param select Pointer to access/update select->quick (if any) + @param limit LIMIT clause parameter + @param [out] need_sort TRUE if filesort needed + @param [out] reverse + TRUE if the key is reversed again given ORDER (undefined if key == MAX_KEY) + + @return + - MAX_KEY if no key found (need_sort == TRUE) + - MAX_KEY if quick select result order is OK (need_sort == FALSE) + - key number (either index scan or quick select) (need_sort == FALSE) + + @note + Side effects: + - may deallocate or deallocate and replace select->quick; + - may set table->quick_condition_rows and table->quick_rows[...] + to table->file->stats.records. +*/ + +uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, + ha_rows limit, bool *need_sort, bool *reverse) +{ + if (select && select->quick && select->quick->unique_key_range()) + { // Single row select (always "ordered"): Ok to use with key field UPDATE + *need_sort= FALSE; + /* + Returning of MAX_KEY here prevents updating of used_key_is_modified + in mysql_update(). Use quick select "as is". + */ + return MAX_KEY; + } + + if (!order) + { + *need_sort= FALSE; + if (select && select->quick) + return select->quick->index; // index or MAX_KEY, use quick select as is + else + return table->file->key_used_on_scan; // MAX_KEY or index for some engines + } + + if (!is_simple_order(order)) // just to cut further expensive checks + { + *need_sort= TRUE; + return MAX_KEY; + } + + if (select && select->quick) + { + if (select->quick->index == MAX_KEY) + { + *need_sort= TRUE; + return MAX_KEY; + } + + uint used_key_parts; + switch (test_if_order_by_key(order, table, select->quick->index, + &used_key_parts)) { + case 1: // desired order + *need_sort= FALSE; + return select->quick->index; + case 0: // unacceptable order + *need_sort= TRUE; + return MAX_KEY; + case -1: // desired order, but opposite direction + { + QUICK_SELECT_I *reverse_quick; + if ((reverse_quick= + select->quick->make_reverse(used_key_parts))) + { + select->set_quick(reverse_quick); + *need_sort= FALSE; + return select->quick->index; + } + else + { + *need_sort= TRUE; + return MAX_KEY; + } + } + } + DBUG_ASSERT(0); + } + else if (limit != HA_POS_ERROR) + { // check if some index scan & LIMIT is more efficient than filesort + + /* + Update quick_condition_rows since single table UPDATE/DELETE procedures + don't call make_join_statistics() and leave this variable uninitialized. + */ + table->quick_condition_rows= table->file->stats.records; + + int key, direction; + if (test_if_cheaper_ordering(NULL, order, table, + table->keys_in_use_for_order_by, -1, + limit, + &key, &direction, &limit) && + !is_key_used(table, key, table->write_set)) + { + *need_sort= FALSE; + *reverse= (direction < 0); + return key; + } + } + *need_sort= TRUE; + return MAX_KEY; +} + + /** @} (end of group Query_Optimizer) */ diff --git a/sql/sql_select.h b/sql/sql_select.h index 2c44dba74c3..0496870bb3f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -847,4 +847,12 @@ inline bool optimizer_flag(THD *thd, uint flag) return (thd->variables.optimizer_switch & flag); } +uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, + ha_rows limit, bool *need_sort, bool *reverse); +ORDER *simple_remove_const(ORDER *order, COND *where); +bool const_expression_in_where(COND *cond, Item *comp_item, + Field *comp_field= NULL, + Item **const_item= NULL); + + #endif /* SQL_SELECT_INCLUDED */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e0e32b81e03..97c8f59d7df 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4886,6 +4886,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (wait_while_table_is_used(thd, table->table, HA_EXTRA_PREPARE_FOR_RENAME)) goto err; + DEBUG_SYNC(thd, "after_admin_flush"); /* Flush entries in the query cache involving this table. */ query_cache_invalidate3(thd, table->table, 0); /* @@ -5153,7 +5154,11 @@ send_result_message: { if (table->table->s->tmp_table) { - if (open_for_modify) + /* + If the table was not opened successfully, do not try to get + status information. (Bug#47633) + */ + if (open_for_modify && !open_error) table->table->file->info(HA_STATUS_CONST); } else if (open_for_modify || fatal_error) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 127368cef5c..25c1fd6fa1e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -203,12 +203,13 @@ int mysql_update(THD *thd, { bool using_limit= limit != HA_POS_ERROR; bool safe_update= test(thd->variables.option_bits & OPTION_SAFE_UPDATES); - bool used_key_is_modified, transactional_table, will_batch; + bool used_key_is_modified= FALSE, transactional_table, will_batch; bool can_compare_record; int res; int error, loc_error; - uint used_index= MAX_KEY, dup_key_found; + uint used_index, dup_key_found; bool need_sort= TRUE; + bool reverse= FALSE; #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; #endif @@ -358,11 +359,7 @@ int mysql_update(THD *thd, my_ok(thd); // No matching records DBUG_RETURN(0); } - if (!select && limit != HA_POS_ERROR) - { - if ((used_index= get_index_for_order(table, order, limit)) != MAX_KEY) - need_sort= FALSE; - } + /* If running in safe sql mode, don't allow updates without keys */ if (table->quick_keys.is_clear_all()) { @@ -378,24 +375,20 @@ int mysql_update(THD *thd, table->mark_columns_needed_for_update(); - /* Check if we are modifying a key that we are used to search with */ - - if (select && select->quick) - { - used_index= select->quick->index; - used_key_is_modified= (!select->quick->unique_key_range() && - select->quick->is_keys_used(table->write_set)); + table->update_const_key_parts(conds); + order= simple_remove_const(order, conds); + + used_index= get_index_for_order(order, table, select, limit, + &need_sort, &reverse); + if (need_sort) + { // Assign table scan index to check below for modified key fields: + used_index= table->file->key_used_on_scan; } - else - { - used_key_is_modified= 0; - if (used_index == MAX_KEY) // no index for sort order - used_index= table->file->key_used_on_scan; - if (used_index != MAX_KEY) - used_key_is_modified= is_key_used(table, used_index, table->write_set); + if (used_index != MAX_KEY) + { // Check if we are modifying a key that we are used to search with: + used_key_is_modified= is_key_used(table, used_index, table->write_set); } - #ifdef WITH_PARTITION_STORAGE_ENGINE if (used_key_is_modified || order || partition_key_modified(table, table->write_set)) @@ -414,7 +407,7 @@ int mysql_update(THD *thd, table->use_all_columns(); } - /* note: We avoid sorting avoid if we sort on the used index */ + /* note: We avoid sorting if we sort on the used index */ if (order && (need_sort || used_key_is_modified)) { /* @@ -476,7 +469,7 @@ int mysql_update(THD *thd, if (used_index == MAX_KEY || (select && select->quick)) init_read_record(&info, thd, table, select, 0, 1, FALSE); else - init_read_record_idx(&info, thd, table, 1, used_index); + init_read_record_idx(&info, thd, table, 1, used_index, reverse); thd_proc_info(thd, "Searching rows for update"); ha_rows tmp_limit= limit; diff --git a/sql/table.cc b/sql/table.cc index dbd657bee67..4e6f2ae2860 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -33,6 +33,7 @@ #include "sql_base.h" // release_table_share #include #include "my_md5.h" +#include "sql_select.h" /* INFORMATION_SCHEMA name */ LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")}; @@ -4916,6 +4917,61 @@ void init_mdl_requests(TABLE_LIST *table_list) } +/** + Update TABLE::const_key_parts for single table UPDATE/DELETE query + + @param conds WHERE clause expression + + @retval TRUE error (OOM) + @retval FALSE success + + @note + Set const_key_parts bits if key fields are equal to constants in + the WHERE expression. +*/ + +bool TABLE::update_const_key_parts(COND *conds) +{ + bzero((char*) const_key_parts, sizeof(key_part_map) * s->keys); + + if (conds == NULL) + return FALSE; + + for (uint index= 0; index < s->keys; index++) + { + KEY_PART_INFO *keyinfo= key_info[index].key_part; + KEY_PART_INFO *keyinfo_end= keyinfo + key_info[index].key_parts; + + for (key_part_map part_map= (key_part_map)1; + keyinfo < keyinfo_end; + keyinfo++, part_map<<= 1) + { + if (const_expression_in_where(conds, NULL, keyinfo->field)) + const_key_parts[index]|= part_map; + } + } + return FALSE; +} + +/** + Test if the order list consists of simple field expressions + + @param order Linked list of ORDER BY arguments + + @return TRUE if @a order is empty or consist of simple field expressions +*/ + +bool is_simple_order(ORDER *order) +{ + for (ORDER *ord= order; ord; ord= ord->next) + { + if (ord->item[0]->real_item()->type() != Item::FIELD_ITEM) + return FALSE; + } + return TRUE; +} + + /***************************************************************************** ** Instansiate templates *****************************************************************************/ diff --git a/sql/table.h b/sql/table.h index 08b9a6e0a01..2bf390aee4d 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1104,6 +1104,8 @@ public: file->extra(HA_EXTRA_NO_KEYREAD); } } + + bool update_const_key_parts(COND *conds); }; @@ -2088,6 +2090,8 @@ inline void mark_as_null_row(TABLE *table) bfill(table->null_flags,table->s->null_bytes,255); } +bool is_simple_order(ORDER *order); + #endif /* MYSQL_CLIENT */ #endif /* TABLE_INCLUDED */ diff --git a/sql/transaction.cc b/sql/transaction.cc index 78551d6fcf7..f6786f20dcf 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -419,9 +419,13 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name) thd->transaction.savepoints= sv; /* - Release metadata locks that were acquired during this savepoint unit. + Release metadata locks that were acquired during this savepoint unit + unless binlogging is on. Releasing locks with binlogging on can break + replication as it allows other connections to drop these tables before + rollback to savepoint is written to the binlog. */ - if (!res) + bool binlog_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin; + if (!res && !binlog_on) thd->mdl_context.rollback_to_savepoint(sv->mdl_savepoint); DBUG_RETURN(test(res)); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 0bcc022a0dc..25267bfb9ea 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1736,6 +1736,21 @@ err: { mysql_file_close(new_file, MYF(0)); info->dfile=new_file= -1; + /* + On Windows, the old data file cannot be deleted if it is either + open, or memory mapped. Closing the file won't remove the memory + map implicilty on Windows. We closed the data file, but we keep + the MyISAM table open. A memory map will be closed on the final + mi_close() only. So we need to unmap explicitly here. After + renaming the new file under the hook, we couldn't use the map of + the old file any more anyway. + */ + if (info->s->file_map) + { + (void) my_munmap((char*) info->s->file_map, + (size_t) info->s->mmaped_length); + info->s->file_map= NULL; + } if (change_to_newfile(share->data_file_name,MI_NAME_DEXT, DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 63d20f127a1..67b81225b13 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -103,6 +103,7 @@ #include "myrg_def.h" #include "thr_malloc.h" // int_sql_alloc #include "sql_class.h" // THD +#include "debug_sync.h" static handler *myisammrg_create_handler(handlerton *hton, TABLE_SHARE *table, @@ -755,6 +756,7 @@ int ha_myisammrg::attach_children(void) /* Must not call this with attached children. */ DBUG_ASSERT(!this->file->children_attached); + DEBUG_SYNC(current_thd, "before_myisammrg_attach"); /* Must call this with children list in place. */ DBUG_ASSERT(this->table->pos_in_table_list->next_global == this->children_l);