2723 Marc Alff 2009-01-06 [merge]
Merge mysql-6.0 --> mysql-6.0-wl2110-review
removed:
mysql-test/t/rpl_slave_exec_mode_basic.test
added:
config/ac-macros/libmemcached.m4
config/ac-macros/search_for_lib.m4
mysql-test/r/innodb_bug34053.result
mysql-test/t/innodb_bug34053.test
mysql-test/t/rpl_slave_exec_mode_basic.test
modified:
BUILD/compile-dist
BUILD/compile-pentium-gcov
BUILD/compile-solaris-amd64
Makefile.am
configure.in
libmysqld/examples/test-run
mysql-test/create-test-result
mysql-test/mysql-test-run.pl
mysql-test/r/func_math.result
mysql-test/r/group_by.result
mysql-test/r/subselect.result
mysql-test/r/subselect2.result
mysql-test/r/subselect3.result
mysql-test/r/subselect3_jcl6.result
mysql-test/r/subselect_mat.result
mysql-test/r/subselect_no_mat.result
mysql-test/r/subselect_no_opts.result
mysql-test/r/subselect_no_semijoin.result
mysql-test/r/subselect_sj.result
mysql-test/r/subselect_sj2.result
mysql-test/r/subselect_sj2_jcl6.result
mysql-test/r/subselect_sj_jcl6.result
mysql-test/r/type_varchar.result
mysql-test/t/func_math.test
mysql-test/t/partition_not_windows.test
mysql-test/t/subselect.test
mysql-test/t/subselect3.test
mysql-test/t/subselect_mat.test
netware/BUILD/nwbootstrap
sql/handler.h
sql/item_cmpfunc.h
sql/item_func.cc
sql/item_subselect.cc
sql/item_subselect.h
sql/mysql_priv.h
sql/mysqld.cc
sql/opt_range.cc
sql/opt_range.h
sql/records.h
sql/sql_base.cc
sql/sql_class.h
sql/sql_join_cache.cc
sql/sql_lex.h
sql/sql_select.cc
sql/sql_select.h
sql/sql_test.cc
sql/sql_union.cc
sql/table.h
storage/archive/support/archive_read_test.slap
storage/innobase/pars/make_bison.sh
storage/innobase/pars/make_flex.sh
storage/maria/ma_test_big.sh
storage/myisam/mi_test_all.sh
storage/myisam/myisam_backup_engine.cc
storage/ndb/demos/run_demo1-PS.sh
storage/ndb/demos/run_demo1-SS.sh
support-files/my-small.cnf.sh
support-files/mysql.spec.sh
2722 Marc Alff 2008-12-19 [merge]
Merge mysql-6.0 --> mysql-6.0-wl2110-review
removed:
.bzr-mysql.moved/
.bzr-mysql.moved/default.conf
mysql-test/include/wait_until_disconnected.inc
mysql-test/r/innodb_bug34053.result
mysql-test/r/rpl_slave_exec_mode_basic.result
mysql-test/suite/rpl_ndb_big/r/rpl_ndb_log.result
mysql-test/suite/rpl_ndb_big/t/rpl_ndb_log-master.opt
mysql-test/suite/rpl_ndb_big/t/rpl_ndb_log.test
mysql-test/t/innodb_bug34053.test
mysql-test/t/rpl_slave_exec_mode_basic.test
added:
mysql-test/extra/rpl_tests/rpl_row_basic_no_pk.test
mysql-test/include/UnicodeData.txt
mysql-test/include/mysqladmin_shutdown.inc
mysql-test/include/show_qc_status.inc
mysql-test/include/wait_until_disconnected.inc
mysql-test/include/world.inc
mysql-test/include/world_schema.inc
mysql-test/include/world_schema1.inc
mysql-test/r/join_cache.result
mysql-test/r/join_nested_jcl6.result
mysql-test/r/join_outer_jcl6.result
mysql-test/r/maria_mrr.result
mysql-test/r/rpl_slave_allow_batching_basic.result
mysql-test/r/rpl_slave_compressed_protocol_basic.result
mysql-test/r/rpl_slave_exec_mode_basic.result
mysql-test/r/rpl_slave_net_timeout_basic.result
mysql-test/r/select_jcl6.result
mysql-test/r/subselect3_jcl6.result
mysql-test/r/subselect_sj2_jcl6.result
mysql-test/r/subselect_sj_jcl6.result
mysql-test/std_data/ndb_apply_status.frm
mysql-test/suite/backup_engines/r/backup_partition.result
mysql-test/suite/backup_engines/t/backup_partition.test
mysql-test/suite/falcon/r/falcon_bug_29246.result
mysql-test/suite/falcon/r/falcon_bug_34351_A-big.result
mysql-test/suite/falcon/r/falcon_bug_34351_C-big.result
mysql-test/suite/falcon/r/falcon_bug_39702.result
mysql-test/suite/falcon/r/falcon_bug_40614.result
mysql-test/suite/falcon/r/falcon_bug_40994.result
mysql-test/suite/falcon/r/falcon_information_schema.result
mysql-test/suite/falcon/r/falcon_unicode-big.result
mysql-test/suite/falcon/t/falcon_bug_29246.test
mysql-test/suite/falcon/t/falcon_bug_34351_A-big.test
mysql-test/suite/falcon/t/falcon_bug_34351_C-big.test
mysql-test/suite/falcon/t/falcon_bug_39702.test
mysql-test/suite/falcon/t/falcon_bug_40614.test
mysql-test/suite/falcon/t/falcon_bug_40994.test
mysql-test/suite/falcon/t/falcon_information_schema.test
mysql-test/suite/falcon/t/falcon_unicode-big.test
mysql-test/suite/maria/r/maria-recovery3.result
mysql-test/suite/maria/r/maria_showlog_error.result
mysql-test/suite/maria/t/maria-recovery3-master.opt
mysql-test/suite/maria/t/maria-recovery3.test
mysql-test/suite/maria/t/maria_showlog_error.test
mysql-test/suite/ndb/r/bug36547.result
mysql-test/suite/ndb/r/ndb_cache_trans.result
mysql-test/suite/ndb/r/ndb_dbug_lock.result
mysql-test/suite/ndb/r/ndb_discover_db.result
mysql-test/suite/ndb/r/ndb_discover_db2.result
mysql-test/suite/ndb/t/bug36547.test
mysql-test/suite/ndb/t/ndb_cache_trans.test
mysql-test/suite/ndb/t/ndb_dbug_lock.test
mysql-test/suite/ndb/t/ndb_discover_db.test
mysql-test/suite/ndb/t/ndb_discover_db2-master.opt
mysql-test/suite/ndb/t/ndb_discover_db2.test
mysql-test/suite/ndb_binlog/
mysql-test/suite/ndb_binlog/r/
mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result
mysql-test/suite/ndb_binlog/t/
mysql-test/suite/ndb_binlog/t/ndb_binlog_restore-master.opt
mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test
mysql-test/suite/parts/r/partition_alter2_1_maria.result
mysql-test/suite/parts/r/partition_alter2_2_maria.result
mysql-test/suite/parts/r/partition_auto_increment_maria.result
mysql-test/suite/parts/t/partition_alter2_1_maria.test
mysql-test/suite/parts/t/partition_alter2_2_maria.test
mysql-test/suite/parts/t/partition_auto_increment_maria.test
mysql-test/suite/rpl/r/rpl_extraCol_falcon.result
mysql-test/suite/rpl/r/rpl_extraColmaster_falcon.result
mysql-test/suite/rpl/r/rpl_locktrans_falcon.result
mysql-test/suite/rpl/r/rpl_relay_space_falcon.result
mysql-test/suite/rpl/r/rpl_row_blob_falcon.result
mysql-test/suite/rpl/r/rpl_truncate_falcon.result
mysql-test/suite/rpl/t/rpl_extraCol_falcon.test
mysql-test/suite/rpl/t/rpl_extraColmaster_falcon.test
mysql-test/suite/rpl/t/rpl_locktrans_falcon.test
mysql-test/suite/rpl/t/rpl_relay_space_falcon.test
mysql-test/suite/rpl/t/rpl_row_blob_falcon.test
mysql-test/suite/rpl/t/rpl_truncate_falcon.test
mysql-test/suite/rpl_ndb/r/rpl_ndb_bug22045.result
mysql-test/suite/rpl_ndb/t/rpl_ndb_bug22045.test
mysql-test/t/join_cache.test
mysql-test/t/join_nested_jcl6.test
mysql-test/t/join_outer_jcl6.test
mysql-test/t/maria_mrr.test
mysql-test/t/rpl_slave_allow_batching_basic.test
mysql-test/t/rpl_slave_compressed_protocol_basic.test
mysql-test/t/rpl_slave_exec_mode_basic.test
mysql-test/t/rpl_slave_net_timeout_basic.test
mysql-test/t/select_jcl6.test
mysql-test/t/subselect3_jcl6.test
mysql-test/t/subselect_sj2_jcl6.test
mysql-test/t/subselect_sj_jcl6.test
mysys/tests/
mysys/tests/Makefile.am
mysys/tests/test_thr_mutex.c
sql/backup/debug.h
sql/ha_ndbcluster_lock_ext.h
sql/sql_join_cache.cc
storage/falcon/CompareAndSwapSparc.h
storage/ndb/include/util/NdbTap.hpp
storage/ndb/ndbapi-examples/ndbapi_recattr_vs_record/
storage/ndb/ndbapi-examples/ndbapi_recattr_vs_record/Makefile
storage/ndb/ndbapi-examples/ndbapi_recattr_vs_record/main.cpp
storage/ndb/src/common/util/ndb_show_compat.cpp
storage/ndb/swig/
storage/ndb/swig/Makefile.am
storage/ndb/swig/globals.i
storage/ndb/swig/mgmapi/
storage/ndb/swig/mgmapi/ClusterState.i
storage/ndb/swig/mgmapi/NdbLogEvent.i
storage/ndb/swig/mgmapi/NdbLogEventManager.i
storage/ndb/swig/mgmapi/NdbMgm.i
storage/ndb/swig/mgmapi/NdbMgmFactory.i
storage/ndb/swig/mgmapi/NdbMgmReply.i
storage/ndb/swig/mgmapi/NodeState.i
storage/ndb/swig/mgmapi/events.i
storage/ndb/swig/mgmapi/listeners.i
storage/ndb/swig/mgmapi/mgmglobals.i
storage/ndb/swig/ndbapi/
storage/ndb/swig/ndbapi/Ndb.i
storage/ndb/swig/ndbapi/NdbBlob.i
storage/ndb/swig/ndbapi/NdbClusterConnection.i
storage/ndb/swig/ndbapi/NdbDictionary.i
storage/ndb/swig/ndbapi/NdbError.i
storage/ndb/swig/ndbapi/NdbEventOperation.i
storage/ndb/swig/ndbapi/NdbFactory.i
storage/ndb/swig/ndbapi/NdbIndexOperation.i
storage/ndb/swig/ndbapi/NdbIndexScanOperation.i
storage/ndb/swig/ndbapi/NdbOperation.i
storage/ndb/swig/ndbapi/NdbRecAttr.i
storage/ndb/swig/ndbapi/NdbScanFilter.i
storage/ndb/swig/ndbapi/NdbScanOperation.i
storage/ndb/swig/ndbapi/NdbTransaction.i
storage/ndb/swig/ndbapi/ndbglobals.i
storage/ndb/test/include/SqlClient.hpp
storage/ndb/test/ndbapi/testUpgrade.cpp
storage/ndb/test/run-test/atrt-backtrace.sh
storage/ndb/test/run-test/command.cpp
storage/ndb/test/run-test/db.cpp
storage/ndb/test/run-test/db.sql
storage/ndb/test/src/SqlClient.cpp
renamed:
mysql-test/r/rpl_slave_allow_batching_basic.result => mysql-test/r/slave_allow_batching_basic.result
mysql-test/r/rpl_slave_compressed_protocol_basic.result => mysql-test/r/slave_compressed_protocol_basic.result
mysql-test/r/rpl_slave_net_timeout_basic.result => mysql-test/r/slave_net_timeout_basic.result
mysql-test/suite/funcs_1/r/is_collation_charset_applic.result => mysql-test/suite/funcs_1/r/is_collation_character_set_applicability.result
mysql-test/suite/funcs_1/t/is_collation_charset_applic.test => mysql-test/suite/funcs_1/t/is_collation_character_set_applicability.test
mysql-test/suite/ndb/r/ndb_binlog_basic.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_basic.result
mysql-test/suite/ndb/r/ndb_binlog_ddl_multi.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_ddl_multi.result
mysql-test/suite/ndb/r/ndb_binlog_discover.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_discover.result
mysql-test/suite/ndb/r/ndb_binlog_ignore_db.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_ignore_db.result
mysql-test/suite/ndb/r/ndb_binlog_log_bin.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_log_bin.result
mysql-test/suite/ndb/r/ndb_binlog_multi.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_multi.result
mysql-test/suite/ndb/t/ndb_binlog_basic.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_basic.test
mysql-test/suite/ndb/t/ndb_binlog_ddl_multi.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_ddl_multi.test
mysql-test/suite/ndb/t/ndb_binlog_discover.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_discover.test
mysql-test/suite/ndb/t/ndb_binlog_ignore_db-master.opt => mysql-test/suite/ndb_binlog/t/ndb_binlog_ignore_db-master.opt
mysql-test/suite/ndb/t/ndb_binlog_ignore_db.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_ignore_db.test
mysql-test/suite/ndb/t/ndb_binlog_log_bin.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_log_bin.test
mysql-test/suite/ndb/t/ndb_binlog_multi.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_multi.test
mysql-test/suite/ndb_team/r/ndb_binlog_format.result => mysql-test/suite/ndb_binlog/r/ndb_binlog_format.result
mysql-test/suite/ndb_team/r/ndb_dd_restore_compat.result => mysql-test/suite/ndb/r/ndb_dd_restore_compat.result
mysql-test/suite/ndb_team/t/ndb_binlog_format.test => mysql-test/suite/ndb_binlog/t/ndb_binlog_format.test
mysql-test/suite/ndb_team/t/ndb_dd_restore_compat.test => mysql-test/suite/ndb/t/ndb_dd_restore_compat.test
mysql-test/suite/rpl_ndb_big/r/rpl_ndb_add_column.result => mysql-test/suite/rpl_ndb/r/rpl_ndb_add_column.result
mysql-test/suite/rpl_ndb_big/t/rpl_ndb_add_column.test => mysql-test/suite/rpl_ndb/t/rpl_ndb_add_column.test
mysql-test/t/rpl_slave_allow_batching_basic.test => mysql-test/t/slave_allow_batching_basic.test
mysql-test/t/rpl_slave_compressed_protocol_basic.test => mysql-test/t/slave_compressed_protocol_basic.test
mysql-test/t/rpl_slave_net_timeout_basic.test => mysql-test/t/slave_net_timeout_basic.test
mysys/test_charset.c => mysys/tests/test_charset.c
mysys/test_dir.c => mysys/tests/test_dir.c
mysys/testhash.c => mysys/tests/testhash.c
storage/ndb/src/common/util/ndb_init.c => storage/ndb/src/common/util/ndb_init.cpp
modified:
.bzrignore
BUILD/SETUP.sh
BUILD/autorun.sh
CMakeLists.txt
Makefile.am
client/CMakeLists.txt
client/Makefile.am
client/mysql.cc
client/mysqladmin.cc
client/mysqldump.c
client/mysqlimport.c
client/mysqlshow.c
client/mysqlslap.c
client/mysqltest.c
cluster_change_hist.txt
config/ac-macros/ha_ndbcluster.m4
config/ac-macros/misc.m4
config/ac-macros/zlib.m4
configure.in
dbug/CMakeLists.txt
dbug/Makefile.am
dbug/dbug.c
extra/CMakeLists.txt
extra/Makefile.am
include/config-win.h
include/hash.h
include/my_base.h
include/my_pthread.h
include/mysql.h.pp
include/mysql_com.h
include/thr_lock.h
include/waiting_threads.h
libmysql/CMakeLists.txt
libmysql/Makefile.am
libmysql/Makefile.shared
libmysqld/CMakeLists.txt
libmysqld/Makefile.am
libmysqld/examples/CMakeLists.txt
libmysqld/examples/Makefile.am
mysql-test/extra/rpl_tests/rpl_row_basic.test
mysql-test/extra/rpl_tests/rpl_truncate_helper.test
mysql-test/include/have_blackhole.inc
mysql-test/include/maria_empty_logs.inc
mysql-test/include/restart_mysqld.inc
mysql-test/include/wait_until_connected_again.inc
mysql-test/lib/mtr_cases.pl
mysql-test/lib/mtr_report.pl
mysql-test/mysql-test-run.pl
mysql-test/r/compress.result
mysql-test/r/fulltext.result
mysql-test/r/index_merge_myisam.result
mysql-test/r/join_nested.result
mysql-test/r/join_outer.result
mysql-test/r/myisam_mrr.result
mysql-test/r/named_pipe.result
mysql-test/r/order_by.result
mysql-test/r/pool_of_threads.result
mysql-test/r/select.result
mysql-test/r/shm.result
mysql-test/r/signal.result
mysql-test/r/signal_demo3.result
mysql-test/r/signal_utf32.result
mysql-test/r/sp-error.result
mysql-test/r/ssl.result
mysql-test/r/ssl_compress.result
mysql-test/r/subselect3.result
mysql-test/r/subselect_sj.result
mysql-test/r/subselect_sj2.result
mysql-test/r/view.result
mysql-test/suite/backup/r/backup.result
mysql-test/suite/backup/r/backup_backupdir.result
mysql-test/suite/backup/r/backup_default.result
mysql-test/suite/backup/r/backup_errors.result
mysql-test/suite/backup/r/backup_views.result
mysql-test/suite/backup/t/backup.test
mysql-test/suite/backup/t/backup_backupdir.test
mysql-test/suite/backup/t/backup_default.test
mysql-test/suite/backup/t/backup_errors.test
mysql-test/suite/backup/t/backup_myisam1.test
mysql-test/suite/backup/t/backup_views.test
mysql-test/suite/backup/t/disabled.def
mysql-test/suite/binlog/r/binlog_multi_engine.result
mysql-test/suite/falcon/r/falcon_bug_22089.result
mysql-test/suite/falcon/r/falcon_bug_22181.result
mysql-test/suite/falcon/r/falcon_bug_34351_A.result
mysql-test/suite/falcon/r/falcon_bug_34351_C.result
mysql-test/suite/falcon/r/falcon_bug_39708.result
mysql-test/suite/falcon/r/falcon_online_index.result
mysql-test/suite/falcon/r/falcon_options.result
mysql-test/suite/falcon/r/falcon_options2.result
mysql-test/suite/falcon/r/falcon_select.result
mysql-test/suite/falcon/r/index_merge_falcon.result
mysql-test/suite/falcon/t/disabled.def
mysql-test/suite/falcon/t/falcon_bug_22089.test
mysql-test/suite/falcon/t/falcon_bug_22181.test
mysql-test/suite/falcon/t/falcon_bug_28095.test
mysql-test/suite/falcon/t/falcon_bug_34351_A.test
mysql-test/suite/falcon/t/falcon_bug_34351_C.test
mysql-test/suite/falcon/t/falcon_bug_39708-master.opt
mysql-test/suite/falcon/t/falcon_bug_39708.test
mysql-test/suite/falcon/t/falcon_options.test
mysql-test/suite/falcon/t/falcon_options2.test
mysql-test/suite/funcs_1/r/ndb_trig_1011ext.result
mysql-test/suite/funcs_1/r/processlist_val_ps.result
mysql-test/suite/funcs_1/t/disabled.def
mysql-test/suite/funcs_2/t/disabled.def
mysql-test/suite/maria/r/maria-big.result
mysql-test/suite/maria/r/maria-preload.result
mysql-test/suite/maria/r/maria-recovery-big.result
mysql-test/suite/maria/r/maria.result
mysql-test/suite/maria/r/maria3.result
mysql-test/suite/maria/r/maria_notembedded.result
mysql-test/suite/maria/t/maria-big.test
mysql-test/suite/maria/t/maria-lock.test
mysql-test/suite/maria/t/maria-recovery-big-master.opt
mysql-test/suite/maria/t/maria-recovery-big.test
mysql-test/suite/maria/t/maria.test
mysql-test/suite/maria/t/maria3.test
mysql-test/suite/maria/t/maria_notembedded.test
mysql-test/suite/ndb/r/ndb_alter_table.result
mysql-test/suite/ndb/r/ndb_alter_table3.result
mysql-test/suite/ndb/r/ndb_alter_table_backup.result
mysql-test/suite/ndb/r/ndb_alter_table_online.result
mysql-test/suite/ndb/r/ndb_alter_table_online2.result
mysql-test/suite/ndb/r/ndb_basic.result
mysql-test/suite/ndb/r/ndb_blob.result
mysql-test/suite/ndb/r/ndb_cache.result
mysql-test/suite/ndb/r/ndb_condition_pushdown.result
mysql-test/suite/ndb/r/ndb_dd_ddl.result
mysql-test/suite/ndb/r/ndb_insert.result
mysql-test/suite/ndb/r/ndb_multi_row.result
mysql-test/suite/ndb/r/ndb_partition_range.result
mysql-test/suite/ndb/r/ndb_read_multi_range.result
mysql-test/suite/ndb/r/ndb_replace.result
mysql-test/suite/ndb/r/ndb_restore.result
mysql-test/suite/ndb/r/ndb_restore_compat.result
mysql-test/suite/ndb/r/ndb_restore_different_endian_data.result
mysql-test/suite/ndb/r/ndb_single_user.result
mysql-test/suite/ndb/r/ndb_trigger.result
mysql-test/suite/ndb/t/disabled.def
mysql-test/suite/ndb/t/ndb_alter_table.test
mysql-test/suite/ndb/t/ndb_alter_table3.test
mysql-test/suite/ndb/t/ndb_alter_table_backup.test
mysql-test/suite/ndb/t/ndb_alter_table_online.test
mysql-test/suite/ndb/t/ndb_alter_table_online2.test
mysql-test/suite/ndb/t/ndb_basic.test
mysql-test/suite/ndb/t/ndb_blob.test
mysql-test/suite/ndb/t/ndb_cache.test
mysql-test/suite/ndb/t/ndb_cache2.test
mysql-test/suite/ndb/t/ndb_condition_pushdown.test
mysql-test/suite/ndb/t/ndb_dd_ddl.test
mysql-test/suite/ndb/t/ndb_dd_dump.test
mysql-test/suite/ndb/t/ndb_insert.test
mysql-test/suite/ndb/t/ndb_partition_range.test
mysql-test/suite/ndb/t/ndb_read_multi_range.test
mysql-test/suite/ndb/t/ndb_replace.test
mysql-test/suite/ndb/t/ndb_restore.test
mysql-test/suite/ndb/t/ndb_restore_compat.test
mysql-test/suite/ndb/t/ndb_restore_different_endian_data.test
mysql-test/suite/ndb/t/ndb_single_user.test
mysql-test/suite/ndb/t/ndb_trigger.test
mysql-test/suite/ndb_team/r/ndb_autodiscover3.result
mysql-test/suite/ndb_team/t/ndb_autodiscover3.test
mysql-test/suite/ndb_team/t/rpl_ndb_dd_advance.test
mysql-test/suite/parts/r/partition_engine_ndb.result
mysql-test/suite/rpl/r/rpl_heartbeat.result
mysql-test/suite/rpl/r/rpl_locktrans_innodb.result
mysql-test/suite/rpl/r/rpl_rbr_to_sbr.result
mysql-test/suite/rpl/r/rpl_truncate_2myisam.result
mysql-test/suite/rpl/r/rpl_truncate_3innodb.result
mysql-test/suite/rpl/t/disabled.def
mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test
mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test
mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test
mysql-test/suite/rpl_ndb/r/rpl_ndb_basic.result
mysql-test/suite/rpl_ndb/t/disabled.def
mysql-test/suite/rpl_ndb/t/rpl_ndb_basic.test
mysql-test/suite/rpl_ndb_big/r/rpl_ndb_apply_status.result
mysql-test/suite/rpl_ndb_big/r/rpl_row_basic_7ndb.result
mysql-test/suite/rpl_ndb_big/t/disabled.def
mysql-test/suite/rpl_ndb_big/t/rpl_ndb_apply_status.test
mysql-test/suite/rpl_ndb_big/t/rpl_row_basic_7ndb.test
mysql-test/t/events_logs_tests-master.opt
mysql-test/t/fulltext.test
mysql-test/t/log_tables-big-master.opt
mysql-test/t/log_tables-master.opt
mysql-test/t/multi_statement-master.opt
mysql-test/t/partition_not_windows.test
mysql-test/t/ps-master.opt
mysql-test/t/show_check-master.opt
mysql-test/t/slow_query_log_file_basic-master.opt
mysql-test/t/slow_query_log_file_func-master.opt
mysql-test/t/sp-error.test
mysql-test/t/status.test
mysql-test/t/subselect3.test
mysql-test/t/union-master.opt
mysys/CMakeLists.txt
mysys/Makefile.am
mysys/hash.c
mysys/lf_hash.c
mysys/my_bitmap.c
mysys/my_getopt.c
mysys/my_init.c
mysys/my_pthread.c
mysys/my_sleep.c
mysys/my_thr_init.c
mysys/my_wincond.c
mysys/my_winthread.c
mysys/mysys_priv.h
mysys/queues.c
mysys/stacktrace.c
mysys/thr_mutex.c
mysys/waiting_threads.c
netware/Makefile.am
regex/CMakeLists.txt
regex/Makefile.am
scripts/CMakeLists.txt
scripts/Makefile.am
scripts/make_win_bin_dist
sql/CMakeLists.txt
sql/Makefile.am
sql/backup/CMakeLists.txt
sql/backup/backup_info.cc
sql/backup/backup_info.h
sql/backup/backup_kernel.h
sql/backup/be_thread.cc
sql/backup/data_backup.cc
sql/backup/image_info.cc
sql/backup/image_info.h
sql/backup/kernel.cc
sql/backup/logger.cc
sql/backup/logger.h
sql/backup/restore_info.h
sql/backup/stream.cc
sql/backup/stream.h
sql/event_db_repository.cc
sql/event_parse_data.cc
sql/event_parse_data.h
sql/event_queue.cc
sql/event_scheduler.cc
sql/events.cc
sql/field.cc
sql/field.h
sql/gen_lex_hash.cc
sql/ha_ndbcluster.cc
sql/ha_ndbcluster.h
sql/ha_ndbcluster_binlog.cc
sql/ha_ndbcluster_binlog.h
sql/ha_ndbcluster_cond.cc
sql/ha_ndbcluster_cond.h
sql/ha_ndbcluster_connection.cc
sql/ha_ndbcluster_connection.h
sql/ha_partition.cc
sql/ha_partition.h
sql/handler.cc
sql/handler.h
sql/item.cc
sql/item.h
sql/item_create.cc
sql/item_func.cc
sql/item_func.h
sql/lock.cc
sql/log.cc
sql/log_event.cc
sql/mysql_priv.h
sql/mysqld.cc
sql/opt_range.cc
sql/partition_info.h
sql/protocol.cc
sql/rpl_injector.cc
sql/rpl_injector.h
sql/rpl_mi.cc
sql/set_var.cc
sql/share/errmsg.txt
sql/si_logs.h
sql/sp_cache.cc
sql/sp_cache.h
sql/sp_head.cc
sql/sql_audit.cc
sql/sql_base.cc
sql/sql_cache.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_connect.cc
sql/sql_db.cc
sql/sql_delete.cc
sql/sql_insert.cc
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_parse.cc
sql/sql_partition.cc
sql/sql_rename.cc
sql/sql_repl.cc
sql/sql_select.cc
sql/sql_select.h
sql/sql_show.cc
sql/sql_show.h
sql/sql_table.cc
sql/sql_union.cc
sql/sql_update.cc
sql/sql_yacc.yy
sql/table.cc
sql/table.h
sql/udf_example.c
storage/archive/Makefile.am
storage/archive/archive_reader.c
storage/blackhole/CMakeLists.txt
storage/blackhole/ha_blackhole.cc
storage/blackhole/ha_blackhole.h
storage/csv/CMakeLists.txt
storage/example/CMakeLists.txt
storage/falcon/CompareAndSwapSparc.il
storage/falcon/Configuration.cpp
storage/falcon/DataPage.cpp
storage/falcon/Database.cpp
storage/falcon/IO.cpp
storage/falcon/Index.cpp
storage/falcon/IndexRootPage.cpp
storage/falcon/IndexWalker.cpp
storage/falcon/Interlock.h
storage/falcon/Log.h
storage/falcon/Makefile.am
storage/falcon/MySQLCollation.cpp
storage/falcon/PageInventoryPage.cpp
storage/falcon/SRLBlobDelete.h
storage/falcon/SRLBlobUpdate.h
storage/falcon/SRLCreateIndex.h
storage/falcon/SRLCreateSection.h
storage/falcon/SRLCreateTableSpace.cpp
storage/falcon/SRLCreateTableSpace.h
storage/falcon/SRLData.h
storage/falcon/SRLDelete.h
storage/falcon/SRLDeleteIndex.cpp
storage/falcon/SRLDeleteIndex.h
storage/falcon/SRLDropTableSpace.cpp
storage/falcon/SRLDropTableSpace.h
storage/falcon/SRLFreePage.h
storage/falcon/SRLIndexAdd.h
storage/falcon/SRLIndexDelete.h
storage/falcon/SRLIndexPage.h
storage/falcon/SRLInversionPage.h
storage/falcon/SRLOverflowPages.h
storage/falcon/SRLRecordLocator.h
storage/falcon/SRLRecordStub.h
storage/falcon/SRLSectionLine.h
storage/falcon/SRLSectionPage.h
storage/falcon/SRLSectionPromotion.h
storage/falcon/SRLSequencePage.h
storage/falcon/SRLUpdateBlob.h
storage/falcon/SRLUpdateIndex.h
storage/falcon/SRLUpdateRecords.cpp
storage/falcon/SRLUpdateRecords.h
storage/falcon/SerialLog.cpp
storage/falcon/SerialLog.h
storage/falcon/SerialLogRecord.cpp
storage/falcon/SerialLogRecord.h
storage/falcon/StorageTable.cpp
storage/falcon/StorageVersion.h
storage/falcon/Table.cpp
storage/falcon/Table.h
storage/falcon/Transaction.cpp
storage/falcon/TransformLib/StringTransform.cpp
storage/falcon/Value.cpp
storage/falcon/ha_falcon.cpp
storage/falcon/ha_falcon.h
storage/falcon/plug.in
storage/heap/CMakeLists.txt
storage/heap/Makefile.am
storage/innobase/CMakeLists.txt
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.h
storage/maria/CMakeLists.txt
storage/maria/KNOWN_BUGS.txt
storage/maria/Makefile.am
storage/maria/ha_maria.cc
storage/maria/ha_maria.h
storage/maria/ma_bitmap.c
storage/maria/ma_blockrec.c
storage/maria/ma_blockrec.h
storage/maria/ma_checkpoint.c
storage/maria/ma_close.c
storage/maria/ma_commit.c
storage/maria/ma_control_file.c
storage/maria/ma_delete.c
storage/maria/ma_extra.c
storage/maria/ma_key.c
storage/maria/ma_loghandler.c
storage/maria/ma_open.c
storage/maria/ma_pagecache.c
storage/maria/ma_recovery.c
storage/maria/ma_rkey.c
storage/maria/ma_rnext.c
storage/maria/ma_rnext_same.c
storage/maria/ma_state.c
storage/maria/ma_state.h
storage/maria/ma_test1.c
storage/maria/ma_test2.c
storage/maria/ma_update.c
storage/maria/ma_write.c
storage/maria/maria_def.h
storage/maria/trnman.c
storage/maria/trnman_public.h
storage/maria/unittest/CMakeLists.txt
storage/maria/unittest/Makefile.am
storage/myisam/CMakeLists.txt
storage/myisam/Makefile.am
storage/myisam/ha_myisam.cc
storage/myisam/ha_myisam.h
storage/myisam/mi_open.c
storage/myisam/myisampack.c
storage/myisammrg/CMakeLists.txt
storage/myisammrg/ha_myisammrg.cc
storage/ndb/Makefile.am
storage/ndb/config/common.mk.am
storage/ndb/config/type_ndbapitest.mk.am
storage/ndb/config/type_ndbapitools.mk.am
storage/ndb/docs/doxygen/postdoxy.pl
storage/ndb/include/debugger/SignalLoggerManager.hpp
storage/ndb/include/kernel/Interpreter.hpp
storage/ndb/include/kernel/NodeState.hpp
storage/ndb/include/kernel/signaldata/AttrInfo.hpp
storage/ndb/include/kernel/signaldata/DictLock.hpp
storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp
storage/ndb/include/kernel/signaldata/KeyInfo.hpp
storage/ndb/include/kernel/signaldata/ListTables.hpp
storage/ndb/include/kernel/signaldata/SumaImpl.hpp
storage/ndb/include/logger/LogHandler.hpp
storage/ndb/include/logger/Logger.hpp
storage/ndb/include/mgmapi/mgmapi.h
storage/ndb/include/mgmapi/mgmapi_config_parameters.h
storage/ndb/include/mgmapi/mgmapi_debug.h
storage/ndb/include/mgmapi/mgmapi_error.h
storage/ndb/include/mgmapi/ndb_logevent.h
storage/ndb/include/ndb_constants.h
storage/ndb/include/ndb_version.h.in
storage/ndb/include/ndbapi/Ndb.hpp
storage/ndb/include/ndbapi/NdbApi.hpp
storage/ndb/include/ndbapi/NdbBlob.hpp
storage/ndb/include/ndbapi/NdbDictionary.hpp
storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp
storage/ndb/include/ndbapi/NdbIndexStat.hpp
storage/ndb/include/ndbapi/NdbInterpretedCode.hpp
storage/ndb/include/ndbapi/NdbOperation.hpp
storage/ndb/include/ndbapi/NdbRecAttr.hpp
storage/ndb/include/ndbapi/NdbReceiver.hpp
storage/ndb/include/ndbapi/NdbScanFilter.hpp
storage/ndb/include/ndbapi/NdbScanOperation.hpp
storage/ndb/include/ndbapi/NdbTransaction.hpp
storage/ndb/include/util/BaseString.hpp
storage/ndb/include/util/InputStream.hpp
storage/ndb/include/util/NdbOut.hpp
storage/ndb/include/util/OutputStream.hpp
storage/ndb/include/util/SimpleProperties.hpp
storage/ndb/include/util/SocketServer.hpp
storage/ndb/include/util/basestring_vsnprintf.h
storage/ndb/include/util/ndb_opts.h
storage/ndb/include/util/socket_io.h
storage/ndb/ndbapi-examples/Makefile
storage/ndb/ndbapi-examples/mgmapi_logevent/Makefile
storage/ndb/ndbapi-examples/mgmapi_logevent2/Makefile
storage/ndb/ndbapi-examples/ndbapi_async/Makefile
storage/ndb/ndbapi-examples/ndbapi_async1/Makefile
storage/ndb/ndbapi-examples/ndbapi_blob/Makefile
storage/ndb/ndbapi-examples/ndbapi_blob_ndbrecord/Makefile
storage/ndb/ndbapi-examples/ndbapi_blob_ndbrecord/main.cpp
storage/ndb/ndbapi-examples/ndbapi_event/Makefile
storage/ndb/ndbapi-examples/ndbapi_retries/Makefile
storage/ndb/ndbapi-examples/ndbapi_s_i_ndbrecord/Makefile
storage/ndb/ndbapi-examples/ndbapi_s_i_ndbrecord/main.cpp
storage/ndb/ndbapi-examples/ndbapi_scan/Makefile
storage/ndb/ndbapi-examples/ndbapi_simple/Makefile
storage/ndb/ndbapi-examples/ndbapi_simple_dual/Makefile
storage/ndb/ndbapi-examples/ndbapi_simple_index/Makefile
storage/ndb/src/Makefile.am
storage/ndb/src/common/debugger/EventLogger.cpp
storage/ndb/src/common/debugger/signaldata/SignalNames.cpp
storage/ndb/src/common/logger/LogHandler.cpp
storage/ndb/src/common/logger/Logger.cpp
storage/ndb/src/common/portlib/NdbCondition.c
storage/ndb/src/common/portlib/NdbTick.c
storage/ndb/src/common/transporter/TCP_Transporter.cpp
storage/ndb/src/common/transporter/Transporter.cpp
storage/ndb/src/common/transporter/TransporterRegistry.cpp
storage/ndb/src/common/util/BaseString.cpp
storage/ndb/src/common/util/Makefile.am
storage/ndb/src/common/util/OutputStream.cpp
storage/ndb/src/common/util/SocketServer.cpp
storage/ndb/src/common/util/socket_io.cpp
storage/ndb/src/common/util/version.c
storage/ndb/src/cw/cpcd/APIService.cpp
storage/ndb/src/cw/cpcd/Makefile.am
storage/ndb/src/cw/cpcd/Process.cpp
storage/ndb/src/cw/cpcd/main.cpp
storage/ndb/src/kernel/Makefile.am
storage/ndb/src/kernel/blocks/ERROR_codes.txt
storage/ndb/src/kernel/blocks/Makefile.am
storage/ndb/src/kernel/blocks/backup/Backup.cpp
storage/ndb/src/kernel/blocks/backup/Makefile.am
storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
storage/ndb/src/kernel/blocks/dbdict/Makefile.am
storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
storage/ndb/src/kernel/blocks/dbdih/Makefile.am
storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
storage/ndb/src/kernel/blocks/dblqh/Makefile.am
storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
storage/ndb/src/kernel/blocks/dbtup/Makefile.am
storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp
storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp
storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
storage/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
storage/ndb/src/kernel/blocks/lgman.cpp
storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
storage/ndb/src/kernel/blocks/restore.cpp
storage/ndb/src/kernel/blocks/suma/Suma.cpp
storage/ndb/src/kernel/blocks/suma/Suma.hpp
storage/ndb/src/kernel/blocks/suma/SumaInit.cpp
storage/ndb/src/kernel/blocks/trix/Trix.cpp
storage/ndb/src/kernel/blocks/trix/Trix.hpp
storage/ndb/src/kernel/blocks/tsman.cpp
storage/ndb/src/kernel/error/ErrorReporter.cpp
storage/ndb/src/kernel/main.cpp
storage/ndb/src/kernel/vm/Configuration.cpp
storage/ndb/src/kernel/vm/Emulator.cpp
storage/ndb/src/kernel/vm/LongSignal.hpp
storage/ndb/src/kernel/vm/Makefile.am
storage/ndb/src/kernel/vm/RequestTracker.hpp
storage/ndb/src/kernel/vm/SafeCounter.cpp
storage/ndb/src/kernel/vm/SafeCounter.hpp
storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp
storage/ndb/src/kernel/vm/SimulatedBlock.cpp
storage/ndb/src/kernel/vm/SimulatedBlock.hpp
storage/ndb/src/kernel/vm/TransporterCallback.cpp
storage/ndb/src/kernel/vm/WatchDog.cpp
storage/ndb/src/kernel/vm/bench_pool.cpp
storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp
storage/ndb/src/kernel/vm/pc.hpp
storage/ndb/src/mgmapi/LocalConfig.cpp
storage/ndb/src/mgmapi/mgmapi.cpp
storage/ndb/src/mgmclient/CommandInterpreter.cpp
storage/ndb/src/mgmclient/Makefile.am
storage/ndb/src/mgmsrv/ConfigInfo.cpp
storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
storage/ndb/src/mgmsrv/Makefile.am
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/Services.cpp
storage/ndb/src/mgmsrv/main.cpp
storage/ndb/src/ndbapi/ClusterMgr.cpp
storage/ndb/src/ndbapi/DictCache.cpp
storage/ndb/src/ndbapi/DictCache.hpp
storage/ndb/src/ndbapi/Makefile.am
storage/ndb/src/ndbapi/Ndb.cpp
storage/ndb/src/ndbapi/NdbApiSignal.hpp
storage/ndb/src/ndbapi/NdbBlob.cpp
storage/ndb/src/ndbapi/NdbDictionary.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
storage/ndb/src/ndbapi/NdbIndexStat.cpp
storage/ndb/src/ndbapi/NdbInterpretedCode.cpp
storage/ndb/src/ndbapi/NdbOperation.cpp
storage/ndb/src/ndbapi/NdbOperationDefine.cpp
storage/ndb/src/ndbapi/NdbOperationExec.cpp
storage/ndb/src/ndbapi/NdbOperationInt.cpp
storage/ndb/src/ndbapi/NdbOperationSearch.cpp
storage/ndb/src/ndbapi/NdbRecAttr.cpp
storage/ndb/src/ndbapi/NdbReceiver.cpp
storage/ndb/src/ndbapi/NdbRecord.hpp
storage/ndb/src/ndbapi/NdbScanFilter.cpp
storage/ndb/src/ndbapi/NdbScanOperation.cpp
storage/ndb/src/ndbapi/NdbTransaction.cpp
storage/ndb/src/ndbapi/Ndbif.cpp
storage/ndb/src/ndbapi/Ndbinit.cpp
storage/ndb/src/ndbapi/ObjectMap.cpp
storage/ndb/src/ndbapi/ObjectMap.hpp
storage/ndb/src/ndbapi/TransporterFacade.cpp
storage/ndb/src/ndbapi/TransporterFacade.hpp
storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
storage/ndb/src/ndbapi/ndberror.c
storage/ndb/test/include/AtrtClient.hpp
storage/ndb/test/include/DbUtil.hpp
storage/ndb/test/include/HugoAsynchTransactions.hpp
storage/ndb/test/include/HugoOperations.hpp
storage/ndb/test/include/HugoTransactions.hpp
storage/ndb/test/include/NDBT_Test.hpp
storage/ndb/test/include/NdbRestarter.hpp
storage/ndb/test/ndbapi/Makefile.am
storage/ndb/test/ndbapi/ScanFilter.hpp
storage/ndb/test/ndbapi/ScanFunctions.hpp
storage/ndb/test/ndbapi/ScanInterpretTest.hpp
storage/ndb/test/ndbapi/acrt/NdbRepStress.cpp
storage/ndb/test/ndbapi/bank/Bank.cpp
storage/ndb/test/ndbapi/bank/BankLoad.cpp
storage/ndb/test/ndbapi/bench/mainAsyncGenerator.cpp
storage/ndb/test/ndbapi/bench/ndb_async2.cpp
storage/ndb/test/ndbapi/bench/testData.h
storage/ndb/test/ndbapi/flexAsynch.cpp
storage/ndb/test/ndbapi/flexBench.cpp
storage/ndb/test/ndbapi/flexScan.cpp
storage/ndb/test/ndbapi/msa.cpp
storage/ndb/test/ndbapi/testBlobs.cpp
storage/ndb/test/ndbapi/testDataBuffers.cpp
storage/ndb/test/ndbapi/testDict.cpp
storage/ndb/test/ndbapi/testIndex.cpp
storage/ndb/test/ndbapi/testIndexStat.cpp
storage/ndb/test/ndbapi/testInterpreter.cpp
storage/ndb/test/ndbapi/testNDBT.cpp
storage/ndb/test/ndbapi/testNdbApi.cpp
storage/ndb/test/ndbapi/testNodeRestart.cpp
storage/ndb/test/ndbapi/testOIBasic.cpp
storage/ndb/test/ndbapi/testOperations.cpp
storage/ndb/test/ndbapi/testPartitioning.cpp
storage/ndb/test/ndbapi/testSRBank.cpp
storage/ndb/test/ndbapi/testScan.cpp
storage/ndb/test/ndbapi/testScanFilter.cpp
storage/ndb/test/ndbapi/testScanPerf.cpp
storage/ndb/test/ndbapi/testSystemRestart.cpp
storage/ndb/test/ndbapi/testTransactions.cpp
storage/ndb/test/ndbapi/test_event.cpp
storage/ndb/test/run-test/Makefile.am
storage/ndb/test/run-test/atrt-analyze-result.sh
storage/ndb/test/run-test/atrt.hpp
storage/ndb/test/run-test/autotest-boot.sh
storage/ndb/test/run-test/autotest-run.sh
storage/ndb/test/run-test/daily-basic-tests.txt
storage/ndb/test/run-test/daily-devel-tests.txt
storage/ndb/test/run-test/files.cpp
storage/ndb/test/run-test/main.cpp
storage/ndb/test/run-test/setup.cpp
storage/ndb/test/run-test/test-tests.txt
storage/ndb/test/src/AtrtClient.cpp
storage/ndb/test/src/CpcClient.cpp
storage/ndb/test/src/DbUtil.cpp
storage/ndb/test/src/HugoAsynchTransactions.cpp
storage/ndb/test/src/HugoOperations.cpp
storage/ndb/test/src/HugoTransactions.cpp
storage/ndb/test/src/NDBT_Tables.cpp
storage/ndb/test/src/NDBT_Test.cpp
storage/ndb/test/src/NdbBackup.cpp
storage/ndb/test/src/NdbRestarter.cpp
storage/ndb/test/src/UtilTransactions.cpp
storage/ndb/test/tools/connect.cpp
storage/ndb/test/tools/hugoPkRead.cpp
storage/ndb/test/tools/rep_latency.cpp
storage/ndb/tools/desc.cpp
storage/ndb/tools/ndb_size.pl
storage/ndb/tools/restore/Restore.cpp
storage/ndb/tools/restore/consumer_restore.cpp
storage/ndb/tools/restore/restore_main.cpp
storage/ndb/tools/select_all.cpp
storage/ndb/tools/select_count.cpp
storage/ndb/tools/waiter.cpp
strings/CMakeLists.txt
strings/Makefile.am
strings/conf_to_src.c
support-files/build-tags
support-files/compiler_warnings.supp
support-files/mysql.spec.sh
tests/CMakeLists.txt
unittest/examples/CMakeLists.txt
unittest/mysys/CMakeLists.txt
unittest/mysys/Makefile.am
unittest/mytap/CMakeLists.txt
vio/CMakeLists.txt
zlib/CMakeLists.txt
mysql-test/r/slave_allow_batching_basic.result
mysql-test/suite/ndb_binlog/r/ndb_binlog_basic.result
mysql-test/suite/ndb_binlog/r/ndb_binlog_ddl_multi.result
mysql-test/suite/ndb_binlog/r/ndb_binlog_log_bin.result
mysql-test/suite/ndb_binlog/t/ndb_binlog_basic.test
mysql-test/suite/ndb_binlog/r/ndb_binlog_format.result
mysql-test/t/slave_allow_batching_basic.test
storage/ndb/src/common/util/ndb_init.cpp
=== modified file 'BUILD/compile-dist'
--- a/BUILD/compile-dist 2008-11-22 15:24:06 +0000
+++ b/BUILD/compile-dist 2008-12-29 12:05:15 +0000
@@ -11,16 +11,33 @@ test -f Makefile && make maintainer-clea
path=`dirname $0`
. $path/autorun.sh
+gmake=
+for x in gmake gnumake make; do
+ if $x --version 2>/dev/null | grep GNU > /dev/null; then
+ gmake=$x
+ break;
+ fi
+done
+
+if [ -z "$gmake" ]; then
+ # Our build may not depend on GNU make, but I wouldn't count on it
+ echo "Please install GNU make, and ensure it is in your path as gnumake, gmake, or make" >&2
+ exit 2
+fi
+
# Default to gcc for CC and CXX
if test -z "$CXX" ; then
+ export CXX
CXX=gcc
# Set some required compile options
if test -z "$CXXFLAGS" ; then
+ export CXXFLAGS
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti"
fi
fi
if test -z "$CC" ; then
+ export CC
CC=gcc
fi
@@ -28,32 +45,18 @@ fi
# Use ccache, if available
if ccache -V > /dev/null 2>&1
then
- if echo "$CC" | grep "ccache" > /dev/null
+ if echo "$CC" | grep -v ccache > /dev/null
then
- :
- else
+ export CC
CC="ccache $CC"
fi
- if echo "$CXX" | grep "ccache" > /dev/null
+ if echo "$CXX" | grep -v ccache > /dev/null
then
- :
- else
+ export CXX
CXX="ccache $CXX"
fi
fi
-if test -z "$MAKE"
-then
- if gmake -v > /dev/null 2>&1
- then
- MAKE="gmake"
- else
- MAKE="make"
- fi
-fi
-
-export CC CXX MAKE
-
# Make sure to enable all features that affect "make dist"
# Remember that configure restricts the man pages to the configured features !
./configure \
@@ -61,5 +64,5 @@ export CC CXX MAKE
--with-embedded-server \
--with-falcon \
--with-ndbcluster
-$MAKE
+$gmake
=== modified file 'BUILD/compile-pentium-gcov'
--- a/BUILD/compile-pentium-gcov 2007-08-22 18:02:23 +0000
+++ b/BUILD/compile-pentium-gcov 2008-12-31 13:18:04 +0000
@@ -7,7 +7,7 @@ CCACHE_GCOV_VERSION_ENABLED=0
if ccache -V > /dev/null 2>&1
then
CCACHE_VER=`ccache -V | head -1 | sed s/"ccache version "//`
- if test "$CCACHE_VER" == "2.4-gcov"
+ if test "$CCACHE_VER" = "2.4-gcov"
then
CCACHE_GCOV_VERSION_ENABLED=1
else
@@ -20,7 +20,8 @@ export CCACHE_GCOV_VERSION_ENABLED
path=`dirname $0`
. "$path/SETUP.sh"
-export LDFLAGS="$gcov_link_flags"
+LDFLAGS="$gcov_link_flags"
+export LDFLAGS
extra_flags="$pentium_cflags $debug_cflags $max_cflags $gcov_compile_flags"
c_warnings="$c_warnings $debug_extra_warnings"
=== modified file 'BUILD/compile-solaris-amd64'
--- a/BUILD/compile-solaris-amd64 2007-04-12 11:20:38 +0000
+++ b/BUILD/compile-solaris-amd64 2008-12-31 13:18:04 +0000
@@ -1,16 +1,18 @@
-#!/usr/bin/bash
+#!/bin/sh
-function _find_mysql_root () (
+_find_mysql_root ()
+{
+ (
while [ "x$PWD" != "x/" ]; do
# Check if some directories are present
if [ -d BUILD -a -d sql -a -d mysys ]; then
echo "$PWD"
- return 0
+ break
fi
cd ..
done
- return 1
)
+}
make -k clean || true
/bin/rm -f */.deps/*.P config.cache
@@ -28,7 +30,7 @@ CFLAGS="$warning_flags $compiler_flags"
CXXFLAGS=""
LDFLAGS="-O3 -g -static-libgcc"
LIBS=-lmtmalloc
-root=$(_find_mysql_root)
+root=`_find_mysql_root`
$root/configure \
--prefix=/usr/local/mysql \
=== modified file 'Makefile.am'
--- a/Makefile.am 2008-12-13 11:02:16 +0000
+++ b/Makefile.am 2008-12-17 18:40:14 +0000
@@ -178,8 +178,8 @@ test-bt:
fi
-if [ -d mysql-test/suite/nist ] ; then \
cd mysql-test ; MTR_BUILD_THREAD=auto \
+ @PERL@ ./mysql-test-run.pl --comment=NIST+normal --force --suite=nist ; \
@PERL@ ./mysql-test-run.pl --comment=NIST+ps --force --suite=nist --ps-protocol ; \
- @PERL@ ./mysql-test-run.pl --comment=nist+ps --force --suite=nist --ps-protocol ; \
fi
-if [ -e bin/mysqltest_embedded -o -e libmysqld/examples/mysqltest_embedded ] ; then \
cd mysql-test ; MTR_BUILD_THREAD=auto \
=== added file 'config/ac-macros/libmemcached.m4'
--- a/config/ac-macros/libmemcached.m4 1970-01-01 00:00:00 +0000
+++ b/config/ac-macros/libmemcached.m4 2008-12-20 01:41:31 +0000
@@ -0,0 +1,29 @@
+dnl
+dnl Copyright (C) 2008 Sun Microsystems
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; version 2 of the License.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+dnl
+dnl Check to find libmemcached.
+
+AC_DEFUN([_SEARCH_FOR_LIBMEMCACHED],[
+ SEARCH_FOR_LIB(memcached,memcached_create,[libmemcached/memcached.h])
+ AM_CONDITIONAL([BUILD_MEMCACHED],[test "$ac_cv_have_memcached" = "yes"])
+])
+
+dnl Split this into a _hidden function and a public with a require. This way
+dnl any number of plugins can call the code and the real guts only get
+dnl called once.
+AC_DEFUN([WITH_LIBMEMCACHED],[
+ AC_REQUIRE([_SEARCH_FOR_LIBMEMCACHED])
+])
=== added file 'config/ac-macros/search_for_lib.m4'
--- a/config/ac-macros/search_for_lib.m4 1970-01-01 00:00:00 +0000
+++ b/config/ac-macros/search_for_lib.m4 2008-12-20 01:41:31 +0000
@@ -0,0 +1,107 @@
+dnl
+dnl Copyright (C) 2008 Sun Microsystems
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; version 2 of the License.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+dnl
+dnl Contributed with Love by Drizzle. If you make any modifications, they'd
+dnl love to know about them.
+dnl
+dnl SEARCH_FOR_LIB(LIB, FUNCTIONS, FUNCTION,
+dnl [ACTION-IF-NOT-FOUND],
+dnl [LIBS_TO_ADD])
+
+AC_DEFUN([SEARCH_FOR_LIB],
+[
+ AS_VAR_PUSHDEF([with_lib], [with_$1])
+ AS_VAR_PUSHDEF([ac_header], [ac_cv_header_$3])
+ AS_VAR_PUSHDEF([have_lib], [ac_cv_have_$1])
+ AS_VAR_PUSHDEF([libs_var], AS_TR_CPP([$1_LIBS]))
+ AS_VAR_PUSHDEF([cflags_var], AS_TR_CPP([$1_CFLAGS]))
+ AS_VAR_PUSHDEF([path_var], AS_TR_CPP([$1_PATH]))
+ AS_LITERAL_IF([$1],
+ [AS_VAR_PUSHDEF([ac_lib], [ac_cv_lib_$1_$2])],
+ [AS_VAR_PUSHDEF([ac_lib], [ac_cv_lib_$1''_$2])])
+
+ AS_IF([test "x$prefix" = "xNONE"],
+ [AS_VAR_SET([path_var],["$ac_default_prefix"])],
+ [AS_VAR_SET([path_var],["$prefix"])])
+
+
+ AC_ARG_WITH([$1],
+ [AS_HELP_STRING([--with-$1@<:@=DIR@:>@],
+ [Use lib$1 in DIR])],
+ [ AS_VAR_SET([with_lib], [$withval]) ],
+ [ AS_VAR_SET([with_lib], [yes]) ])
+
+ AS_IF([test AS_VAR_GET([with_lib]) = yes],[
+ AC_CHECK_HEADERS([$3])
+
+ my_save_LIBS="$LIBS"
+ LIBS="$5"
+ AC_CHECK_LIB($1, $2)
+ AS_VAR_SET([libs_var],[${LIBS}])
+ LIBS="${my_save_LIBS}"
+ AS_VAR_SET([cflags_var],[""])
+ AS_IF([test AS_VAR_GET([ac_header]) = "$3" -a AS_VAR_GET([ac_lib]) = yes],
+ [AS_VAR_SET([have_lib],[yes])
+ AS_VAR_SET([path_var],[$PATH])
+ ],
+ [AS_VAR_SET([have_lib],[no])
+ AS_VAR_SET([with_lib],["AS_VAR_GET([path_var]) /usr/local /opt/csw /opt/local"])
+ ])
+ ])
+ AS_IF([test "AS_VAR_GET([with_lib])" != yes],[
+ for libloc in AS_VAR_GET([with_lib])
+ do
+ AC_MSG_CHECKING(for $1 in $libloc)
+ if test -f $libloc/$3 -a -f $libloc/lib$1.a
+ then
+ owd=`pwd`
+ if cd $libloc; then libloc=`pwd`; cd $owd; fi
+ AS_VAR_SET([cflags_var],[-I$libloc])
+ AS_VAR_SET([libs_var],["-L$libloc -l$1"])
+ AS_VAR_SET([path_var],["$libloc:$PATH"])
+ AS_VAR_SET([have_lib],[yes])
+ AC_MSG_RESULT([yes])
+ break
+ elif test -f $libloc/include/$3 -a -f $libloc/lib/lib$1.a; then
+ owd=`pwd`
+ if cd $libloc; then libloc=`pwd`; cd $owd; fi
+ AS_VAR_SET([cflags_var],[-I$libloc/include])
+ AS_VAR_SET([libs_var],["-L$libloc/lib -l$1"])
+ AS_VAR_SET([path_var],["$libloc/bin:$PATH"])
+ AS_VAR_SET([have_lib],[yes])
+ AC_MSG_RESULT([yes])
+ break
+ else
+ AC_MSG_RESULT([no])
+ AS_VAR_SET([have_lib],[no])
+ fi
+ done
+ ])
+ AS_IF([test AS_VAR_GET([have_lib]) = no],[
+ AC_MSG_WARN([$3 or lib$1.a not found. Try installing $1 developement packages])
+ $4
+ ])
+ AC_SUBST(libs_var)
+ AC_SUBST(cflags_var)
+ AC_SUBST(path_var)
+ AS_VAR_POPDEF([with_lib])
+ AS_VAR_POPDEF([ac_header])
+ AS_VAR_POPDEF([libs_var])
+ AS_VAR_POPDEF([cflags_var])
+ AS_VAR_POPDEF([path_var])
+ AS_VAR_POPDEF([have_lib])
+ AS_VAR_POPDEF([ac_lib])
+])
=== modified file 'configure.in'
--- a/configure.in 2008-12-17 13:06:53 +0000
+++ b/configure.in 2008-12-31 13:49:36 +0000
@@ -64,6 +64,8 @@ sinclude(config/ac-macros/readline.m4)
sinclude(config/ac-macros/ssl.m4)
sinclude(config/ac-macros/libevent.m4)
sinclude(config/ac-macros/zlib.m4)
+sinclude(config/search_for_lib.m4)
+sinclude(config/libmemcached.m4)
# Remember to add a directory sql/share/LANGUAGE
AVAILABLE_LANGUAGES="\
@@ -403,7 +405,7 @@ fi
MYSQL_PROG_AR
# libmysqlclient versioning when linked with GNU ld.
-if $LD --version 2>/dev/null| grep GNU >/dev/null 2>&1; then
+if $LD --version 2>/dev/null | grep GNU >/dev/null 2>&1; then
LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_builddir)/libmysql/libmysql.ver"
AC_CONFIG_FILES(libmysql/libmysql.ver)
fi
=== modified file 'libmysqld/examples/test-run'
--- a/libmysqld/examples/test-run 2006-11-13 06:39:15 +0000
+++ b/libmysqld/examples/test-run 2008-12-31 13:18:04 +0000
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/bin/bash
# This is slapped together as a quick way to run the tests and
# is not meant for prime time. Please hack at it and submit
=== modified file 'mysql-test/create-test-result'
--- a/mysql-test/create-test-result 2004-08-16 14:09:57 +0000
+++ b/mysql-test/create-test-result 2008-12-31 13:18:04 +0000
@@ -10,13 +10,13 @@ if [ -z "$EDITOR" ] ; then
EDITOR=vi
fi
-function die()
+die()
{
echo $1
exit 1
}
-function usage()
+usage()
{
echo "Usage: $0 test_name"
exit 1
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2008-12-14 11:36:15 +0000
+++ b/mysql-test/mysql-test-run.pl 2008-12-17 19:46:23 +0000
@@ -1473,16 +1473,22 @@ sub executable_setup_ndb () {
"$glob_basedir/storage/ndb",
"$glob_basedir/bin");
+ # Some might be found in sbin, not bin.
+ my $daemon_path= mtr_file_exists("$glob_basedir/ndb",
+ "$glob_basedir/storage/ndb",
+ "$glob_basedir/sbin",
+ "$glob_basedir/bin");
+
$exe_ndbd=
mtr_exe_maybe_exists("$ndb_path/src/kernel/ndbd",
- "$ndb_path/ndbd",
+ "$daemon_path/ndbd",
"$glob_basedir/libexec/ndbd");
$exe_ndb_mgm=
mtr_exe_maybe_exists("$ndb_path/src/mgmclient/ndb_mgm",
"$ndb_path/ndb_mgm");
$exe_ndb_mgmd=
mtr_exe_maybe_exists("$ndb_path/src/mgmsrv/ndb_mgmd",
- "$ndb_path/ndb_mgmd",
+ "$daemon_path/ndb_mgmd",
"$glob_basedir/libexec/ndb_mgmd");
$exe_ndb_waiter=
mtr_exe_maybe_exists("$ndb_path/tools/ndb_waiter",
=== modified file 'mysql-test/r/func_math.result'
--- a/mysql-test/r/func_math.result 2008-11-24 09:53:39 +0000
+++ b/mysql-test/r/func_math.result 2008-12-22 12:44:57 +0000
@@ -383,8 +383,10 @@ SELECT b DIV 900 y FROM t1 GROUP BY y;
y
0
Warnings:
-Warning 1292 Truncated incorrect INTEGER value: 'str1'
-Warning 1292 Truncated incorrect INTEGER value: 'str2'
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: 'str1'
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: 'str2'
SELECT c DIV 900 y FROM t1 GROUP BY y;
y
0
@@ -460,3 +462,8 @@ SELECT POW(10, 309);
POW(10, 309)
NULL
End of 5.1 tests
+select 123456789012345678901234567890.123456789012345678901234567890 div 1 as x;
+ERROR 22003: Out of range value for column 'x' at row 1
+select "123456789012345678901234567890.123456789012345678901234567890" div 1 as x;
+ERROR 22003: Out of range value for column 'x' at row 1
+End of 6.0 tests
=== modified file 'mysql-test/r/group_by.result'
--- a/mysql-test/r/group_by.result 2008-11-06 18:39:27 +0000
+++ b/mysql-test/r/group_by.result 2008-11-26 13:04:00 +0000
@@ -1543,8 +1543,8 @@ id select_type table type possible_keys
EXPLAIN SELECT 1 FROM t1 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Start temporary
-1 PRIMARY t1 eq_ref PRIMARY,i2 PRIMARY 4 test.t1.a 1 Using index; End temporary
+1 PRIMARY t1 index PRIMARY,i2 PRIMARY 4 NULL 144 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t1)
CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
@@ -1556,8 +1556,8 @@ id select_type table type possible_keys
EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Start temporary
-1 PRIMARY t2 index a a 5 NULL 4 Using where; Using index; End temporary; Using join buffer
+1 PRIMARY t2 index a a 5 NULL 4 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t2)
SHOW VARIABLES LIKE 'old';
Variable_name Value
old OFF
=== added file 'mysql-test/r/innodb_bug34053.result'
--- a/mysql-test/r/innodb_bug34053.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug34053.result 2008-09-15 21:33:05 +0000
@@ -0,0 +1 @@
+SET storage_engine=InnoDB;
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result 2008-12-14 11:36:15 +0000
+++ b/mysql-test/r/subselect.result 2008-12-22 20:00:22 +0000
@@ -1356,11 +1356,11 @@ a
3
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index; Start temporary
-1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using index
-1 PRIMARY t3 index a a 5 NULL 3 100.00 Using where; Using index; End temporary; Using join buffer
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY t3 index a a 5 NULL 3 100.00 Using index
+1 PRIMARY t1 ref a a 10 test.t2.a,test.t3.a 116 100.00 Using index; FirstMatch(t2)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t3`.`a` = `test`.`t1`.`b`))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` = `test`.`t3`.`a`))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -2818,8 +2818,8 @@ Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Start temporary
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; End temporary; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
@@ -4367,13 +4367,13 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
DROP TABLE t1;
End of 5.0 tests.
create table t_out (subcase char(3),
=== modified file 'mysql-test/r/subselect2.result'
--- a/mysql-test/r/subselect2.result 2008-05-01 22:41:35 +0000
+++ b/mysql-test/r/subselect2.result 2008-07-27 19:17:41 +0000
@@ -123,16 +123,16 @@ DOCID DOCNAME DOCTYPEID FOLDERID AUTHOR
c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff17444553544200 c373e9f5ad0796c0eca4444553544200 Goldilocks 2003-06-09 11:21:06 Title: Last Discussion NULL Setting new abstract and keeping doc checked out 2003-06-09 10:51:26 2003-06-09 10:51:26 NULL NULL NULL 03eea05112b845949f3fd03278b5fe43 2003-06-09 11:21:06 admin 0 NULL Discussion NULL NULL
EXPLAIN EXTENDED SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion';
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t3 ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX CMFLDRPARNT_IDX 35 const 6 100.00 Using index condition; Using where
-1 PRIMARY t3 ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX CMFLDRPARNT_IDX 35 test.t3.FOLDERID 1 100.00 Using where
-1 PRIMARY t3 ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX CMFLDRPARNT_IDX 35 test.t3.FOLDERID 1 100.00 Using where
-1 PRIMARY t3 ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX CMFLDRPARNT_IDX 35 test.t3.FOLDERID 1 100.00 Using where
-1 PRIMARY t3 ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX CMFLDRPARNT_IDX 35 test.t3.FOLDERID 1 100.00 Using where
-1 PRIMARY t2 ALL DDOCTYPEID_IDX,DFOLDERID_IDX NULL NULL NULL 9 77.78 Using where; Using join buffer
+1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 9 100.00 Using where
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 34 test.t2.DOCID 1 100.00
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 34 test.t2.DOCTYPEID 1 100.00
+2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 func 1 100.00 Using where
+2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 100.00 Using where
+2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 100.00 Using where
+2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 100.00 Using where
+2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`DOCID` AS `DOCID`,`test`.`t2`.`DOCNAME` AS `DOCNAME`,`test`.`t2`.`DOCTYPEID` AS `DOCTYPEID`,`test`.`t2`.`FOLDERID` AS `FOLDERID`,`test`.`t2`.`AUTHOR` AS `AUTHOR`,`test`.`t2`.`CREATED` AS `CREATED`,`test`.`t2`.`TITLE` AS `TITLE`,`test`.`t2`.`SUBTITLE` AS `SUBTITLE`,`test`.`t2`.`DOCABSTRACT` AS `DOCABSTRACT`,`test`.`t2`.`PUBLISHDATE` AS `PUBLISHDATE`,`test`.`t2`.`EXPIRATIONDATE` AS `EXPIRATIONDATE`,`test`.`t2`.`LOCKEDBY` AS `LOCKEDBY`,`test`.`t2`.`STATUS` AS `STATUS`,`test`.`t2`.`PARENTDOCID` AS `PARENTDOCID`,`test`.`t2`.`REPID` AS `REPID`,`test`.`t2`.`MODIFIED` AS `MODIFIED`,`test`.`t2`.`MODIFIER` AS `MODIFIER`,`test`.`t2`.`PUBLISHSTATUS` AS `PUBLISHSTATUS`,`test`.`t2`.`ORIGINATOR` AS `ORIGINATOR`,`test`.`t4`.`DOCTYPENAME` AS `DOCTYPENAME`,`test`.`t1`.`CONTENTSIZE` AS `CONTENTSIZE`,`test`.`t1`.`MIMETYPE` AS `MIMETYPE` from `test`.`t3` join `test`.`t3` join `test`.`t3` join `test`.`t3` join `test`.`t3` join `test`.`t2` join `test`.`t4` left join `
test`.`t1` on((`test`.`t1`.`DOCID` = `test`.`t2`.`DOCID`)) where ((`test`.`t4`.`DOCTYPEID` = `test`.`t2`.`DOCTYPEID`) and (`test`.`t2`.`FOLDERID` = `test`.`t3`.`FOLDERID`) and (`test`.`t3`.`PARENTID` = `test`.`t3`.`FOLDERID`) and (`test`.`t3`.`PARENTID` = `test`.`t3`.`FOLDERID`) and (`test`.`t3`.`PARENTID` = `test`.`t3`.`FOLDERID`) and (`test`.`t3`.`PARENTID` = `test`.`t3`.`FOLDERID`) and (`test`.`t3`.`FOLDERNAME` = 'Level1') and (`test`.`t3`.`PARENTID` = '2f6161e879db43c1a5b82c21ddc49089') and (`test`.`t3`.`FOLDERNAME` = 'Level2') and (`test`.`t3`.`FOLDERNAME` = 'Level3') and (`test`.`t3`.`FOLDERNAME` = 'CopiedFolder') and (`test`.`t3`.`FOLDERNAME` = 'Movie Reviews') and (`test`.`t2`.`DOCNAME` = 'Last Discussion'))
+Note 1003 select `test`.`t2`.`DOCID` AS `DOCID`,`test`.`t2`.`DOCNAME` AS `DOCNAME`,`test`.`t2`.`DOCTYPEID` AS `DOCTYPEID`,`test`.`t2`.`FOLDERID` AS `FOLDERID`,`test`.`t2`.`AUTHOR` AS `AUTHOR`,`test`.`t2`.`CREATED` AS `CREATED`,`test`.`t2`.`TITLE` AS `TITLE`,`test`.`t2`.`SUBTITLE` AS `SUBTITLE`,`test`.`t2`.`DOCABSTRACT` AS `DOCABSTRACT`,`test`.`t2`.`PUBLISHDATE` AS `PUBLISHDATE`,`test`.`t2`.`EXPIRATIONDATE` AS `EXPIRATIONDATE`,`test`.`t2`.`LOCKEDBY` AS `LOCKEDBY`,`test`.`t2`.`STATUS` AS `STATUS`,`test`.`t2`.`PARENTDOCID` AS `PARENTDOCID`,`test`.`t2`.`REPID` AS `REPID`,`test`.`t2`.`MODIFIED` AS `MODIFIED`,`test`.`t2`.`MODIFIER` AS `MODIFIER`,`test`.`t2`.`PUBLISHSTATUS` AS `PUBLISHSTATUS`,`test`.`t2`.`ORIGINATOR` AS `ORIGINATOR`,`test`.`t4`.`DOCTYPENAME` AS `DOCTYPENAME`,`test`.`t1`.`CONTENTSIZE` AS `CONTENTSIZE`,`test`.`t1`.`MIMETYPE` AS `MIMETYPE` from `test`.`t2` join `test`.`t4` left join `test`.`t1` on((`test`.`t1`.`DOCID` = `test`.`t2`.`DOCID`)) where ((`test`.`t4`.`DOCTY
PEID` = `test`.`t2`.`DOCTYPEID`) and (`test`.`t2`.`DOCNAME` = 'Last Discussion') and <in_optimizer>(`test`.`t2`.`FOLDERID`,<exists>(select 1 AS `Not_used` from `test`.`t3` join `test`.`t3` join `test`.`t3` join `test`.`t3` join `test`.`t3` where ((`test`.`t3`.`FOLDERID` = `test`.`t3`.`PARENTID`) and (`test`.`t3`.`FOLDERID` = `test`.`t3`.`PARENTID`) and (`test`.`t3`.`FOLDERID` = `test`.`t3`.`PARENTID`) and (`test`.`t3`.`FOLDERID` = `test`.`t3`.`PARENTID`) and (`test`.`t3`.`FOLDERNAME` = 'Level1') and (`test`.`t3`.`PARENTID` = '2f6161e879db43c1a5b82c21ddc49089') and (`test`.`t3`.`FOLDERNAME` = 'Level2') and (`test`.`t3`.`FOLDERNAME` = 'Level3') and (`test`.`t3`.`FOLDERNAME` = 'CopiedFolder') and (`test`.`t3`.`FOLDERNAME` = 'Movie Reviews') and (<cache>(`test`.`t2`.`FOLDERID`) = `test`.`t3`.`FOLDERID`)))))
drop table t1, t2, t3, t4;
CREATE TABLE t1 (a int(10) , PRIMARY KEY (a)) Engine=InnoDB;
INSERT INTO t1 VALUES (1),(2);
=== modified file 'mysql-test/r/subselect3.result'
--- a/mysql-test/r/subselect3.result 2008-12-08 21:15:06 +0000
+++ b/mysql-test/r/subselect3.result 2008-12-23 04:05:29 +0000
@@ -1,4 +1,4 @@
-drop table if exists t0, t1, t2, t3, t4, t5;
+drop table if exists t0, t1, t2, t3, t4, t5, t11, t12, t21, t22;
create table t1 (oref int, grp int, ie int) ;
insert into t1 (oref, grp, ie) values
(1, 1, 1),
@@ -99,7 +99,7 @@ oref a
1 1
show status like '%Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 11
+Handler_read_rnd_next 5
delete from t2;
insert into t2 values (NULL, 0),(NULL, 0), (NULL, 0), (NULL, 0);
flush status;
@@ -337,8 +337,8 @@ dd NULL 0
bb NULL NULL
select oref, a from t2 where a in (select ie from t1 where oref=t2.oref);
oref a
-aa 1
ff 2
+aa 1
select oref, a from t2 where a not in (select ie from t1 where oref=t2.oref);
oref a
bb 2
@@ -421,8 +421,8 @@ dd NULL 0
bb NULL NULL
select oref, a from t2 where a in (select ie from t1 where oref=t2.oref);
oref a
-aa 1
ff 2
+aa 1
select oref, a from t2 where a not in (select ie from t1 where oref=t2.oref);
oref a
bb 2
@@ -515,8 +515,8 @@ aa 1 1 1
dd 1 NULL 0
select oref, a, b from t2 where (a,b) in (select ie1,ie2 from t1 where oref=t2.oref);
oref a b
-aa 1 1
ff 2 2
+aa 1 1
select oref, a, b from t2 where (a,b) not in (select ie1,ie2 from t1 where oref=t2.oref);
oref a b
bb 2 1
@@ -560,8 +560,8 @@ aa 1 1 1
dd 1 NULL 0
select oref, a, b from t2 where (a,b) in (select ie1,ie2 from t1 where oref=t2.oref);
oref a b
-aa 1 1
ff 2 2
+aa 1 1
select oref, a, b from t2 where (a,b) not in (select ie1,ie2 from t1 where oref=t2.oref);
oref a b
bb 2 1
@@ -838,6 +838,332 @@ t1.a < (select t4.a+10
from t4, t5 limit 2));
ERROR 21000: Subquery returns more than 1 row
drop table t0, t1, t2, t3, t4, t5;
+CREATE TABLE t1 (
+a int(11) NOT NULL,
+b int(11) NOT NULL,
+c datetime default NULL,
+PRIMARY KEY (a),
+KEY idx_bc (b,c)
+);
+INSERT INTO t1 VALUES
+(406989,67,'2006-02-23 17:08:46'), (150078,67,'2005-10-26 11:17:45'),
+(406993,67,'2006-02-27 11:20:57'), (245655,67,'2005-12-08 15:59:08'),
+(406994,67,'2006-02-27 11:26:46'), (256,67,NULL),
+(398341,67,'2006-02-20 04:48:44'), (254,67,NULL),(1120,67,NULL),
+(406988,67,'2006-02-23 17:07:22'), (255,67,NULL),
+(398340,67,'2006-02-20 04:38:53'),(406631,67,'2006-02-23 10:49:42'),
+(245653,67,'2005-12-08 15:59:07'),(406992,67,'2006-02-24 16:47:18'),
+(245654,67,'2005-12-08 15:59:08'),(406995,67,'2006-02-28 11:55:00'),
+(127261,67,'2005-10-13 12:17:58'),(406991,67,'2006-02-24 16:42:32'),
+(245652,67,'2005-12-08 15:58:27'),(398545,67,'2006-02-20 04:53:13'),
+(154504,67,'2005-10-28 11:53:01'),(9199,67,NULL),(1,67,'2006-02-23 15:01:35'),
+(223456,67,NULL),(4101,67,NULL),(1133,67,NULL),
+(406990,67,'2006-02-23 18:01:45'),(148815,67,'2005-10-25 15:34:17'),
+(148812,67,'2005-10-25 15:30:01'),(245651,67,'2005-12-08 15:58:27'),
+(154503,67,'2005-10-28 11:52:38');
+create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
+create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
+create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
+create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
+update t22 set c = '2005-12-08 15:58:27' where a = 255;
+explain select t21.* from t21,t22 where t21.a = t22.a and
+t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t11 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort; Start materialize; Scan
+1 PRIMARY t12 ALL NULL NULL NULL NULL 8 Using where; End materialize; Using join buffer
+1 PRIMARY t21 ALL NULL NULL NULL NULL 26 Using where; Using join buffer
+1 PRIMARY t22 ALL NULL NULL NULL NULL 32 Using where; Using join buffer
+select t21.* from t21,t22 where t21.a = t22.a and
+t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+a b c
+256 67 NULL
+drop table t1, t11, t12, t21, t22;
+create table t1(a int);
+insert into t1 values (0),(1);
+set @@optimizer_switch='no_firstmatch';
+explain
+select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY X ALL NULL NULL NULL NULL 2
+2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY Z ALL NULL NULL NULL NULL 2 Materialize
+select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
+subq
+NULL
+0
+set @@optimizer_switch='';
+drop table t1;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 as select * from t0;
+insert into t1 select a+10 from t0;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+insert into t0 values(2);
+explain select * from t1 where 2 in (select a from t0);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 11 Using where; Start temporary; End temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using join buffer
+select * from t1 where 2 in (select a from t0);
+a
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+set @@optimizer_switch='no_materialization';
+explain select * from t1 where 2 in (select a from t0);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 11 Using where; FirstMatch
+1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using join buffer
+select * from t1 where 2 in (select a from t0);
+a
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+set @@optimizer_switch='';
+explain select * from (select a from t0) X where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11
+1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using where; FirstMatch(<derived2>)
+2 DERIVED t0 ALL NULL NULL NULL NULL 11
+drop table t0, t1;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (kp1 int, kp2 int, c int, filler char(100), key(kp1, kp2));
+insert into t1 select A.a+10*(B.a+10*C.a), 0, 0, 'filler' from t0 A, t0 B, t0 C;
+insert into t1 select * from t1 where kp1 < 20;
+create table t3 (a int);
+insert into t3 select A.a + 10*B.a from t0 A, t0 B;
+explain select * from t3 where a in (select kp1 from t1 where kp1<20);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+create table t4 (pk int primary key);
+insert into t4 select a from t3;
+explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
+and t4.pk=t1.c);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using MRR; LooseScan
+1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+drop table t1, t3, t4;
+create table t1 (a int) as select * from t0 where a < 5;
+set @save_max_heap_table_size=@@max_heap_table_size;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+set @@max_heap_table_size= 16384;
+explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY E ALL NULL NULL NULL NULL 5 Start temporary
+1 PRIMARY A ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY C ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY D ALL NULL NULL NULL NULL 10 Using where; End temporary; Using join buffer
+flush status;
+select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E);
+count(*)
+4999
+show status like 'Created_tmp_disk_tables';
+Variable_name Value
+Created_tmp_disk_tables 1
+set @save_max_heap_table_size=@@max_heap_table_size;
+set @@optimizer_switch=default;
+drop table t0, t1;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 values (1),(2);
+create table t3 ( a int , filler char(100), key(a));
+insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
+explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t2.a 1
+select * from t3 where a in (select a from t2);
+a filler
+1 filler
+2 filler
+drop table t0, t2, t3;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+create table t1 (a date);
+insert into t1 values ('2008-01-01'),('2008-01-01'),('2008-02-01'),('2008-02-01');
+create table t2 (a int);
+insert into t2 values (1),(2);
+create table t3 (a char(10));
+insert into t3 select * from t1;
+insert into t3 values (1),(2);
+explain select * from t2 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer
+explain select * from t2 where a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer
+explain select * from t2 where a in (select a from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer
+explain select * from t1 where a in (select a from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
+1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer
+drop table t1, t2, t3;
+create table t1 (a decimal);
+insert into t1 values (1),(2);
+explain select * from t1 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer
+drop table t1;
+set @@optimizer_switch=default;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 as select * from t1;
+create table t3 (a int, b int, filler char(100), key(a));
+insert into t3 select A.a + 10*B.a, A.a + 10*B.a, 'filler' from t1 A, t1 B, t1 C;
+explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t2.a 10
+explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 10
+explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+2 SUBQUERY A ALL NULL NULL NULL NULL 10
+2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
+explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+2 SUBQUERY A ALL NULL NULL NULL NULL 10
+2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
+explain select straight_join * from t2 X, t2 Y
+where X.a in (select straight_join A.a from t1 A, t1 B);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY X ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY Y ALL NULL NULL NULL NULL 10 Using join buffer
+2 SUBQUERY A ALL NULL NULL NULL NULL 10
+2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
+create table t0 (a int, b int);
+insert into t0 values(1,1);
+explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 system NULL NULL NULL NULL 1
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t2.a 10
+create table t4 as select a as x, a as y from t1;
+explain select * from t0, t3 where (t3.a, t3.b) in (select x,y from t4) and (t3.a < 10 or t3.a >30);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 system NULL NULL NULL NULL 1
+1 PRIMARY t4 ALL NULL NULL NULL NULL 10 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t4.x 10 Using where
+drop table t0,t1,t2,t3,t4;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int, b int, filler char(100), key(a,b));
+insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
+create table t2 as select * from t1;
+explain select * from t2 where a in (select b from t1 where a=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range a a 5 NULL 8 Using where; Using index; LooseScan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range a a 5 NULL 8 Using where; Using index; LooseScan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+drop table t1,t2;
+create table t1 (a int, b int);
+insert into t1 select a,a from t0;
+create table t2 (a int, b int);
+insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
+set @@optimizer_switch='no_firstmatch';
+explain select * from t1 where (a,b) in (select a,b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Materialize
+set @save_optimizer_search_depth=@@optimizer_search_depth;
+set @@optimizer_search_depth=63;
+explain select * from t1 where (a,b) in (select a,b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Materialize
+set @@optimizer_search_depth=@save_optimizer_search_depth;
+set @@optimizer_switch='';
+drop table t0, t1, t2;
+create table t0 (a decimal(4,2));
+insert into t0 values (10.24), (22.11);
+create table t1 as select * from t0;
+insert into t1 select * from t0;
+explain select * from t0 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 2
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t0)
+select * from t0 where a in (select a from t1);
+a
+10.24
+22.11
+drop table t0, t1;
+create table t0(a date);
+insert into t0 values ('2008-01-01'),('2008-02-02');
+create table t1 as select * from t0;
+insert into t1 select * from t0;
+explain select * from t0 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 2
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t0)
+select * from t0 where a in (select a from t1);
+a
+2008-01-01
+2008-02-02
+drop table t0, t1;
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 as select a as a, a as b, a as c from t0 where a < 3;
+create table t2 as select a as a, a as b from t0 where a < 3;
+insert into t2 select * from t2;
+explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Start materialize
+1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using join buffer
+1 PRIMARY Z ALL NULL NULL NULL NULL 6 End materialize; Using join buffer
+drop table t0,t1,t2;
BUG#40118 Crash when running Batched Key Access and requiring one match for each key
=== modified file 'mysql-test/r/subselect3_jcl6.result'
--- a/mysql-test/r/subselect3_jcl6.result 2008-12-08 21:15:06 +0000
+++ b/mysql-test/r/subselect3_jcl6.result 2008-12-23 04:05:29 +0000
@@ -2,7 +2,7 @@ set join_cache_level=6;
show variables like 'join_cache_level';
Variable_name Value
join_cache_level 6
-drop table if exists t0, t1, t2, t3, t4, t5;
+drop table if exists t0, t1, t2, t3, t4, t5, t11, t12, t21, t22;
create table t1 (oref int, grp int, ie int) ;
insert into t1 (oref, grp, ie) values
(1, 1, 1),
@@ -103,7 +103,7 @@ oref a
1 1
show status like '%Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 11
+Handler_read_rnd_next 5
delete from t2;
insert into t2 values (NULL, 0),(NULL, 0), (NULL, 0), (NULL, 0);
flush status;
@@ -842,6 +842,333 @@ t1.a < (select t4.a+10
from t4, t5 limit 2));
ERROR 21000: Subquery returns more than 1 row
drop table t0, t1, t2, t3, t4, t5;
+CREATE TABLE t1 (
+a int(11) NOT NULL,
+b int(11) NOT NULL,
+c datetime default NULL,
+PRIMARY KEY (a),
+KEY idx_bc (b,c)
+);
+INSERT INTO t1 VALUES
+(406989,67,'2006-02-23 17:08:46'), (150078,67,'2005-10-26 11:17:45'),
+(406993,67,'2006-02-27 11:20:57'), (245655,67,'2005-12-08 15:59:08'),
+(406994,67,'2006-02-27 11:26:46'), (256,67,NULL),
+(398341,67,'2006-02-20 04:48:44'), (254,67,NULL),(1120,67,NULL),
+(406988,67,'2006-02-23 17:07:22'), (255,67,NULL),
+(398340,67,'2006-02-20 04:38:53'),(406631,67,'2006-02-23 10:49:42'),
+(245653,67,'2005-12-08 15:59:07'),(406992,67,'2006-02-24 16:47:18'),
+(245654,67,'2005-12-08 15:59:08'),(406995,67,'2006-02-28 11:55:00'),
+(127261,67,'2005-10-13 12:17:58'),(406991,67,'2006-02-24 16:42:32'),
+(245652,67,'2005-12-08 15:58:27'),(398545,67,'2006-02-20 04:53:13'),
+(154504,67,'2005-10-28 11:53:01'),(9199,67,NULL),(1,67,'2006-02-23 15:01:35'),
+(223456,67,NULL),(4101,67,NULL),(1133,67,NULL),
+(406990,67,'2006-02-23 18:01:45'),(148815,67,'2005-10-25 15:34:17'),
+(148812,67,'2005-10-25 15:30:01'),(245651,67,'2005-12-08 15:58:27'),
+(154503,67,'2005-10-28 11:52:38');
+create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
+create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
+create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
+create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
+update t22 set c = '2005-12-08 15:58:27' where a = 255;
+explain select t21.* from t21,t22 where t21.a = t22.a and
+t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t11 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort; Start materialize; Scan
+1 PRIMARY t12 ALL NULL NULL NULL NULL 8 Using where; End materialize; Using join buffer
+1 PRIMARY t21 ALL NULL NULL NULL NULL 26 Using where; Using join buffer
+1 PRIMARY t22 ALL NULL NULL NULL NULL 32 Using where; Using join buffer
+select t21.* from t21,t22 where t21.a = t22.a and
+t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+a b c
+256 67 NULL
+256 67 NULL
+drop table t1, t11, t12, t21, t22;
+create table t1(a int);
+insert into t1 values (0),(1);
+set @@optimizer_switch='no_firstmatch';
+explain
+select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY X ALL NULL NULL NULL NULL 2
+2 DEPENDENT SUBQUERY Y ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY Z ALL NULL NULL NULL NULL 2 Materialize
+select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
+subq
+NULL
+0
+set @@optimizer_switch='';
+drop table t1;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 as select * from t0;
+insert into t1 select a+10 from t0;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+insert into t0 values(2);
+explain select * from t1 where 2 in (select a from t0);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 11 Using where; Start temporary; End temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using join buffer
+select * from t1 where 2 in (select a from t0);
+a
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+set @@optimizer_switch='no_materialization';
+explain select * from t1 where 2 in (select a from t0);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 11 Using where; FirstMatch
+1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using join buffer
+select * from t1 where 2 in (select a from t0);
+a
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+set @@optimizer_switch='';
+explain select * from (select a from t0) X where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11
+1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using where; FirstMatch(<derived2>); Using join buffer
+2 DERIVED t0 ALL NULL NULL NULL NULL 11
+drop table t0, t1;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (kp1 int, kp2 int, c int, filler char(100), key(kp1, kp2));
+insert into t1 select A.a+10*(B.a+10*C.a), 0, 0, 'filler' from t0 A, t0 B, t0 C;
+insert into t1 select * from t1 where kp1 < 20;
+create table t3 (a int);
+insert into t3 select A.a + 10*B.a from t0 A, t0 B;
+explain select * from t3 where a in (select kp1 from t1 where kp1<20);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+create table t4 (pk int primary key);
+insert into t4 select a from t3;
+explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
+and t4.pk=t1.c);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using MRR; LooseScan
+1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+drop table t1, t3, t4;
+create table t1 (a int) as select * from t0 where a < 5;
+set @save_max_heap_table_size=@@max_heap_table_size;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+set @@max_heap_table_size= 16384;
+explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY E ALL NULL NULL NULL NULL 5 Start temporary
+1 PRIMARY A ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY C ALL NULL NULL NULL NULL 10 Using join buffer
+1 PRIMARY D ALL NULL NULL NULL NULL 10 Using where; End temporary; Using join buffer
+flush status;
+select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E);
+count(*)
+4999
+show status like 'Created_tmp_disk_tables';
+Variable_name Value
+Created_tmp_disk_tables 1
+set @save_max_heap_table_size=@@max_heap_table_size;
+set @@optimizer_switch=default;
+drop table t0, t1;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 values (1),(2);
+create table t3 ( a int , filler char(100), key(a));
+insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
+explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t2.a 1 Using join buffer
+select * from t3 where a in (select a from t2);
+a filler
+1 filler
+2 filler
+drop table t0, t2, t3;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+create table t1 (a date);
+insert into t1 values ('2008-01-01'),('2008-01-01'),('2008-02-01'),('2008-02-01');
+create table t2 (a int);
+insert into t2 values (1),(2);
+create table t3 (a char(10));
+insert into t3 select * from t1;
+insert into t3 values (1),(2);
+explain select * from t2 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer
+explain select * from t2 where a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer
+explain select * from t2 where a in (select a from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer
+explain select * from t1 where a in (select a from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Start temporary
+1 PRIMARY t3 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer
+drop table t1, t2, t3;
+create table t1 (a decimal);
+insert into t1 values (1),(2);
+explain select * from t1 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer
+drop table t1;
+set @@optimizer_switch=default;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 as select * from t1;
+create table t3 (a int, b int, filler char(100), key(a));
+insert into t3 select A.a + 10*B.a, A.a + 10*B.a, 'filler' from t1 A, t1 B, t1 C;
+explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t2.a 10 Using join buffer
+explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 10
+explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+2 SUBQUERY A ALL NULL NULL NULL NULL 10
+2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
+explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where
+2 SUBQUERY A ALL NULL NULL NULL NULL 10
+2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
+explain select straight_join * from t2 X, t2 Y
+where X.a in (select straight_join A.a from t1 A, t1 B);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY X ALL NULL NULL NULL NULL 10 Using where
+1 PRIMARY Y ALL NULL NULL NULL NULL 10 Using join buffer
+2 SUBQUERY A ALL NULL NULL NULL NULL 10
+2 SUBQUERY B ALL NULL NULL NULL NULL 10 Using join buffer
+create table t0 (a int, b int);
+insert into t0 values(1,1);
+explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 system NULL NULL NULL NULL 1
+1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t2.a 10 Using join buffer
+create table t4 as select a as x, a as y from t1;
+explain select * from t0, t3 where (t3.a, t3.b) in (select x,y from t4) and (t3.a < 10 or t3.a >30);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 system NULL NULL NULL NULL 1
+1 PRIMARY t4 ALL NULL NULL NULL NULL 10 Using where; Materialize; Scan
+1 PRIMARY t3 ref a a 5 test.t4.x 10 Using where; Using join buffer
+drop table t0,t1,t2,t3,t4;
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int, b int, filler char(100), key(a,b));
+insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
+create table t2 as select * from t1;
+explain select * from t2 where a in (select b from t1 where a=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range a a 5 NULL 8 Using where; Using index; LooseScan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range a a 5 NULL 8 Using where; Using index; LooseScan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer
+drop table t1,t2;
+create table t1 (a int, b int);
+insert into t1 select a,a from t0;
+create table t2 (a int, b int);
+insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
+set @@optimizer_switch='no_firstmatch';
+explain select * from t1 where (a,b) in (select a,b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Materialize
+set @save_optimizer_search_depth=@@optimizer_search_depth;
+set @@optimizer_search_depth=63;
+explain select * from t1 where (a,b) in (select a,b from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 10
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Materialize
+set @@optimizer_search_depth=@save_optimizer_search_depth;
+set @@optimizer_switch='';
+drop table t0, t1, t2;
+create table t0 (a decimal(4,2));
+insert into t0 values (10.24), (22.11);
+create table t1 as select * from t0;
+insert into t1 select * from t0;
+explain select * from t0 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 2
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t0); Using join buffer
+select * from t0 where a in (select a from t1);
+a
+10.24
+22.11
+drop table t0, t1;
+create table t0(a date);
+insert into t0 values ('2008-01-01'),('2008-02-02');
+create table t1 as select * from t0;
+insert into t1 select * from t0;
+explain select * from t0 where a in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 ALL NULL NULL NULL NULL 2
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t0); Using join buffer
+select * from t0 where a in (select a from t1);
+a
+2008-01-01
+2008-02-02
+drop table t0, t1;
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 as select a as a, a as b, a as c from t0 where a < 3;
+create table t2 as select a as a, a as b from t0 where a < 3;
+insert into t2 select * from t2;
+explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Start materialize
+1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using join buffer
+1 PRIMARY Z ALL NULL NULL NULL NULL 6 End materialize; Using join buffer
+drop table t0,t1,t2;
BUG#40118 Crash when running Batched Key Access and requiring one match for each key
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result 2008-04-24 23:59:38 +0000
+++ b/mysql-test/r/subselect_mat.result 2008-11-26 14:36:11 +0000
@@ -41,7 +41,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`)))))
select * from t1 where a1 in (select b1 from t2 where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -52,7 +52,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` AS `b1` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`)))))
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -63,7 +63,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`)))))
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -74,7 +74,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,min(`test`.`t2`.`b2`) AS `min(b2)` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,min(`test`.`t2`.`b2`) AS `min(b2)` from `test`.`t2` where (`test`.`t2`.`b1` > '0') group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`min(b2)`)))))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -85,7 +85,7 @@ id select_type table type possible_keys
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 SUBQUERY t2i index it2i1,it2i3 it2i1 9 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))))
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -96,7 +96,7 @@ id select_type table type possible_keys
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 SUBQUERY t2i range it2i1,it2i3 it2i1 9 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` AS `b1` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`)))))
select * from t1i where a1 in (select b1 from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -107,7 +107,7 @@ id select_type table type possible_keys
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`)))))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -118,7 +118,7 @@ id select_type table type possible_keys
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`)))))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -129,7 +129,7 @@ id select_type table type possible_keys
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`min(b2)`)))))
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -140,7 +140,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2i range NULL it2i3 9 NULL 3 100.00 Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,max(`test`.`t2i`.`b2`) AS `max(b2)` from `test`.`t2i` group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,max(`test`.`t2i`.`b2`) AS `max(b2)` from `test`.`t2i` group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`max(b2)`)))))
select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1);
a1 a2
1 - 01 2 - 01
@@ -169,7 +169,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,min(`test`.`t2i`.`b2`) AS `min(b2)` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`min(b2)`)))))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -209,7 +209,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`)))))
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -220,7 +220,7 @@ id select_type table type possible_keys
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 SUBQUERY t2i index NULL it2i3 18 NULL 5 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`)))))
select * from t1i where (a1, a2) in (select b1, b2 from t2i order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -275,7 +275,7 @@ id select_type table type possible_keys
4 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key wh
ere ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
select * from t1
where (a1, a2) in (select b1, b2 from t2 where b1 > '0') and
(a1, a2) in (select c1, c2 from t3
@@ -294,7 +294,7 @@ id select_type table type possible_keys
4 SUBQUERY t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where (<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key))) and <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from `test`.`t3i` where <in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key))))
+Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where (<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from `test`.`t3i` where <in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary
table> on distinct_key where ((`test`.`t3i`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3i`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`c2`))))))
select * from t1i
where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i
@@ -317,7 +317,7 @@ id select_type table type possible_keys
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`
.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materi
alized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -342,7 +342,7 @@ id select_type table type possible_keys
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key)))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from `test`.`t3` `t3c` where <in_optimizer>(
(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c
`.`c2` AS `c2` from `test`.`t3` `t3c` where <in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key where ((`test`.`t3c`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3c`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
@@ -378,7 +378,7 @@ id select_type table type possible_keys
8 SUBQUERY t2i index it2i1,it2i3 it2i3 18 NULL 5 100.00 Using where; Using index
NULL UNION RESULT <union1,7> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key)))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <material
ize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where (<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key))) and <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `t
est`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from `test`.`t3i` where <in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key)))))
+Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%02') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`))))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` AS `c2` from `test`.`t3` where (`test`.`t3`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) group by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on dis
tinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` A
S `a2` from `test`.`t1i` where (<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`b2`))))) and <in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1` AS `c1`,`test`.`t3i`.`c2` AS `c2` from `test`.`t3i` where <in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key where ((`test`.`t3i`.`c1` = `materiali
zed subselect`.`b1`) and (`test`.`t3i`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where ((`test`.`t1i`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1i`.`a2` = `materialized subselect`.`c2`)))))))
(select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -407,7 +407,7 @@ id select_type table type possible_keys
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <p
rimary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <p
rimary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `materialized subselect`.`c1`) and (`test`.`t1`.`a2` = `materialized subselect`.`c2`))))))
select * from t1
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(a1, a2) in (select c1, c2 from t3
@@ -430,7 +430,7 @@ id select_type table type possible_keys
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (selec
t `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key))) ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`c1` = `test`.`t1`.`a1`) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where ((`test`.`t1`.`a1` > '0') and (<cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2`)) union select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((`test`.`t2`.`b1` < '9') and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (selec
t `test`.`t2i`.`b1` AS `b1`,`test`.`t2i`.`b2` AS `b2` from `test`.`t2i` where (`test`.`t2i`.`b2` > '0') ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`b1`) and (`test`.`t3`.`c2` = `materialized subselect`.`b2`))))) ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where ((`test`.`t3`.`c1` = `materialized subselect`.`c1`) and (`test`.`t3`.`c2` = `materialized subselect`.`c2`))))))
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -476,7 +476,7 @@ id select_type table type possible_keys
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key)))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from `test`.`t3` `t3c` where (<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>
(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (((`test`.`t2i`.`b2` > '0') or (`test`.`t2i`.`b2` = `test`.`t1`.`a2`)) and (<cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1`) and (<cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1` AS `b1`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where ((<in_optimizer>(`test`.`t2`.`b2`,<exists>(select 1 AS `Not_used` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`)))) or <in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` AS `c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `materialized subselect`.`c2`)))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`)))) and <in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t3c`.`c1` AS `c1`,`test`.`t3c`.`c2` AS `c2` from `test`.`t3` `t3c` where (<i
n_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (((`test`.`t2i`.`b2` > '0') or (`test`.`t2i`.`b2` = `test`.`t1`.`a2`)) and (<cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1`) and (<cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`))))) and (<cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1`) and (<cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))))
explain extended
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -611,7 +611,7 @@ id select_type table type possible_keys
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) AS `substring(b1,1,16)` from `test`.`t2_16` where (`test`.`t2_16`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) AS `substring(b1,1,16)` from `test`.`t2_16` where (`test`.`t2_16`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_16`.`a1` = `materialized subselect`.`substring(b1,1,16)`)))))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select substring(b1,1,16) from t2_16 where b1 > '0');
@@ -640,7 +640,7 @@ id select_type table type possible_keys
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_16` group by `test`.`t2_16`.`b2` ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_16` group by `test`.`t2_16`.`b2` ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_16`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -657,12 +657,12 @@ where t2.b2 = substring(t2_16.b2,1,6) an
t2.b1 IN (select c1 from t3 where c2 > '0')));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 SUBQUERY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 DEPENDENT SUBQUERY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer
4 SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(concat(`test`.`t1`.`a1`,'x'),concat(`test`.`t1`.`a1`,'x') in ( <materialize> (select left(`test`.`t1_16`.`a1`,8) AS `left(a1,8)` from `test`.`t1_16` where <in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`) in (select `test`.`t2_16`.`b1` AS `b1`,`test`.`t2_16`.`b2` AS `b2` from `test`.`t2_16` join `test`.`t2` where ((`test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6)) and <in_optimizer>(`test`.`t2`.`b1`,`test`.`t2`.`b1` in ( <materialize> (select `test`.`t3`.`c1` AS `c1` from `test`.`t3` where (`test`.`t3`.`c2` > '0') ), <primary_index_lookup>(`test`.`t2`.`b1` in <temporary table> on distinct_key))) and (<cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`) and (<cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))) ), <primary_index_lookup>(concat(`test`.`t1`.`a1`,'x') in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(select 1 AS `Not_used` from `test`.`t1_16` where (<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`) in (select `test`.`t2_16`.`b1` AS `b1`,`test`.`t2_16`.`b2` AS `b2` from `test`.`t2_16` join `test`.`t2` where ((`test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6)) and <in_optimizer>(`test`.`t2`.`b1`,`test`.`t2`.`b1` in ( <materialize> (select `test`.`t3`.`c1` AS `c1` from `test`.`t3` where (`test`.`t3`.`c2` > '0') ), <primary_index_lookup>(`test`.`t2`.`b1` in <temporary table> on distinct_key where ((`test`.`t2`.`b1` = `materialized subselect`.`c1`))))) and (<cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`) and (<cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))) and (<cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8)))))
drop table t1_16, t2_16, t3_16;
set @blob_len = 512;
set @suffix_len = @blob_len - @prefix_len;
@@ -724,7 +724,7 @@ id select_type table type possible_keys
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) AS `substring(b1,1,512)` from `test`.`t2_512` where (`test`.`t2_512`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) AS `substring(b1,1,512)` from `test`.`t2_512` where (`test`.`t2_512`.`b1` > '0') ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_512`.`a1` = `materialized subselect`.`substring(b1,1,512)`)))))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select substring(b1,1,512) from t2_512 where b1 > '0');
@@ -738,13 +738,11 @@ id select_type table type possible_keys
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
left(a1,7) left(a2,7)
-1 - 01x 2 - 01x
-1 - 02x 2 - 02x
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_512
@@ -753,13 +751,11 @@ id select_type table type possible_keys
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_512`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
left(a1,7) left(a2,7)
-1 - 01x 2 - 01x
-1 - 02x 2 - 02x
drop table t1_512, t2_512, t3_512;
set @blob_len = 1024;
set @suffix_len = @blob_len - @prefix_len;
@@ -835,13 +831,11 @@ id select_type table type possible_keys
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
left(a1,7) left(a2,7)
-1 - 01x 2 - 01x
-1 - 02x 2 - 02x
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_1024
@@ -850,13 +844,11 @@ id select_type table type possible_keys
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1024`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
left(a1,7) left(a2,7)
-1 - 01x 2 - 01x
-1 - 02x 2 - 02x
drop table t1_1024, t2_1024, t3_1024;
set @blob_len = 1025;
set @suffix_len = @blob_len - @prefix_len;
@@ -932,13 +924,11 @@ id select_type table type possible_keys
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
left(a1,7) left(a2,7)
-1 - 01x 2 - 01x
-1 - 02x 2 - 02x
set @@group_concat_max_len = 256;
explain extended select left(a1,7), left(a2,7)
from t1_1025
@@ -947,13 +937,11 @@ id select_type table type possible_keys
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') AS `group_concat(b1)` from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where ((`test`.`t1_1025`.`a1` = `materialized subselect`.`group_concat(b1)`)))))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
left(a1,7) left(a2,7)
-1 - 01x 2 - 01x
-1 - 02x 2 - 02x
drop table t1_1025, t2_1025, t3_1025;
create table t1bit (a1 bit(3), a2 bit(3));
create table t2bit (b1 bit(3), b2 bit(3));
@@ -971,7 +959,7 @@ id select_type table type possible_keys
1 PRIMARY t1bit ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2bit ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from `test`.`t1bit` where <in_optimizer>((`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`),(`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`) in ( <materialize> (select `test`.`t2bit`.`b1` AS `b1`,`test`.`t2bit`.`b2` AS `b2` from `test`.`t2bit` ), <primary_index_lookup>(`test`.`t1bit`.`a1` in <temporary table> on distinct_key)))
+Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from `test`.`t1bit` where <in_optimizer>((`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`),(`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`) in ( <materialize> (select `test`.`t2bit`.`b1` AS `b1`,`test`.`t2bit`.`b2` AS `b2` from `test`.`t2bit` ), <primary_index_lookup>(`test`.`t1bit`.`a1` in <temporary table> on distinct_key where ((`test`.`t1bit`.`a1` = `materialized subselect`.`b1`) and (`test`.`t1bit`.`a2` = `materialized subselect`.`b2`)))))
select bin(a1), bin(a2)
from t1bit
where (a1, a2) in (select b1, b2 from t2bit);
@@ -1042,7 +1030,7 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1056,7 +1044,7 @@ id select_type table type possible_keys
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1070,7 +1058,7 @@ id select_type table type possible_keys
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using where; Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1083,7 +1071,7 @@ id select_type table type possible_keys
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1095,7 +1083,7 @@ id select_type table type possible_keys
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` AS `c` from `test`.`t2` where (`test`.`t2`.`d` >= 20) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`c`)))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1145,3 +1133,50 @@ t2.a = 3 and not t2.a not in (select t2.
1
1
drop table t2;
+create table t1 (a1 int key);
+create table t2 (b1 int);
+insert into t1 values (5);
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+min(a1)
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+min(a1)
+set @@optimizer_switch='no_semijoin';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+2 SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+select min(a1) from t1 where 7 in (select b1 from t2);
+min(a1)
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+select min(a1) from t1 where 7 in (select b1 from t2);
+min(a1)
+NULL
+drop table t1,t2;
+create table t1 (a char(2), b varchar(10));
+insert into t1 values ('a', 'aaa');
+insert into t1 values ('aa', 'aaaa');
+set @@optimizer_switch='no_semijoin';
+explain select a,b from t1 where b in (select a from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
+select a,b from t1 where b in (select a from t1);
+a b
+prepare st1 from "select a,b from t1 where b in (select a from t1)";
+execute st1;
+a b
+execute st1;
+a b
+drop table t1;
=== modified file 'mysql-test/r/subselect_no_mat.result'
--- a/mysql-test/r/subselect_no_mat.result 2008-12-13 11:02:16 +0000
+++ b/mysql-test/r/subselect_no_mat.result 2008-12-13 20:01:27 +0000
@@ -1360,11 +1360,11 @@ a
3
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index; Start temporary
-1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using index
-1 PRIMARY t3 index a a 5 NULL 3 100.00 Using where; Using index; End temporary; Using join buffer
+1 PRIMARY t2 index a a 5 NULL 4 100.00 Using index
+1 PRIMARY t3 index a a 5 NULL 3 100.00 Using index
+1 PRIMARY t1 ref a a 10 test.t2.a,test.t3.a 116 100.00 Using index; FirstMatch(t2)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t3`.`a` = `test`.`t1`.`b`))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` = `test`.`t3`.`a`))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -2822,8 +2822,8 @@ Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Start temporary
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; End temporary; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
@@ -3411,7 +3411,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3422,7 +3422,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1 Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
@@ -4368,16 +4368,16 @@ CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` having (<cache>(1) = <ref_null_helper>(1))))
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (<cache>(1) = <ref_null_helper>(1))))
DROP TABLE t1;
End of 5.0 tests.
create table t_out (subcase char(3),
=== modified file 'mysql-test/r/subselect_no_opts.result'
--- a/mysql-test/r/subselect_no_opts.result 2008-12-13 11:02:16 +0000
+++ b/mysql-test/r/subselect_no_opts.result 2008-12-13 20:01:27 +0000
@@ -2822,10 +2822,10 @@ Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Start temporary
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; End temporary; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = 'N') and (<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) and (<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`))))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -3411,7 +3411,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3422,7 +3422,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1 Using filesort
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
@@ -4219,8 +4219,8 @@ CREATE INDEX I1 ON t1 (a);
CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index I1 I1 2 NULL 2 Using index; LooseScan
-1 PRIMARY t1 ref I2 I2 13 test.t1.a 2 Using index condition
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t1 index_subquery I1 I1 2 func 2 Using index; Using where
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(10));
@@ -4229,15 +4229,15 @@ CREATE INDEX I1 ON t2 (a);
CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index I1 I1 4 NULL 2 Using index; LooseScan
-1 PRIMARY t2 ref I2 I2 13 test.t2.a 2 Using index condition
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 index_subquery I1 I1 4 func 2 Using index; Using where
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
a b
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index I1 I1 2 NULL 2 Using where; Using index; LooseScan
-1 PRIMARY t1 ref I2 I2 13 test.t1.a 2 Using index condition
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t1 index_subquery I1 I1 2 func 2 Using index; Using where
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
a b
DROP TABLE t1,t2;
@@ -4368,16 +4368,16 @@ CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` having (<cache>(1) = <ref_null_helper>(1))))
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
-2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (<cache>(1) = <ref_null_helper>(1))))
DROP TABLE t1;
End of 5.0 tests.
create table t_out (subcase char(3),
=== modified file 'mysql-test/r/subselect_no_semijoin.result'
--- a/mysql-test/r/subselect_no_semijoin.result 2008-12-13 11:02:16 +0000
+++ b/mysql-test/r/subselect_no_semijoin.result 2008-12-13 20:01:27 +0000
@@ -1300,7 +1300,7 @@ id select_type table type possible_keys
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
2 SUBQUERY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1310,7 +1310,7 @@ id select_type table type possible_keys
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1321,7 +1321,7 @@ id select_type table type possible_keys
2 SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using index
2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1343,7 +1343,7 @@ id select_type table type possible_keys
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1353,7 +1353,7 @@ id select_type table type possible_keys
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1364,7 +1364,7 @@ id select_type table type possible_keys
2 SUBQUERY t3 index a a 5 NULL 3 100.00 Using index
2 SUBQUERY t1 index NULL a 10 NULL 10004 100.00 Using where; Using index; Using join buffer
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1380,7 +1380,7 @@ id select_type table type possible_keys
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 SUBQUERY t1 index NULL a 10 NULL 10005 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key)))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`)))))
drop table t0, t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -2822,10 +2822,10 @@ Warnings:
Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Start temporary
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; End temporary; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = 'N') ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where ((`test`.`t1`.`one` = `materialized subselect`.`one`) and (`test`.`t1`.`two` = `materialized subselect`.`two`)))))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -4219,8 +4219,8 @@ CREATE INDEX I1 ON t1 (a);
CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index I1 I1 2 NULL 2 Using index; LooseScan
-1 PRIMARY t1 ref I2 I2 13 test.t1.a 2 Using index condition
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t1 index NULL I1 2 NULL 2 Using index
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(10));
@@ -4229,15 +4229,15 @@ CREATE INDEX I1 ON t2 (a);
CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index I1 I1 4 NULL 2 Using index; LooseScan
-1 PRIMARY t2 ref I2 I2 13 test.t2.a 2 Using index condition
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t2 index NULL I1 4 NULL 2 Using index
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
a b
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index I1 I1 2 NULL 2 Using where; Using index; LooseScan
-1 PRIMARY t1 ref I2 I2 13 test.t1.a 2 Using index condition
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t1 index NULL I1 2 NULL 2 Using where; Using index
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
a b
DROP TABLE t1,t2;
@@ -4371,13 +4371,13 @@ id select_type table type possible_keys
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key)))
+Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,1 in ( <materialize> (select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `materialized subselect`.`1`)))))
DROP TABLE t1;
End of 5.0 tests.
create table t_out (subcase char(3),
=== modified file 'mysql-test/r/subselect_sj.result'
--- a/mysql-test/r/subselect_sj.result 2008-12-08 21:15:06 +0000
+++ b/mysql-test/r/subselect_sj.result 2008-12-22 19:03:25 +0000
@@ -72,19 +72,19 @@ select * from t1 left join (t2 A, t2 B)
id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY A ALL NULL NULL NULL NULL 3 100.00 Using where
-1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00
-1 PRIMARY t10 eq_ref PRIMARY PRIMARY 4 test.B.A 1 100.00 Using index
+1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00 Using where
+2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t10` join `test`.`t2` `A` join `test`.`t2` `B`) on(((`test`.`A`.`A` = `test`.`t1`.`A`) And 1 And (`test`.`B`.`A` = `test`.`t10`.`pk`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on(((`test`.`A`.`A` = `test`.`t1`.`A`) And <in_optimizer>(`test`.`B`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`B`.`A`) in t10 on PRIMARY))))) where 1
t2 should be wrapped into OJ-nest, so we have "t1 LJ (t2 J t10)"
explAin extended
select * from t1 left join t2 on (t2.A= t1.A And t2.A in (select pk from t10));
id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
-1 PRIMARY t10 eq_ref PRIMARY PRIMARY 4 test.t2.A 1 100.00 Using index
+2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join (`test`.`t10` join `test`.`t2`) on(((`test`.`t2`.`A` = `test`.`t1`.`A`) And 1 And (`test`.`t2`.`A` = `test`.`t10`.`pk`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(((`test`.`t2`.`A` = `test`.`t1`.`A`) And <in_optimizer>(`test`.`t2`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`t2`.`A`) in t10 on PRIMARY))))) where 1
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
=== modified file 'mysql-test/r/subselect_sj2.result'
--- a/mysql-test/r/subselect_sj2.result 2008-09-04 18:18:11 +0000
+++ b/mysql-test/r/subselect_sj2.result 2008-12-22 19:03:25 +0000
@@ -32,8 +32,8 @@ a b
9 5
explain select * from t2 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
-1 PRIMARY t2 ref b b 5 test.t1.a 2 End temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Materialize; Scan
+1 PRIMARY t2 ref b b 5 test.t1.a 2
select * from t2 where b in (select a from t1);
a b
1 1
@@ -50,8 +50,8 @@ primary key(pk1, pk2, pk3)
insert into t3 select a,a, a,a,a from t0;
explain select * from t3 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
-1 PRIMARY t3 ref b b 5 test.t1.a 1 End temporary
+1 PRIMARY t3 ALL b NULL NULL NULL 10
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t3)
select * from t3 where b in (select a from t1);
a b pk1 pk2 pk3
1 1 1 1 1
@@ -73,8 +73,8 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a
from t0 A, t0 B where B.a <5;
explain select * from t3 where b in (select a from t0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Start temporary
-1 PRIMARY t3 ref b b 5 test.t0.a 1 End temporary
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Materialize; Scan
+1 PRIMARY t3 ref b b 5 test.t0.a 1
select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5);
a b pk1 pk2
0 0 0 0
@@ -95,8 +95,8 @@ set join_buffer_size= @save_join_buffer_
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index b b 5 NULL 10 Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t2 index b b 5 NULL 10 Using index; Materialize
select * from t1;
a b
1 1
@@ -123,8 +123,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; End temporary; Using join buffer
+1 PRIMARY it ALL NULL NULL NULL NULL 22 Materialize; Scan
+1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -155,8 +155,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ot ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY it ALL NULL NULL NULL NULL 32 Using where; End temporary; Using join buffer
+1 PRIMARY ot ALL NULL NULL NULL NULL 22
+1 PRIMARY it ALL NULL NULL NULL NULL 32 Materialize
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -180,8 +180,8 @@ a mid(filler1, 1,10) length(filler1)=len
16 filler1234 1
17 filler1234 1
18 filler1234 1
-3 duplicate 1
19 filler1234 1
+3 duplicate 1
19 duplicate 1
insert into t1 select a+20, 'filler123456', 'filler123456' from t0;
insert into t1 select a+20, 'filler123456', 'filler123456' from t0;
@@ -189,8 +189,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; End temporary; Using join buffer
+1 PRIMARY it ALL NULL NULL NULL NULL 22 Materialize; Scan
+1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -221,8 +221,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ot ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY it ALL NULL NULL NULL NULL 52 Using where; End temporary; Using join buffer
+1 PRIMARY ot ALL NULL NULL NULL NULL 22
+1 PRIMARY it ALL NULL NULL NULL NULL 52 Materialize
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -246,8 +246,8 @@ a mid(filler1, 1,10) length(filler1)=len
16 filler1234 1
17 filler1234 1
18 filler1234 1
-3 duplicate 1
19 filler1234 1
+3 duplicate 1
19 duplicate 1
drop table t1, t2;
create table t1 (a int, b int, key(a));
@@ -261,8 +261,8 @@ explain select *
from t0 where a in
(select t2.a+t3.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Start temporary
-1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Using join buffer
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10
+1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Start temporary; Using join buffer
1 PRIMARY t2 ref a a 5 test.t1.a 1 Using index
1 PRIMARY t3 ref a a 5 test.t1.a 1 Using where; Using index; End temporary
drop table t0, t1,t2,t3;
@@ -300,9 +300,9 @@ t2.Code IN (SELECT Country FROM t3
WHERE Language='English' AND Percentage > 10 AND
t2.Population > 100000);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Using MRR; Start temporary
-1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where; End temporary
-1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t2.Code,const 1 Using index condition; Using where
+1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Using MRR
+1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where
+1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t3.Country 1 Using index condition; Using where
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (
Code char(3) NOT NULL DEFAULT '',
@@ -337,8 +337,8 @@ EXPLAIN SELECT Name FROM t1
WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL CountryCode NULL NULL NULL 545 Using where; Start temporary
-1 PRIMARY t1 eq_ref PRIMARY PRIMARY 3 test.t2.CountryCode 1 End temporary
+1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 31
+1 PRIMARY t2 ALL CountryCode NULL NULL NULL 545 Using where; Materialize
SELECT Name FROM t1
WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
@@ -559,7 +559,7 @@ select * from t1 left join t2 on (t2.a=
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using index
+2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY PRIMARY 4 func 1 Using index
drop table t0, t1, t2, t3;
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -671,8 +671,8 @@ alter table t3 add primary key(id), add
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t3 index a a 5 NULL 30000 Using index; LooseScan
-1 PRIMARY t2 ref a a 5 test.t3.a 1 Using index
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY t3 index a a 5 NULL 30000 Using index; Materialize
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
=== modified file 'mysql-test/r/subselect_sj2_jcl6.result'
--- a/mysql-test/r/subselect_sj2_jcl6.result 2008-11-05 00:53:38 +0000
+++ b/mysql-test/r/subselect_sj2_jcl6.result 2008-12-22 19:03:25 +0000
@@ -36,8 +36,8 @@ a b
9 5
explain select * from t2 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
-1 PRIMARY t2 ref b b 5 test.t1.a 2 End temporary; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Materialize; Scan
+1 PRIMARY t2 ref b b 5 test.t1.a 2 Using join buffer
select * from t2 where b in (select a from t1);
a b
1 1
@@ -54,8 +54,8 @@ primary key(pk1, pk2, pk3)
insert into t3 select a,a, a,a,a from t0;
explain select * from t3 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Start temporary
-1 PRIMARY t3 ref b b 5 test.t1.a 1 End temporary; Using join buffer
+1 PRIMARY t3 ALL b NULL NULL NULL 10
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t3); Using join buffer
select * from t3 where b in (select a from t1);
a b pk1 pk2 pk3
1 1 1 1 1
@@ -77,8 +77,8 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a
from t0 A, t0 B where B.a <5;
explain select * from t3 where b in (select a from t0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Start temporary
-1 PRIMARY t3 ref b b 5 test.t0.a 1 End temporary; Using join buffer
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Materialize; Scan
+1 PRIMARY t3 ref b b 5 test.t0.a 1 Using join buffer
select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5);
a b pk1 pk2
0 0 0 0
@@ -99,8 +99,8 @@ set join_buffer_size= @save_join_buffer_
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index b b 5 NULL 10 Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t2 index b b 5 NULL 10 Using index; Materialize
select * from t1;
a b
1 1
@@ -127,8 +127,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; End temporary; Using join buffer
+1 PRIMARY it ALL NULL NULL NULL NULL 22 Materialize; Scan
+1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -159,8 +159,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ot ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY it ALL NULL NULL NULL NULL 32 Using where; End temporary; Using join buffer
+1 PRIMARY ot ALL NULL NULL NULL NULL 22
+1 PRIMARY it ALL NULL NULL NULL NULL 32 Materialize
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -184,8 +184,8 @@ a mid(filler1, 1,10) length(filler1)=len
16 filler1234 1
17 filler1234 1
18 filler1234 1
-3 duplicate 1
19 filler1234 1
+3 duplicate 1
19 duplicate 1
insert into t1 select a+20, 'filler123456', 'filler123456' from t0;
insert into t1 select a+20, 'filler123456', 'filler123456' from t0;
@@ -193,8 +193,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; End temporary; Using join buffer
+1 PRIMARY it ALL NULL NULL NULL NULL 22 Materialize; Scan
+1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -225,8 +225,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ot ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY it ALL NULL NULL NULL NULL 52 Using where; End temporary; Using join buffer
+1 PRIMARY ot ALL NULL NULL NULL NULL 22
+1 PRIMARY it ALL NULL NULL NULL NULL 52 Materialize
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -250,8 +250,8 @@ a mid(filler1, 1,10) length(filler1)=len
16 filler1234 1
17 filler1234 1
18 filler1234 1
-3 duplicate 1
19 filler1234 1
+3 duplicate 1
19 duplicate 1
drop table t1, t2;
create table t1 (a int, b int, key(a));
@@ -265,8 +265,8 @@ explain select *
from t0 where a in
(select t2.a+t3.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Start temporary
-1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Using join buffer
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10
+1 PRIMARY t1 index NULL a 5 NULL 10 Using index; Start temporary; Using join buffer
1 PRIMARY t2 ref a a 5 test.t1.a 1 Using index
1 PRIMARY t3 ref a a 5 test.t1.a 1 Using where; Using index; End temporary
drop table t0, t1,t2,t3;
@@ -304,9 +304,9 @@ t2.Code IN (SELECT Country FROM t3
WHERE Language='English' AND Percentage > 10 AND
t2.Population > 100000);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Using MRR; Start temporary
-1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t1.Country 1 Using where; End temporary; Using join buffer
-1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t2.Code,const 1 Using index condition; Using where; Using join buffer
+1 PRIMARY t1 range Population,Country Population 4 NULL 1 Using index condition; Using MRR
+1 PRIMARY t3 eq_ref PRIMARY,Percentage PRIMARY 33 test.t1.Country,const 1 Using index condition; Using where; Using join buffer
+1 PRIMARY t2 eq_ref PRIMARY,Population PRIMARY 3 test.t3.Country 1 Using where; Using join buffer
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (
Code char(3) NOT NULL DEFAULT '',
@@ -341,8 +341,8 @@ EXPLAIN SELECT Name FROM t1
WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL CountryCode NULL NULL NULL 545 Using where; Start temporary
-1 PRIMARY t1 eq_ref PRIMARY PRIMARY 3 test.t2.CountryCode 1 End temporary; Using join buffer
+1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 31
+1 PRIMARY t2 ALL CountryCode NULL NULL NULL 545 Using where; Materialize
SELECT Name FROM t1
WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
@@ -562,8 +562,8 @@ explain
select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t3));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using index
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY PRIMARY 4 func 1 Using index
drop table t0, t1, t2, t3;
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -675,8 +675,8 @@ alter table t3 add primary key(id), add
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t3 index a a 5 NULL 30000 Using index; LooseScan
-1 PRIMARY t2 ref a a 5 test.t3.a 1 Using index
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY t3 index a a 5 NULL 30000 Using index; Materialize
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
=== modified file 'mysql-test/r/subselect_sj_jcl6.result'
--- a/mysql-test/r/subselect_sj_jcl6.result 2008-12-08 21:15:06 +0000
+++ b/mysql-test/r/subselect_sj_jcl6.result 2008-12-22 19:03:25 +0000
@@ -75,20 +75,20 @@ explAin extended
select * from t1 left join (t2 A, t2 B) on ( A.A= t1.A And B.A in (select pk from t10));
id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
-1 PRIMARY A ALL NULL NULL NULL NULL 3 100.00 Using where
-1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00
-1 PRIMARY t10 eq_ref PRIMARY PRIMARY 4 test.B.A 1 100.00 Using index
+1 PRIMARY A ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer
+1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer
+2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t10` join `test`.`t2` `A` join `test`.`t2` `B`) on(((`test`.`A`.`A` = `test`.`t1`.`A`) And 1 And (`test`.`B`.`A` = `test`.`t10`.`pk`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on(((`test`.`A`.`A` = `test`.`t1`.`A`) And <in_optimizer>(`test`.`B`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`B`.`A`) in t10 on PRIMARY))))) where 1
t2 should be wrapped into OJ-nest, so we have "t1 LJ (t2 J t10)"
explAin extended
select * from t1 left join t2 on (t2.A= t1.A And t2.A in (select pk from t10));
id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
-1 PRIMARY t10 eq_ref PRIMARY PRIMARY 4 test.t2.A 1 100.00 Using index
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer
+2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join (`test`.`t10` join `test`.`t2`) on(((`test`.`t2`.`A` = `test`.`t1`.`A`) And 1 And (`test`.`t2`.`A` = `test`.`t10`.`pk`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(((`test`.`t2`.`A` = `test`.`t1`.`A`) And <in_optimizer>(`test`.`t2`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`t2`.`A`) in t10 on PRIMARY))))) where 1
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
=== modified file 'mysql-test/r/type_varchar.result'
--- a/mysql-test/r/type_varchar.result 2008-11-24 09:53:39 +0000
+++ b/mysql-test/r/type_varchar.result 2008-12-22 10:11:13 +0000
@@ -475,8 +475,9 @@ a (a DIV 2)
60 30
t 0
Warnings:
-Warning 1292 Truncated incorrect INTEGER value: '1a'
-Warning 1292 Truncated incorrect INTEGER value: 't '
+Warning 1292 Truncated incorrect DECIMAL value: '1a'
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: 't '
SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a;
a CAST(a AS SIGNED)
10 10
=== modified file 'mysql-test/t/func_math.test'
--- a/mysql-test/t/func_math.test 2008-04-07 15:57:54 +0000
+++ b/mysql-test/t/func_math.test 2008-12-11 15:27:05 +0000
@@ -283,3 +283,14 @@ SELECT EXP(750);
SELECT POW(10, 309);
--echo End of 5.1 tests
+
+#
+# Bug #8457: Precision math: DIV returns incorrect result with large decimal value
+#
+
+--error ER_WARN_DATA_OUT_OF_RANGE
+select 123456789012345678901234567890.123456789012345678901234567890 div 1 as x;
+--error ER_WARN_DATA_OUT_OF_RANGE
+select "123456789012345678901234567890.123456789012345678901234567890" div 1 as x;
+
+--echo End of 6.0 tests
=== added file 'mysql-test/t/innodb_bug34053.test'
--- a/mysql-test/t/innodb_bug34053.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug34053.test 2008-09-15 21:33:05 +0000
@@ -0,0 +1,50 @@
+#
+# Make sure http://bugs.mysql.com/34053 remains fixed.
+#
+
+-- source include/not_embedded.inc
+-- source include/have_innodb.inc
+
+SET storage_engine=InnoDB;
+
+# we do not really care about what gets printed, we are only
+# interested in getting success or failure according to our
+# expectations
+-- disable_query_log
+-- disable_result_log
+
+GRANT USAGE ON *.* TO 'shane'@'localhost' IDENTIFIED BY '12345';
+FLUSH PRIVILEGES;
+
+-- connect (con1,localhost,shane,12345,)
+
+-- connection con1
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB;
+CREATE TABLE innodb_monitorx (a INT) ENGINE=INNODB;
+DROP TABLE innodb_monitorx;
+CREATE TABLE innodb_monito (a INT) ENGINE=INNODB;
+DROP TABLE innodb_monito;
+CREATE TABLE xinnodb_monitor (a INT) ENGINE=INNODB;
+DROP TABLE xinnodb_monitor;
+CREATE TABLE nnodb_monitor (a INT) ENGINE=INNODB;
+DROP TABLE nnodb_monitor;
+
+-- connection default
+CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
+CREATE TABLE innodb_mem_validate (a INT) ENGINE=INNODB;
+
+-- connection con1
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+DROP TABLE innodb_monitor;
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
+DROP TABLE innodb_mem_validate;
+
+-- connection default
+DROP TABLE innodb_monitor;
+DROP TABLE innodb_mem_validate;
+DROP USER 'shane'@'localhost';
+
+-- disconnect con1
=== modified file 'mysql-test/t/partition_not_windows.test'
--- a/mysql-test/t/partition_not_windows.test 2008-12-13 11:02:16 +0000
+++ b/mysql-test/t/partition_not_windows.test 2008-12-17 18:40:14 +0000
@@ -3,8 +3,6 @@
--source include/have_partition.inc
# DATA DIRECTORY/INDEX DIRECTORY require symbolic link support
--source include/have_symlink.inc
-# realpath is not compiled in when building with valgrind
---source include/not_valgrind.inc
# The test for Bug 20770 is disabled on Windows due to BUG#19107; it
# should be moved into partition.test once the bug has been resolved.
=== added file 'mysql-test/t/rpl_slave_exec_mode_basic.test'
--- a/mysql-test/t/rpl_slave_exec_mode_basic.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/rpl_slave_exec_mode_basic.test 2008-09-11 08:01:28 +0000
@@ -0,0 +1,42 @@
+############## mysql-test\t\slave_exec_mode_basic.test #########################
+# #
+# Variable Name: slave_exec_mode #
+# Scope: GLOBAL & SESSION #
+# Access Type: Dynamic #
+# Data Type: Numeric #
+# Default Value: 1 #
+# Range: 1 - 65536 #
+# #
+# #
+# Creation Date: 2008-02-07 #
+# Author: Rizwan Maredia #
+# #
+# Description: Test Cases of Dynamic System Variable slave_exec_mode #
+# that checks the behavior of this variable in the following ways #
+# * Default Value #
+# * Valid & Invalid values #
+# * Scope & Access method #
+# * Data Integrity #
+# #
+# Reference: http://dev.mysql.com/doc/refman/5.1/en/ #
+# server-system-variables.html #
+# #
+################################################################################
+
+--source include/have_log_bin.inc
+--source include/load_sysvars.inc
+
+########################################################################
+# START OF slave_exec_mode TESTS #
+########################################################################
+
+
+########################################################################
+# Saving initial value of slave_exec_mode in a temporary variable #
+########################################################################
+SET @start_value = @@global.slave_exec_mode;
+--echo 'This variable is not supported in version 5.1.22. It is introduced in 5.1.24'
+
+########################################################################
+# END OF slave_exec_mode TESTS #
+########################################################################
=== removed file 'mysql-test/t/rpl_slave_exec_mode_basic.test'
--- a/mysql-test/t/rpl_slave_exec_mode_basic.test 2008-08-08 14:37:49 +0000
+++ b/mysql-test/t/rpl_slave_exec_mode_basic.test 1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
-############## mysql-test\t\slave_exec_mode_basic.test #########################
-# #
-# Variable Name: slave_exec_mode #
-# Scope: GLOBAL & SESSION #
-# Access Type: Dynamic #
-# Data Type: Numeric #
-# Default Value: 1 #
-# Range: 1 - 65536 #
-# #
-# #
-# Creation Date: 2008-02-07 #
-# Author: Rizwan Maredia #
-# #
-# Description: Test Cases of Dynamic System Variable slave_exec_mode #
-# that checks the behavior of this variable in the following ways #
-# * Default Value #
-# * Valid & Invalid values #
-# * Scope & Access method #
-# * Data Integrity #
-# #
-# Reference: http://dev.mysql.com/doc/refman/5.1/en/ #
-# server-system-variables.html #
-# #
-################################################################################
-
---source include/load_sysvars.inc
-
-########################################################################
-# START OF slave_exec_mode TESTS #
-########################################################################
-
-
-########################################################################
-# Saving initial value of slave_exec_mode in a temporary variable #
-########################################################################
-SET @start_value = @@global.slave_exec_mode;
---echo 'This variable is not supported in version 5.1.22. It is introduced in 5.1.24'
-
-########################################################################
-# END OF slave_exec_mode TESTS #
-########################################################################
=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test 2008-12-14 11:36:15 +0000
+++ b/mysql-test/t/subselect.test 2008-12-22 20:00:22 +0000
@@ -1,3 +1,11 @@
+#
+# NOTE. Please do not switch connection inside this test.
+# subselect.test is included from several other test cases which set
+# explicit session properties that must be preserved throughout the test.
+# If you need to use a dedicated connection for a test case,
+# close the new connection and switch back to "default" as soon
+# as possible.
+#
# Initialise
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
@@ -1460,10 +1468,13 @@ drop table t1;
#
# Subselect in non-select command just after connection
+# Disconnect new connection and switch back when test is finished
#
connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
connection root;
set @got_val= (SELECT 1 FROM (SELECT 'A' as my_col) as T1 ) ;
+disconnect root;
+connection default;
#
# primary query with temporary table and subquery with groupping
=== modified file 'mysql-test/t/subselect3.test'
--- a/mysql-test/t/subselect3.test 2008-12-13 11:02:16 +0000
+++ b/mysql-test/t/subselect3.test 2008-12-22 20:10:35 +0000
@@ -1,5 +1,5 @@
--disable_warnings
-drop table if exists t0, t1, t2, t3, t4, t5;
+drop table if exists t0, t1, t2, t3, t4, t5, t11, t12, t21, t22;
--enable_warnings
#
@@ -702,6 +702,264 @@ where
drop table t0, t1, t2, t3, t4, t5;
+#
+# Test for the problem with using sj-materialization when subquery's select
+# list element SCOL is covered by equality propagation and has preceding equal
+# column PCOL which belongs to a table within the the semi-join nest: SJM-Scan
+# process should unpack column value not to SCOL but rather to PCOL, as
+# substitute_best_equal has made all conditions to refer to PCOL.
+#
+CREATE TABLE t1 (
+ a int(11) NOT NULL,
+ b int(11) NOT NULL,
+ c datetime default NULL,
+ PRIMARY KEY (a),
+ KEY idx_bc (b,c)
+);
+
+INSERT INTO t1 VALUES
+(406989,67,'2006-02-23 17:08:46'), (150078,67,'2005-10-26 11:17:45'),
+(406993,67,'2006-02-27 11:20:57'), (245655,67,'2005-12-08 15:59:08'),
+(406994,67,'2006-02-27 11:26:46'), (256,67,NULL),
+(398341,67,'2006-02-20 04:48:44'), (254,67,NULL),(1120,67,NULL),
+(406988,67,'2006-02-23 17:07:22'), (255,67,NULL),
+(398340,67,'2006-02-20 04:38:53'),(406631,67,'2006-02-23 10:49:42'),
+(245653,67,'2005-12-08 15:59:07'),(406992,67,'2006-02-24 16:47:18'),
+(245654,67,'2005-12-08 15:59:08'),(406995,67,'2006-02-28 11:55:00'),
+(127261,67,'2005-10-13 12:17:58'),(406991,67,'2006-02-24 16:42:32'),
+(245652,67,'2005-12-08 15:58:27'),(398545,67,'2006-02-20 04:53:13'),
+(154504,67,'2005-10-28 11:53:01'),(9199,67,NULL),(1,67,'2006-02-23 15:01:35'),
+(223456,67,NULL),(4101,67,NULL),(1133,67,NULL),
+(406990,67,'2006-02-23 18:01:45'),(148815,67,'2005-10-25 15:34:17'),
+(148812,67,'2005-10-25 15:30:01'),(245651,67,'2005-12-08 15:58:27'),
+(154503,67,'2005-10-28 11:52:38');
+
+create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
+create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
+create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
+create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
+
+update t22 set c = '2005-12-08 15:58:27' where a = 255;
+explain select t21.* from t21,t22 where t21.a = t22.a and
+t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+select t21.* from t21,t22 where t21.a = t22.a and
+t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+
+drop table t1, t11, t12, t21, t22;
+
+#
+# Test sj-materialization re-execution. The test isn't meaningful (materialized
+# table stays the same across all executions) because it's hard to create a
+# dataset that would verify correct re-execution without hitting BUG#31480
+#
+create table t1(a int);
+insert into t1 values (0),(1);
+
+set @@optimizer_switch='no_firstmatch';
+explain
+select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
+select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
+set @@optimizer_switch='';
+
+drop table t1;
+
+#
+# Test confluent duplicate weedout
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 as select * from t0;
+insert into t1 select a+10 from t0;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+insert into t0 values(2);
+explain select * from t1 where 2 in (select a from t0);
+select * from t1 where 2 in (select a from t0);
+set @@optimizer_switch='no_materialization';
+explain select * from t1 where 2 in (select a from t0);
+select * from t1 where 2 in (select a from t0);
+set @@optimizer_switch='';
+
+
+#
+# FirstMatch referring to a derived table
+#
+explain select * from (select a from t0) X where a in (select a from t1);
+drop table t0, t1;
+
+#
+# LooseScan: Check if we can pick it together with range access
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t1 (kp1 int, kp2 int, c int, filler char(100), key(kp1, kp2));
+insert into t1 select A.a+10*(B.a+10*C.a), 0, 0, 'filler' from t0 A, t0 B, t0 C;
+insert into t1 select * from t1 where kp1 < 20;
+
+create table t3 (a int);
+insert into t3 select A.a + 10*B.a from t0 A, t0 B;
+
+explain select * from t3 where a in (select kp1 from t1 where kp1<20);
+
+create table t4 (pk int primary key);
+insert into t4 select a from t3;
+
+explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
+and t4.pk=t1.c);
+
+drop table t1, t3, t4;
+
+#
+# Test if we handle duplicate elimination temptable overflowing to disk
+#
+create table t1 (a int) as select * from t0 where a < 5;
+
+set @save_max_heap_table_size=@@max_heap_table_size;
+set @@optimizer_switch='no_firstmatch,no_materialization';
+set @@max_heap_table_size= 16384;
+
+explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E);
+flush status;
+select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E);
+show status like 'Created_tmp_disk_tables';
+set @save_max_heap_table_size=@@max_heap_table_size;
+set @@optimizer_switch=default;
+drop table t0, t1;
+
+#
+# Materialize + Scan + ref access to the subsequent table based on scanned
+# value
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 values (1),(2);
+create table t3 ( a int , filler char(100), key(a));
+insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
+explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
+select * from t3 where a in (select a from t2);
+
+drop table t0, t2, t3;
+
+#
+# DATETIME type checks
+#
+set @@optimizer_switch='no_firstmatch,no_materialization';
+create table t1 (a date);
+insert into t1 values ('2008-01-01'),('2008-01-01'),('2008-02-01'),('2008-02-01');
+create table t2 (a int);
+insert into t2 values (1),(2);
+create table t3 (a char(10));
+insert into t3 select * from t1;
+insert into t3 values (1),(2);
+explain select * from t2 where a in (select a from t1);
+explain select * from t2 where a in (select a from t2);
+explain select * from t2 where a in (select a from t3);
+explain select * from t1 where a in (select a from t3);
+drop table t1, t2, t3;
+create table t1 (a decimal);
+insert into t1 values (1),(2);
+explain select * from t1 where a in (select a from t1);
+drop table t1;
+set @@optimizer_switch=default;
+
+#
+# SJ-Materialization-scan for non-first table
+#
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 as select * from t1;
+create table t3 (a int, b int, filler char(100), key(a));
+insert into t3 select A.a + 10*B.a, A.a + 10*B.a, 'filler' from t1 A, t1 B, t1 C;
+explain select * from t1, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30) and t1.a =3;
+
+#
+# Verify that straight_join modifier in parent or child prevents flattening
+#
+explain select straight_join * from t1 A, t1 B where A.a in (select a from t2);
+explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
+explain select * from t2 where a in (select straight_join A.a from t1 A, t1 B);
+explain select straight_join * from t2 X, t2 Y
+where X.a in (select straight_join A.a from t1 A, t1 B);
+
+#
+# SJ-Materialization scan + first table being system const table
+#
+create table t0 (a int, b int);
+insert into t0 values(1,1);
+explain select * from t0, t3 where t3.a in (select a from t2) and (t3.a < 10 or t3.a >30);
+create table t4 as select a as x, a as y from t1;
+explain select * from t0, t3 where (t3.a, t3.b) in (select x,y from t4) and (t3.a < 10 or t3.a >30);
+drop table t0,t1,t2,t3,t4;
+
+#
+# LooseScan with ref access
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int, b int, filler char(100), key(a,b));
+insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
+create table t2 as select * from t1;
+
+explain select * from t2 where a in (select b from t1 where a=3);
+explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
+
+drop table t1,t2;
+
+#
+# Multi-column sj-materialization with lookups
+#
+create table t1 (a int, b int);
+insert into t1 select a,a from t0;
+create table t2 (a int, b int);
+insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
+
+set @@optimizer_switch='no_firstmatch';
+explain select * from t1 where (a,b) in (select a,b from t2);
+
+# A smallish test if find_best() still works for semi-join optimization:
+set @save_optimizer_search_depth=@@optimizer_search_depth;
+set @@optimizer_search_depth=63;
+explain select * from t1 where (a,b) in (select a,b from t2);
+set @@optimizer_search_depth=@save_optimizer_search_depth;
+set @@optimizer_switch='';
+
+drop table t0, t1, t2;
+
+
+#
+# Primitive SJ-Materialization tests for DECIMAL and DATE
+#
+create table t0 (a decimal(4,2));
+insert into t0 values (10.24), (22.11);
+create table t1 as select * from t0;
+insert into t1 select * from t0;
+explain select * from t0 where a in (select a from t1);
+select * from t0 where a in (select a from t1);
+drop table t0, t1;
+
+create table t0(a date);
+insert into t0 values ('2008-01-01'),('2008-02-02');
+create table t1 as select * from t0;
+insert into t1 select * from t0;
+explain select * from t0 where a in (select a from t1);
+select * from t0 where a in (select a from t1);
+drop table t0, t1;
+
+#
+# Fix a trivial crash with SJ-Materialization lookup, multiple tables in the
+# subquery, and a condition on some of inner tables but not others
+#
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 as select a as a, a as b, a as c from t0 where a < 3;
+create table t2 as select a as a, a as b from t0 where a < 3;
+insert into t2 select * from t2;
+
+explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
+
+drop table t0,t1,t2;
+
--echo
--echo BUG#40118 Crash when running Batched Key Access and requiring one match for each key
--echo
@@ -718,4 +976,3 @@ set join_cache_level=6;
select * from t0 where t0.a in (select t1.a from t1 where t1.b=0);
set join_cache_level=@save_join_cache_level;
drop table t0, t1;
-
=== modified file 'mysql-test/t/subselect_mat.test'
--- a/mysql-test/t/subselect_mat.test 2008-04-24 23:59:38 +0000
+++ b/mysql-test/t/subselect_mat.test 2008-11-20 15:34:15 +0000
@@ -806,3 +806,44 @@ select 1 from t2 where
t2.a = 3 and not t2.a not in (select t2.b from t2);
drop table t2;
+#
+# BUG#37896 Assertion on entry of Item_in_subselect::exec on subquery with AND NOT
+#
+create table t1 (a1 int key);
+create table t2 (b1 int);
+insert into t1 values (5);
+
+# Query with group by, executed via materialization
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+# Query with group by, executed via IN=>EXISTS
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+
+# Executed with materialization
+set @@optimizer_switch='no_semijoin';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+select min(a1) from t1 where 7 in (select b1 from t2);
+# Executed with semi-join. Notice, this time we get a different result (NULL).
+# This is the only correct result of all four queries. This difference is
+# filed as BUG#40037.
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+select min(a1) from t1 where 7 in (select b1 from t2);
+drop table t1,t2;
+
+#
+# BUG#36752 "subquery materialization produces wrong results when comparing different types"
+#
+create table t1 (a char(2), b varchar(10));
+insert into t1 values ('a', 'aaa');
+insert into t1 values ('aa', 'aaaa');
+
+set @@optimizer_switch='no_semijoin';
+explain select a,b from t1 where b in (select a from t1);
+select a,b from t1 where b in (select a from t1);
+prepare st1 from "select a,b from t1 where b in (select a from t1)";
+execute st1;
+execute st1;
+drop table t1;
=== modified file 'netware/BUILD/nwbootstrap'
--- a/netware/BUILD/nwbootstrap 2008-08-18 15:08:57 +0000
+++ b/netware/BUILD/nwbootstrap 2008-12-31 13:18:04 +0000
@@ -143,7 +143,9 @@ bk changes -v -r$rev..$revision > $targe
if test -d $doc_dir
then
echo "adding the latest manual..."
- install -m 644 $doc_dir/Docs/{manual,reservedwords}.texi $target_dir/Docs/
+ install -m 644 $doc_dir/Docs/manual.texi \
+ $doc_dir/Docs/reservedwords.texi \
+ $target_dir/Docs/
fi
# make files writeable
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2008-12-14 11:36:15 +0000
+++ b/sql/handler.h 2008-12-31 13:49:36 +0000
@@ -1254,6 +1254,17 @@ public:
add_io_cnt * add_avg_cost) / io_count_sum;
io_count= io_count_sum;
}
+
+ /*
+ To be used when we go from old single value-based cost calculations to
+ the new COST_VECT-based.
+ */
+ void convert_from_cost(double cost)
+ {
+ zero();
+ avg_io_cost= 1.0;
+ io_count= cost;
+ }
};
void get_sweep_read_cost(TABLE *table, ha_rows nrows, bool interrupted,
=== modified file 'sql/item_cmpfunc.h'
--- a/sql/item_cmpfunc.h 2008-11-27 16:44:19 +0000
+++ b/sql/item_cmpfunc.h 2008-12-13 20:01:27 +0000
@@ -463,13 +463,23 @@ public:
class Item_func_eq :public Item_bool_rowready_func2
{
public:
- Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
+ Item_func_eq(Item *a,Item *b) :
+ Item_bool_rowready_func2(a,b), in_equality_no(UINT_MAX)
+ {}
longlong val_int();
enum Functype functype() const { return EQ_FUNC; }
enum Functype rev_functype() const { return EQ_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "="; }
Item *negated_item();
+ /*
+ - If this equality is created from the subquery's IN-equality:
+ number of the item it was created from, e.g. for
+ (a,b) IN (SELECT c,d ...) a=c will have in_equality_no=0,
+ and b=d will have in_equality_no=1.
+ - Otherwise, UINT_MAX
+ */
+ uint in_equality_no;
};
class Item_func_equal :public Item_bool_rowready_func2
@@ -1562,6 +1572,7 @@ public:
for them. We have to take care of restricting the predicate such an
object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik.
*/
+struct st_join_table;
class Item_equal: public Item_bool_func
{
@@ -1598,6 +1609,9 @@ public:
virtual void print(String *str, enum_query_type query_type);
CHARSET_INFO *compare_collation()
{ return fields.head()->collation.collation; }
+ friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
+ Item_equal *item_equal);
+ friend bool setup_sj_materialization(struct st_join_table *tab);
};
class COND_EQUAL: public Sql_alloc
=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc 2008-12-14 11:36:15 +0000
+++ b/sql/item_func.cc 2008-12-31 13:49:36 +0000
@@ -1368,6 +1368,38 @@ void Item_func_div::fix_length_and_dec()
longlong Item_func_int_div::val_int()
{
DBUG_ASSERT(fixed == 1);
+
+ /*
+ Perform division using DECIMAL math if either of the operands has a
+ non-integer type
+ */
+ if (args[0]->result_type() != INT_RESULT ||
+ args[1]->result_type() != INT_RESULT)
+ {
+ my_decimal value0, value1, tmp;
+ my_decimal *val0, *val1;
+ longlong res;
+ int err;
+
+ val0= args[0]->val_decimal(&value0);
+ val1= args[1]->val_decimal(&value1);
+ if ((null_value= (args[0]->null_value || args[1]->null_value)))
+ return 0;
+
+ if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp,
+ val0, val1, 0)) > 3)
+ {
+ if (err == E_DEC_DIV_ZERO)
+ signal_divide_by_null();
+ return 0;
+ }
+
+ if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) &
+ E_DEC_OVERFLOW)
+ my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0), name, 1);
+ return res;
+ }
+
longlong value=args[0]->val_int();
longlong val2=args[1]->val_int();
if ((null_value= (args[0]->null_value || args[1]->null_value)))
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2008-10-20 09:16:47 +0000
+++ b/sql/item_subselect.cc 2008-11-26 14:36:11 +0000
@@ -1005,6 +1005,7 @@ Item_in_subselect::single_value_transfor
Check that the right part of the subselect contains no more than one
column. E.g. in SELECT 1 IN (SELECT * ..) the right part is (SELECT * ...)
*/
+ // psergey: duplicated_subselect_card_check
if (select_lex->item_list.elements > 1)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
@@ -1362,6 +1363,7 @@ Item_in_subselect::row_value_transformer
DBUG_ENTER("Item_in_subselect::row_value_transformer");
+ // psergey: duplicated_subselect_card_check
if (select_lex->item_list.elements != left_expr->cols())
{
my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols());
@@ -1696,6 +1698,8 @@ Item_in_subselect::select_in_like_transf
In some optimisation cases we will not need this Item_in_optimizer
object, but we can't know it here, but here we need address correct
reference on left expresion.
+
+ //psergey: he means confluent cases like "... IN (SELECT 1)"
*/
if (!optimizer)
{
@@ -1896,7 +1900,11 @@ bool Item_in_subselect::init_left_expr_c
bool use_result_field= FALSE;
outer_join= unit->outer_select()->join;
- if (!outer_join || !outer_join->tables)
+ /*
+ An IN predicate might be evaluated in a query for which all tables have
+ been optimzied away.
+ */
+ if (!outer_join || !outer_join->tables || !outer_join->tables_list)
return TRUE;
/*
If we use end_[send | write]_group to handle complete rows of the outer
@@ -2218,11 +2226,6 @@ int subselect_single_select_engine::exec
SELECT_LEX_UNIT *unit= select_lex->master_unit();
unit->set_limit(unit->global_parameters);
- if (join->flatten_subqueries())
- {
- thd->is_fatal_error= TRUE;
- DBUG_RETURN(1);
- }
if (join->optimize())
{
thd->where= save_where;
@@ -3110,11 +3113,54 @@ bool subselect_hash_sj_engine::init_perm
KEY_PART_INFO *cur_key_part= tmp_key->key_part;
store_key **ref_key= tab->ref.key_copy;
uchar *cur_ref_buff= tab->ref.key_buff;
+
+ /*
+ Create an artificial condition to post-filter those rows matched by index
+ lookups that cannot be distinguished by the index lookup procedure, e.g.
+ because of truncation. Prepared statements execution requires that
+ fix_fields is called for every execution. In order to call fix_fields we
+ need to create a Name_resolution_context and a corresponding TABLE_LIST
+ for the temporary table for the subquery, so that all column references
+ to the materialized subquery table can be resolved correctly.
+ */
+ DBUG_ASSERT(cond == NULL);
+ if (!(cond= new Item_cond_and))
+ DBUG_RETURN(TRUE);
+ /*
+ Table reference for tmp_table that is used to resolve column references
+ (Item_fields) to columns in tmp_table.
+ */
+ TABLE_LIST *tmp_table_ref;
+ if (!(tmp_table_ref= (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
+ DBUG_RETURN(TRUE);
+
+ tmp_table_ref->init_one_table(NULL, 0, "materialized subselect", 22,
+ "materialized subselect", TL_READ);
+ tmp_table_ref->table= tmp_table;
+
+ /* Name resolution context for all tmp_table columns created below. */
+ Name_resolution_context *context= new Name_resolution_context;
+ context->init();
+ context->first_name_resolution_table=
+ context->last_name_resolution_table= tmp_table_ref;
for (uint i= 0; i < tmp_key_parts; i++, cur_key_part++, ref_key++)
{
- tab->ref.items[i]= item_in->left_expr->element_index(i);
+ Item_func_eq *eq_cond; /* New equi-join condition for the current column. */
+ /* Item for the corresponding field from the materialized temp table. */
+ Item_field *right_col_item;
int null_count= test(cur_key_part->field->real_maybe_null());
+ tab->ref.items[i]= item_in->left_expr->element_index(i);
+
+ if (!(right_col_item= new Item_field(thd, context, cur_key_part->field)) ||
+ !(eq_cond= new Item_func_eq(tab->ref.items[i], right_col_item)) ||
+ ((Item_cond_and*)cond)->add(eq_cond))
+ {
+ delete cond;
+ cond= NULL;
+ DBUG_RETURN(TRUE);
+ }
+
*ref_key= new store_key_item(thd, cur_key_part->field,
/* TODO:
the NULL byte is taken into account in
@@ -3131,6 +3177,9 @@ bool subselect_hash_sj_engine::init_perm
tab->ref.key_err= 1;
tab->ref.key_parts= tmp_key_parts;
+ if (cond->fix_fields(thd, &cond))
+ DBUG_RETURN(TRUE);
+
DBUG_RETURN(FALSE);
}
@@ -3150,6 +3199,12 @@ bool subselect_hash_sj_engine::init_runt
the subquery if not yet created.
*/
materialize_engine->prepare();
+ /*
+ Repeat name resolution for 'cond' since cond is not part of any
+ clause of the query, and it is not 'fixed' during JOIN::prepare.
+ */
+ if (cond && !cond->fixed && cond->fix_fields(thd, &cond))
+ return TRUE;
/* Let our engine reuse this query plan for materialization. */
materialize_join= materialize_engine->join;
materialize_join->change_result(result);
@@ -3207,9 +3262,8 @@ int subselect_hash_sj_engine::exec()
int res= 0;
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= materialize_engine->select_lex;
- if ((res= materialize_join->flatten_subqueries()) ||
- (res= materialize_join->optimize()))
- goto err;
+ if ((res= materialize_join->optimize()))
+ goto err; /* purecov: inspected */
materialize_join->exec();
if ((res= test(materialize_join->error || thd->is_fatal_error)))
goto err;
=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h 2008-05-01 03:53:36 +0000
+++ b/sql/item_subselect.h 2008-11-10 18:36:50 +0000
@@ -36,10 +36,21 @@ class Item_subselect :public Item_result
public:
/* thread handler, will be assigned in fix_fields only */
THD *thd;
- /* substitution instead of subselect in case of optimization */
+ /*
+ Used inside Item_subselect::fix_fields() according to this scenario:
+ > Item_subselect::fix_fields
+ > engine->prepare
+ > child_join->prepare
+ (Here we realize we need to do the rewrite and set
+ substitution= some new Item, eg. Item_in_optimizer )
+ < child_join->prepare
+ < engine->prepare
+ *ref= substitution;
+ < Item_subselect::fix_fields
+ */
Item *substitution;
- /* unit of subquery */
public:
+ /* unit of subquery */
st_select_lex_unit *unit;
protected:
/* engine that perform execution of subselect (single select or union) */
@@ -303,6 +314,17 @@ public:
- (TABLE_LIST*)1 if the predicate is in the WHERE.
*/
TABLE_LIST *expr_join_nest;
+ /*
+ Types of left_expr and subquery's select list allow to perform subquery
+ materialization. Currently, we set this to FALSE when it as well could
+ be TRUE. This is to be properly addressed with fix for BUG#36752.
+ */
+ bool types_allow_materialization;
+
+ /*
+ Same as above, but they also allow to scan the materialized table.
+ */
+ bool sjm_scan_allowed;
/* The method chosen to execute the IN predicate. */
enum enum_exec_method {
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2008-12-19 14:59:10 +0000
+++ b/sql/mysql_priv.h 2009-01-06 19:37:13 +0000
@@ -392,7 +392,6 @@ enum open_table_mode
#define DISK_SEEK_PROP_COST ((double)0.1/BLOCKS_IN_AVG_SEEK)
-
/**
Number of rows in a reference table when refereed through a not unique key.
This value is only used when we don't know anything about the key
@@ -400,6 +399,12 @@ enum open_table_mode
*/
#define MATCHING_ROWS_IN_OTHER_TABLE 10
+/*
+ Subquery materialization-related constants
+*/
+#define HEAP_TEMPTABLE_LOOKUP_COST 0.05
+#define DISK_TEMPTABLE_LOOKUP_COST 1.0
+
/** Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used). */
#define KEY_DEFAULT_PACK_LENGTH 8
@@ -570,7 +575,7 @@ enum open_table_mode
#define OPTIMIZER_SWITCH_NO_MATERIALIZATION 1
#define OPTIMIZER_SWITCH_NO_SEMIJOIN 2
#define OPTIMIZER_SWITCH_NO_LOOSE_SCAN 4
-
+#define OPTIMIZER_SWITCH_NO_FIRSTMATCH 8
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
@@ -1849,6 +1854,7 @@ void TEST_filesort(SORT_FIELD *sortorder
void print_plan(JOIN* join,uint idx, double record_count, double read_time,
double current_read_time, const char *info);
void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array);
+void print_sjm(SJ_MATERIALIZATION_INFO *sjm);
#define EXTRA_DEBUG_DUMP_TABLE_LISTS
#ifdef EXTRA_DEBUG_DUMP_TABLE_LISTS
void dump_TABLE_LIST_graph(SELECT_LEX *select_lex, TABLE_LIST* tl);
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-12-19 14:59:10 +0000
+++ b/sql/mysqld.cc 2009-01-06 19:37:13 +0000
@@ -329,7 +329,7 @@ TYPELIB sql_mode_typelib= { array_elemen
static const char *optimizer_switch_names[]=
{
- "no_materialization", "no_semijoin", "no_loosescan",
+ "no_materialization", "no_semijoin", "no_loosescan", "no_firstmatch",
NullS
};
@@ -339,6 +339,7 @@ static const unsigned int optimizer_swit
/*no_materialization*/ 18,
/*no_semijoin*/ 11,
/*no_loosescan*/ 12,
+ /*no_firstmatch*/ 13
};
TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc 2008-12-16 11:29:22 +0000
+++ b/sql/opt_range.cc 2008-12-31 13:49:36 +0000
@@ -671,6 +671,11 @@ public:
*/
bool using_real_indexes;
+ /*
+ Aggressively remove "scans" that do not have conditions on first
+ keyparts. Such scans are usable when doing partition pruning but not
+ regular range optimization.
+ */
bool remove_jump_scans;
/*
=== modified file 'sql/opt_range.h'
--- a/sql/opt_range.h 2008-08-25 18:23:27 +0000
+++ b/sql/opt_range.h 2008-12-27 02:32:25 +0000
@@ -108,7 +108,11 @@ class QUICK_RANGE :public Sql_alloc {
4. Delete the select:
delete quick;
-
+
+ NOTE
+ quick select doesn't use Sql_alloc/MEM_ROOT allocation because "range
+ checked for each record" functionality may create/destroy
+ O(#records_in_some_table) quick selects during query execution.
*/
class QUICK_SELECT_I
=== modified file 'sql/records.h'
--- a/sql/records.h 2008-09-12 09:09:27 +0000
+++ b/sql/records.h 2008-10-31 18:53:23 +0000
@@ -25,6 +25,7 @@ class handler;
struct TABLE;
class THD;
class SQL_SELECT;
+class Copy_field;
/**
A context for reading through a single table using a chosen access method:
@@ -60,7 +61,13 @@ struct READ_RECORD
uchar *cache,*cache_pos,*cache_end,*read_positions;
struct st_io_cache *io_cache;
bool print_error, ignore_not_found_rows;
- struct st_join_table *do_insideout_scan;
+
+ /*
+ SJ-Materialization runtime may need to read fields from the materialized
+ table and unpack them into original table fields:
+ */
+ Copy_field *copy_field;
+ Copy_field *copy_field_end;
public:
READ_RECORD() {}
@@ -74,3 +81,4 @@ void init_read_record_idx(READ_RECORD *i
void end_read_record(READ_RECORD *info);
#endif /* SQL_RECORDS_H */
+
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-12-19 14:59:10 +0000
+++ b/sql/sql_base.cc 2009-01-06 19:37:13 +0000
@@ -3650,9 +3650,6 @@ int open_tables(THD *thd, TABLE_LIST **s
*/
for (tables= *start; tables ;tables= tables->next_global)
{
- DBUG_PRINT("tcache", ("opening table: '%s'.'%s' item: %p",
- tables->db, tables->table_name, tables));
-
safe_to_ignore_table= FALSE;
/*
@@ -3698,6 +3695,8 @@ int open_tables(THD *thd, TABLE_LIST **s
}
DBUG_RETURN(-1);
}
+ DBUG_PRINT("tcache", ("opening table: '%s'.'%s' item: %p",
+ tables->db, tables->table_name, tables)); //psergey: invalid read of size 1 here
(*counter)++;
/* Not a placeholder: must be a base table or a view. Let us open it. */
@@ -6530,7 +6529,14 @@ int setup_wild(THD *thd, TABLE_LIST *tab
/* make * substituting permanent */
SELECT_LEX *select_lex= thd->lex->current_select;
select_lex->with_wild= 0;
- select_lex->item_list= fields;
+
+ /*
+ The assignment below is translated to memcpy() call (at least on some
+ platforms). memcpy() expects that source and destination areas do not
+ overlap. That problem was detected by valgrind.
+ */
+ if (&select_lex->item_list != &fields)
+ select_lex->item_list= fields;
thd->restore_active_arena(arena, &backup);
}
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-12-19 14:59:10 +0000
+++ b/sql/sql_class.h 2009-01-06 19:37:13 +0000
@@ -2812,6 +2812,67 @@ public:
bool send_data(List<Item> &items);
};
+struct st_table_ref;
+
+
+/*
+ Optimizer and executor structure for the materialized semi-join info. This
+ structure contains
+ - The sj-materialization temporary table
+ - Members needed to make index lookup or a full scan of the temptable.
+*/
+class SJ_MATERIALIZATION_INFO : public Sql_alloc
+{
+public:
+ /* Optimal join sub-order */
+ struct st_position *positions;
+
+ uint tables; /* Number of tables in the sj-nest */
+
+ /* Expected #rows in the materialized table */
+ double rows;
+
+ /*
+ Cost to materialize - execute the sub-join and write rows into temp.table
+ */
+ COST_VECT materialization_cost;
+
+ /* Cost to make one lookup in the temptable */
+ COST_VECT lookup_cost;
+
+ /* Cost of scanning the materialized table */
+ COST_VECT scan_cost;
+
+ /* --- Execution structures ---------- */
+
+ /*
+ TRUE <=> This structure is used for execution. We don't necessarily pick
+ sj-materialization, so some of SJ_MATERIALIZATION_INFO structures are not
+ used by materialization
+ */
+ bool is_used;
+
+ bool materialized; /* TRUE <=> materialization already performed */
+ /*
+ TRUE - the temptable is read with full scan
+ FALSE - we use the temptable for index lookups
+ */
+ bool is_sj_scan;
+
+ /* The temptable and its related info */
+ TMP_TABLE_PARAM sjm_table_param;
+ List<Item> sjm_table_cols;
+ TABLE *table;
+
+ /* Structure used to make index lookups */
+ struct st_table_ref *tab_ref;
+ Item *in_equality; /* See create_subq_in_equalities() */
+
+ Item *join_cond; /* See comments in make_join_select() */
+ Copy_field *copy_field; /* Needed for SJ_Materialization scan */
+};
+
+
/* Structs used when sorting */
typedef struct st_sort_field {
=== modified file 'sql/sql_join_cache.cc'
--- a/sql/sql_join_cache.cc 2008-12-11 00:21:13 +0000
+++ b/sql/sql_join_cache.cc 2008-12-22 19:03:25 +0000
@@ -67,7 +67,6 @@ uint add_flag_field_to_join_cache(uchar
copy->type= 0;
copy->field= 0;
copy->referenced_field_no= 0;
- copy->get_rowid= NULL;
(*field)++;
return length;
}
@@ -123,7 +122,6 @@ uint add_table_data_fields_to_join_cache
}
copy->field= *fld_ptr;
copy->referenced_field_no= 0;
- copy->get_rowid= NULL;
copy++;
(*field_cnt)++;
used_fields--;
@@ -350,21 +348,13 @@ void JOIN_CACHE:: create_remaining_field
©, ©_ptr);
/* SemiJoinDuplicateElimination: allocate space for rowid if needed */
- if (tab->rowid_keep_flags & JOIN_TAB::KEEP_ROWID)
+ if (tab->keep_current_rowid)
{
copy->str= table->file->ref;
copy->length= table->file->ref_length;
copy->type= 0;
copy->field= 0;
copy->referenced_field_no= 0;
- copy->get_rowid= NULL;
- if (tab->rowid_keep_flags & JOIN_TAB::CALL_POSITION)
- {
- /* We will need to call h->position(): */
- copy->get_rowid= tab->table;
- /* And those after us won't have to: */
- tab->rowid_keep_flags &= ~((int)JOIN_TAB::CALL_POSITION);
- }
length+= copy->length;
data_field_count++;
copy++;
@@ -986,12 +976,6 @@ uint JOIN_CACHE::write_record_data(uchar
}
else
{
- if (copy->get_rowid)
- {
- /* SemiJoinDuplicateElimination: get the rowid into table->ref */
- copy->get_rowid->file->position(copy->get_rowid->record[0]);
- }
-
switch (copy->type) {
case CACHE_VARSTR1:
/* Copy the significant part of the short varstring field */
@@ -1670,6 +1654,9 @@ enum_nested_loop_state JOIN_CACHE_BNL::j
info= &join_tab->read_record;
do
{
+ if (join_tab->keep_current_rowid)
+ join_tab->table->file->position(join_tab->table->record[0]);
+
if (join->thd->killed)
{
/* The user has aborted the execution of the query */
@@ -2168,6 +2155,8 @@ enum_nested_loop_state JOIN_CACHE_BKA::j
rc= NESTED_LOOP_KILLED;
goto finish;
}
+ if (join_tab->keep_current_rowid)
+ join_tab->table->file->position(join_tab->table->record[0]);
/*
If only the first match is needed and it has been already found
for the associated partial join record then the returned candidate
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2008-12-19 14:59:10 +0000
+++ b/sql/sql_lex.h 2009-01-06 19:37:13 +0000
@@ -821,7 +821,7 @@ public:
}
void clear_index_hints(void) { index_hints= NULL; }
-
+ bool is_part_of_union() { return master_unit()->is_union(); }
private:
/* current index hint kind. used in filling up index_hints */
enum index_hint_type current_index_hint_type;
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2008-12-16 11:29:22 +0000
+++ b/sql/sql_select.cc 2008-12-31 13:49:36 +0000
@@ -54,6 +54,7 @@ struct st_sargable_param;
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
DYNAMIC_ARRAY *keyuse);
+static bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
JOIN_TAB *join_tab,
uint tables, COND *conds,
@@ -64,11 +65,11 @@ static int sort_keyuse(KEYUSE *a,KEYUSE
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
table_map used_tables);
-static bool choose_plan(JOIN *join,table_map join_tables);
-
-static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd,
- table_map remaining_tables, uint idx,
- double record_count, double read_time);
+static bool choose_plan(JOIN *join, table_map join_tables);
+static void best_access_path(JOIN *join, JOIN_TAB *s,
+ table_map remaining_tables, uint idx,
+ bool disable_jbuf, double record_count,
+ POSITION *pos, POSITION *loose_scan_pos);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static bool greedy_search(JOIN *join, table_map remaining_tables,
uint depth, uint prune_level);
@@ -78,8 +79,9 @@ static bool best_extension_by_limited_se
double read_time, uint depth,
uint prune_level);
static uint determine_search_depth(JOIN* join);
-static int join_tab_cmp(const void* ptr1, const void* ptr2);
-static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
+static int join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2);
+static int join_tab_cmp_straight(const void *dummy, const void* ptr1, const void* ptr2);
+static int join_tab_cmp_embedded_first(const void *emb, const void* ptr1, const void *ptr2);
/*
TODO: 'find_best' is here only temporarily until 'greedy_search' is
tested and approved.
@@ -95,7 +97,9 @@ static store_key *get_store_key(THD *thd
uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
static void make_outerjoin_info(JOIN *join);
-static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
+static Item*
+make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, table_map sjm_tables);
+static bool make_join_select(JOIN *join, Item *item);
static bool make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after);
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
static void update_depend_map(JOIN *join);
@@ -122,9 +126,13 @@ static uint build_bitmap_for_nested_join
uint first_unused);
static
-void advance_sj_state(const table_map remaining_tables, const JOIN_TAB *tab);
+void advance_sj_state(JOIN *join, const table_map remaining_tables,
+ const JOIN_TAB *s, uint idx,
+ double *current_record_count, double *current_read_time,
+ POSITION *loose_scan_pos);
+
static void restore_prev_sj_state(const table_map remaining_tables,
- const JOIN_TAB *tab);
+ const JOIN_TAB *tab, uint idx);
static COND *optimize_cond(JOIN *join, COND *conds,
List<TABLE_LIST> *join_list,
@@ -164,6 +172,7 @@ static int join_read_const_table(JOIN_TA
static int join_read_system(JOIN_TAB *tab);
static int join_read_const(JOIN_TAB *tab);
static int join_read_key(JOIN_TAB *tab);
+static int join_read_key2(JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref);
static int join_read_always_key(JOIN_TAB *tab);
static int join_read_last_key(JOIN_TAB *tab);
static int join_no_more_records(READ_RECORD *info);
@@ -207,7 +216,7 @@ static int remove_dup_with_hash_index(TH
uint field_count, Field **first_field,
ulong key_length,Item *having);
-static bool cmp_buffer_with_ref(JOIN_TAB *tab);
+static bool cmp_buffer_with_ref(THD *thd, TABLE *table, TABLE_REF *tab_ref);
static bool setup_new_fields(THD *thd, List<Item> &fields,
List<Item> &all_fields, ORDER *new_order);
static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array,
@@ -240,24 +249,31 @@ void select_describe(JOIN *join, bool ne
bool distinct, const char *message=NullS);
static Item *remove_additional_cond(Item* conds);
static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
-static bool test_if_ref(COND *root_cond,
+static bool test_if_ref(Item *root_cond,
Item_field *left_item,Item *right_item);
-static bool replace_where_subcondition(JOIN *join, TABLE_LIST *emb_nest,
+static bool replace_where_subcondition(JOIN *join, Item **expr,
Item *old_cond, Item *new_cond,
bool do_fix_fields);
+void get_partial_join_cost(JOIN *join, uint idx, double *read_time_arg,
+ double *record_count_arg);
+static uint make_join_orderinfo(JOIN *join);
+static int
+join_read_record_no_init(JOIN_TAB *tab);
+static
+bool subquery_types_allow_materialization(THD *thd,
+ Item_in_subselect *in_subs,
+ bool *scan_allowed);
+int do_sj_reset(SJ_TMP_TABLE *sj_tbl);
+TABLE *create_duplicate_weedout_tmp_table(THD *thd, uint uniq_tuple_length_arg,
+ SJ_TMP_TABLE *sjtbl);
+inline bool optimizer_flag(THD *thd, uint flag)
+{
+ return (thd->variables.optimizer_switch & flag);
+}
-/*
- This is used to mark equalities that were made from i-th IN-equality.
- We limit semi-join InsideOut optimization to handling max 64 inequalities,
- The following variable occupies 64 addresses.
-*/
-const char *subq_sj_cond_name=
- "0123456789ABCDEF0123456789abcdef0123456789ABCDEF0123456789abcdef-sj-cond";
+Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
+ bool *inherited_fl);
-static bool bitmap_covers(const table_map x, const table_map y)
-{
- return !test(y & ~x);
-}
/**
This handles SELECT with and without UNION.
@@ -550,145 +566,157 @@ JOIN::prepare(Item ***rref_pointer_array
DBUG_RETURN(-1); /* purecov: inspected */
thd->lex->allow_sum_func= save_allow_sum_func;
}
+
+ /*
+ If
+ 1) this join is inside a subquery (of any type except FROM-clause
+ subquery) and
+ 2) we aren't just normalizing a VIEW
+
+ Then perform early unconditional subquery transformations:
+ - Convert subquery predicate into semi-join, or
+ - Mark the subquery for execution using materialization, or
+ - Perform IN->EXISTS transformation, or
+ - Perform more/less ALL/ANY -> MIN/MAX rewrite
+ - Substitute trivial scalar-context subquery with its value
- if (!thd->lex->view_prepare_mode)
+ TODO: for PS, make the whole block execute only on the first execution
+ */
+ Item_subselect *subselect;
+ if (!thd->lex->view_prepare_mode && // (1)
+ (subselect= select_lex->master_unit()->item)) // (2)
{
- Item_subselect *subselect;
Item_in_subselect *in_subs= NULL;
+ if (subselect->substype() == Item_subselect::IN_SUBS)
+ in_subs= (Item_in_subselect*)subselect;
+ DBUG_PRINT("info", ("Checking if subq can be converted to semi-join"));
/*
- Are we in a subquery predicate?
- TODO: the block below will be executed for every PS execution without need.
+ Check if we're in subquery that is a candidate for flattening into a
+ semi-join (which is done in flatten_subqueries()). The
+ requirements are:
+ 1. Subquery predicate is an IN/=ANY subq predicate
+ 2. Subquery is a single SELECT (not a UNION)
+ 3. Subquery does not have GROUP BY or ORDER BY
+ 4. Subquery does not use aggregate functions or HAVING
+ 5. Subquery predicate is at the AND-top-level of ON/WHERE clause
+ 6. We are not in a subquery of a single table UPDATE/DELETE that
+ doesn't have a JOIN (TODO: We should handle this at some
+ point by switching to multi-table UPDATE/DELETE)
+ 7. We're not in a confluent table-less subquery, like "SELECT 1".
+ 8. No execution method was already chosen (by a prepared statement)
+ 9. Parent select is not a confluent table-less select
+ 10. Neither parent nor child select have STRAIGHT_JOIN option.
*/
- if ((subselect= select_lex->master_unit()->item))
- {
- bool do_semijoin= !test(thd->variables.optimizer_switch &
- OPTIMIZER_SWITCH_NO_SEMIJOIN);
- if (subselect->substype() == Item_subselect::IN_SUBS)
- in_subs= (Item_in_subselect*)subselect;
+ if (!optimizer_flag(thd, OPTIMIZER_SWITCH_NO_SEMIJOIN) &&
+ in_subs && // 1
+ !select_lex->is_part_of_union() && // 2
+ !select_lex->group_list.elements && !order && // 3
+ !having && !select_lex->with_sum_func && // 4
+ thd->thd_marker.emb_on_expr_nest && // 5
+ select_lex->outer_select()->join && // 6
+ select_lex->master_unit()->first_select()->leaf_tables && // 7
+ in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED && // 8
+ select_lex->outer_select()->leaf_tables && // 9
+ !((select_options | select_lex->outer_select()->join->select_options)
+ & SELECT_STRAIGHT_JOIN)) // 10
+ {
+ DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
+ in_subs->types_allow_materialization=
+ subquery_types_allow_materialization(thd, in_subs,
+ &in_subs->sjm_scan_allowed);
+
+ if (thd->stmt_arena->state != Query_arena::PREPARED)
+ {
+ SELECT_LEX *current= thd->lex->current_select;
+ thd->lex->current_select= current->return_after_parsing();
+ char const *save_where= thd->where;
+ thd->where= "IN/ALL/ANY subquery";
+
+ bool failure= !in_subs->left_expr->fixed &&
+ in_subs->left_expr->fix_fields(thd,
+ &in_subs->left_expr);
+ thd->lex->current_select= current;
+ thd->where= save_where;
+ in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
+ if (failure)
+ DBUG_RETURN(-1); /* purecov: deadcode */
+ /*
+ Check if the left and right expressions have the same # of
+ columns, i.e. we don't have a case like
+ (oe1, oe2) IN (SELECT ie1, ie2, ie3 ...)
- DBUG_PRINT("info", ("Checking if subq can be converted to semi-join"));
- /*
- Check if we're in subquery that is a candidate for flattening into a
- semi-join (which is done done in flatten_subqueries()). The
- requirements are:
- 1. Subquery predicate is an IN/=ANY subq predicate
- 2. Subquery is a single SELECT (not a UNION)
- 3. Subquery does not have GROUP BY or ORDER BY
- 4. Subquery does not use aggregate functions or HAVING
- 5. Subquery predicate is at the AND-top-level of ON/WHERE clause
- 6. No execution method was already chosen (by a prepared statement).
- 7. Parent SELECT is not a confluent "SELECT ... FROM DUAL" w/o tables
- (*). We are not in a subquery of a single table UPDATE/DELETE that
- doesn't have a JOIN (TODO: We should handle this at some
- point by switching to multi-table UPDATE/DELETE)
-
- (**). We're not in a confluent table-less subquery, like
- "SELECT 1".
- */
- if (in_subs && // 1
- !select_lex->master_unit()->first_select()->next_select() && // 2
- !select_lex->group_list.elements && !order && // 3
- !having && !select_lex->with_sum_func && // 4
- thd->thd_marker.emb_on_expr_nest && // 5
- select_lex->outer_select()->join && // (*)
- select_lex->master_unit()->first_select()->leaf_tables && // (**)
- do_semijoin &&
- in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED && // 6
- select_lex->outer_select()->leaf_tables) // 7
- {
- DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
-
- if (thd->stmt_arena->state != Query_arena::PREPARED)
- {
- SELECT_LEX *current= thd->lex->current_select;
- thd->lex->current_select= current->return_after_parsing();
- char const *save_where= thd->where;
- thd->where= "IN/ALL/ANY subquery";
-
- bool failure= !in_subs->left_expr->fixed &&
- in_subs->left_expr->fix_fields(thd,
- &in_subs->left_expr);
- thd->lex->current_select= current;
- thd->where= save_where;
- in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
- if (failure)
- DBUG_RETURN(-1);
- /*
- Check that the right part of the subselect contains no more than one
- column. E.g. in SELECT 1 IN (SELECT * ..) the right part is (SELECT * ...)
- */
- if (subselect->substype() == Item_subselect::IN_SUBS &&
- (select_lex->item_list.elements !=
- ((Item_in_subselect*)subselect)->left_expr->cols()))
- {
- my_error(ER_OPERAND_COLUMNS, MYF(0), ((Item_in_subselect*)subselect)->left_expr->cols());
- DBUG_RETURN(-1);
- }
+ TODO why do we have this duplicated in IN->EXISTS transformers?
+ psergey-todo: fix these: grep for duplicated_subselect_card_check
+ */
+ if (select_lex->item_list.elements != in_subs->left_expr->cols())
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols());
+ DBUG_RETURN(-1);
}
-
- /* Register the subquery for further processing */
- select_lex->outer_select()->join->sj_subselects.append(thd->mem_root, in_subs);
- in_subs->expr_join_nest= thd->thd_marker.emb_on_expr_nest;
}
- else
- {
- DBUG_PRINT("info", ("Subquery can't be converted to semi-join"));
- bool do_materialize= !test(thd->variables.optimizer_switch &
- OPTIMIZER_SWITCH_NO_MATERIALIZATION);
- /*
- Check if the subquery predicate can be executed via materialization.
- The required conditions are:
- 1. Subquery predicate is an IN/=ANY subq predicate
- 2. Subquery is a single SELECT (not a UNION)
- 3. Subquery is not a table-less query. In this case there is no
- point in materializing.
+
+ /* Register the subquery for further processing */
+ select_lex->outer_select()->join->sj_subselects.append(thd->mem_root, in_subs);
+ in_subs->expr_join_nest= thd->thd_marker.emb_on_expr_nest;
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Subquery can't be converted to semi-join"));
+ /*
+ Check if the subquery predicate can be executed via materialization.
+ The required conditions are:
+ 1. Subquery predicate is an IN/=ANY subq predicate
+ 2. Subquery is a single SELECT (not a UNION)
+ 3. Subquery is not a table-less query. In this case there is no
+ point in materializing.
3A The upper query is not a confluent SELECT ... FROM DUAL. We
can't do materialization for SELECT .. FROM DUAL because it
does not call setup_subquery_materialization(). We could make
SELECT ... FROM DUAL call that function but that doesn't seem
to be the case that is worth handling.
- 4. Subquery predicate is a top-level predicate
- (this implies it is not negated)
- TODO: this is a limitation that should be lifeted once we
- implement correct NULL semantics (WL#3830)
- 5. Subquery is non-correlated
- TODO:
- This is an overly restrictive condition. It can be extended to:
- (Subquery is non-correlated ||
- Subquery is correlated to any query outer to IN predicate ||
- (Subquery is correlated to the immediate outer query &&
- Subquery !contains {GROUP BY, ORDER BY [LIMIT],
- aggregate functions}) && subquery predicate is not under "NOT IN"))
- 6. No execution method was already chosen (by a prepared statement).
-
- (*) The subquery must be part of a SELECT statement. The current
- condition also excludes multi-table update statements.
-
- We have to determine whether we will perform subquery materialization
- before calling the IN=>EXISTS transformation, so that we know whether to
- perform the whole transformation or only that part of it which wraps
- Item_in_subselect in an Item_in_optimizer.
- */
- if (do_materialize &&
- in_subs && // 1
- !select_lex->master_unit()->first_select()->next_select() && // 2
- select_lex->master_unit()->first_select()->leaf_tables && // 3
- thd->lex->sql_command == SQLCOM_SELECT && // *
- select_lex->outer_select()->leaf_tables) // 3A
- {
- if (in_subs->is_top_level_item() && // 4
- !in_subs->is_correlated && // 5
- in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED) // 6
- in_subs->exec_method= Item_in_subselect::MATERIALIZATION;
- }
-
- Item_subselect::trans_res trans_res;
- if ((trans_res= subselect->select_transformer(this)) !=
- Item_subselect::RES_OK)
- {
- select_lex->fix_prepare_information(thd, &conds, &having);
- DBUG_RETURN((trans_res == Item_subselect::RES_ERROR));
- }
+ 4. Subquery predicate is a top-level predicate
+ (this implies it is not negated)
+ TODO: this is a limitation that should be lifted once we
+ implement correct NULL semantics (WL#3830)
+ 5. Subquery is non-correlated
+ TODO:
+ This is an overly restrictive condition. It can be extended to:
+ (Subquery is non-correlated ||
+ Subquery is correlated to any query outer to IN predicate ||
+ (Subquery is correlated to the immediate outer query &&
+ Subquery !contains {GROUP BY, ORDER BY [LIMIT],
+ aggregate functions}) && subquery predicate is not under "NOT IN"))
+ 6. No execution method was already chosen (by a prepared statement).
+
+ (*) The subquery must be part of a SELECT statement. The current
+ condition also excludes multi-table update statements.
+
+ We have to determine whether we will perform subquery materialization
+ before calling the IN=>EXISTS transformation, so that we know whether to
+ perform the whole transformation or only that part of it which wraps
+ Item_in_subselect in an Item_in_optimizer.
+ */
+ if (!optimizer_flag(thd, OPTIMIZER_SWITCH_NO_MATERIALIZATION) &&
+ in_subs && // 1
+ !select_lex->is_part_of_union() && // 2
+ select_lex->master_unit()->first_select()->leaf_tables && // 3
+ thd->lex->sql_command == SQLCOM_SELECT && // *
+ select_lex->outer_select()->leaf_tables && // 3A
+ subquery_types_allow_materialization(thd, in_subs, NULL))
+ {
+ // psergey-todo: duplicated_subselect_card_check: where it's done?
+ if (in_subs->is_top_level_item() && // 4
+ !in_subs->is_correlated && // 5
+ in_subs->exec_method == Item_in_subselect::NOT_TRANSFORMED) // 6
+ in_subs->exec_method= Item_in_subselect::MATERIALIZATION;
+ }
+
+ Item_subselect::trans_res trans_res;
+ if ((trans_res= subselect->select_transformer(this)) !=
+ Item_subselect::RES_OK)
+ {
+ select_lex->fix_prepare_information(thd, &conds, &having);
+ DBUG_RETURN((trans_res == Item_subselect::RES_ERROR));
}
}
}
@@ -825,6 +853,118 @@ err:
/*
+ Check if subquery's compared types allow materialization.
+
+ SYNOPSIS
+ subquery_types_allow_materialization()
+ thd Thread handle
+ in_subs Subquery predicate
+ scan_allowed OUT If the return value is TRUE:
+ indicates whether it is possible to use subquery
+ materialization and scan the materialized table
+ Else
+ undefined
+ DESCRIPTION
+ This is a temporary fix for BUG#36752.
+
+ There are two subquery materialization strategies:
+
+ 1. Materialize and do index lookups in the materialized table. See
+ BUG#36752 for description of restrictions we need to put on the
+ compared expressions.
+
+ 2. Materialize and then do a full scan of the materialized table. At the
+ moment, this strategy's applicability criteria are even stricter than
+ in #1.
+
+ This is so because of the following: consider an uncorrelated subquery
+
+ ...WHERE (ot1.col1, ot2.col2 ...) IN (SELECT ie1,ie2,... FROM it1 ...)
+
+ and a join order that could be used to do sjm-materialization:
+
+ SJM-Scan(it1, it1), ot1, ot2
+
+ IN-equalities will be parts of conditions attached to the outer tables:
+
+ ot1: ot1.col1 = ie1 AND ... (C1)
+ ot2: ot1.col2 = ie2 AND ... (C2)
+
+ besides those there may be additional references to ie1 and ie2
+ generated by equality propagation. The problem with evaluating C1 and
+ C2 is that ie{1,2} refer to subquery tables' columns, while we only have
+ current value of materialization temptable. Our solution is to
+ * require that all ie{N} are table column references. This allows
+ to copy the values of materialization temptable columns to the
+ original table's columns (see setup_sj_materialization for more
+ details)
+ * require that compared columns have exactly the same type. This is
+ a temporary measure to avoid BUG#36752-type problems.
+
+ RETURN
+ TRUE Yes, subquery types allow materialization
+ FALSE No, or this is an invalid subquery
+*/
+
+static
+bool subquery_types_allow_materialization(THD *thd,
+ Item_in_subselect *in_subs,
+ bool *scan_allowed)
+{
+ DBUG_ENTER("subquery_types_allow_materialization");
+
+ /* Fix the left expression if it is not yet fixed */
+ if (!in_subs->left_expr->fixed)
+ {
+ SELECT_LEX *save_lex= thd->lex->current_select;
+ thd->lex->current_select= save_lex->outer_select();
+ char const *save_where= thd->where;
+ thd->where= "IN/ALL/ANY subquery";
+ bool res= in_subs->left_expr->fix_fields(thd, &in_subs->left_expr);
+ thd->where= save_where;
+ thd->lex->current_select=save_lex;
+ if (res)
+ DBUG_RETURN(FALSE);
+ }
+
+ List_iterator<Item> it(in_subs->unit->first_select()->item_list);
+ uint elements= in_subs->unit->first_select()->item_list.elements;
+ // psergey: duplicated_subselect_card_check
+ if (in_subs->left_expr->cols() != elements)
+ DBUG_RETURN(FALSE);
+
+ bool all_are_fields= TRUE;
+ for (uint i= 0; i < elements; i++)
+ {
+ Item *outer= in_subs->left_expr->element_index(i);
+ Item *inner= it++;
+ all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM &&
+ inner->real_item()->type() == Item::FIELD_ITEM);
+ if (outer->result_type() != inner->result_type())
+ DBUG_RETURN(FALSE);
+ switch (outer->result_type()) {
+ case STRING_RESULT:
+ if (outer->is_datetime() != inner->is_datetime())
+ DBUG_RETURN(FALSE);
+
+ if (!(outer->collation.collation == inner->collation.collation
+ /*&& outer->max_length <= inner->max_length */))
+ DBUG_RETURN(FALSE);
+ /*case INT_RESULT:
+ if (!(outer->unsigned_flag ^ inner->unsigned_flag))
+ DBUG_RETURN(FALSE); */
+ default:
+ ;/* suitable for materialization */
+ }
+ }
+ if (scan_allowed)
+ *scan_allowed= all_are_fields;
+ DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
Remove the predicates pushed down into the subquery
SYNOPSIS
@@ -860,7 +1000,7 @@ void JOIN::remove_subq_pushed_predicates
((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM &&
- test_if_ref (this->conds,
+ test_if_ref (this->conds,
(Item_field *)((Item_func *)conds)->arguments()[1],
((Item_func *)conds)->arguments()[0]))
{
@@ -907,8 +1047,6 @@ static void save_index_subquery_explain_
}
-
-
/*
Check if the table's rowid is included in the temptable
@@ -966,10 +1104,6 @@ static bool sj_table_is_included(JOIN *j
}
-TABLE *create_duplicate_weedout_tmp_table(THD *thd, uint uniq_tuple_length_arg,
- SJ_TMP_TABLE *sjtbl);
-
-
/*
Setup the strategies to eliminate semi-join duplicates.
@@ -982,14 +1116,15 @@ TABLE *create_duplicate_weedout_tmp_tabl
be used.
DESCRIPTION
- Setup the strategies to eliminate semi-join duplicates. ATM there are 3
+ Setup the strategies to eliminate semi-join duplicates. ATM there are 4
strategies:
1. DuplicateWeedout (use of temptable to remove duplicates based on rowids
of row combinations)
2. FirstMatch (pick only the 1st matching row combination of inner tables)
- 3. InsideOut (scanning the sj-inner table in a way that groups duplicates
+ 3. LooseScan (scanning the sj-inner table in a way that groups duplicates
together and picking the 1st one)
+ 4. SJ-Materialization.
The join order has "duplicate-generating ranges", and every range is
served by one strategy or a combination of FirstMatch with with some
@@ -1015,12 +1150,12 @@ TABLE *create_duplicate_weedout_tmp_tabl
(1) - Prefix of OuterTables (those that participate in
IN-equality and/or are correlated with subquery) and outer
- Noncorrelated Tables.
+ Non-correlated tables.
(2) - The handled range. The range starts with the first sj-inner
table, and covers all sj-inner and outer tables
- Within the range, Inner, Outer, outer Noncorrelated tables
+ Within the range, Inner, Outer, outer non-correlated tables
may follow in any order.
- (3) - The suffix of outer Noncorrelated tables.
+ (3) - The suffix of outer non-correlated tables.
FirstMatch strategy
~~~~~~~~~~~~~~~~~~~
@@ -1032,12 +1167,12 @@ TABLE *create_duplicate_weedout_tmp_tabl
(1) - Prefix of outer and non-correlated tables
(2) - The handled range, which may contain only inner and
non-correlated tables.
- (3) - The suffix of outer Noncorrelated tables.
+ (3) - The suffix of outer non-correlated tables.
- InsideOut strategy
+ LooseScan strategy
~~~~~~~~~~~~~~~~~~
- (ot|ct|nt) [ insideout_tbl (ot|nt|it)* it ] (ot|nt)*
+ (ot|ct|nt) [ loosescan_tbl (ot|nt|it)* it ] (ot|nt)*
+--------+ +===========+ +=============+ +------+
(1) (2) (3) (4)
@@ -1045,7 +1180,7 @@ TABLE *create_duplicate_weedout_tmp_tabl
all the non-trivially correlated outer tables. (non-trivially means
that the correlation is not just through the IN-equality).
- (2) - Inner table for which the InsideOut scan is performed.
+ (2) - Inner table for which the LooseScan scan is performed.
(3) - The remainder of the duplicate-generating range. It is served by
application of FirstMatch strategy, with the exception that
@@ -1053,333 +1188,217 @@ TABLE *create_duplicate_weedout_tmp_tabl
(4) - THe suffix of outer and outer non-correlated tables.
- If several strategies are applicable, their relative priorities are:
- 1. InsideOut
- 2. FirstMatch
- 3. DuplicateWeedout
-
- This function walks over the join order and sets up the strategies by
- setting appropriate members in join_tab structures.
+
+ The choice between the strategies is made by the join optimizer (see
+ advance_sj_state() and fix_semijoin_strategies_for_picked_join_order()).
+ This function sets up all fields/structures/etc needed for execution except
+ for setup/initialization of semi-join materialization which is done in
+ setup_sj_materialization() (todo: can't we move that to here also?)
RETURN
FALSE OK
TRUE Out of memory error
*/
-static
-int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, uint no_jbuf_after)
+int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
+ uint no_jbuf_after)
{
- table_map cur_map= join->const_table_map | PSEUDO_TABLE_BITS;
- enum sj_strategy_enum {
- SJ_STRATEGY_INVALID,
- SJ_STRATEGY_INSIDEOUT,
- SJ_STRATEGY_DUPS_WEEDOUT,
- SJ_STRATEGY_DUPS_WEEDOUT_JBUF
- };
- struct {
- /*
- 0 - invalid (EOF marker),
- 1 - InsideOut,
- 2 - Temptable (maybe confluent),
- 3 - Temptable with join buffering
- */
- enum sj_strategy_enum strategy;
- uint start_idx; /* Left range bound */
- uint end_idx; /* Right range bound */
- /*
- For Temptable strategy: Bitmap of all outer and correlated tables from
- all involved join nests.
- */
- table_map outer_tables;
- } dups_ranges [MAX_TABLES];
-
- TABLE_LIST *emb_insideout_nest= NULL;
- table_map emb_sj_map= 0; /* A bitmap of sj-nests (that is, their sj-inner
- tables) whose ranges we're in */
- table_map emb_outer_tables= 0; /* sj-outer tables for those sj-nests */
- table_map range_start_map; /* table_map at current range start */
- bool dealing_with_jbuf= FALSE; /* TRUE <=> table within cur range uses join buf */
- int cur_range= 0;
uint i;
-
+ THD *thd= join->thd;
DBUG_ENTER("setup_semijoin_dups_elimination");
- LINT_INIT(range_start_map); // protected by emb_sj_map
- /*
- First pass: locate the duplicate-generating ranges and pick the strategies.
- */
+
for (i= join->const_tables ; i < join->tables ; i++)
{
- JOIN_TAB *tab=join->join_tab+i;
- TABLE *table=tab->table;
- cur_map |= table->map;
-
- if (tab->emb_sj_nest) // Encountered an sj-inner table
- {
- if (!emb_sj_map)
+ JOIN_TAB *tab=join->join_tab + i;
+ POSITION *pos= join->best_positions + i;
+ uint keylen, keyno;
+ switch (pos->sj_strategy) {
+ case SJ_OPT_MATERIALIZE:
+ case SJ_OPT_MATERIALIZE_SCAN:
+ /* Do nothing */
+ i += pos->n_sj_tables;
+ break;
+ case SJ_OPT_LOOSE_SCAN:
{
- dups_ranges[cur_range].start_idx= i;
- range_start_map= cur_map & ~table->map;
- /*
- Remember if this is a possible start of range that is covered by
- the InsideOut strategy (the reason that it is not covered could
- be that it overlaps with anther semi-join's range. we don't
- support InsideOut for joined ranges)
- */
- if (join->best_positions[i].insideout_key != MAX_KEY)
- emb_insideout_nest= tab->emb_sj_nest;
- }
-
- emb_sj_map |= tab->emb_sj_nest->sj_inner_tables;
- emb_outer_tables |= tab->emb_sj_nest->nested_join->sj_depends_on;
+ /* We jump from the last table to the first one */
+ tab->loosescan_match_tab= tab + pos->n_sj_tables - 1;
- if (tab->emb_sj_nest != emb_insideout_nest)
- {
- /*
- Two different semi-joins interleave. This cannot be handled by
- InsideOut strategy.
- */
- emb_insideout_nest= NULL;
+ /* Calculate key length */
+ keylen= 0;
+ keyno= pos->loosescan_key;
+ for (uint kp=0; kp < pos->loosescan_parts; kp++)
+ keylen += tab->table->key_info[keyno].key_part[kp].store_length;
+
+ tab->loosescan_key_len= keylen;
+ if (pos->n_sj_tables > 1)
+ tab[pos->n_sj_tables - 1].do_firstmatch= tab;
+ i += pos->n_sj_tables;
+ break;
}
- }
-
- if (emb_sj_map) /* We're in duplicate-generating range */
- {
- if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
- tab->type == JT_ALL && tab->use_quick != 2 && !tab->first_inner &&
- i <= no_jbuf_after && !dealing_with_jbuf)
+ case SJ_OPT_DUPS_WEEDOUT:
{
/*
- This table uses join buffering, which makes use of FirstMatch or
- InsideOut strategies impossible for the current and (we assume)
- preceding duplicate-producing ranges.
- That is, for the join order:
-
- x x [ x x] x [x x x] x [x x X* x] x
- | | | | | \
- +-----+ +-----+ | join buffering use
- r1 r2 we're here
-
- we'll have to remove r1 and r2 and use duplicate-elimination
- strategy that spans all the tables, starting from the very 1st
- one.
- */
- dealing_with_jbuf= TRUE;
- emb_insideout_nest= FALSE;
-
- /*
- Absorb all preceding duplicate-eliminating ranges. Their strategies
- do not matter:
+ Check for join buffering. If there is one, move the first table
+ forwards, but do not destroy other duplicate elimination methods.
*/
- for (int prev_range= 0; prev_range < cur_range; prev_range++)
+ uint first_table= i;
+ for (uint j= i; j < i + pos->n_sj_tables; j++)
{
- dups_ranges[cur_range].outer_tables |=
- dups_ranges[prev_range].outer_tables;
+ if (join->best_positions[j].use_join_buffer && j <= no_jbuf_after)
+ {
+ first_table= join->const_tables;
+ break;
+ }
}
- dups_ranges[0].start_idx= 0; /* Will need to start from the 1st table */
- dups_ranges[0].outer_tables= dups_ranges[cur_range].outer_tables;
- cur_range= 0;
- }
- /*
- Check if we are at the end of duplicate-producing range. We are if
-
- 1. It's an InsideOut range (which presumes all correlated tables are
- in the prefix), and all inner tables are in the join order prefix,
- or
- 2. It's a DuplicateElimination range (possibly covering several
- SJ-nests), and all inner, outer, and correlated tables of all
- sj-nests are in the join order prefix.
- */
- bool end_of_range= FALSE;
- if (emb_insideout_nest &&
- bitmap_covers(cur_map, emb_insideout_nest->sj_inner_tables))
- {
- /* Save that this range is handled with InsideOut: */
- dups_ranges[cur_range].strategy= SJ_STRATEGY_INSIDEOUT;
- end_of_range= TRUE;
- }
- else if (bitmap_covers(cur_map, emb_outer_tables | emb_sj_map))
- {
+ SJ_TMP_TABLE::TAB sjtabs[MAX_TABLES];
+ SJ_TMP_TABLE::TAB *last_tab= sjtabs;
+ uint jt_rowid_offset= 0; // # tuple bytes are already occupied (w/o NULL bytes)
+ uint jt_null_bits= 0; // # null bits in tuple bytes
/*
- This is a complete range to be handled with either DuplicateWeedout
- or FirstMatch
+ Walk through the range and remember
+ - tables that need their rowids to be put into temptable
+ - the last outer table
*/
- dups_ranges[cur_range].strategy=
- dealing_with_jbuf? SJ_STRATEGY_DUPS_WEEDOUT_JBUF:
- SJ_STRATEGY_DUPS_WEEDOUT;
- /*
- This will hold tables from within the range that need to be put
- into the join buffer before we can use the FirstMatch on its tail.
- */
- dups_ranges[cur_range].outer_tables= emb_outer_tables &
- ~range_start_map;
- end_of_range= TRUE;
- }
-
- if (end_of_range)
- {
- dups_ranges[cur_range].end_idx= i+1;
- emb_sj_map= emb_outer_tables= 0;
- emb_insideout_nest= NULL;
- dealing_with_jbuf= FALSE;
- dups_ranges[++cur_range].strategy= SJ_STRATEGY_INVALID;
- }
- else
- {
- /* We don't support interleaving for InsideOut*/
- if (!tab->emb_sj_nest)
- emb_insideout_nest= NULL;
- }
- }
- }
-
- THD *thd= join->thd;
- SJ_TMP_TABLE **next_sjtbl_ptr= &join->sj_tmp_tables;
- /*
- The second pass: setup the chosen strategies
- */
- for (int j= 0; j < cur_range; j++)
- {
- JOIN_TAB *tab=join->join_tab + dups_ranges[j].start_idx;
- JOIN_TAB *jump_to;
- bool first_match_only= FALSE;
- if (dups_ranges[j].strategy == SJ_STRATEGY_INSIDEOUT)
- {
- /* We jump from the last table to the first one */
- tab->insideout_match_tab= join->join_tab + dups_ranges[j].end_idx - 1;
-
- /* Calculate key length */
- uint nparts= join->best_positions[dups_ranges[j].start_idx].insideout_parts;
- uint keyno= join->best_positions[dups_ranges[j].start_idx].insideout_key;
- uint keylen= 0;
- for (uint kp=0; kp < nparts; kp++)
- keylen += tab->table->key_info[keyno].key_part[kp].store_length;
- tab->insideout_key_len= keylen;
- jump_to= tab++;
- }
- else // DuplicateWeedout or FirstMatch
- {
- SJ_TMP_TABLE::TAB sjtabs[MAX_TABLES];
- table_map cur_map= join->const_table_map | PSEUDO_TABLE_BITS;
- uint jt_rowid_offset= 0; // # tuple bytes are already occupied (w/o NULL bytes)
- uint jt_null_bits= 0; // # null bits in tuple bytes
- SJ_TMP_TABLE::TAB *last_tab= sjtabs;
- uint rowid_keep_flags= JOIN_TAB::CALL_POSITION | JOIN_TAB::KEEP_ROWID;
- JOIN_TAB *last_outer_tab= tab - 1;
- first_match_only= TRUE;
- /*
- Walk through the range and remember
- - tables that need their rowids to be put into temptable
- - the last outer table
- */
- for (; tab < join->join_tab + dups_ranges[j].end_idx; tab++)
- {
- if (sj_table_is_included(join, tab))
- {
- last_tab->join_tab= tab;
- last_tab->rowid_offset= jt_rowid_offset;
- jt_rowid_offset += tab->table->file->ref_length;
- if (tab->table->maybe_null)
+ for (JOIN_TAB *j=join->join_tab + first_table;
+ j < join->join_tab + i + pos->n_sj_tables; j++)
+ {
+ if (sj_table_is_included(join, j))
{
- last_tab->null_byte= jt_null_bits / 8;
- last_tab->null_bit= jt_null_bits++;
+ last_tab->join_tab= j;
+ last_tab->rowid_offset= jt_rowid_offset;
+ jt_rowid_offset += j->table->file->ref_length;
+ if (j->table->maybe_null)
+ {
+ last_tab->null_byte= jt_null_bits / 8;
+ last_tab->null_bit= jt_null_bits++;
+ }
+ last_tab++;
+ j->table->prepare_for_position();
+ j->keep_current_rowid= TRUE;
}
- last_tab++;
- tab->table->prepare_for_position();
- tab->rowid_keep_flags= rowid_keep_flags;
- first_match_only= FALSE;
- }
- cur_map |= tab->table->map;
- if (!tab->emb_sj_nest && bitmap_covers(cur_map,
- dups_ranges[j].outer_tables))
- last_outer_tab= tab;
- }
+ }
- if (jt_rowid_offset) /* Temptable has at least one rowid */
- {
SJ_TMP_TABLE *sjtbl;
- uint tabs_size= (last_tab - sjtabs) * sizeof(SJ_TMP_TABLE::TAB);
- if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))) ||
- !(sjtbl->tabs= (SJ_TMP_TABLE::TAB*) thd->alloc(tabs_size)))
- DBUG_RETURN(TRUE);
- memcpy(sjtbl->tabs, sjtabs, tabs_size);
- sjtbl->tabs_end= sjtbl->tabs + (last_tab - sjtabs);
- sjtbl->rowid_len= jt_rowid_offset;
- sjtbl->null_bits= jt_null_bits;
- sjtbl->null_bytes= (jt_null_bits + 7)/8;
-
- *next_sjtbl_ptr= sjtbl;
- next_sjtbl_ptr= &(sjtbl->next);
- sjtbl->next= NULL;
-
- sjtbl->tmp_table=
- create_duplicate_weedout_tmp_table(thd,
- sjtbl->rowid_len +
- sjtbl->null_bytes,
- sjtbl);
+ if (jt_rowid_offset) /* Temptable has at least one rowid */
+ {
+ uint tabs_size= (last_tab - sjtabs) * sizeof(SJ_TMP_TABLE::TAB);
+ if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))) ||
+ !(sjtbl->tabs= (SJ_TMP_TABLE::TAB*) thd->alloc(tabs_size)))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ memcpy(sjtbl->tabs, sjtabs, tabs_size);
+ sjtbl->is_confluent= FALSE;
+ sjtbl->tabs_end= sjtbl->tabs + (last_tab - sjtabs);
+ sjtbl->rowid_len= jt_rowid_offset;
+ sjtbl->null_bits= jt_null_bits;
+ sjtbl->null_bytes= (jt_null_bits + 7)/8;
+ sjtbl->tmp_table=
+ create_duplicate_weedout_tmp_table(thd,
+ sjtbl->rowid_len +
+ sjtbl->null_bytes,
+ sjtbl);
+ join->sj_tmp_tables.push_back(sjtbl->tmp_table);
+ }
+ else
+ {
+ /*
+ This is confluent case where the entire subquery predicate does
+ not depend on anything at all, ie this is
+ WHERE const IN (uncorrelated select)
+ */
+ if (!(sjtbl= (SJ_TMP_TABLE*)thd->alloc(sizeof(SJ_TMP_TABLE))))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ sjtbl->tmp_table= NULL;
+ sjtbl->is_confluent= TRUE;
+ sjtbl->have_confluent_row= FALSE;
+ }
+ join->join_tab[first_table].flush_weedout_table= sjtbl;
+ join->join_tab[i + pos->n_sj_tables - 1].check_weed_out_table= sjtbl;
- join->join_tab[dups_ranges[j].start_idx].flush_weedout_table= sjtbl;
- join->join_tab[dups_ranges[j].end_idx - 1].check_weed_out_table= sjtbl;
+ i += pos->n_sj_tables;
+ break;
}
- tab= last_outer_tab + 1;
- jump_to= last_outer_tab;
- }
-
- /* Create the FirstMatch tail */
- for (; tab < join->join_tab + dups_ranges[j].end_idx; tab++)
- {
- if (!tab->emb_sj_nest)
- jump_to= tab;
- if (first_match_only)
+ case SJ_OPT_FIRST_MATCH:
{
- tab->first_sj_inner_tab= join->join_tab + dups_ranges[j].start_idx;
- tab->last_sj_inner_tab= join->join_tab + dups_ranges[j].end_idx - 1;
+ JOIN_TAB *j, *jump_to= tab-1;
+ for (j= tab; j != tab + pos->n_sj_tables; j++)
+ {
+ if (!tab->emb_sj_nest)
+ jump_to= tab;
+ else
+ {
+ tab->first_sj_inner_tab= tab;
+ tab->last_sj_inner_tab= tab + pos->n_sj_tables - 1;
+ }
+ }
+ j[-1].do_firstmatch= jump_to;
+ i += pos->n_sj_tables;
+ break;
}
+ case SJ_OPT_NONE:
+ break;
}
- if (tab - 1 != jump_to)
- tab[-1].do_firstmatch= jump_to;
}
DBUG_RETURN(FALSE);
}
/*
- Destroy all temporary tables created by NL-semijoin runtime.
+ Destroy all temporary tables created by NL-semijoin runtime
*/
static void destroy_sj_tmp_tables(JOIN *join)
{
- for (SJ_TMP_TABLE *sj_tbl= join->sj_tmp_tables; sj_tbl;
- sj_tbl= sj_tbl->next)
+ List_iterator<TABLE> it(join->sj_tmp_tables);
+ TABLE *table;
+ while ((table= it++))
{
- if (sj_tbl->tmp_table)
- free_tmp_table(join->thd, sj_tbl->tmp_table);
+ /*
+ SJ-Materialization tables are initialized for either sequential reading
+ or index lookup, DuplicateWeedout tables are not initialized for read
+ (we only write to them), so need to call ha_index_or_rnd_end.
+ */
+ table->file->ha_index_or_rnd_end();
+ free_tmp_table(join->thd, table);
}
- join->sj_tmp_tables= NULL;
+ join->sj_tmp_tables.empty();
+ join->sjm_info_list.empty();
}
/*
Remove all records from all temp tables used by NL-semijoin runtime
+
+ SYNOPSIS
+ clear_sj_tmp_tables()
+ join The join to remove tables for
+
+ DESCRIPTION
+ Remove all records from all temp tables used by NL-semijoin runtime. This
+ must be done before every join re-execution.
*/
static int clear_sj_tmp_tables(JOIN *join)
{
int res;
- for (SJ_TMP_TABLE *sj_tbl= join->sj_tmp_tables; sj_tbl;
- sj_tbl= sj_tbl->next)
+ List_iterator<TABLE> it(join->sj_tmp_tables);
+ TABLE *table;
+ while ((table= it++))
{
- if (sj_tbl->tmp_table)
- {
- if ((res= sj_tbl->tmp_table->file->ha_delete_all_rows()))
- return res;
- }
+ if ((res= table->file->ha_delete_all_rows()))
+ return res; /* purecov: inspected */
+ }
+
+ SJ_MATERIALIZATION_INFO *sjm;
+ List_iterator<SJ_MATERIALIZATION_INFO> it2(join->sjm_info_list);
+ while ((sjm= it2++))
+ {
+ sjm->materialized= FALSE;
}
return 0;
}
-uint make_join_orderinfo(JOIN *join);
/**
global select optimisation.
@@ -1403,6 +1422,12 @@ JOIN::optimize()
optimized= 1;
thd_proc_info(thd, "optimizing");
+
+ /* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */
+ if (flatten_subqueries())
+ DBUG_RETURN(1); /* purecov: inspected */
+ /* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */
+
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt);
/* select_limit is used to decide if we are likely to scan the whole table */
@@ -1573,6 +1598,9 @@ JOIN::optimize()
QT_ORDINARY););
conds= table_independent_conds;
}
+ /* Create all structures needed for materialized subquery execution. */
+ if (setup_subquery_materialization())
+ DBUG_RETURN(1);
}
}
if (!tables_list)
@@ -1628,15 +1656,7 @@ JOIN::optimize()
/* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true
}
- select= make_select(*all_tables, const_table_map,
- const_table_map, conds, 1, &error);
- if (error)
- { /* purecov: inspected */
- error= -1; /* purecov: inspected */
- DBUG_PRINT("error",("Error: make_select() failed"));
- DBUG_RETURN(1);
- }
-
+ error= 0;
reset_nj_counters(join_list);
make_outerjoin_info(this);
@@ -1677,7 +1697,7 @@ JOIN::optimize()
{
conds=new Item_int((longlong) 0,1); // Always false
}
- if (make_join_select(this, select, conds))
+ if (make_join_select(this, conds))
{
zero_result_cause=
"Impossible WHERE noticed after reading const tables";
@@ -1894,11 +1914,6 @@ JOIN::optimize()
(select_options & (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) |
(select_lex->ftfunc_list->elements ? SELECT_NO_JOIN_CACHE : 0);
- sj_tmp_tables= NULL;
- if (!select_lex->sj_nests.is_empty())
- setup_semijoin_dups_elimination(this, select_opts_for_readinfo,
- no_jbuf_after);
-
// No cache for MATCH == 'Don't use join buffering when we use MATCH'.
if (make_join_readinfo(this, select_opts_for_readinfo, no_jbuf_after))
DBUG_RETURN(1);
@@ -2905,7 +2920,6 @@ JOIN::destroy()
if (exec_tmp_table2)
free_tmp_table(thd, exec_tmp_table2);
destroy_sj_tmp_tables(this);
- delete select;
delete_dynamic(&keyuse);
delete procedure;
DBUG_RETURN(error);
@@ -3005,7 +3019,7 @@ mysql_select(THD *thd, Item ***rref_poin
else
{
if (!(join= new JOIN(thd, fields, select_options, result)))
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(TRUE); /* purecov: inspected */
thd_proc_info(thd, "init");
thd->used_tables=0; // Updated by setup_fields
if (err= join->prepare(rref_pointer_array, tables, wild_num,
@@ -3016,14 +3030,6 @@ mysql_select(THD *thd, Item ***rref_poin
}
}
- /* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */
- if (join->flatten_subqueries())
- {
- err= 1;
- goto err;
- }
- /* dump_TABLE_LIST_struct(select_lex, select_lex->leaf_tables); */
-
if ((err= join->optimize()))
{
goto err; // 1
@@ -3252,6 +3258,7 @@ bool convert_subq_to_sj(JOIN *parent_joi
sj_nest->join_list= emb_join_list;
sj_nest->embedding= emb_tbl_nest;
sj_nest->alias= (char*) "(sj-nest)";
+ sj_nest->sj_subq_pred= subq_pred;
/* Nests do not participate in those 'chains', so: */
/* sj_nest->next_leaf= sj_nest->next_local= sj_nest->next_global == NULL*/
emb_join_list->push_back(sj_nest);
@@ -3335,7 +3342,7 @@ bool convert_subq_to_sj(JOIN *parent_joi
/*
Create the IN-equalities and inject them into semi-join's ON expression.
- Additionally, for InsideOut strategy
+ Additionally, for LooseScan strategy
- Record the number of IN-equalities.
- Create list of pointers to (oe1, ..., ieN). We'll need the list to
see which of the expressions are bound and which are not (for those
@@ -3355,9 +3362,9 @@ bool convert_subq_to_sj(JOIN *parent_joi
{
nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr);
- Item *item_eq= new Item_func_eq(subq_pred->left_expr,
+ Item_func_eq *item_eq= new Item_func_eq(subq_pred->left_expr,
subq_lex->ref_pointer_array[0]);
- item_eq->name= (char*)subq_sj_cond_name;
+ item_eq->in_equality_no= 0;
sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq);
}
else
@@ -3366,10 +3373,10 @@ bool convert_subq_to_sj(JOIN *parent_joi
{
nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr->
element_index(i));
- Item *item_eq=
+ Item_func_eq *item_eq=
new Item_func_eq(subq_pred->left_expr->element_index(i),
subq_lex->ref_pointer_array[i]);
- item_eq->name= (char*)subq_sj_cond_name + (i % 64);
+ item_eq->in_equality_no= i;
sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq);
}
}
@@ -3418,13 +3425,46 @@ bool convert_subq_to_sj(JOIN *parent_joi
/*
- Convert candidate subquery predicates to semi-joins
+ Convert semi-join subquery predicates into semi-join join nests
SYNOPSIS
JOIN::flatten_subqueries()
DESCRIPTION
- Convert candidate subquery predicates to semi-joins.
+
+ Convert candidate subquery predicates into semi-join join nests. This
+ transformation is performed once in query lifetime and is irreversible.
+
+ Conversion of one subquery predicate
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ We start with a join that has a semi-join subquery:
+
+ SELECT ...
+ FROM ot, ...
+ WHERE oe IN (SELECT ie FROM it1 ... itN WHERE subq_where) AND outer_where
+
+ and convert it into a semi-join nest:
+
+ SELECT ...
+ FROM ot SEMI JOIN (it1 ... itN), ...
+ WHERE outer_where AND subq_where AND oe=ie
+
+ that is, in order to do the conversion, we need to
+
+ * Create the "SEMI JOIN (it1 .. itN)" part and add it into the parent
+ query's FROM structure.
+ * Add "AND subq_where AND oe=ie" into parent query's WHERE (or ON if
+ the subquery predicate was in an ON expression)
+ * Remove the subquery predicate from the parent query's WHERE
+
+ Considerations when converting many predicates
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ A join may have at most MAX_TABLES tables. This may prevent us from
+ flattening all subqueries when the total number of tables in parent and
+ child selects exceeds MAX_TABLES.
+ We deal with this problem by flattening children's subqueries first and
+ then using a heuristic rule to determine each subquery predicate's
+ "priority".
RETURN
FALSE OK
@@ -3441,7 +3481,7 @@ bool JOIN::flatten_subqueries()
if (sj_subselects.elements() == 0)
DBUG_RETURN(FALSE);
- /* 1. Fix children subqueries */
+ /* First, convert child join's subqueries. We proceed bottom-up here */
for (in_subq= sj_subselects.front(), in_subq_end= sj_subselects.back();
in_subq != in_subq_end; in_subq++)
{
@@ -3452,6 +3492,20 @@ bool JOIN::flatten_subqueries()
(*in_subq)->sj_convert_priority=
(*in_subq)->is_correlated * MAX_TABLES + child_join->outer_tables;
}
+
+ // Temporary measure: disable semi-joins when they are together with outer
+ // joins.
+ for (TABLE_LIST *tbl= select_lex->leaf_tables; tbl; tbl=tbl->next_leaf)
+ {
+ TABLE_LIST *embedding= tbl->embedding;
+ if (tbl->on_expr || (tbl->embedding && !(embedding->sj_on_expr &&
+ !embedding->embedding)))
+ {
+ in_subq= sj_subselects.front();
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+ goto skip_conversion;
+ }
+ }
//dump_TABLE_LIST_struct(select_lex, select_lex->leaf_tables);
/*
@@ -3469,9 +3523,11 @@ bool JOIN::flatten_subqueries()
tables + (*in_subq)->unit->first_select()->join->tables < MAX_TABLES;
in_subq++)
{
- if (replace_where_subcondition(this, (*in_subq)->emb_on_expr_nest,
- *in_subq, new Item_int(1), FALSE))
- DBUG_RETURN(TRUE);
+ Item **tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
+ &conds : &((*in_subq)->emb_on_expr_nest->on_expr);
+ if (replace_where_subcondition(this, tree, *in_subq, new Item_int(1),
+ FALSE))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
}
for (in_subq= sj_subselects.front();
@@ -3482,9 +3538,7 @@ bool JOIN::flatten_subqueries()
if (convert_subq_to_sj(this, *in_subq))
DBUG_RETURN(TRUE);
}
- if (arena)
- thd->restore_active_arena(arena, &backup);
-
+skip_conversion:
/* 3. Finalize those we didn't convert */
for (; in_subq!= in_subq_end; in_subq++)
{
@@ -3508,10 +3562,26 @@ bool JOIN::flatten_subqueries()
Item *substitute= (*in_subq)->substitution;
bool do_fix_fields= !(*in_subq)->substitution->fixed;
- if (replace_where_subcondition(this, (*in_subq)->emb_on_expr_nest,
- *in_subq, substitute, do_fix_fields))
+ Item **tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
+ &conds : &((*in_subq)->emb_on_expr_nest->on_expr);
+ if (replace_where_subcondition(this, tree, *in_subq, substitute,
+ do_fix_fields))
DBUG_RETURN(TRUE);
+ (*in_subq)->substitution= NULL;
+
+ if (!thd->stmt_arena->is_conventional())
+ {
+ tree= ((*in_subq)->emb_on_expr_nest == (TABLE_LIST*)1)?
+ &select_lex->prep_where : &((*in_subq)->emb_on_expr_nest->prep_on_expr);
+
+ if (replace_where_subcondition(this, tree, *in_subq, substitute,
+ FALSE))
+ DBUG_RETURN(TRUE);
+ }
}
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
sj_subselects.clear();
DBUG_RETURN(FALSE);
}
@@ -3657,6 +3727,19 @@ bool find_eq_ref_candidate(TABLE *table,
This operation is (and should be) performed at each PS execution since
tables may become/cease to be constant across PS reexecutions.
+
+ NOTE
+ Table pullout may make uncorrelated subquery correlated. Consider this
+ example:
+
+ ... WHERE oe IN (SELECT it1.primary_key WHERE p(it1, it2) ... )
+
+ here table it1 can be pulled out (we have it1.primary_key=oe which gives
+ us functional dependency). Once it1 is pulled out, all references to it1
+ from p(it1, it2) become references to outside of the subquery and thus
+ make the subquery (i.e. its semi-join nest) correlated.
+ Making the subquery (i.e. its semi-join nest) correlated prevents us from
+ using Materialization or LooseScan to execute it.
RETURN
0 - OK
@@ -3713,6 +3796,11 @@ int pull_out_semijoin_tables(JOIN *join)
pulled_tables |= tbl->table->map;
DBUG_PRINT("info", ("Table %s pulled out (reason: func dep)",
tbl->table->alias));
+ /*
+ Pulling a table out of uncorrelated subquery in general makes
+ makes it correlated. See the NOTE to this funtion.
+ */
+ sj_nest->sj_subq_pred->is_correlated= TRUE;
}
}
}
@@ -3739,14 +3827,12 @@ int pull_out_semijoin_tables(JOIN *join)
{
if (inner_tables & tbl->table->map)
{
- // This table is not pulled out
+ /* This table is not pulled out */
tbl->table->reginfo.join_tab->emb_sj_nest= sj_nest;
}
else
{
- /*
- This table has been pulled out of the semi-join nest
- */
+ /* This table has been pulled out of the semi-join nest */
tbl->table->reginfo.join_tab->emb_sj_nest= NULL;
/*
Pull the table up in the same way as simplify_joins() does:
@@ -3777,6 +3863,7 @@ int pull_out_semijoin_tables(JOIN *join)
DBUG_RETURN(0);
}
+
/*****************************************************************************
Create JOIN_TABS, make a guess about the table types,
Approximate how many records will be used in each table
@@ -3822,6 +3909,65 @@ typedef struct st_sargable_param
uint num_values; /* number of values in the above array */
} SARGABLE_PARAM;
+
+
+/*
+ Get estimated record length for semi-join materialization temptable
+
+ SYNOPSIS
+ get_tmp_table_rec_length()
+ items IN subquery's select list.
+
+ DESCRIPTION
+ Calculate estimated record length for semi-join materialization
+ temptable. It's an estimate because we don't follow every bit of
+ create_tmp_table()'s logic. This isn't necessary as the return value of
+ this function is used only for cost calculations.
+
+ RETURN
+ Length of the temptable record, in bytes
+*/
+
+static uint get_tmp_table_rec_length(List<Item> &items)
+{
+ uint len= 0;
+ Item *item;
+ List_iterator<Item> it(items);
+ while ((item= it++))
+ {
+ switch (item->result_type()) {
+ case REAL_RESULT:
+ len += sizeof(double);
+ break;
+ case INT_RESULT:
+ if (item->max_length >= (MY_INT32_NUM_DECIMAL_DIGITS - 1))
+ len += 8;
+ else
+ len += 4;
+ break;
+ case STRING_RESULT:
+ enum enum_field_types type;
+ /* DATE/TIME and GEOMETRY fields have STRING_RESULT result type. */
+ if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
+ type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE ||
+ type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_GEOMETRY)
+ len += 8;
+ else
+ len += item->max_length;
+ break;
+ case DECIMAL_RESULT:
+ len += 10;
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0); /* purecov: deadcode */
+ break;
+ }
+ }
+ return len;
+}
+
+
/**
Calculate the best possible join and initialize the join structure.
@@ -4260,10 +4406,15 @@ make_join_statistics(JOIN *join, TABLE_L
join->const_tables=const_count;
join->found_const_table_map=found_const_table_map;
- /* Find an optimal join order of the non-constant tables. */
if (join->const_tables != join->tables)
- {
optimize_keyuse(join, keyuse_array);
+
+ if (optimize_semijoin_nests(join, all_table_map))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+
+ /* Find an optimal join order of the non-constant tables. */
+ if (join->const_tables != join->tables)
+ {
if (choose_plan(join, all_table_map & ~join->const_table_map))
DBUG_RETURN(TRUE);
}
@@ -4278,6 +4429,140 @@ make_join_statistics(JOIN *join, TABLE_L
}
+/*
+ Optimize semi-join nests that could be run with sj-materialization
+
+ SYNOPSIS
+ optimize_semijoin_nests()
+ join The join to optimize semi-join nests for
+ all_table_map Bitmap of all tables in the join
+
+ DESCRIPTION
+ Optimize each of the semi-join nests that can be run with
+ materialization. For each of the nests, we
+ - Generate the best join order for this "sub-join" and remember it;
+ - Remember the sub-join execution cost (it's part of materialization
+ cost);
+ - Calculate other costs that will be incurred if we decide
+ to use materialization strategy for this semi-join nest.
+
+ All obtained information is saved and will be used by the main join
+ optimization pass.
+
+ RETURN
+ FALSE Ok
+ TRUE Out of memory error
+*/
+
+static bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
+{
+ DBUG_ENTER("optimize_semijoin_nests");
+ List_iterator<TABLE_LIST> sj_list_it(join->select_lex->sj_nests);
+ TABLE_LIST *sj_nest;
+ if (!optimizer_flag(join->thd, OPTIMIZER_SWITCH_NO_MATERIALIZATION))
+ {
+ while ((sj_nest= sj_list_it++))
+ {
+ sj_nest->sj_mat_info= NULL;
+ if (sj_nest->sj_inner_tables && /* not everything was pulled out */
+ !sj_nest->sj_subq_pred->is_correlated &&
+ sj_nest->sj_subq_pred->types_allow_materialization)
+ {
+ join->emb_sjm_nest= sj_nest;
+ if (choose_plan(join, all_table_map))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ /*
+ The best plan to run the subquery is now in join->best_positions,
+ save it.
+ */
+ uint n_tables= my_count_bits(sj_nest->sj_inner_tables);
+ SJ_MATERIALIZATION_INFO* sjm;
+ if (!(sjm= new SJ_MATERIALIZATION_INFO) ||
+ !(sjm->positions= (POSITION*)join->thd->alloc(sizeof(POSITION)*
+ n_tables)))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ sjm->tables= n_tables;
+ sjm->is_used= FALSE;
+ double subjoin_out_rows, subjoin_read_time;
+ get_partial_join_cost(join, n_tables,
+ &subjoin_read_time, &subjoin_out_rows);
+
+ sjm->materialization_cost.convert_from_cost(subjoin_read_time);
+ sjm->rows= subjoin_out_rows;
+
+ List<Item> &right_expr_list=
+ sj_nest->sj_subq_pred->unit->first_select()->item_list;
+ /*
+ Adjust output cardinality estimates. If the subquery has form
+
+ ... oe IN (SELECT t1.colX, t2.colY, func(X,Y,Z) )
+
+ then the number of distinct output record combinations has an
+ upper bound of product of number of records matching the tables
+ that are used by the SELECT clause.
+ TODO:
+ We can get a more precise estimate if we
+ - use rec_per_key cardinality estimates. For simple cases like
+ "oe IN (SELECT t.key ...)" it is trivial.
+ - Functional dependencies between the tables in the semi-join
+ nest (the payoff is probably less here?)
+ */
+ {
+ for (uint i=0 ; i < join->const_tables + sjm->tables ; i++)
+ {
+ JOIN_TAB *tab= join->best_positions[i].table;
+ join->map2table[tab->table->tablenr]= tab;
+ }
+ List_iterator<Item> it(right_expr_list);
+ Item *item;
+ table_map map= 0;
+ while ((item= it++))
+ map |= item->used_tables();
+ map= map & ~PSEUDO_TABLE_BITS;
+ Table_map_iterator tm_it(map);
+ int tableno;
+ double rows= 1.0;
+ while ((tableno = tm_it.next_bit()) != Table_map_iterator::BITMAP_END)
+ rows *= join->map2table[tableno]->table->quick_condition_rows;
+ sjm->rows= min(sjm->rows, rows);
+ }
+ memcpy(sjm->positions, join->best_positions + join->const_tables,
+ sizeof(POSITION) * n_tables);
+
+ /*
+ Calculate temporary table parameters and usage costs
+ */
+ uint rowlen= get_tmp_table_rec_length(right_expr_list);
+ double lookup_cost;
+ if (rowlen * subjoin_out_rows< join->thd->variables.max_heap_table_size)
+ lookup_cost= HEAP_TEMPTABLE_LOOKUP_COST;
+ else
+ lookup_cost= DISK_TEMPTABLE_LOOKUP_COST;
+
+ /*
+ Let materialization cost include the cost to write the data into the
+ temporary table:
+ */
+ sjm->materialization_cost.add_io(subjoin_out_rows, lookup_cost);
+
+ /*
+ Set the cost to do a full scan of the temptable (will need this to
+ consider doing sjm-scan):
+ */
+ sjm->scan_cost.zero();
+ sjm->scan_cost.add_io(sjm->rows, lookup_cost);
+
+ sjm->lookup_cost.convert_from_cost(lookup_cost);
+ sj_nest->sj_mat_info= sjm;
+ DBUG_EXECUTE("opt", print_sjm(sjm););
+ }
+ }
+ }
+ join->emb_sjm_nest= NULL;
+ DBUG_RETURN(FALSE);
+}
+
+
/*****************************************************************************
Check with keys are used and with tables references with tables
Updates in stat:
@@ -4433,6 +4718,50 @@ merge_key_fields(KEY_FIELD *start,KEY_FI
return first_free;
}
+/*
+ Given a field, return its index in semi-join's select list, or UINT_MAX
+
+ DESCRIPTION
+ Given a field, we find its table; then see if the table is within a
+ semi-join nest and if the field was in select list of the subselect.
+ If it was, we return field's index in the select list. The value is used
+ by LooseScan strategy.
+*/
+
+static uint get_semi_join_select_list_index(Field *field)
+{
+ uint res= UINT_MAX;
+ TABLE_LIST *emb_sj_nest;
+ if ((emb_sj_nest= field->table->pos_in_table_list->embedding) &&
+ emb_sj_nest->sj_on_expr)
+ {
+ Item_in_subselect *subq_pred= emb_sj_nest->sj_subq_pred;
+ st_select_lex *subq_lex= subq_pred->unit->first_select();
+ if (subq_pred->left_expr->cols() == 1)
+ {
+ Item *sel_item= subq_lex->ref_pointer_array[0];
+ if (sel_item->type() == Item::FIELD_ITEM &&
+ ((Item_field*)sel_item)->field->eq(field))
+ {
+ res= 0;
+ }
+ }
+ else
+ {
+ for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
+ {
+ Item *sel_item= subq_lex->ref_pointer_array[i];
+ if (sel_item->type() == Item::FIELD_ITEM &&
+ ((Item_field*)sel_item)->field->eq(field))
+ {
+ res= i;
+ break;
+ }
+ }
+ }
+ }
+ return res;
+}
/**
Add a possible key to array of possible keys if it's usable as a key
@@ -4598,9 +4927,8 @@ add_key_field(KEY_FIELD **key_fields,uin
((*value)->type() == Item::FIELD_ITEM) &&
((Item_field*)*value)->field->maybe_null());
(*key_fields)->cond_guard= NULL;
- (*key_fields)->sj_pred_no= (cond->name >= subq_sj_cond_name &&
- cond->name < subq_sj_cond_name + 64)?
- cond->name - subq_sj_cond_name: UINT_MAX;
+
+ (*key_fields)->sj_pred_no= get_semi_join_select_list_index(field);
(*key_fields)++;
}
@@ -4901,7 +5229,8 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array
keyuse.null_rejecting= key_field->null_rejecting;
keyuse.cond_guard= key_field->cond_guard;
keyuse.sj_pred_no= key_field->sj_pred_no;
- keyuse.ref_table_rows= 0;
+ /* This will be set accordingly in optimize_keyuse */
+ keyuse.ref_table_rows= ~(ha_rows) 0;
(void) insert_dynamic(keyuse_array,(uchar*) &keyuse);
}
}
@@ -5361,6 +5690,10 @@ set_position(JOIN *join,uint idx,JOIN_TA
join->positions[idx].records_read=1.0; /* This is a const table */
join->positions[idx].ref_depend_map= 0;
+ join->positions[idx].loosescan_key= MAX_KEY; /* Not a LooseScan */
+ join->positions[idx].sj_strategy= SJ_OPT_NONE;
+ join->positions[idx].use_join_buffer= FALSE;
+
/* Move the const table as down as possible in best_ref */
JOIN_TAB **pos=join->best_ref+idx+1;
JOIN_TAB *next=join->best_ref[idx];
@@ -5415,6 +5748,267 @@ ulonglong get_bound_sj_equalities(TABLE_
}
+/*
+ This is a class for considering possible loose index scan optimizations.
+ It's usage pattern is as follows:
+ best_access_path()
+ {
+ Loose_scan_opt opt;
+
+ opt.init()
+ for each index we can do ref access with
+ {
+ opt.next_ref_key();
+ for each keyuse
+ opt.add_keyuse();
+ opt.check_ref_access();
+ }
+
+ if (some criteria for range scans)
+ opt.check_range_access();
+
+ opt.get_best_option();
+ }
+*/
+
+class Loose_scan_opt
+{
+public:
+ /* All methods must check this before doing anything else */
+ bool try_loosescan;
+
+ /*
+ If we consider (oe1, .. oeN) IN (SELECT ie1, .. ieN) then ieK=oeK is
+ called sj-equality. If oeK depends only on preceding tables then such
+ equality is called 'bound'.
+ */
+ ulonglong bound_sj_equalities;
+
+ /* Accumulated properties of ref access we're now considering: */
+ ulonglong handled_sj_equalities;
+ key_part_map loose_scan_keyparts;
+ uint max_loose_keypart;
+ bool part1_conds_met;
+
+ /*
+ Use of quick select is a special case. Some of its properties:
+ */
+ uint quick_uses_applicable_index;
+ uint quick_max_loose_keypart;
+
+ /* Best loose scan method so far */
+ uint best_loose_scan_key;
+ double best_loose_scan_cost;
+ double best_loose_scan_records;
+ KEYUSE *best_loose_scan_start_key;
+
+ uint best_max_loose_keypart;
+
+ Loose_scan_opt():
+ try_loosescan(FALSE),
+ bound_sj_equalities(0),
+ quick_uses_applicable_index(FALSE)
+ {
+ LINT_INIT(quick_max_loose_keypart); /* Protected by quick_uses_applicable_index */
+ /* The following are protected by best_loose_scan_cost!= DBL_MAX */
+ LINT_INIT(best_loose_scan_key);
+ LINT_INIT(best_loose_scan_records);
+ LINT_INIT(best_max_loose_keypart);
+ LINT_INIT(best_loose_scan_start_key);
+ }
+
+ void init(JOIN *join, JOIN_TAB *s, table_map remaining_tables)
+ {
+ /*
+ Discover the bound equalities. We need to do this if
+ 1. The next table is an SJ-inner table, and
+ 2. It is the first table from that semijoin, and
+ 3. We're not within a semi-join range (i.e. all semi-joins either have
+ all or none of their tables in join_table_map), except
+ s->emb_sj_nest (which we've just entered, see #2).
+ 4. All non-IN-equality correlation references from this sj-nest are
+ bound
+ 5. But some of the IN-equalities aren't (so this can't be handled by
+ FirstMatch strategy)
+ */
+ best_loose_scan_cost= DBL_MAX;
+ if (!join->emb_sjm_nest && s->emb_sj_nest && // (1)
+ s->emb_sj_nest->sj_in_exprs < 64 &&
+ ((remaining_tables & s->emb_sj_nest->sj_inner_tables) == // (2)
+ s->emb_sj_nest->sj_inner_tables) && // (2)
+ join->cur_sj_inner_tables == 0 && // (3)
+ !(remaining_tables &
+ s->emb_sj_nest->nested_join->sj_corr_tables) && // (4)
+ remaining_tables & s->emb_sj_nest->nested_join->sj_depends_on &&// (5)
+ !optimizer_flag(join->thd, OPTIMIZER_SWITCH_NO_LOOSE_SCAN))
+ {
+ /* This table is an LooseScan scan candidate */
+ bound_sj_equalities= get_bound_sj_equalities(s->emb_sj_nest,
+ remaining_tables);
+ try_loosescan= TRUE;
+ DBUG_PRINT("info", ("Will try LooseScan scan, bound_map=%llx",
+ (longlong)bound_sj_equalities));
+ }
+ }
+
+ void next_ref_key()
+ {
+ handled_sj_equalities=0;
+ loose_scan_keyparts= 0;
+ max_loose_keypart= 0;
+ part1_conds_met= FALSE;
+ }
+
+ void add_keyuse(table_map remaining_tables, KEYUSE *keyuse)
+ {
+ if (try_loosescan && keyuse->sj_pred_no != UINT_MAX)
+ {
+ if (!(remaining_tables & keyuse->used_tables))
+ {
+ /*
+ This allows to use equality propagation to infer that some
+ sj-equalities are bound.
+ */
+ bound_sj_equalities |= 1ULL << keyuse->sj_pred_no;
+ }
+ else
+ {
+ handled_sj_equalities |= 1ULL << keyuse->sj_pred_no;
+ loose_scan_keyparts |= ((key_part_map)1) << keyuse->keypart;
+ set_if_bigger(max_loose_keypart, keyuse->keypart);
+ }
+ }
+ }
+
+ bool have_a_case() { return test(handled_sj_equalities); }
+
+ void check_ref_access_part1(JOIN_TAB *s, uint key, KEYUSE *start_key,
+ table_map found_part)
+ {
+ /*
+ Check if we can use LooseScan semi-join strategy. We can if
+ 1. This is the right table at right location
+ 2. All IN-equalities are either
+ - "bound", ie. the outer_expr part refers to the preceding tables
+ - "handled", ie. covered by the index we're considering
+ 3. Index order allows to enumerate subquery's duplicate groups in
+ order. This happens when the index definition matches this
+ pattern:
+
+ (handled_col|bound_col)* (other_col|bound_col)
+
+ */
+ if (try_loosescan && // (1)
+ (handled_sj_equalities | bound_sj_equalities) == // (2)
+ PREV_BITS(ulonglong, s->emb_sj_nest->sj_in_exprs) && // (2)
+ (PREV_BITS(key_part_map, max_loose_keypart+1) & // (3)
+ (found_part | loose_scan_keyparts)) == // (3)
+ (found_part | loose_scan_keyparts) && // (3)
+ !key_uses_partial_cols(s->table, key))
+ {
+ /* Ok, can use the strategy */
+ part1_conds_met= TRUE;
+ if (s->quick && s->quick->index == key &&
+ s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE)
+ {
+ quick_uses_applicable_index= TRUE;
+ quick_max_loose_keypart= max_loose_keypart;
+ }
+ DBUG_PRINT("info", ("Can use LooseScan scan"));
+
+ /*
+ Check if this is a confluent where there are no usable bound
+ IN-equalities, e.g. we have
+
+ outer_expr IN (SELECT innertbl.key FROM ...)
+
+ and outer_expr cannot be evaluated yet, so it's actually full
+ index scan and not a ref access
+ */
+ if (!(found_part & 1 ) && /* no usable ref access for 1st key part */
+ s->table->covering_keys.is_set(key))
+ {
+ DBUG_PRINT("info", ("Can use full index scan for LooseScan"));
+
+ /* Calculate the cost of complete loose index scan. */
+ double records= rows2double(s->table->file->stats.records);
+
+ /* The cost is entire index scan cost (divided by 2) */
+ double read_time= s->table->file->index_only_read_time(key, records);
+
+ /*
+ Now find out how many different keys we will get (for now we
+ ignore the fact that we have "keypart_i=const" restriction for
+ some key components, that may make us think think that loose
+ scan will produce more distinct records than it actually will)
+ */
+ ulong rpc;
+ if ((rpc= s->table->key_info[key].rec_per_key[max_loose_keypart]))
+ records= records / rpc;
+
+ // TODO: previous version also did /2
+ if (read_time < best_loose_scan_cost)
+ {
+ best_loose_scan_key= key;
+ best_loose_scan_cost= read_time;
+ best_loose_scan_records= records;
+ best_max_loose_keypart= max_loose_keypart;
+ best_loose_scan_start_key= start_key;
+ }
+ }
+ }
+ }
+
+ void check_ref_access_part2(uint key, KEYUSE *start_key, double records,
+ double read_time)
+ {
+ if (part1_conds_met && read_time < best_loose_scan_cost)
+ {
+ /* TODO use rec-per-key-based fanout calculations */
+ best_loose_scan_key= key;
+ best_loose_scan_cost= read_time;
+ best_loose_scan_records= records;
+ best_max_loose_keypart= max_loose_keypart;
+ best_loose_scan_start_key= start_key;
+ }
+ }
+
+ void check_range_access(JOIN *join, uint idx, QUICK_SELECT_I *quick)
+ {
+ /* TODO: this the right part restriction: */
+ if (quick_uses_applicable_index && idx == join->const_tables &&
+ quick->read_time < best_loose_scan_cost)
+ {
+ best_loose_scan_key= quick->index;
+ best_loose_scan_cost= quick->read_time;
+ /* this is ok because idx == join->const_tables */
+ best_loose_scan_records= rows2double(quick->records);
+ best_max_loose_keypart= quick_max_loose_keypart;
+ best_loose_scan_start_key= NULL;
+ }
+ }
+
+ void save_to_position(JOIN_TAB *tab, POSITION *pos)
+ {
+ pos->read_time= best_loose_scan_cost;
+ if (best_loose_scan_cost != DBL_MAX)
+ {
+ pos->records_read= best_loose_scan_records;
+ pos->key= best_loose_scan_start_key;
+ pos->loosescan_key= best_loose_scan_key;
+ pos->loosescan_parts= best_max_loose_keypart + 1;
+ pos->use_join_buffer= FALSE;
+ pos->table= tab;
+ // todo need ref_depend_map ?
+ DBUG_PRINT("info", ("Produced a LooseScan plan, key %s, %s",
+ tab->table->key_info[best_loose_scan_key].name,
+ best_loose_scan_start_key? "(ref access)":
+ "(range/index access)"));
+ }
+ }
+};
+
+
/**
Find the best access path for an extension of a partial execution
plan and add this path to the plan.
@@ -5432,9 +6026,12 @@ ulonglong get_bound_sj_equalities(TABLE_
@param thd thread for the connection that submitted the query
@param remaining_tables set of tables not included into the partial plan yet
@param idx the length of the partial plan
+ @param disable_jbuf TRUE<=> Don't use join buffering
@param record_count estimate for the number of records returned by the
partial plan
- @param read_time the cost of the partial plan
+ @param pos OUT Table access plan
+ @param loose_scan_pos OUT Table plan that uses loosescan, or set cost to
+ DBL_MAX if not possible.
@return
None
@@ -5443,12 +6040,14 @@ ulonglong get_bound_sj_equalities(TABLE_
static void
best_access_path(JOIN *join,
JOIN_TAB *s,
- THD *thd,
table_map remaining_tables,
uint idx,
+ bool disable_jbuf,
double record_count,
- double read_time)
+ POSITION *pos,
+ POSITION *loose_scan_pos)
{
+ THD *thd= join->thd;
KEYUSE *best_key= 0;
uint best_max_key_part= 0;
my_bool found_constraint= 0;
@@ -5458,52 +6057,19 @@ best_access_path(JOIN *join,
table_map best_ref_depends_map= 0;
double tmp;
ha_rows rec;
- uint best_is_sj_inside_out= MAX_KEY;
- uint best_sj_keyparts;
- bool try_sj_inside_out= FALSE;
- uint sj_insideout_quick_select= FALSE;
- uint sj_insideout_quick_max_sj_keypart;
- uint sj_inside_out_scan= MAX_KEY;
+ bool best_uses_jbuf= FALSE;
+
+ Loose_scan_opt loose_scan_opt;
DBUG_ENTER("best_access_path");
- LINT_INIT(best_sj_keyparts); // Protected by sj_inside_out_scan
- LINT_INIT(sj_insideout_quick_max_sj_keypart); // Protected by sj_insideout_quick_*
+ loose_scan_opt.init(join, s, remaining_tables);
+
if (s->keyuse)
{ /* Use key if possible */
TABLE *table= s->table;
KEYUSE *keyuse,*start_key=0;
double best_records= DBL_MAX;
uint max_key_part=0;
- ulonglong bound_sj_equalities= 0;
- /*
- Discover the bound equalites. We need to do this, if
- 1. The next table is an SJ-inner table, and
- 2. It is the first table from that semijoin, and
- 3. We're not within a semi-join range (i.e. all semi-joins either have
- all or none of their tables in join_table_map), except
- s->emb_sj_nest (which we've just entered, see #2).
- 4. All non-IN-equality correlation references from this sj-nest are
- bound
- 5. But some of the IN-equalities aren't (so this can't be handled by
- FirstMatch strategy)
- */
- if (s->emb_sj_nest && // (1)
- s->emb_sj_nest->sj_in_exprs < 64 &&
- ((remaining_tables & s->emb_sj_nest->sj_inner_tables) == // (2)
- s->emb_sj_nest->sj_inner_tables) && // (2)
- join->cur_emb_sj_nests == s->emb_sj_nest->sj_inner_tables && // (3)
- !(remaining_tables &
- s->emb_sj_nest->nested_join->sj_corr_tables) && // (4)
- remaining_tables & s->emb_sj_nest->nested_join->sj_depends_on &&// (5)
- !test(thd->variables.optimizer_switch & OPTIMIZER_SWITCH_NO_LOOSE_SCAN))
- {
- /* This table is an InsideOut scan candidate */
- bound_sj_equalities= get_bound_sj_equalities(s->emb_sj_nest,
- remaining_tables);
- try_sj_inside_out= TRUE;
- DBUG_PRINT("info", ("Will try InsideOut scan, bound_map=%llx",
- (longlong)bound_sj_equalities));
- }
/* Test how we can use keys */
rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key
@@ -5521,9 +6087,8 @@ best_access_path(JOIN *join,
/* Calculate how many key segments of the current key we can use */
start_key= keyuse;
- ulonglong handled_sj_equalities=0;
- key_part_map sj_insideout_map= 0;
- uint max_sj_keypart= 0;
+
+ loose_scan_opt.next_ref_key();
DBUG_PRINT("info", ("Considering ref access on key %s",
keyuse->table->key_info[keyuse->key].name));
@@ -5535,7 +6100,6 @@ best_access_path(JOIN *join,
do /* For each way to access the keypart */
{
-
/*
if 1. expression doesn't refer to forward tables
2. we won't get two ref-or-null's
@@ -5564,19 +6128,7 @@ best_access_path(JOIN *join,
if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
ref_or_null_part |= keyuse->keypart_map;
}
-
- if (try_sj_inside_out && keyuse->sj_pred_no != UINT_MAX)
- {
- if (!(remaining_tables & keyuse->used_tables))
- bound_sj_equalities |= 1ULL << keyuse->sj_pred_no;
- else
- {
- handled_sj_equalities |= 1ULL << keyuse->sj_pred_no;
- sj_insideout_map |= ((key_part_map)1) << keyuse->keypart;
- set_if_bigger(max_sj_keypart, keyuse->keypart);
- }
- }
-
+ loose_scan_opt.add_keyuse(remaining_tables, keyuse);
keyuse++;
} while (keyuse->table == table && keyuse->key == key &&
keyuse->keypart == keypart);
@@ -5586,13 +6138,12 @@ best_access_path(JOIN *join,
/*
Assume that that each key matches a proportional part of table.
*/
- if (!found_part && !ft_key && !handled_sj_equalities)
+ if (!found_part && !ft_key && !loose_scan_opt.have_a_case())
continue; // Nothing usable found
if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables
- sj_inside_out_scan= MAX_KEY;
/*
ft-keys require special treatment
*/
@@ -5608,73 +6159,9 @@ best_access_path(JOIN *join,
else
{
found_constraint= test(found_part);
- /*
- Check if we can use InsideOut semi-join strategy. We can if
- 1. This is the right table at right location
- 2. All IN-equalities are either
- - "bound", ie. the outer_expr part refers to the preceding tables
- - "handled", ie. covered by the index we're considering
- 3. Index order allows to enumerate subquery's duplicate groups in
- order. This happens when the index definition matches this
- pattern:
-
- (handled_col|bound_col)* (other_col|bound_col)
-
- */
- if (try_sj_inside_out && // (1)
- (handled_sj_equalities | bound_sj_equalities) == // (2)
- PREV_BITS(ulonglong, s->emb_sj_nest->sj_in_exprs) && // (2)
- (PREV_BITS(key_part_map, max_sj_keypart+1) & // (3)
- (found_part | sj_insideout_map)) == // (3)
- (found_part | sj_insideout_map) && // (3)
- !key_uses_partial_cols(s->table, key))
- {
- /* Ok, can use the strategy */
- sj_inside_out_scan= key;
- if (s->quick && s->quick->index == key &&
- s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE)
- {
- sj_insideout_quick_select= TRUE;
- sj_insideout_quick_max_sj_keypart= max_sj_keypart;
- }
- DBUG_PRINT("info", ("Can use InsideOut scan"));
-
- /*
- Check if this is a confluent where there are no usable bound
- IN-equalities, e.g. we have
+ loose_scan_opt.check_ref_access_part1(s, key, start_key, found_part);
- outer_expr IN (SELECT innertbl.key FROM ...)
-
- and outer_expr cannot be evaluated yet, so it's actually full
- index scan and not a ref access
- */
- if (!(found_part & 1 ) && /* no usable ref access for 1st key part */
- table->covering_keys.is_set(key))
- {
- DBUG_PRINT("info", ("Can use full index scan for InsideOut"));
- /* Calculate the cost of complete loose index scan. */
- records= rows2double(s->table->file->stats.records);
-
- /* The cost is entire index scan cost (divided by 2) */
- best_time= s->table->file->index_only_read_time(key, records);
-
- /*
- Now find out how many different keys we will get (for now we
- ignore the fact that we have "keypart_i=const" restriction for
- some key components, that may make us think think that loose
- scan will produce more distinct records than it actually will)
- */
- ulong rpc;
- if ((rpc= keyinfo->rec_per_key[max_sj_keypart]))
- records= records / rpc;
- start_key= NULL;
- /* Fall through */
- }
- }
-
- /*
- Check if we found full key
- */
+ /* Check if we found full key */
if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
!ref_or_null_part)
{ /* use eq key */
@@ -5922,13 +6409,7 @@ best_access_path(JOIN *join,
else
tmp= best_time; // Do nothing
}
-
- if ((sj_inside_out_scan != MAX_KEY) && !start_key)
- {
- tmp= tmp/2;
- if (records)
- records= records/2;
- }
+ loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
} /* not ft_key */
if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
@@ -5939,8 +6420,6 @@ best_access_path(JOIN *join,
best_key= start_key;
best_max_key_part= max_key_part;
best_ref_depends_map= found_ref;
- best_is_sj_inside_out= sj_inside_out_scan;
- best_sj_keyparts= max_sj_keypart;
}
} /* for each key */
records= best_records;
@@ -5981,7 +6460,6 @@ best_access_path(JOIN *join,
! s->table->covering_keys.is_clear_all() && best_key && !s->quick) &&// (3)
!(s->table->force_index && best_key && !s->quick)) // (4)
{ // Check full join
- sj_inside_out_scan= MAX_KEY;
ha_rows rnd_records= s->found_records;
/*
If there is a filtering condition on the table (i.e. ref analyzer found
@@ -6007,6 +6485,7 @@ best_access_path(JOIN *join,
than FULL: so if RANGE is present, it's always preferred to FULL.
Here we estimate its cost.
*/
+
if (s->quick)
{
/*
@@ -6021,17 +6500,14 @@ best_access_path(JOIN *join,
tmp= record_count *
(s->quick->read_time +
(s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
-
- if (sj_insideout_quick_select && idx == join->const_tables)
- {
- sj_inside_out_scan= s->quick->index;
- }
+
+ loose_scan_opt.check_range_access(join, idx, s->quick);
}
else
{
/* Estimate cost of reading table. */
tmp= s->table->file->scan_time();
- if (s->table->map & join->outer_join) // Can't use join cache
+ if ((s->table->map & join->outer_join) || disable_jbuf) // Can't use join cache
{
/*
For each record we have to:
@@ -6077,19 +6553,21 @@ best_access_path(JOIN *join,
best_key= 0;
/* range/index_merge/ALL/index access method are "independent", so: */
best_ref_depends_map= 0;
- best_is_sj_inside_out= sj_inside_out_scan;
- best_sj_keyparts= sj_insideout_quick_max_sj_keypart;
+ best_uses_jbuf= test(!disable_jbuf && !((s->table->map &
+ join->outer_join)));
}
}
-
+
/* Update the cost information for the current partial plan */
- join->positions[idx].records_read= records;
- join->positions[idx].read_time= best;
- join->positions[idx].key= best_key;
- join->positions[idx].table= s;
- join->positions[idx].ref_depend_map= best_ref_depends_map;
- join->positions[idx].insideout_key= best_is_sj_inside_out;
- join->positions[idx].insideout_parts= best_sj_keyparts + 1;
+ pos->records_read= records;
+ pos->read_time= best;
+ pos->key= best_key;
+ pos->table= s;
+ pos->ref_depend_map= best_ref_depends_map;
+ pos->loosescan_key= MAX_KEY;
+ pos->use_join_buffer= best_uses_jbuf;
+
+ loose_scan_opt.save_to_position(s, loose_scan_pos);
if (!best_key &&
idx == join->const_tables &&
@@ -6114,6 +6592,9 @@ best_access_path(JOIN *join,
the query
@param join_tables set of the tables in the query
+ @param sj_nest If not NULL, optimize a subjoin of tables within the
+ given semi-join nest.
+
@todo
'MAX_TABLES+2' denotes the old implementation of find_best before
the greedy version. Will be removed when greedy_search is approved.
@@ -6133,19 +6614,73 @@ choose_plan(JOIN *join, table_map join_t
DBUG_ENTER("choose_plan");
join->cur_embedding_map= 0;
+ join->cur_dups_producing_tables= 0;
reset_nj_counters(join->join_list);
- /*
- if (SELECT_STRAIGHT_JOIN option is set)
- reorder tables so dependent tables come after tables they depend
- on, otherwise keep tables in the order they were specified in the query
- else
- Apply heuristic: pre-sort all access plans with respect to the number of
- records accessed.
- */
- my_qsort(join->best_ref + join->const_tables,
- join->tables - join->const_tables, sizeof(JOIN_TAB*),
- straight_join ? join_tab_cmp_straight : join_tab_cmp);
- join->cur_emb_sj_nests= 0;
+ qsort2_cmp jtab_sort_func;
+
+ if (join->emb_sjm_nest)
+ {
+ /* We're optimizing semi-join materialization nest, so put the
+ tables from this semi-join as first
+ */
+ jtab_sort_func= join_tab_cmp_embedded_first;
+ }
+ else
+ {
+ /*
+ if (SELECT_STRAIGHT_JOIN option is set)
+ reorder tables so dependent tables come after tables they depend
+ on, otherwise keep tables in the order they were specified in the query
+ else
+ Apply heuristic: pre-sort all access plans with respect to the number of
+ records accessed.
+ */
+ jtab_sort_func= straight_join ? join_tab_cmp_straight : join_tab_cmp;
+ }
+ my_qsort2(join->best_ref + join->const_tables,
+ join->tables - join->const_tables, sizeof(JOIN_TAB*),
+ jtab_sort_func, (void*)join->emb_sjm_nest);
+ join->cur_sj_inner_tables= 0;
+
+#if 0
+ if (!join->emb_sjm_nest && straight_join)
+ {
+ /* Put all sj-inner tables right after their last outer table table. */
+ uint inner;
+
+ /* Find the first inner table (inner tables follow outer) */
+ for (inner= join->const_tables;
+ inner < join->tables && !join->best_ref[inner]->emb_sj_nest;
+ inner++);
+
+ while (inner < join->tables) /* for each group of inner tables... */
+ {
+ TABLE_LIST *emb_sj_nest= join->best_ref[inner]->emb_sj_nest;
+ uint n_tables= my_count_bits(emb_sj_nest->sj_inner_tables);
+ table_map cur_map= join->const_table_map;
+ table_map needed_map= emb_sj_nest->nested_join->sj_depends_on |
+ emb_sj_nest->nested_join->sj_corr_tables;
+ /* Locate the last outer table with which this semi-join is correlated */
+ uint last_outer;
+ for (last_outer= join->const_tables; last_outer < inner; last_outer++)
+ {
+ cur_map |= join->best_ref[last_outer]->table->map;
+ if (!(needed_map & ~cur_map))
+ break;
+ }
+ /* Move the inner tables to here */
+ JOIN_TAB *tmp[MAX_TABLES];
+ memcpy(tmp, join->best_ref + inner, n_tables*sizeof(JOIN_TAB));
+ for (uint i= inner - 1; i > last_outer; i--)
+ {
+ join->best_ref[i + n_tables]= join->best_ref[i];
+ }
+ memcpy(join->best_ref + last_outer + 1, tmp, n_tables*sizeof(JOIN_TAB));
+ inner += n_tables;
+ }
+ }
+#endif
+
if (straight_join)
{
optimize_straight_join(join, join_tables);
@@ -6209,7 +6744,7 @@ choose_plan(JOIN *join, table_map join_t
*/
static int
-join_tab_cmp(const void* ptr1, const void* ptr2)
+join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2)
{
JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
@@ -6231,10 +6766,18 @@ join_tab_cmp(const void* ptr1, const voi
*/
static int
-join_tab_cmp_straight(const void* ptr1, const void* ptr2)
+join_tab_cmp_straight(const void *dummy, const void* ptr1, const void* ptr2)
{
JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
+
+ /*
+ We don't do subquery flattening if the parent or child select has
+ STRAIGHT_JOIN modifier. It is complicated to implement and the semantics
+ is hardly useful.
+ */
+ DBUG_ASSERT(!jt1->emb_sj_nest);
+ DBUG_ASSERT(!jt2->emb_sj_nest);
if (jt1->dependent & jt2->table->map)
return 1;
@@ -6243,6 +6786,38 @@ join_tab_cmp_straight(const void* ptr1,
return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
}
+
+/*
+ Same as join_tab_cmp but tables from within the given semi-join nest go
+ first. Used when the optimizing semi-join materialization nests.
+*/
+
+static int
+join_tab_cmp_embedded_first(const void *emb, const void* ptr1, const void* ptr2)
+{
+ const TABLE_LIST *emb_nest= (TABLE_LIST*) emb;
+ JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
+ JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
+
+ if (jt1->emb_sj_nest == emb_nest && jt2->emb_sj_nest != emb_nest)
+ return -1;
+ if (jt1->emb_sj_nest != emb_nest && jt2->emb_sj_nest == emb_nest)
+ return 1;
+
+ if (jt1->dependent & jt2->table->map)
+ return 1;
+ if (jt2->dependent & jt1->table->map)
+ return -1;
+
+ if (jt1->found_records > jt2->found_records)
+ return 1;
+ if (jt1->found_records < jt2->found_records)
+ return -1;
+
+ return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
+}
+
+
/**
Heuristic procedure to automatically guess a reasonable degree of
exhaustiveness for the greedy search procedure.
@@ -6326,30 +6901,88 @@ optimize_straight_join(JOIN *join, table
uint idx= join->const_tables;
double record_count= 1.0;
double read_time= 0.0;
+ POSITION loose_scan_pos;
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
/* Find the best access method from 's' to the current partial plan */
- advance_sj_state(join_tables, s);
- best_access_path(join, s, join->thd, join_tables, idx,
- record_count, read_time);
+ best_access_path(join, s, join_tables, idx, FALSE, record_count,
+ join->positions + idx, &loose_scan_pos);
+
/* compute the cost of the new plan extended with 's' */
record_count*= join->positions[idx].records_read;
read_time+= join->positions[idx].read_time;
+ advance_sj_state(join, join_tables, s, idx, &record_count, &read_time,
+ &loose_scan_pos);
+
join_tables&= ~(s->table->map);
++idx;
}
-
- read_time+= record_count / (double) TIME_FOR_COMPARE;
- if (join->sort_by_table &&
- join->sort_by_table != join->positions[join->const_tables].table->table)
- read_time+= record_count; // We have to make a temp table
- memcpy((uchar*) join->best_positions, (uchar*) join->positions,
- sizeof(POSITION)*idx);
- join->best_read= read_time;
+
+ read_time+= record_count / (double) TIME_FOR_COMPARE;
+ if (join->sort_by_table &&
+ join->sort_by_table != join->positions[join->const_tables].table->table)
+ read_time+= record_count; // We have to make a temp table
+ memcpy((uchar*) join->best_positions, (uchar*) join->positions,
+ sizeof(POSITION)*idx);
+ join->best_read= read_time;
+}
+
+
+/*
+ Check if the last tables of the partial join order allow to use
+ sj-materialization strategy for them
+
+ SYNOPSIS
+ at_sjmat_pos()
+ join
+ remaining_tables
+ tab the last table's join tab
+ idx last table's index
+ loose_scan OUT TRUE <=> use LooseScan
+
+ RETURN
+ TRUE Yes, can apply sj-materialization
+ FALSE No, some of the requirements are not met
+*/
+
+SJ_MATERIALIZATION_INFO *
+at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab,
+ uint idx, bool *loose_scan)
+{
+ /*
+ Check if
+ 1. We're in a semi-join nest that can be run with SJ-materialization
+ 2. All the tables correlated through the IN subquery are in the prefix
+ */
+ TABLE_LIST *emb_sj_nest= tab->emb_sj_nest;
+ table_map suffix= remaining_tables & ~tab->table->map;
+ if (emb_sj_nest && emb_sj_nest->sj_mat_info &&
+ !(suffix & emb_sj_nest->sj_inner_tables))
+ {
+ /*
+ Walk back and check if all immediately preceding tables are from
+ this semi-join.
+ */
+ uint n_tables= my_count_bits(tab->emb_sj_nest->sj_inner_tables);
+ for (uint i= 1; i < n_tables ; i++)
+ {
+ if (join->positions[idx - i].table->emb_sj_nest != tab->emb_sj_nest)
+ return NULL;
+ }
+ *loose_scan= test(remaining_tables & ~tab->table->map &
+ (emb_sj_nest->sj_inner_tables |
+ emb_sj_nest->nested_join->sj_depends_on));
+ if (*loose_scan && !emb_sj_nest->sj_subq_pred->sjm_scan_allowed)
+ return NULL;
+ else
+ return emb_sj_nest->sj_mat_info;
+ }
+ return NULL;
}
+
/**
Find a good, possibly optimal, query execution plan (QEP) by a greedy search.
@@ -6444,11 +7077,15 @@ greedy_search(JOIN *join,
uint size_remain; // cardinality of remaining_tables
POSITION best_pos;
JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
+ uint n_tables; // ==join->tables or # tables in the sj-mat nest we're optimizing
DBUG_ENTER("greedy_search");
/* number of tables that remain to be optimized */
- size_remain= my_count_bits(remaining_tables);
+ n_tables= size_remain= my_count_bits(remaining_tables &
+ (join->emb_sjm_nest?
+ join->emb_sjm_nest->sj_inner_tables :
+ ~(table_map)0));
do {
/* Find the extension of the current QEP with the lowest cost */
@@ -6463,9 +7100,8 @@ greedy_search(JOIN *join,
'join->best_positions' contains a complete optimal extension of the
current partial QEP.
*/
- DBUG_EXECUTE("opt", print_plan(join, join->tables,
- record_count, read_time, read_time,
- "optimal"););
+ DBUG_EXECUTE("opt", print_plan(join, n_tables, record_count, read_time,
+ read_time, "optimal"););
DBUG_RETURN(FALSE);
}
@@ -6496,13 +7132,53 @@ greedy_search(JOIN *join,
--size_remain;
++idx;
- DBUG_EXECUTE("opt", print_plan(join, join->tables,
- record_count, read_time, read_time,
- "extended"););
+ DBUG_EXECUTE("opt", print_plan(join, n_tables, record_count, read_time,
+ read_time, "extended"););
} while (TRUE);
}
+/*
+ Calculate a cost of given partial join order
+
+ SYNOPSIS
+ get_partial_join_cost()
+ join IN Join to use. join->positions holds the
+ partial join order
+ idx IN # tables in the partial join order
+ read_time_arg OUT Store read time here
+ record_count_arg OUT Store record count here
+
+ DESCRIPTION
+
+ This is needed for semi-join materialization code. The idea is that
+ we detect sj-materialization after we've put all sj-inner tables into
+ the join prefix
+
+ prefix-tables semi-join-inner-tables tN
+ ^--we're here
+
+ and we'll need to get the cost of prefix-tables prefix again.
+*/
+
+void get_partial_join_cost(JOIN *join, uint n_tables, double *read_time_arg,
+ double *record_count_arg)
+{
+ double record_count= 1;
+ double read_time= 0.0;
+ for (uint i= join->const_tables; i < n_tables + join->const_tables ; i++)
+ {
+ if (join->best_positions[i].records_read)
+ {
+ record_count *= join->best_positions[i].records_read;
+ read_time += join->best_positions[i].read_time;
+ }
+ }
+ *read_time_arg= read_time;// + record_count / TIME_FOR_COMPARE;
+ *record_count_arg= record_count;
+}
+
+
/**
Find a good, possibly optimal, query execution plan (QEP) by a possibly
exhaustive search.
@@ -6649,22 +7325,33 @@ best_extension_by_limited_search(JOIN
DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time,
"part_plan"););
+ table_map allowed_tables= ~(table_map)0;
+ if (join->emb_sjm_nest)
+ allowed_tables= join->emb_sjm_nest->sj_inner_tables;
+
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
table_map real_table_bit= s->table->map;
if ((remaining_tables & real_table_bit) &&
+ (allowed_tables & real_table_bit) &&
!(remaining_tables & s->dependent) &&
(!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s)))
{
double current_record_count, current_read_time;
- advance_sj_state(remaining_tables, s);
+ POSITION *position= join->positions + idx;
/* Find the best access method from 's' to the current partial plan */
- best_access_path(join, s, thd, remaining_tables, idx,
- record_count, read_time);
+ POSITION loose_scan_pos;
+ best_access_path(join, s, remaining_tables, idx, FALSE, record_count,
+ join->positions + idx, &loose_scan_pos);
+
/* Compute the cost of extending the plan with 's' */
- current_record_count= record_count * join->positions[idx].records_read;
- current_read_time= read_time + join->positions[idx].read_time;
+
+ current_record_count= record_count * position->records_read;
+ current_read_time= read_time + position->read_time;
+
+ advance_sj_state(join, remaining_tables, s, idx, ¤t_record_count,
+ ¤t_read_time, &loose_scan_pos);
/* Expand only partial plans with lower cost than the best QEP so far */
if ((current_read_time +
@@ -6678,7 +7365,7 @@ best_extension_by_limited_search(JOIN
(double) TIME_FOR_COMPARE),
"prune_by_cost"););
restore_prev_nj_state(s);
- restore_prev_sj_state(remaining_tables, s);
+ restore_prev_sj_state(remaining_tables, s, idx);
continue;
}
@@ -6711,12 +7398,12 @@ best_extension_by_limited_search(JOIN
current_read_time,
"pruned_by_heuristic"););
restore_prev_nj_state(s);
- restore_prev_sj_state(remaining_tables, s);
+ restore_prev_sj_state(remaining_tables, s, idx);
continue;
}
}
- if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) )
+ if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) & allowed_tables )
{ /* Recursively expand the current partial plan */
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
if (best_extension_by_limited_search(join,
@@ -6753,7 +7440,7 @@ best_extension_by_limited_search(JOIN
"full_plan"););
}
restore_prev_nj_state(s);
- restore_prev_sj_state(remaining_tables, s);
+ restore_prev_sj_state(remaining_tables, s, idx);
}
}
DBUG_RETURN(FALSE);
@@ -6807,9 +7494,9 @@ find_best(JOIN *join,table_map rest_tabl
(!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s)))
{
double records, best;
- advance_sj_state(rest_tables, s);
- best_access_path(join, s, thd, rest_tables, idx, record_count,
- read_time);
+ POSITION loose_scan_pos;
+ best_access_path(join, s, rest_tables, idx, FALSE, record_count,
+ join->positions + idx, &loose_scan_pos);
records= join->positions[idx].records_read;
best= join->positions[idx].read_time;
/*
@@ -6818,6 +7505,9 @@ find_best(JOIN *join,table_map rest_tabl
*/
double current_record_count=record_count*records;
double current_read_time=read_time+best;
+ advance_sj_state(join, rest_tables, s, idx, ¤t_record_count,
+ ¤t_read_time, &loose_scan_pos);
+
if (best_record_count > current_record_count ||
best_read_time > current_read_time ||
idx == join->const_tables && s->table == join->sort_by_table)
@@ -6836,7 +7526,7 @@ find_best(JOIN *join,table_map rest_tabl
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
}
restore_prev_nj_state(s);
- restore_prev_sj_state(rest_tables, s);
+ restore_prev_sj_state(rest_tables, s, idx);
if (join->select_options & SELECT_STRAIGHT_JOIN)
break; // Don't test all combinations
}
@@ -6991,12 +7681,231 @@ prev_record_reads(JOIN *join, uint idx,
}
-/**
+/*
+ Fix semi-join strategies for the picked join order
+
+ SYNOPSIS
+ fix_semijoin_strategies_for_picked_join_order()
+ join The join with the picked join order
+
+ DESCRIPTION
+ Fix semi-join strategies for the picked join order. This is a step that
+ needs to be done right after we have fixed the join order. What we do
+ here is switch join's semi-join strategy description from backward-based
+ to forwards based.
+
+ When join optimization is in progress, we re-consider semi-join
+ strategies after we've added another table. Here's an illustration.
+ Suppose the join optimization is underway:
+
+ 1) ot1 it1 it2
+ sjX -- looking at (ot1, it1, it2) join prefix, we decide
+ to use semi-join strategy sjX.
+
+ 2) ot1 it1 it2 ot2
+ sjX sjY -- Having added table ot2, we now may consider
+ another semi-join strategy and decide to use a
+ different strategy sjY. Note that the record
+ of sjX has remained under it2. That is
+ necessary because we need to be able to get
+ back to (ot1, it1, it2) join prefix.
+ what makes things even worse is that there are cases where the choice
+ of sjY changes the way we should access it2.
+
+ 3) [ot1 it1 it2 ot2 ot3]
+ sjX sjY -- This means that after join optimization is
+ finished, semi-join info should be read
+ right-to-left (while nearly all plan refinement
+ functions, EXPLAIN, etc proceed from left to
+ right)
+
+ This function does the needed reversal, making it possible to read the
+ join and semi-join order from left to right.
+*/
+
+static void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
+{
+ uint table_count=join->tables;
+ uint tablenr;
+ table_map remaining_tables= 0;
+ table_map handled_tabs= 0;
+ for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--)
+ {
+ POSITION *pos= join->best_positions + tablenr;
+ JOIN_TAB *s= pos->table;
+ uint first;
+ LINT_INIT(first); // Set by every branch except SJ_OPT_NONE which doesn't use it
+
+ if ((handled_tabs & s->table->map) || pos->sj_strategy == SJ_OPT_NONE)
+ {
+ remaining_tables |= s->table->map;
+ continue;
+ }
+
+ if (pos->sj_strategy == SJ_OPT_MATERIALIZE)
+ {
+ SJ_MATERIALIZATION_INFO *sjm= s->emb_sj_nest->sj_mat_info;
+ sjm->is_used= TRUE;
+ sjm->is_sj_scan= FALSE;
+ memcpy(pos - sjm->tables + 1, sjm->positions,
+ sizeof(POSITION) * sjm->tables);
+ first= tablenr - sjm->tables + 1;
+ join->best_positions[first].n_sj_tables= sjm->tables;
+ join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE;
+ }
+ else if (pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN)
+ {
+ POSITION *first_inner= join->best_positions + pos->sjm_scan_last_inner;
+ SJ_MATERIALIZATION_INFO *sjm= first_inner->table->emb_sj_nest->sj_mat_info;
+ sjm->is_used= TRUE;
+ sjm->is_sj_scan= TRUE;
+ first= pos->sjm_scan_last_inner - sjm->tables + 1;
+ memcpy(join->best_positions + first,
+ sjm->positions, sizeof(POSITION) * sjm->tables);
+ join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN;
+ join->best_positions[first].n_sj_tables= sjm->tables;
+ /*
+ Do what advance_sj_state did: re-run best_access_path for every table
+ in the [last_inner_table + 1; pos..) range
+ */
+ double prefix_rec_count;
+ /* Get the prefix record count */
+ if (first == join->const_tables)
+ prefix_rec_count= 1.0;
+ else
+ prefix_rec_count= join->best_positions[first-1].prefix_record_count;
+
+ /* Add materialization record count*/
+ prefix_rec_count *= sjm->rows;
+
+ uint i;
+ table_map rem_tables= remaining_tables;
+ for (i= tablenr; i != (first + sjm->tables - 1); i--)
+ rem_tables |= join->best_positions[i].table->table->map;
+
+ POSITION dummy;
+ join->cur_sj_inner_tables= 0;
+ for (i= first + sjm->tables; i <= tablenr; i++)
+ {
+ best_access_path(join, join->best_positions[i].table, rem_tables, i, FALSE,
+ prefix_rec_count, join->best_positions + i, &dummy);
+ prefix_rec_count *= join->best_positions[i].records_read;
+ rem_tables &= ~join->best_positions[i].table->table->map;
+ }
+ }
+
+ if (pos->sj_strategy == SJ_OPT_FIRST_MATCH)
+ {
+ first= pos->first_firstmatch_table;
+ join->best_positions[first].sj_strategy= SJ_OPT_FIRST_MATCH;
+ join->best_positions[first].n_sj_tables= tablenr - first + 1;
+ POSITION dummy; // For loose scan paths
+ double record_count= (first== join->const_tables)? 1.0:
+ join->best_positions[tablenr - 1].prefix_record_count;
+
+ table_map rem_tables= remaining_tables;
+ uint idx;
+ for (idx= first; idx <= tablenr; idx++)
+ {
+ rem_tables |= join->best_positions[idx].table->table->map;
+ }
+ /*
+ Re-run best_access_path to produce best access methods that do not use
+ join buffering
+ */
+ join->cur_sj_inner_tables= 0;
+ for (idx= first; idx <= tablenr; idx++)
+ {
+ if (join->best_positions[idx].use_join_buffer)
+ {
+ best_access_path(join, join->best_positions[idx].table,
+ rem_tables, idx, TRUE /* no jbuf */,
+ record_count, join->best_positions + idx, &dummy);
+ }
+ record_count *= join->best_positions[idx].records_read;
+ rem_tables &= ~join->best_positions[idx].table->table->map;
+ }
+ }
+
+ if (pos->sj_strategy == SJ_OPT_LOOSE_SCAN)
+ {
+ first= pos->first_loosescan_table;
+ POSITION *first_pos= join->best_positions + first;
+ POSITION loose_scan_pos; // For loose scan paths
+ double record_count= (first== join->const_tables)? 1.0:
+ join->best_positions[tablenr - 1].prefix_record_count;
+
+ table_map rem_tables= remaining_tables;
+ uint idx;
+ for (idx= first; idx <= tablenr; idx++)
+ rem_tables |= join->best_positions[idx].table->table->map;
+ /*
+ Re-run best_access_path to produce best access methods that do not use
+ join buffering
+ */
+ join->cur_sj_inner_tables= 0;
+ for (idx= first; idx <= tablenr; idx++)
+ {
+ if (join->best_positions[idx].use_join_buffer || (idx == first))
+ {
+ best_access_path(join, join->best_positions[idx].table,
+ rem_tables, idx, TRUE /* no jbuf */,
+ record_count, join->best_positions + idx,
+ &loose_scan_pos);
+ if (idx==first)
+ join->best_positions[idx]= loose_scan_pos;
+ }
+ rem_tables &= ~join->best_positions[idx].table->table->map;
+ record_count *= join->best_positions[idx].records_read;
+ }
+ first_pos->sj_strategy= SJ_OPT_LOOSE_SCAN;
+ first_pos->n_sj_tables= my_count_bits(first_pos->table->emb_sj_nest->sj_inner_tables);
+ }
+
+ if (pos->sj_strategy == SJ_OPT_DUPS_WEEDOUT)
+ {
+ /*
+ Duplicate Weedout starting at pos->first_dupsweedout_table, ending at
+ this table.
+ */
+ first= pos->first_dupsweedout_table;
+ join->best_positions[first].sj_strategy= SJ_OPT_DUPS_WEEDOUT;
+ join->best_positions[first].n_sj_tables= tablenr - first + 1;
+ }
+
+ uint i_end= first + join->best_positions[first].n_sj_tables;
+ for (uint i= first; i < i_end; i++)
+ handled_tabs |= join->best_positions[i].table->table->map;
+
+ if (tablenr != first)
+ pos->sj_strategy= SJ_OPT_NONE;
+ remaining_tables |= s->table->map;
+ }
+}
+
+
+/*
Set up join struct according to best position.
+
+ SYNOPSIS
+ get_best_combination()
+ join The join to process
+
+ DESCRIPTION
+ Setup join structures according the picked join order:
+ - finalize semi-join strategy choices (see
+ fix_semijoin_strategies_for_picked_join_order)
+
+ - create join->join_tab array and put there the JOIN_TABs in the join order
+
+ - create ref access data structures
+
+ RETURN
+ FALSE OK
+ TRUE Out of memory
*/
-static bool
-get_best_combination(JOIN *join)
+static bool get_best_combination(JOIN *join)
{
uint i,tablenr;
table_map used_tables;
@@ -7014,6 +7923,9 @@ get_best_combination(JOIN *join)
join->full_join=0;
used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
+
+ fix_semijoin_strategies_for_picked_join_order(join);
+
for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++)
{
TABLE *form;
@@ -7024,18 +7936,22 @@ get_best_combination(JOIN *join)
if (!*j->on_expr_ref)
form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN
DBUG_PRINT("info",("type: %d", j->type));
+
if (j->type == JT_CONST)
continue; // Handled in make_join_stat..
- j->insideout_match_tab= NULL;
+
+ j->loosescan_match_tab= NULL; //non-nulls will be set later
j->ref.key = -1;
j->ref.key_parts=0;
+
if (j->type == JT_SYSTEM)
continue;
- if (j->keys.is_clear_all() || !(keyuse= join->best_positions[tablenr].key))
+ if (j->keys.is_clear_all() || !(keyuse= join->best_positions[tablenr].key) ||
+ (join->best_positions[tablenr].sj_strategy == SJ_OPT_LOOSE_SCAN))
{
j->type=JT_ALL;
- j->index= join->best_positions[tablenr].insideout_key;
+ j->index= join->best_positions[tablenr].loosescan_key;
if (tablenr != join->const_tables)
join->full_join=1;
}
@@ -7330,9 +8246,11 @@ make_simple_join(JOIN *join,TABLE *tmp_t
join_tab->read_first_record= join_init_read_record;
join_tab->join=join;
join_tab->ref.key_parts= 0;
+ join_tab->keep_current_rowid= FALSE;
join_tab->flush_weedout_table= join_tab->check_weed_out_table= NULL;
join_tab->do_firstmatch= NULL;
- join_tab->insideout_match_tab= NULL;
+ join_tab->loosescan_match_tab= NULL;
+ join_tab->emb_sj_nest= NULL;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
tmp_table->status=0;
tmp_table->null_row=0;
@@ -7584,15 +8502,19 @@ make_outerjoin_info(JOIN *join)
}
-static bool
-make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
+static bool make_join_select(JOIN *join, Item *cond)
{
THD *thd= join->thd;
DBUG_ENTER("make_join_select");
- if (select)
{
add_not_null_conds(join);
table_map used_tables;
+ /*
+ Step #1: Extract constant condition
+ - Extract and check the constant part of the WHERE
+ - Extract constant parts of ON expressions from outer
+ joins and attach them appropriately.
+ */
if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */
{ /* there may be a select without a cond. */
if (join->tables > 1)
@@ -7645,20 +8567,41 @@ make_join_select(JOIN *join,SQL_SELECT *
}
}
}
- used_tables=((select->const_tables=join->const_table_map) |
- OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
+
+ /*
+ Step #2: Extract WHERE/ON parts
+ */
+ table_map save_used_tables= 0;
+ used_tables= join->const_table_map | OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
+ JOIN_TAB *tab;
+ table_map current_map;
for (uint i=join->const_tables ; i < join->tables ; i++)
{
- JOIN_TAB *tab=join->join_tab+i;
+ tab= join->join_tab+i;
/*
first_inner is the X in queries like:
SELECT * FROM t1 LEFT OUTER JOIN (t2 JOIN t3) ON X
*/
JOIN_TAB *first_inner_tab= tab->first_inner;
- table_map current_map= tab->table->map;
+ current_map= tab->table->map;
bool use_quick_range=0;
COND *tmp;
+ /*
+ Tables that are within SJ-Materialization nests cannot have their
+ conditions referring to preceding non-const tables.
+ - If we're looking at the first SJM table, reset used_tables
+ to refer to only allowed tables
+ */
+ if (tab->emb_sj_nest && tab->emb_sj_nest->sj_mat_info &&
+ tab->emb_sj_nest->sj_mat_info->is_used &&
+ !(used_tables & tab->emb_sj_nest->sj_inner_tables))
+ {
+ save_used_tables= used_tables;
+ used_tables= join->const_table_map | OUTER_REF_TABLE_BIT |
+ RAND_TABLE_BIT;
+ }
+
/*
Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
@@ -7717,11 +8660,10 @@ make_join_select(JOIN *join,SQL_SELECT *
tab->type == JT_EQ_REF || first_inner_tab)
{
DBUG_EXECUTE("where",print_where(tmp,tab->table->alias, QT_ORDINARY););
- SQL_SELECT *sel= tab->select= ((SQL_SELECT*)
- thd->memdup((uchar*) select,
- sizeof(*select)));
+ SQL_SELECT *sel= tab->select= new (thd->mem_root) SQL_SELECT;
if (!sel)
DBUG_RETURN(1); // End of memory
+ sel->read_tables= sel->const_tables= join->const_table_map;
/*
If tab is an inner table of an outer join operation,
add a match guard to the pushed down predicate.
@@ -7889,7 +8831,6 @@ make_join_select(JOIN *join,SQL_SELECT *
'on expression' are guaranteed not to be checked for
the null complemented row.
*/
-
/* First push down constant conditions from on expressions */
for (JOIN_TAB *join_tab= join->join_tab+join->const_tables;
join_tab < join->join_tab+join->tables ; join_tab++)
@@ -7975,6 +8916,33 @@ make_join_select(JOIN *join,SQL_SELECT *
}
first_inner_tab= first_inner_tab->first_upper;
}
+
+ if (save_used_tables && !(used_tables &
+ ~(tab->emb_sj_nest->sj_inner_tables |
+ join->const_table_map | PSEUDO_TABLE_BITS)))
+ {
+ /*
+ We have reached the end of semi join nest. That is, the join order
+ looks like this:
+
+ outer_tbl1 SJ-Materialize(inner_tbl1 ... inner_tblN) outer_tbl ...
+ ^
+ \-we're here
+ At this point, we need to produce two conditions
+ - A condition that can be checked when we have all of the sj-inner
+ tables (inner_tbl1 ... inner_tblN). This will be used while doing
+ materialization.
+ - A condition that can be checked when we have all of the tables
+ in the prefix (both inner and outer).
+ */
+ tab->emb_sj_nest->sj_mat_info->join_cond=
+ cond ?
+ make_cond_after_sjm(cond, cond, save_used_tables, used_tables):
+ NULL;
+ used_tables= save_used_tables | used_tables;
+ save_used_tables= 0;
+ }
+
}
}
DBUG_RETURN(0);
@@ -8305,16 +9273,29 @@ static void push_index_cond(JOIN_TAB *ta
- /*
- Determine if the set is already ordered for ORDER BY, so it can
- disable join cache because it will change the ordering of the results.
- Code handles sort table that is at any location (not only first after
- the const tables) despite the fact that it's currently prohibited.
- We must disable join cache if the first non-const table alone is
- ordered. If there is a temp table the ordering is done as a last
- operation and doesn't prevent join cache usage.
- */
-uint make_join_orderinfo(JOIN *join)
+/*
+ Determine {after which table we'll produce ordered set}
+
+ SYNOPSIS
+ make_join_orderinfo()
+ join
+
+
+ DESCRIPTION
+ Determine if the set is already ordered for ORDER BY, so it can
+ disable join cache because it will change the ordering of the results.
+ Code handles sort table that is at any location (not only first after
+ the const tables) despite the fact that it's currently prohibited.
+ We must disable join cache if the first non-const table alone is
+ ordered. If there is a temp table the ordering is done as a last
+ operation and doesn't prevent join cache usage.
+
+ RETURN
+ Number of table after which the set will be ordered
+ join->tables if we don't need an ordered set
+*/
+
+static uint make_join_orderinfo(JOIN *join)
{
uint i;
if (join->need_tmp)
@@ -8334,7 +9315,6 @@ uint make_join_orderinfo(JOIN *join)
return i-1;
}
-
/*
Deny usage of join buffer for the specified table
@@ -8362,6 +9342,10 @@ void set_join_cache_denial(JOIN_TAB *joi
if (join_tab->use_join_cache)
{
join_tab->use_join_cache= FALSE;
+ /*
+ It could be only sub_select(). It could not be sub_seject_sjm because we
+ don't do join buffering for the first table in sjm nest.
+ */
join_tab[-1].next_select= sub_select;
}
}
@@ -8389,30 +9373,352 @@ void revise_cache_usage(JOIN_TAB *join_t
JOIN_TAB *tab;
JOIN_TAB *first_inner;
- if (join_tab->first_inner)
+ if (join_tab->first_inner)
+ {
+ JOIN_TAB *end_tab= join_tab;
+ for (first_inner= join_tab->first_inner;
+ first_inner;
+ first_inner= first_inner->first_upper)
+ {
+ for (tab= end_tab-1; tab >= first_inner; tab--)
+ set_join_cache_denial(tab);
+ end_tab= first_inner;
+ }
+ }
+ else if (join_tab->first_sj_inner_tab)
+ {
+ first_inner= join_tab->first_sj_inner_tab;
+ for (tab= join_tab-1; tab >= first_inner; tab--)
+ {
+ if (tab->first_sj_inner_tab == first_inner)
+ set_join_cache_denial(tab);
+ }
+ }
+ else set_join_cache_denial(join_tab);
+}
+
+/*
+ end_select-compatible function that writes the record into a sjm temptable
+
+ SYNOPSIS
+ end_sj_materialize()
+ join The join
+ join_tab Last join table
+ end_of_records FALSE <=> This call is made to pass another record
+ combination
+ TRUE <=> EOF (no action)
+
+ DESCRIPTION
+ This function is used by semi-join materialization to capture suquery's
+ resultset and write it into the temptable (that is, materialize it).
+
+ NOTE
+ This function is used only for semi-join materialization. Non-semijoin
+ materialization uses different mechanism.
+
+ RETURN
+