summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Hansson <martin.hansson@sun.com>2009-11-20 13:29:43 +0100
committerMartin Hansson <martin.hansson@sun.com>2009-11-20 13:29:43 +0100
commitca595821498d6a547fa1780df86cdf127b0019b3 (patch)
treefabb9c5fa11cdf96ecdc1297561875b1a58090ed
parentb4a3083dc8b8049e64692ffc8e6e527914fb93da (diff)
parent4205c622e1a741bae1b2d8d213342f8e0bdd936a (diff)
downloadmariadb-git-ca595821498d6a547fa1780df86cdf127b0019b3.tar.gz
merge of Bug#33204 (backport)
-rw-r--r--.bzr-mysql/default.conf2
-rw-r--r--.bzrignore3
-rwxr-xr-xBUILD/build_mccge.sh14
-rwxr-xr-xCMakeLists.txt1
-rw-r--r--Makefile.am13
-rw-r--r--client/mysql.cc32
-rw-r--r--client/mysql_upgrade.c3
-rw-r--r--client/mysqladmin.cc3
-rw-r--r--client/mysqlbinlog.cc17
-rw-r--r--client/mysqlcheck.c5
-rw-r--r--client/mysqldump.c15
-rw-r--r--client/mysqlimport.c3
-rw-r--r--client/mysqlshow.c4
-rw-r--r--client/mysqlslap.c6
-rw-r--r--client/mysqltest.cc130
-rw-r--r--configure.in37
-rw-r--r--dbug/.cvsignore3
-rw-r--r--dbug/Makefile.am15
-rw-r--r--dbug/dbug.c888
-rwxr-xr-xdbug/dbug_add_tags.pl4
-rw-r--r--dbug/doinstall.sh15
-rw-r--r--dbug/install.sh64
-rw-r--r--dbug/mklintlib.sh30
-rw-r--r--dbug/qmake.cmd4
-rwxr-xr-xdbug/remove_function_from_trace.pl26
-rwxr-xr-xdbug/tests-t.pl496
-rw-r--r--dbug/tests.c87
-rw-r--r--dbug/user.r54
-rw-r--r--dbug/vargs.h139
-rw-r--r--extra/my_print_defaults.c3
-rw-r--r--extra/yassl/taocrypt/src/random.cpp1
-rw-r--r--include/Makefile.am5
-rw-r--r--include/config-win.h1
-rw-r--r--include/errmsg.h3
-rw-r--r--include/hash.h34
-rw-r--r--include/m_string.h10
-rw-r--r--include/my_base.h12
-rw-r--r--include/my_dbug.h187
-rw-r--r--include/my_global.h4
-rw-r--r--include/my_pthread.h1
-rw-r--r--include/my_sys.h4
-rw-r--r--include/myisam.h4
-rw-r--r--include/mysql.h138
-rw-r--r--include/mysql.h.pp93
-rw-r--r--include/mysql/plugin.h129
-rw-r--r--include/mysql/plugin.h.pp55
-rw-r--r--include/mysql/service_my_snprintf.h98
-rw-r--r--include/mysql/service_thd_alloc.h128
-rw-r--r--include/mysql/services.h30
-rw-r--r--include/mysql_com.h26
-rw-r--r--include/service_versions.h24
-rwxr-xr-xlibmysql/CMakeLists.txt2
-rw-r--r--libmysql/Makefile.shared2
-rw-r--r--libmysql/client_settings.h10
-rw-r--r--libmysql/errmsg.c3
-rw-r--r--libmysql/libmysql.c534
-rw-r--r--libmysql/libmysql.def10
-rw-r--r--libmysql/manager.c269
-rw-r--r--libmysqld/lib_sql.cc15
-rw-r--r--libmysqld/libmysqld.c21
-rw-r--r--libmysqld/libmysqld.def5
-rw-r--r--libservices/CMakeLists.txt20
-rw-r--r--libservices/HOWTO100
-rw-r--r--libservices/Makefile.am19
-rw-r--r--libservices/my_snprintf_service.c17
-rw-r--r--libservices/thd_alloc_service.c17
-rw-r--r--mysql-test/collections/default.experimental5
-rw-r--r--mysql-test/extra/binlog_tests/drop_temp_table.test10
-rw-r--r--mysql-test/extra/rpl_tests/rpl_loaddata.test61
-rw-r--r--mysql-test/extra/rpl_tests/rpl_stm_000001.test2
-rw-r--r--mysql-test/include/bug38347.inc21
-rw-r--r--mysql-test/include/have_case_insensitive_fs.inc4
-rw-r--r--mysql-test/include/have_community_features.inc4
-rw-r--r--mysql-test/include/have_profiling.inc4
-rw-r--r--mysql-test/include/query_cache_sql_prepare.inc37
-rwxr-xr-xmysql-test/lib/My/SafeProcess/safe_process_win.cc3
-rw-r--r--mysql-test/r/alter_table.result16
-rw-r--r--mysql-test/r/analyse.result112
-rw-r--r--mysql-test/r/bug40113.result29
-rw-r--r--mysql-test/r/case_insensitive_fs.require2
-rw-r--r--mysql-test/r/create.result34
-rw-r--r--mysql-test/r/ctype_collate.result30
-rw-r--r--mysql-test/r/ctype_ldml.result8
-rw-r--r--mysql-test/r/delayed.result22
-rw-r--r--mysql-test/r/drop.result14
-rw-r--r--mysql-test/r/drop_debug.result21
-rw-r--r--mysql-test/r/events_bugs.result14
-rw-r--r--mysql-test/r/explain.result16
-rw-r--r--mysql-test/r/func_math.result3
-rw-r--r--mysql-test/r/func_str.result3
-rw-r--r--mysql-test/r/gis-rtree.result39
-rw-r--r--mysql-test/r/gis.result12
-rw-r--r--mysql-test/r/grant.result731
-rw-r--r--mysql-test/r/grant2.result2
-rw-r--r--mysql-test/r/grant3.result38
-rw-r--r--mysql-test/r/grant4.result123
-rw-r--r--mysql-test/r/grant_lowercase_fs.result16
-rw-r--r--mysql-test/r/have_community_features.require2
-rw-r--r--mysql-test/r/have_profiling.require2
-rw-r--r--mysql-test/r/information_schema.result3
-rw-r--r--mysql-test/r/information_schema_db.result14
-rw-r--r--mysql-test/r/innodb-autoinc.result243
-rw-r--r--mysql-test/r/innodb_bug46000.result18
-rw-r--r--mysql-test/r/innodb_bug47777.result13
-rw-r--r--mysql-test/r/innodb_lock_wait_timeout_1.result357
-rw-r--r--mysql-test/r/innodb_mysql.result62
-rw-r--r--mysql-test/r/insert.result40
-rw-r--r--mysql-test/r/join.result54
-rw-r--r--mysql-test/r/loadxml.result6
-rw-r--r--mysql-test/r/locale.result43
-rw-r--r--mysql-test/r/log_state.result24
-rw-r--r--mysql-test/r/log_state_bug33693.result3
-rw-r--r--mysql-test/r/lowercase_fs_off.result45
-rw-r--r--mysql-test/r/lowercase_table2.result71
-rw-r--r--mysql-test/r/merge.result36
-rw-r--r--mysql-test/r/myisam.result6
-rw-r--r--mysql-test/r/myisam_crash_before_flush_keys.result28
-rw-r--r--mysql-test/r/mysqlbinlog_row.result2
-rw-r--r--mysql-test/r/mysqlbinlog_row_innodb.result8
-rw-r--r--mysql-test/r/mysqlbinlog_row_myisam.result8
-rw-r--r--mysql-test/r/mysqlbinlog_row_trans.result2
-rw-r--r--mysql-test/r/mysqldump.result10
-rw-r--r--mysql-test/r/olap.result20
-rw-r--r--mysql-test/r/outfile.resultbin2149 -> 2137 bytes
-rw-r--r--mysql-test/r/partition.result8
-rw-r--r--mysql-test/r/partition_column.result568
-rw-r--r--mysql-test/r/partition_column_prune.result66
-rw-r--r--mysql-test/r/partition_datatype.result8
-rw-r--r--mysql-test/r/partition_error.result13
-rw-r--r--mysql-test/r/partition_innodb.result35
-rw-r--r--mysql-test/r/partition_list.result11
-rw-r--r--mysql-test/r/partition_mgm_err.result2
-rw-r--r--mysql-test/r/partition_pruning.result332
-rw-r--r--mysql-test/r/partition_range.result93
-rw-r--r--mysql-test/r/partition_utf8.result53
-rw-r--r--mysql-test/r/plugin.result9
-rw-r--r--mysql-test/r/profiling.result7
-rw-r--r--mysql-test/r/ps.result167
-rw-r--r--mysql-test/r/ps_1general.result3
-rw-r--r--mysql-test/r/ps_grant.result6
-rw-r--r--mysql-test/r/query_cache.result2
-rw-r--r--mysql-test/r/query_cache_disabled.result14
-rw-r--r--mysql-test/r/query_cache_ps_no_prot.result41
-rw-r--r--mysql-test/r/query_cache_ps_ps_prot.result41
-rw-r--r--mysql-test/r/range.result206
-rw-r--r--mysql-test/r/select.result41
-rw-r--r--mysql-test/r/show_check.result4
-rw-r--r--mysql-test/r/sp-bugs.result47
-rw-r--r--mysql-test/r/sp-error.result16
-rw-r--r--mysql-test/r/sp-vars.result27
-rw-r--r--mysql-test/r/sp.result32
-rw-r--r--mysql-test/r/sp_trans.result27
-rw-r--r--mysql-test/r/sql_mode.result6
-rw-r--r--mysql-test/r/strict.result2
-rw-r--r--mysql-test/r/subselect.result19
-rw-r--r--mysql-test/r/subselect3.result69
-rw-r--r--mysql-test/r/system_mysql_db.result5
-rw-r--r--mysql-test/r/trigger.result27
-rw-r--r--mysql-test/r/type_decimal.result14
-rw-r--r--mysql-test/r/type_newdecimal.result220
-rw-r--r--mysql-test/r/type_varchar.result20
-rw-r--r--mysql-test/r/update.result11
-rw-r--r--mysql-test/r/view_grant.result27
-rw-r--r--mysql-test/r/xa.result25
-rw-r--r--mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result50
-rw-r--r--mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result1
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_do_db.result42
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result1
-rw-r--r--mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test114
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_do_db.test90
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_func_view.result24
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_storedproc_07.result16
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_trig_03.result10
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_trig_03e.result4
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_views.result20
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_is.result8
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql.result27
-rw-r--r--mysql-test/suite/funcs_1/r/is_routines.result6
-rw-r--r--mysql-test/suite/funcs_1/r/is_statistics.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_user_privileges.result88
-rw-r--r--mysql-test/suite/funcs_1/r/memory_func_view.result24
-rw-r--r--mysql-test/suite/funcs_1/r/memory_storedproc_07.result16
-rw-r--r--mysql-test/suite/funcs_1/r/memory_trig_03.result10
-rw-r--r--mysql-test/suite/funcs_1/r/memory_trig_03e.result4
-rw-r--r--mysql-test/suite/funcs_1/r/memory_views.result20
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_func_view.result24
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_storedproc_07.result16
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_trig_03.result10
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_trig_03e.result4
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_views.result20
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_func_view.result24
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_storedproc_07.result16
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_trig_03.result10
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_trig_03e.result4
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_views.result20
-rw-r--r--mysql-test/suite/funcs_1/r/storedproc.result15
-rw-r--r--mysql-test/suite/innodb/r/innodb-zip.result72
-rw-r--r--mysql-test/suite/innodb/t/disabled.def1
-rw-r--r--mysql-test/suite/innodb/t/innodb-analyze.test4
-rw-r--r--mysql-test/suite/innodb/t/innodb-zip.test46
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug36169.test7
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug36172.test10
-rw-r--r--mysql-test/suite/innodb/t/innodb_information_schema.test16
-rw-r--r--mysql-test/suite/ndb/r/ndb_dd_ddl.result76
-rw-r--r--mysql-test/suite/ndb/t/ndb_dd_ddl.test101
-rw-r--r--mysql-test/suite/parts/inc/partition_key_32col.inc2
-rw-r--r--mysql-test/suite/parts/inc/partition_syntax.inc4
-rw-r--r--mysql-test/suite/parts/r/partition_special_innodb.result2
-rw-r--r--mysql-test/suite/parts/r/partition_special_myisam.result2
-rw-r--r--mysql-test/suite/parts/r/partition_syntax_innodb.result6
-rw-r--r--mysql-test/suite/parts/r/partition_syntax_myisam.result6
-rw-r--r--mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_loaddata.result29
-rw-r--r--mysql-test/suite/rpl/r/rpl_udf.result8
-rw-r--r--mysql-test/suite/rpl/t/rpl_err_ignoredtable.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test3
-rw-r--r--mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test2
-rw-r--r--mysql-test/suite/sys_vars/r/auto_commit_basic.result12
-rw-r--r--mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/big_tables_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/r/flush_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/general_log_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_checksums_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_doublewrite_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_locks_unsafe_for_binlog_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_rollback_on_timeout_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/r/local_infile_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/log_queries_not_using_indexes_basic.result3
-rw-r--r--mysql-test/suite/sys_vars/r/low_priority_updates_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/r/myisam_use_mmap_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/new_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/r/old_passwords_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/r/read_only_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/r/relay_log_purge_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/secure_auth_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/slave_allow_batching_basic.result3
-rw-r--r--mysql-test/suite/sys_vars/r/slave_compressed_protocol_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/slow_query_log_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_auto_is_null_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/sql_big_selects_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_big_tables_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_log_bin_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_log_off_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result10
-rw-r--r--mysql-test/suite/sys_vars/r/sql_notes_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_warnings_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sync_frm_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/timed_mutexes_basic.result6
-rw-r--r--mysql-test/suite/sys_vars/r/unique_checks_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/t/auto_commit_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/big_tables_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/engine_condition_pushdown_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/flush_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/general_log_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_checksums_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_doublewrite_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_locks_unsafe_for_binlog_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_rollback_on_timeout_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/local_infile_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/log_queries_not_using_indexes_basic.test1
-rw-r--r--mysql-test/suite/sys_vars/t/low_priority_updates_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/myisam_use_mmap_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/new_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/old_passwords_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/read_only_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/relay_log_purge_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/secure_auth_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/slave_allow_batching_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/slave_compressed_protocol_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/slow_query_log_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_auto_is_null_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_big_selects_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_big_tables_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_log_bin_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_log_off_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_low_priority_updates_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/sql_notes_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sql_warnings_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/sync_frm_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/timed_mutexes_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/unique_checks_basic.test2
-rw-r--r--mysql-test/t/alter_table.test30
-rw-r--r--mysql-test/t/analyse.test70
-rw-r--r--mysql-test/t/bug40113.test46
-rw-r--r--mysql-test/t/create.test53
-rw-r--r--mysql-test/t/ctype_collate.test12
-rw-r--r--mysql-test/t/ctype_ldml.test8
-rw-r--r--mysql-test/t/ctype_utf8.test35
-rw-r--r--mysql-test/t/delayed.test35
-rw-r--r--mysql-test/t/disabled.def4
-rw-r--r--mysql-test/t/drop.test21
-rw-r--r--mysql-test/t/drop_debug.test35
-rw-r--r--mysql-test/t/explain.test20
-rw-r--r--mysql-test/t/flush_read_lock_kill.test2
-rw-r--r--mysql-test/t/gis-rtree.test21
-rw-r--r--mysql-test/t/gis.test16
-rw-r--r--mysql-test/t/grant.test352
-rw-r--r--mysql-test/t/grant3.test35
-rw-r--r--mysql-test/t/grant4.test146
-rw-r--r--mysql-test/t/grant_lowercase_fs.test30
-rw-r--r--mysql-test/t/information_schema_db.test12
-rw-r--r--mysql-test/t/innodb-autoinc.test120
-rw-r--r--mysql-test/t/innodb.test1
-rw-r--r--mysql-test/t/innodb_bug39438.test4
-rw-r--r--mysql-test/t/innodb_bug44369.test6
-rw-r--r--mysql-test/t/innodb_bug46000.test12
-rw-r--r--mysql-test/t/innodb_bug47777.test24
-rw-r--r--mysql-test/t/innodb_lock_wait_timeout_1-master.opt (renamed from mysql-test/t/bug40113-master.opt)0
-rw-r--r--mysql-test/t/innodb_lock_wait_timeout_1.test230
-rw-r--r--mysql-test/t/innodb_mysql.test47
-rw-r--r--mysql-test/t/insert.test30
-rw-r--r--mysql-test/t/join.test54
-rw-r--r--mysql-test/t/kill.test2
-rw-r--r--mysql-test/t/loadxml.test7
-rw-r--r--mysql-test/t/locale.test23
-rw-r--r--mysql-test/t/log_state.test97
-rw-r--r--mysql-test/t/log_state_bug33693-master.opt1
-rw-r--r--mysql-test/t/log_state_bug33693.test18
-rw-r--r--mysql-test/t/lowercase_fs_off.test62
-rw-r--r--mysql-test/t/lowercase_table2.test72
-rw-r--r--mysql-test/t/merge.test60
-rw-r--r--mysql-test/t/myisam.test12
-rw-r--r--mysql-test/t/myisam_crash_before_flush_keys.test12
-rw-r--r--mysql-test/t/olap.test15
-rw-r--r--mysql-test/t/outfile.test2
-rw-r--r--mysql-test/t/partition.test6
-rw-r--r--mysql-test/t/partition_column.test411
-rw-r--r--mysql-test/t/partition_column_prune.test71
-rw-r--r--mysql-test/t/partition_datatype.test9
-rw-r--r--mysql-test/t/partition_error.test16
-rw-r--r--mysql-test/t/partition_innodb.test45
-rw-r--r--mysql-test/t/partition_list.test2
-rw-r--r--mysql-test/t/partition_mgm_err.test2
-rw-r--r--mysql-test/t/partition_pruning.test20
-rw-r--r--mysql-test/t/partition_range.test72
-rw-r--r--mysql-test/t/partition_utf8.test42
-rw-r--r--mysql-test/t/plugin.test6
-rw-r--r--mysql-test/t/profiling.test2
-rw-r--r--mysql-test/t/ps.test204
-rw-r--r--mysql-test/t/query_cache.test3
-rw-r--r--mysql-test/t/query_cache_disabled-master.opt1
-rw-r--r--mysql-test/t/query_cache_disabled.test15
-rw-r--r--mysql-test/t/range.test90
-rw-r--r--mysql-test/t/select.test33
-rw-r--r--mysql-test/t/sp-bugs.test61
-rw-r--r--mysql-test/t/sp-error.test24
-rw-r--r--mysql-test/t/sp-vars.test39
-rw-r--r--mysql-test/t/sp.test50
-rw-r--r--mysql-test/t/sp_trans.test38
-rw-r--r--mysql-test/t/sql_mode.test15
-rw-r--r--mysql-test/t/subselect.test16
-rw-r--r--mysql-test/t/subselect3.test66
-rw-r--r--mysql-test/t/trigger.test28
-rw-r--r--mysql-test/t/type_decimal.test10
-rw-r--r--mysql-test/t/type_newdecimal.test134
-rw-r--r--mysql-test/t/type_varchar.test18
-rw-r--r--mysql-test/t/update.test15
-rw-r--r--mysql-test/t/variables+c.test2
-rw-r--r--mysql-test/t/view_grant.test34
-rw-r--r--mysql-test/t/xa.test62
-rw-r--r--mysys/default.c14
-rw-r--r--mysys/mf_keycaches.c16
-rw-r--r--mysys/my_error.c23
-rw-r--r--mysys/my_getopt.c4
-rw-r--r--mysys/my_largepage.c2
-rw-r--r--mysys/my_thr_init.c9
-rw-r--r--mysys/typelib.c5
-rw-r--r--plugin/daemon_example/Makefile.am3
-rw-r--r--scripts/mysql_system_tables.sql6
-rw-r--r--scripts/mysql_system_tables_data.sql6
-rw-r--r--scripts/mysql_system_tables_fix.sql19
-rw-r--r--scripts/mysqld_safe.sh8
-rw-r--r--sql-common/client.c264
-rwxr-xr-xsql/CMakeLists.txt2
-rw-r--r--sql/Makefile.am6
-rw-r--r--sql/debug_sync.cc8
-rw-r--r--sql/event_data_objects.cc2
-rw-r--r--sql/event_scheduler.cc6
-rw-r--r--sql/events.cc13
-rw-r--r--sql/field.cc229
-rw-r--r--sql/field.h53
-rw-r--r--sql/ha_ndbcluster.cc131
-rw-r--r--sql/ha_ndbcluster_binlog.cc65
-rw-r--r--sql/ha_partition.cc171
-rw-r--r--sql/ha_partition.h12
-rw-r--r--sql/handler.cc15
-rw-r--r--sql/handler.h13
-rw-r--r--sql/hash_filo.h16
-rw-r--r--sql/hostname.cc2
-rw-r--r--sql/item.cc256
-rw-r--r--sql/item.h35
-rw-r--r--sql/item_cmpfunc.cc202
-rw-r--r--sql/item_cmpfunc.h3
-rw-r--r--sql/item_create.cc48
-rw-r--r--sql/item_func.cc92
-rw-r--r--sql/item_func.h1
-rw-r--r--sql/item_geofunc.cc9
-rw-r--r--sql/item_subselect.cc18
-rw-r--r--sql/item_sum.cc21
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/item_timefunc.cc53
-rw-r--r--sql/item_timefunc.h18
-rw-r--r--sql/lock.cc18
-rw-r--r--sql/log.cc38
-rw-r--r--sql/log_event.cc46
-rw-r--r--sql/log_event_old.cc2
-rw-r--r--sql/my_decimal.h14
-rw-r--r--sql/mysql_priv.h62
-rw-r--r--sql/mysqld.cc57
-rw-r--r--sql/net_serv.cc14
-rw-r--r--sql/opt_range.cc382
-rw-r--r--sql/partition_element.h38
-rw-r--r--sql/partition_info.cc1200
-rw-r--r--sql/partition_info.h82
-rw-r--r--sql/procedure.h2
-rw-r--r--sql/protocol.cc318
-rw-r--r--sql/protocol.h36
-rw-r--r--sql/records.cc28
-rw-r--r--sql/records.h79
-rw-r--r--sql/repl_failsafe.cc25
-rw-r--r--sql/replication.h60
-rw-r--r--sql/rpl_filter.cc12
-rw-r--r--sql/rpl_handler.cc6
-rw-r--r--sql/rpl_injector.h3
-rw-r--r--sql/rpl_tblmap.cc14
-rw-r--r--sql/rpl_tblmap.h9
-rw-r--r--sql/set_var.cc98
-rw-r--r--sql/set_var.h14
-rw-r--r--sql/share/errmsg-utf8.txt21
-rw-r--r--sql/share/errmsg.txt18
-rw-r--r--sql/slave.cc10
-rw-r--r--sql/sp.cc20
-rw-r--r--sql/sp_cache.cc11
-rw-r--r--sql/sp_head.cc107
-rw-r--r--sql/sql_acl.cc384
-rw-r--r--sql/sql_acl.h16
-rw-r--r--sql/sql_base.cc138
-rw-r--r--sql/sql_cache.cc287
-rw-r--r--sql/sql_cache.h32
-rw-r--r--sql/sql_class.cc202
-rw-r--r--sql/sql_class.h143
-rw-r--r--sql/sql_connect.cc44
-rw-r--r--sql/sql_cursor.cc32
-rw-r--r--sql/sql_db.cc73
-rw-r--r--sql/sql_delete.cc8
-rw-r--r--sql/sql_error.cc2
-rw-r--r--sql/sql_handler.cc57
-rw-r--r--sql/sql_help.cc6
-rw-r--r--sql/sql_insert.cc30
-rw-r--r--sql/sql_lex.cc68
-rw-r--r--sql/sql_lex.h39
-rw-r--r--sql/sql_list.cc2
-rw-r--r--sql/sql_list.h6
-rw-r--r--sql/sql_load.cc39
-rw-r--r--sql/sql_locale.cc75
-rw-r--r--sql/sql_parse.cc563
-rw-r--r--sql/sql_partition.cc2164
-rw-r--r--sql/sql_partition.h37
-rw-r--r--sql/sql_plugin.cc160
-rw-r--r--sql/sql_plugin.h10
-rw-r--r--sql/sql_plugin_services.h44
-rw-r--r--sql/sql_prepare.cc868
-rw-r--r--sql/sql_prepare.h367
-rw-r--r--sql/sql_profile.cc6
-rw-r--r--sql/sql_profile.h2
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc8
-rw-r--r--sql/sql_select.cc334
-rw-r--r--sql/sql_select.h19
-rw-r--r--sql/sql_servers.cc36
-rw-r--r--sql/sql_show.cc342
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sql_table.cc209
-rw-r--r--sql/sql_tablespace.cc2
-rw-r--r--sql/sql_test.cc4
-rw-r--r--sql/sql_trigger.cc6
-rw-r--r--sql/sql_udf.cc33
-rw-r--r--sql/sql_update.cc16
-rw-r--r--sql/sql_view.cc15
-rw-r--r--sql/sql_yacc.yy429
-rw-r--r--sql/structs.h29
-rw-r--r--sql/table.cc65
-rw-r--r--sql/table.h36
-rw-r--r--sql/time.cc16
-rw-r--r--sql/tztime.cc28
-rw-r--r--storage/archive/archive_reader.c3
-rw-r--r--storage/archive/ha_archive.cc14
-rw-r--r--storage/blackhole/ha_blackhole.cc27
-rw-r--r--storage/csv/ha_tina.cc26
-rw-r--r--storage/csv/ha_tina.h1
-rw-r--r--storage/example/Makefile.am23
-rw-r--r--storage/example/ha_example.cc36
-rw-r--r--storage/federated/ha_federated.cc18
-rw-r--r--storage/innobase/ChangeLog90
-rw-r--r--storage/innobase/buf/buf0buf.c5
-rw-r--r--storage/innobase/buf/buf0flu.c42
-rw-r--r--storage/innobase/buf/buf0lru.c69
-rw-r--r--storage/innobase/fil/fil0fil.c3
-rw-r--r--storage/innobase/handler/ha_innodb.cc118
-rw-r--r--storage/innobase/handler/ha_innodb.h25
-rw-r--r--storage/innobase/handler/handler0alter.cc12
-rw-r--r--storage/innobase/include/buf0buf.h5
-rw-r--r--storage/innobase/include/buf0buf.ic17
-rw-r--r--storage/innobase/include/handler0alter.h4
-rw-r--r--storage/innobase/include/page0page.ic2
-rw-r--r--storage/innobase/include/row0merge.h2
-rw-r--r--storage/innobase/include/row0mysql.h2
-rw-r--r--storage/innobase/include/row0types.h2
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/os/os0file.c17
-rw-r--r--storage/innobase/os/os0proc.c1
-rw-r--r--storage/innobase/row/row0ins.c6
-rw-r--r--storage/innobase/row/row0merge.c12
-rw-r--r--storage/innobase/row/row0mysql.c2
-rw-r--r--storage/innobase/srv/srv0start.c2
-rw-r--r--storage/myisam/ha_myisam.cc12
-rw-r--r--storage/myisam/mi_check.c7
-rw-r--r--storage/myisam/mi_dynrec.c7
-rw-r--r--storage/myisam/myisamchk.c4
-rw-r--r--storage/myisam/myisampack.c4
-rw-r--r--storage/myisam/sort.c7
-rw-r--r--storage/mysql_storage_engine.cmake2
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp2
-rw-r--r--strings/ctype-uca.c3
-rw-r--r--strings/my_vsnprintf.c62
-rw-r--r--tests/mysql_client_test.c812
-rw-r--r--tests/thread_test.c5
-rw-r--r--unittest/mysys/Makefile.am2
-rw-r--r--unittest/mysys/my_vsnprintf-t.c155
-rw-r--r--vio/viosslfactories.c61
552 files changed, 20766 insertions, 7312 deletions
diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf
index 278fc8fdb7f..5df64e1b26c 100644
--- a/.bzr-mysql/default.conf
+++ b/.bzr-mysql/default.conf
@@ -1,4 +1,4 @@
[MYSQL]
post_commit_to = "commits@lists.mysql.com"
post_push_to = "commits@lists.mysql.com"
-tree_name = "mysql-5.5-next-mr-bugfixing"
+tree_name = "mysql-5.6-next-mr-bugfixing"
diff --git a/.bzrignore b/.bzrignore
index 3b216cf1cea..351417a4353 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -3066,4 +3066,7 @@ sql/share/swedish
sql/share/ukrainian
libmysqld/examples/mysqltest.cc
libmysqld/sql_signal.cc
+libmysqld/rpl_handler.cc
libmysqld/debug_sync.cc
+libmysqld/rpl_handler.cc
+dbug/tests
diff --git a/BUILD/build_mccge.sh b/BUILD/build_mccge.sh
index 379ca1b2c68..3345ac3dcb5 100755
--- a/BUILD/build_mccge.sh
+++ b/BUILD/build_mccge.sh
@@ -1274,7 +1274,7 @@ set_bsd_configs()
if test "x$fast_flag" != "xno" ; then
compiler_flags="$compiler_flags -O3"
else
- compiler_flags="$compiler_flags -O"
+ compiler_flags="$compiler_flags -O0"
fi
set_cc_and_cxx_for_gcc
}
@@ -1305,7 +1305,7 @@ set_linux_configs()
if test "x$fast_flag" != "xno" ; then
compiler_flags="$compiler_flags -O2"
else
- compiler_flags="$compiler_flags -O"
+ compiler_flags="$compiler_flags -O0"
fi
# configure will set proper compiler flags for gcc on Linux
elif test "x$compiler" = "xicc" ; then
@@ -1375,8 +1375,8 @@ set_solaris_configs()
LDFLAGS="$LDFLAGS -O2"
compiler_flags="$compiler_flags -O2"
else
- LDFLAGS="$LDFLAGS -O"
- compiler_flags="$compiler_flags -O"
+ LDFLAGS="$LDFLAGS -O0"
+ compiler_flags="$compiler_flags -O0"
fi
fi
else
@@ -1407,7 +1407,7 @@ set_solaris_configs()
elif test "x$fast_flag" = "xgeneric" ; then
compiler_flags="$compiler_flags -xO2"
else
- compiler_flags="$compiler_flags -xO"
+ compiler_flags="$compiler_flags -xO0"
fi
else
#Using SPARC cpu with SunStudio (Forte) compiler
@@ -1421,7 +1421,7 @@ set_solaris_configs()
elif test "x$fast_flag" = "xgeneric" ; then
compiler_flags="$compiler_flags -xO2"
else
- compiler_flags="$compiler_flags -xO"
+ compiler_flags="$compiler_flags -xO0"
fi
fi
fi
@@ -1452,7 +1452,7 @@ set_macosx_configs()
if test "x$fast_flag" != "xno" ; then
compiler_flags="$compiler_flags -Os"
else
- compiler_flags="$compiler_flags -O"
+ compiler_flags="$compiler_flags -O0"
fi
set_cc_and_cxx_for_gcc
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c6769eca72d..6e53ff30159 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -311,6 +311,7 @@ ADD_SUBDIRECTORY(extra)
ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(sql)
ADD_SUBDIRECTORY(libmysql)
+ADD_SUBDIRECTORY(libservices)
ADD_SUBDIRECTORY(tests)
IF(WITH_EMBEDDED_SERVER)
ADD_SUBDIRECTORY(libmysqld)
diff --git a/Makefile.am b/Makefile.am
index 53be49768de..c208b5b6df1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,7 +23,7 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
@readline_topdir@ sql-common scripts \
- @pstack_dir@ \
+ @pstack_dir@ libservices \
@sql_union_dirs@ unittest \
@sql_server@ @man_dirs@ tests \
netware @libmysqld_dirs@ \
@@ -32,7 +32,7 @@ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
DIST_SUBDIRS = . include Docs zlib \
cmd-line-utils sql-common scripts \
- pstack \
+ pstack libservices \
strings mysys dbug extra regex libmysql libmysql_r client unittest storage plugin \
vio sql man tests \
netware libmysqld \
@@ -98,7 +98,8 @@ test-pr:
test-ns:
cd mysql-test ; \
- @PERL@ ./mysql-test-run.pl $(force) $(mem) --mysqld=--binlog-format=mixed
+ @PERL@ ./mysql-test-run.pl $(force) $(mem) --mysqld=--binlog-format=mixed ; \
+ @PERL@ ./mysql-test-run.pl $(force) $(mem) --suite=funcs_1
test-binlog-statement:
cd mysql-test ; \
@@ -198,6 +199,10 @@ test-bt-fast:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress $(EXP)
+test-bt-fast:
+ -cd mysql-test ; MTR_BUILD_THREAD=auto \
+ @PERL@ ./mysql-test-run.pl --force --comment=ps --ps-protocol --report-features
+
test-bt-debug:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=debug --force --timer \
@@ -205,6 +210,8 @@ test-bt-debug:
test-bt-debug-fast:
+test-bt-debug-fast:
+
# Keep these for a while
test-pl: test
test-full-pl: test-full
diff --git a/client/mysql.cc b/client/mysql.cc
index 35322d37c2b..04cca1a2615 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1114,7 +1114,11 @@ int main(int argc,char *argv[])
close(stdout_fileno_copy); /* Clean up dup(). */
}
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ {
+ my_end(0);
+ exit(1);
+ }
defaults_argv=argv;
if (get_options(argc, (char **) argv))
{
@@ -1281,21 +1285,35 @@ sig_handler handle_sigint(int sig)
MYSQL *kill_mysql= NULL;
/* terminate if no query being executed, or we already tried interrupting */
- if (!executing_query || interrupted_query)
+ /* terminate if no query being executed, or we already tried interrupting */
+ if (!executing_query || (interrupted_query == 2))
+ {
+ tee_fprintf(stdout, "Ctrl-C -- exit!\n");
goto err;
+ }
kill_mysql= mysql_init(kill_mysql);
if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
"", opt_mysql_port, opt_mysql_unix_port,0))
+ {
+ tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n");
goto err;
+ }
+
+ interrupted_query++;
+
+ /* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */
+ if ((interrupted_query == 1) && (mysql_get_server_version(&mysql) < 50000))
+ interrupted_query= 2;
/* kill_buffer is always big enough because max length of %lu is 15 */
- sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql));
- mysql_real_query(kill_mysql, kill_buffer, strlen(kill_buffer));
+ sprintf(kill_buffer, "KILL %s%lu",
+ (interrupted_query == 1) ? "QUERY " : "",
+ mysql_thread_id(&mysql));
+ tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", kill_buffer);
+ mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer));
mysql_close(kill_mysql);
- tee_fprintf(stdout, "Query aborted by Ctrl+C\n");
-
- interrupted_query= 1;
+ tee_fprintf(stdout, "Ctrl-C -- query aborted.\n");
return;
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 05eb80e5455..1a3f61559d6 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -819,7 +819,8 @@ int main(int argc, char **argv)
init_dynamic_string(&conn_args, "", 512, 256))
die("Out of memory");
- load_defaults("my", load_default_groups, &argc, &argv);
+ if (load_defaults("my", load_default_groups, &argc, &argv))
+ die(NULL);
defaults_argv= argv; /* Must be freed by 'free_defaults' */
if (handle_options(&argc, &argv, my_long_options, get_one_option))
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index a3eee14e0d1..c8cbafe72d9 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -304,7 +304,8 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
mysql_init(&mysql);
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ exit(1);
save_argv = argv; /* Save for free_defaults */
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
{
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index a9504232af2..196d355f1dc 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -995,13 +995,13 @@ static struct my_option my_long_options[] =
/* 'unspec' is not mentioned because it is just a placeholder. */
"Determine when the output statements should be base64-encoded BINLOG "
"statements: 'never' disables it and works only for binlogs without "
- "row-based events; 'auto' is the default and prints base64 only when "
- "necessary (i.e., for row-based events and format description events); "
- "'decode-rows' suppresses BINLOG statements for row events, but does "
- "not exit as an error if a row event is found, unlike 'never'; "
- "'always' prints base64 whenever possible. 'always' is for debugging "
- "only and should not be used in a production system. The default is "
- "'auto'. --base64-output is a short form for --base64-output=always."
+ "row-based events; 'decode-rows' decodes row events into commented SQL "
+ "statements if the --verbose option is also given; 'auto' prints base64 "
+ "only when necessary (i.e., for row-based events and format description "
+ "events); 'always' prints base64 whenever possible. 'always' is for "
+ "debugging only and should not be used in a production system. If this "
+ "argument is not given, the default is 'auto'; if it is given with no "
+ "argument, 'always' is used."
,(uchar**) &opt_base64_output_mode_str,
(uchar**) &opt_base64_output_mode_str,
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -2014,7 +2014,8 @@ int main(int argc, char** argv)
my_init_time(); // for time functions
- load_defaults("my", load_default_groups, &argc, &argv);
+ if (load_defaults("my", load_default_groups, &argc, &argv))
+ exit(1);
defaults_argv= argv;
parse_args(&argc, (char***)&argv);
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 1affea1d189..252ee500cf6 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -344,9 +344,8 @@ static int get_options(int *argc, char ***argv)
exit(0);
}
- load_defaults("my", load_default_groups, argc, argv);
-
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
+ if ((ho_error= load_defaults("my", load_default_groups, argc, argv)) ||
+ (ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
if (!what_to_do)
diff --git a/client/mysqldump.c b/client/mysqldump.c
index bd7c8e56fe0..54e7d68e191 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -858,12 +858,13 @@ static int get_options(int *argc, char ***argv)
opt_net_buffer_length= *mysql_params->p_net_buffer_length;
md_result_file= stdout;
- load_defaults("my",load_default_groups,argc,argv);
+ if (load_defaults("my",load_default_groups,argc,argv))
+ return 1;
defaults_argv= *argv;
- if (hash_init(&ignore_table, charset_info, 16, 0, 0,
- (hash_get_key) get_table_key,
- (hash_free_key) free_table_ent, 0))
+ if (my_hash_init(&ignore_table, charset_info, 16, 0, 0,
+ (my_hash_get_key) get_table_key,
+ (my_hash_free_key) free_table_ent, 0))
return(EX_EOM);
/* Don't copy internal log tables */
if (my_hash_insert(&ignore_table,
@@ -1367,8 +1368,8 @@ static void free_resources()
if (md_result_file && md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
- if (hash_inited(&ignore_table))
- hash_free(&ignore_table);
+ if (my_hash_inited(&ignore_table))
+ my_hash_free(&ignore_table);
if (extended_insert)
dynstr_free(&extended_row);
if (insert_pat_inited)
@@ -3958,7 +3959,7 @@ static int init_dumping(char *database, int init_func(char*))
my_bool include_table(const uchar *hash_key, size_t len)
{
- return !hash_search(&ignore_table, hash_key, len);
+ return ! my_hash_search(&ignore_table, hash_key, len);
}
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 5b8ec95c06d..867663db8be 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -592,7 +592,8 @@ int main(int argc, char **argv)
char **argv_to_free;
MY_INIT(argv[0]);
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ return 1;
/* argv is changed in the program */
argv_to_free= argv;
if (get_options(&argc, &argv))
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 206b86d07cf..588ee049546 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -63,7 +63,9 @@ int main(int argc, char **argv)
char *wild;
MYSQL mysql;
MY_INIT(argv[0]);
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ exit(1);
+
get_options(&argc,&argv);
wild=0;
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index f13b5099766..fcfd525bba7 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -299,7 +299,11 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ {
+ my_end(0);
+ exit(1);
+ }
defaults_argv=argv;
if (get_options(&argc,&argv))
{
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 53c0d9514e0..89330b0e31d 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -115,6 +115,8 @@ static uint my_end_arg= 0;
/* Number of lines of the result to include in failure report */
static uint opt_tail_lines= 0;
+static uint opt_connect_timeout= 0;
+
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1;
@@ -260,8 +262,7 @@ enum enum_commands {
Q_SEND, Q_REAP,
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
Q_PING, Q_EVAL,
- Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
- Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
+ Q_EVAL_RESULT,
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_WAIT_FOR_SLAVE_TO_STOP,
@@ -283,7 +284,7 @@ enum enum_commands {
Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE,
Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
- Q_MOVE_FILE,
+ Q_MOVE_FILE, Q_SEND_EVAL,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -320,9 +321,6 @@ const char *command_names[]=
"replace_column",
"ping",
"eval",
- "rpl_probe",
- "enable_rpl_parse",
- "disable_rpl_parse",
"eval_result",
/* Enable/disable that the _query_ is logged to result file */
"enable_query_log",
@@ -381,6 +379,7 @@ const char *command_names[]=
"send_shutdown",
"shutdown_server",
"move_file",
+ "send_eval",
0
};
@@ -662,14 +661,6 @@ public:
LogFile log_file;
LogFile progress_file;
-
-/* Disable functions that only exist in MySQL 4.0 */
-#if MYSQL_VERSION_ID < 40000
-void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
-void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
-int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
-my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
-#endif
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int len);
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
@@ -1138,7 +1129,7 @@ void free_used_memory()
close_connections();
close_files();
- hash_free(&var_hash);
+ my_hash_free(&var_hash);
for (i= 0 ; i < q_lines.elements ; i++)
{
@@ -1171,7 +1162,6 @@ void free_used_memory()
mysql_server_end();
/* Don't use DBUG after mysql_server_end() */
- DBUG_VIOLATION_HELPER_LEAVE;
return;
}
@@ -2001,8 +1991,8 @@ VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
if (length >= MAX_VAR_NAME_LENGTH)
die("Too long variable name: %s", save_var_name);
- if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
- length)))
+ if (!(v = (VAR*) my_hash_search(&var_hash, (const uchar*) save_var_name,
+ length)))
{
char buff[MAX_VAR_NAME_LENGTH+1];
strmake(buff, save_var_name, length);
@@ -2033,7 +2023,7 @@ err:
VAR *var_obtain(const char *name, int len)
{
VAR* v;
- if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
+ if ((v = (VAR*)my_hash_search(&var_hash, (const uchar *) name, len)))
return v;
v = var_init(0, name, len, "", 0);
my_hash_insert(&var_hash, (uchar*)v);
@@ -3851,12 +3841,8 @@ int do_save_master_pos()
MYSQL_ROW row;
MYSQL *mysql = &cur_con->mysql;
const char *query;
- int rpl_parse;
DBUG_ENTER("do_save_master_pos");
- rpl_parse = mysql_rpl_parse_enabled(mysql);
- mysql_disable_rpl_parse(mysql);
-
#ifdef HAVE_NDB_BINLOG
/*
Wait for ndb binlog to be up-to-date with all changes
@@ -4006,10 +3992,6 @@ int do_save_master_pos()
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
master_pos.pos = strtoul(row[1], (char**) 0, 10);
mysql_free_result(res);
-
- if (rpl_parse)
- mysql_enable_rpl_parse(mysql);
-
DBUG_RETURN(0);
}
@@ -4072,29 +4054,6 @@ void do_let(struct st_command *command)
}
-int do_rpl_probe(struct st_command *command __attribute__((unused)))
-{
- DBUG_ENTER("do_rpl_probe");
- if (mysql_rpl_probe(&cur_con->mysql))
- die("Failed in mysql_rpl_probe(): '%s'", mysql_error(&cur_con->mysql));
- DBUG_RETURN(0);
-}
-
-
-int do_enable_rpl_parse(struct st_command *command __attribute__((unused)))
-{
- mysql_enable_rpl_parse(&cur_con->mysql);
- return 0;
-}
-
-
-int do_disable_rpl_parse(struct st_command *command __attribute__((unused)))
-{
- mysql_disable_rpl_parse(&cur_con->mysql);
- return 0;
-}
-
-
/*
Sleep the number of specified seconds
@@ -5025,6 +4984,11 @@ void do_connect(struct st_command *command)
#endif
if (!mysql_init(&con_slot->mysql))
die("Failed on mysql_init()");
+
+ if (opt_connect_timeout)
+ mysql_options(&con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ (void *) &opt_connect_timeout);
+
if (opt_compress || con_compress)
mysql_options(&con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
mysql_options(&con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
@@ -5814,6 +5778,11 @@ static struct my_option my_long_options[] =
{"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select",
(uchar**) &view_protocol, (uchar**) &view_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"connect_timeout", OPT_CONNECT_TIMEOUT,
+ "Number of seconds before connection timeout.",
+ (uchar**) &opt_connect_timeout,
+ (uchar**) &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
+ 120, 0, 3600 * 12, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -5987,7 +5956,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int parse_args(int argc, char **argv)
{
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ exit(1);
+
default_argv= argv;
if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
@@ -6552,8 +6523,6 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
if (!disable_result_log)
{
- ulonglong UNINIT_VAR(affected_rows); /* Ok to be undef if 'disable_info' is set */
-
if (res)
{
MYSQL_FIELD *fields= mysql_fetch_fields(res);
@@ -6570,10 +6539,10 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
/*
Need to call mysql_affected_rows() before the "new"
- query to find the warnings
+ query to find the warnings.
*/
if (!disable_info)
- affected_rows= mysql_affected_rows(mysql);
+ append_info(ds, mysql_affected_rows(mysql), mysql_info(mysql));
/*
Add all warnings to the result. We can't do this if we are in
@@ -6588,9 +6557,6 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
}
}
-
- if (!disable_info)
- append_info(ds, affected_rows, mysql_info(mysql));
}
if (res)
@@ -6831,10 +6797,8 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
MYSQL_STMT *stmt;
DYNAMIC_STRING ds_prepare_warnings;
DYNAMIC_STRING ds_execute_warnings;
- ulonglong affected_rows;
DBUG_ENTER("run_query_stmt");
DBUG_PRINT("query", ("'%-.60s'", query));
- LINT_INIT(affected_rows);
/*
Init a new stmt if it's not already one created for this connection
@@ -6966,11 +6930,12 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
}
/*
- Need to grab affected rows information before getting
- warnings here
+ Fetch info before fetching warnings, since it will be reset
+ otherwise.
*/
+
if (!disable_info)
- affected_rows= mysql_affected_rows(mysql);
+ append_info(ds, mysql_stmt_affected_rows(stmt), mysql_info(mysql));
if (!disable_warnings)
{
@@ -6983,21 +6948,17 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
ds_warnings->length)
{
dynstr_append_mem(ds, "Warnings:\n", 10);
- if (ds_warnings->length)
- dynstr_append_mem(ds, ds_warnings->str,
- ds_warnings->length);
- if (ds_prepare_warnings.length)
- dynstr_append_mem(ds, ds_prepare_warnings.str,
- ds_prepare_warnings.length);
- if (ds_execute_warnings.length)
- dynstr_append_mem(ds, ds_execute_warnings.str,
- ds_execute_warnings.length);
+ if (ds_warnings->length)
+ dynstr_append_mem(ds, ds_warnings->str,
+ ds_warnings->length);
+ if (ds_prepare_warnings.length)
+ dynstr_append_mem(ds, ds_prepare_warnings.str,
+ ds_prepare_warnings.length);
+ if (ds_execute_warnings.length)
+ dynstr_append_mem(ds, ds_execute_warnings.str,
+ ds_execute_warnings.length);
}
}
-
- if (!disable_info)
- append_info(ds, affected_rows, mysql_info(mysql));
-
}
end:
@@ -7046,6 +7007,10 @@ int util_query(MYSQL* org_mysql, const char* query){
if (!(mysql= mysql_init(mysql)))
die("Failed in mysql_init()");
+ if (opt_connect_timeout)
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ (void *) &opt_connect_timeout);
+
/* enable local infile, in non-binary builds often disabled by default */
mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
@@ -7094,7 +7059,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
/*
Evaluate query if this is an eval command
*/
- if (command->type == Q_EVAL)
+ if (command->type == Q_EVAL || command->type == Q_SEND_EVAL)
{
init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
do_eval(&eval_query, command->query, command->end, FALSE);
@@ -7641,8 +7606,8 @@ int main(int argc, char **argv)
my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
- if (hash_init(&var_hash, charset_info,
- 1024, 0, 0, get_var_key, var_free, MYF(0)))
+ if (my_hash_init(&var_hash, charset_info,
+ 1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
var_set_string("$MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION);
@@ -7705,6 +7670,9 @@ int main(int argc, char **argv)
st_connection *con= connections;
if (!( mysql_init(&con->mysql)))
die("Failed in mysql_init()");
+ if (opt_connect_timeout)
+ mysql_options(&con->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ (void *) &opt_connect_timeout);
if (opt_compress)
mysql_options(&con->mysql,MYSQL_OPT_COMPRESS,NullS);
mysql_options(&con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
@@ -7809,9 +7777,6 @@ int main(int argc, char **argv)
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
do_close_connection(command); break;
- case Q_RPL_PROBE: do_rpl_probe(command); break;
- case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(command); break;
- case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(command); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break;
@@ -7918,6 +7883,7 @@ int main(int argc, char **argv)
break;
}
case Q_SEND:
+ case Q_SEND_EVAL:
if (!*command->first_argument)
{
/*
diff --git a/configure.in b/configure.in
index 1564033cf7a..3910422a0f7 100644
--- a/configure.in
+++ b/configure.in
@@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM
#
# When changing major version number please also check switch statement
# in client/mysqlbinlog.cc:check_master_version().
-AM_INIT_AUTOMAKE(mysql, 5.5.0-beta)
+AM_INIT_AUTOMAKE(mysql, 5.6.0-beta)
AM_CONFIG_HEADER([include/config.h:config.h.in])
PROTOCOL_VERSION=10
@@ -617,24 +617,6 @@ then
fi
fi
-AC_MSG_CHECKING(whether features provided by the user community should be included.)
-AC_ARG_ENABLE(community-features,
- AC_HELP_STRING(
- [--disable-community-features],
- [Disable additional features provided by the user community.]),
- [ ENABLE_COMMUNITY_FEATURES=$enableval ],
- [ ENABLE_COMMUNITY_FEATURES=yes ]
- )
-
-if test "$ENABLE_COMMUNITY_FEATURES" = "yes"
-then
- AC_DEFINE([COMMUNITY_SERVER], [1],
- [Whether features provided by the user community should be included])
- AC_MSG_RESULT([yes])
-else
- AC_MSG_RESULT([no])
-fi
-
AC_ARG_WITH(server-suffix,
[ --with-server-suffix Append value to the version string.],
[ MYSQL_SERVER_SUFFIX=`echo "$withval" | sed -e 's/^\(...................................\)..*$/\1/'` ],
@@ -700,21 +682,14 @@ fi
# Add query profiler
AC_MSG_CHECKING(if SHOW PROFILE should be enabled.)
AC_ARG_ENABLE(profiling,
- AS_HELP_STRING([--enable-profiling], [Build a version with query profiling code (req. community-features)]),
+ AS_HELP_STRING([--enable-profiling], [Enable profiling of query lifetime.]),
[ ENABLED_PROFILING=$enableval ],
- [ ENABLED_PROFILING=$ENABLE_COMMUNITY_FEATURES ])
+ [ ENABLED_PROFILING=no ])
+AC_DEFINE([ENABLED_PROFILING], [1], [If SHOW PROFILE should be enabled])
if test "$ENABLED_PROFILING" = "yes"
then
- if test "$ENABLE_COMMUNITY_FEATURES" = "yes";
- then
- AC_DEFINE([ENABLED_PROFILING], [1],
- [If SHOW PROFILE should be enabled])
- AC_MSG_RESULT([yes])
- else
- ENABLED_PROFILING="no"
- AC_MSG_RESULT([no, overridden by community-features disabled])
- fi
+ AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
@@ -2946,7 +2921,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
man/Makefile BUILD/Makefile vio/Makefile dnl
libmysql/Makefile libmysql_r/Makefile client/Makefile dnl
sql/Makefile sql/share/Makefile dnl
- sql/sql_builtin.cc sql-common/Makefile dnl
+ sql/sql_builtin.cc sql-common/Makefile libservices/Makefile dnl
dbug/Makefile scripts/Makefile include/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile support-files/RHEL4-SElinux/Makefile dnl
diff --git a/dbug/.cvsignore b/dbug/.cvsignore
deleted file mode 100644
index e9955884756..00000000000
--- a/dbug/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.deps
-Makefile
-Makefile.in
diff --git a/dbug/Makefile.am b/dbug/Makefile.am
index 872ebdb7902..4091858a1af 100644
--- a/dbug/Makefile.am
+++ b/dbug/Makefile.am
@@ -23,19 +23,20 @@ libdbug_a_SOURCES = dbug.c sanity.c
EXTRA_DIST = CMakeLists.txt example1.c example2.c example3.c \
user.r monty.doc dbug_add_tags.pl \
my_main.c main.c factorial.c dbug_analyze.c \
- CMakeLists.txt
+ CMakeLists.txt tests.c tests-t.pl
NROFF_INC = example1.r example2.r example3.r main.r \
factorial.r output1.r output2.r output3.r \
output4.r output5.r
-CLEANFILES = $(NROFF_INC) user.t user.ps
+CLEANFILES = $(NROFF_INC) user.t user.ps tests-t
# Must be linked with libs that are not compiled yet
-noinst_PROGRAMS = factorial dbug_analyze
+noinst_PROGRAMS = factorial dbug_analyze tests
factorial_SOURCES = my_main.c factorial.c
+tests_SOURCES = tests.c
dbug_analyze_SOURCES = dbug_analyze.c
-all: user.t user.ps
+all: user.t user.ps tests-t
user.t: user.r $(NROFF_INC)
-nroff -mm user.r > $@
@@ -61,5 +62,7 @@ output5.r: factorial
@RM@ -f $@
@SED@ -e 's!\\!\\\\!g' $< > $@
-# Don't update the files from bitkeeper
-%::SCCS/s.%
+# a hack to have executable in builddir, not in srcdir
+tests-t: tests-t.pl
+ cp -f $(srcdir)/tests-t.pl ./tests-t
+
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 1ea160852eb..0a0c56170fa 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -57,29 +57,48 @@
* seismo!bpa!sjuvax!bbanerje
*
* Michael Widenius:
- * DBUG_DUMP - To dump a block of memory.
- * PUSH_FLAG "O" - To be used insted of "o" if we
- * want flushing after each write
- * PUSH_FLAG "A" - as 'O', but we will append to the out file instead
- * of creating a new one.
- * Check of malloc on entry/exit (option "S")
- *
- * DBUG_EXECUTE_IF
- * incremental mode (-#+t:-d,info ...)
- * DBUG_SET, _db_explain_
- * thread-local settings
+ * DBUG_DUMP - To dump a block of memory.
+ * PUSH_FLAG "O" - To be used insted of "o" if we
+ * want flushing after each write
+ * PUSH_FLAG "A" - as 'O', but we will append to the out file instead
+ * of creating a new one.
+ * Check of malloc on entry/exit (option "S")
+ *
+ * Sergei Golubchik:
+ * DBUG_EXECUTE_IF
+ * incremental mode (-#+t:-d,info ...)
+ * DBUG_SET, _db_explain_
+ * thread-local settings
+ * negative lists (-#-d,info => everything but "info")
+ *
+ * function/ syntax
+ * (the logic is - think of a call stack as of a path.
+ * "function" means only this function, "function/" means the hierarchy.
+ * in the future, filters like function1/function2 could be supported.
+ * following this logic glob(7) wildcards are supported.)
*
*/
+/*
+ We can't have SAFE_MUTEX defined here as this will cause recursion
+ in pthread_mutex_lock
+*/
+#undef SAFE_MUTEX
#include <my_global.h>
#include <m_string.h>
#include <errno.h>
+
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#define fnmatch(A,B,C) strcmp(A,B)
+#endif
+
#if defined(MSDOS) || defined(__WIN__)
#include <process.h>
#endif
-
#ifndef DBUG_OFF
@@ -95,21 +114,24 @@
* The following flags are used to determine which
* capabilities the user has enabled with the settings
* push macro.
+ *
+ * TRACE_ON is also used in _db_stack_frame_->level
+ * (until we add flags to _db_stack_frame_, increasing it by 4 bytes)
*/
-#define TRACE_ON 000001 /* Trace enabled */
-#define DEBUG_ON 000002 /* Debug enabled */
-#define FILE_ON 000004 /* File name print enabled */
-#define LINE_ON 000010 /* Line number print enabled */
-#define DEPTH_ON 000020 /* Function nest level print enabled */
-#define PROCESS_ON 000040 /* Process name print enabled */
-#define NUMBER_ON 000100 /* Number each line of output */
-#define PROFILE_ON 000200 /* Print out profiling code */
-#define PID_ON 000400 /* Identify each line with process id */
-#define TIMESTAMP_ON 001000 /* timestamp every line of output */
-#define SANITY_CHECK_ON 002000 /* Check safemalloc on DBUG_ENTER */
-#define FLUSH_ON_WRITE 004000 /* Flush on every write */
-#define OPEN_APPEND 010000 /* Open for append */
+#define DEBUG_ON (1 << 1) /* Debug enabled */
+#define FILE_ON (1 << 2) /* File name print enabled */
+#define LINE_ON (1 << 3) /* Line number print enabled */
+#define DEPTH_ON (1 << 4) /* Function nest level print enabled */
+#define PROCESS_ON (1 << 5) /* Process name print enabled */
+#define NUMBER_ON (1 << 6) /* Number each line of output */
+#define PROFILE_ON (1 << 7) /* Print out profiling code */
+#define PID_ON (1 << 8) /* Identify each line with process id */
+#define TIMESTAMP_ON (1 << 9) /* timestamp every line of output */
+#define SANITY_CHECK_ON (1 << 10) /* Check safemalloc on DBUG_ENTER */
+#define FLUSH_ON_WRITE (1 << 11) /* Flush on every write */
+#define OPEN_APPEND (1 << 12) /* Open for append */
+#define TRACE_ON ((uint)1 << 31) /* Trace enabled. MUST be the highest bit!*/
#define TRACING (cs->stack->flags & TRACE_ON)
#define DEBUGGING (cs->stack->flags & DEBUG_ON)
@@ -119,11 +141,7 @@
* Typedefs to make things more obvious.
*/
-#ifndef __WIN__
-typedef int BOOLEAN;
-#else
-#define BOOLEAN BOOL
-#endif
+#define BOOLEAN my_bool
/*
* Make it easy to change storage classes if necessary.
@@ -139,7 +157,7 @@ typedef int BOOLEAN;
* (G?) which allowed the user to specify this.
*
* If the automatic variables get allocated on the stack in
- * reverse order from their declarations, then define AUTOS_REVERSE.
+ * reverse order from their declarations, then define AUTOS_REVERSE to 1.
* This is used by the code that keeps track of stack usage. For
* forward allocation, the difference in the dbug frame pointers
* represents stack used by the callee function. For reverse allocation,
@@ -154,6 +172,8 @@ typedef int BOOLEAN;
#ifdef M_I386 /* predefined by xenix 386 compiler */
#define AUTOS_REVERSE 1
+#else
+#define AUTOS_REVERSE 0
#endif
/*
@@ -164,7 +184,11 @@ typedef int BOOLEAN;
static void perror(); /* Fake system/library error print routine */
#endif
+#ifdef SAFEMALLOC
IMPORT int _sanity(const char *file,uint line); /* safemalloc sanity checker */
+#else
+#define _sanity(X,Y) (1)
+#endif
/*
* The user may specify a list of functions to trace or
@@ -174,9 +198,18 @@ IMPORT int _sanity(const char *file,uint line); /* safemalloc sanity checker */
struct link {
struct link *next_link; /* Pointer to the next link */
- char str[1]; /* Pointer to link's contents */
+ char flags;
+ char str[1]; /* Pointer to link's contents */
};
+/* flags for struct link and return flags of InList */
+#define SUBDIR 1 /* this MUST be 1 */
+#define INCLUDE 2
+#define EXCLUDE 4
+/* this is not a struct link flag, but only a return flags of InList */
+#define MATCHED 65536
+#define NOT_MATCHED 0
+
/*
* Debugging settings can be pushed or popped off of a
* stack which is implemented as a linked list. Note
@@ -188,18 +221,18 @@ struct link {
*/
struct settings {
- int flags; /* Current settings flags */
- int maxdepth; /* Current maximum trace depth */
- uint delay; /* Delay after each output line */
- int sub_level; /* Sub this from code_state->level */
- FILE *out_file; /* Current output stream */
- FILE *prof_file; /* Current profiling stream */
- char name[FN_REFLEN]; /* Name of output file */
- struct link *functions; /* List of functions */
- struct link *p_functions; /* List of profiled functions */
- struct link *keywords; /* List of debug keywords */
- struct link *processes; /* List of process names */
- struct settings *next; /* Next settings in the list */
+ uint flags; /* Current settings flags */
+ uint maxdepth; /* Current maximum trace depth */
+ uint delay; /* Delay after each output line */
+ uint sub_level; /* Sub this from code_state->level */
+ FILE *out_file; /* Current output stream */
+ FILE *prof_file; /* Current profiling stream */
+ char name[FN_REFLEN]; /* Name of output file */
+ struct link *functions; /* List of functions */
+ struct link *p_functions; /* List of profiled functions */
+ struct link *keywords; /* List of debug keywords */
+ struct link *processes; /* List of process names */
+ struct settings *next; /* Next settings in the list */
};
#define is_shared(S, V) ((S)->next && (S)->next->V == (S)->V)
@@ -212,18 +245,19 @@ struct settings {
static BOOLEAN init_done= FALSE; /* Set to TRUE when initialization done */
static struct settings init_settings;
static const char *db_process= 0;/* Pointer to process name; argv[0] */
+my_bool _dbug_on_= TRUE; /* FALSE if no debugging at all */
typedef struct _db_code_state_ {
const char *process; /* Pointer to process name; usually argv[0] */
- const char *func; /* Name of current user function */
- const char *file; /* Name of current user file */
- char **framep; /* Pointer to current frame */
- struct settings *stack; /* debugging settings */
- const char *jmpfunc; /* Remember current function for setjmp */
- const char *jmpfile; /* Remember current file for setjmp */
- int lineno; /* Current debugger output line number */
- int level; /* Current function nesting level */
- int jmplevel; /* Remember nesting level at setjmp() */
+ const char *func; /* Name of current user function */
+ const char *file; /* Name of current user file */
+ struct _db_stack_frame_ *framep; /* Pointer to current frame */
+ struct settings *stack; /* debugging settings */
+ const char *jmpfunc; /* Remember current function for setjmp */
+ const char *jmpfile; /* Remember current file for setjmp */
+ int lineno; /* Current debugger output line number */
+ uint level; /* Current function nesting level */
+ int jmplevel; /* Remember nesting level at setjmp() */
/*
* The following variables are used to hold the state information
@@ -244,12 +278,16 @@ typedef struct _db_code_state_ {
The test below is so we could call functions with DBUG_ENTER before
my_thread_init().
*/
-#define get_code_state_or_return if (!cs && !((cs=code_state()))) return
+#define get_code_state_if_not_set_or_return if (!cs && !((cs=code_state()))) return
+#define get_code_state_or_return if (!((cs=code_state()))) return
/* Handling lists */
-static struct link *ListAdd(struct link *, const char *, const char *);
-static struct link *ListDel(struct link *, const char *, const char *);
+#define ListAdd(A,B,C) ListAddDel(A,B,C,INCLUDE)
+#define ListDel(A,B,C) ListAddDel(A,B,C,EXCLUDE)
+static struct link *ListAddDel(struct link *, const char *, const char *, int);
static struct link *ListCopy(struct link *);
+static int InList(struct link *linkp,const char *cp);
+static uint ListFlags(struct link *linkp);
static void FreeList(struct link *linkp);
/* OpenClose debug output stream */
@@ -260,10 +298,18 @@ static void PushState(CODE_STATE *cs);
/* Free memory associated with debug state. */
static void FreeState (CODE_STATE *cs, struct settings *state, int free_state);
/* Test for tracing enabled */
-static BOOLEAN DoTrace(CODE_STATE *cs);
+static int DoTrace(CODE_STATE *cs);
+/*
+ return values of DoTrace.
+ Can also be used as bitmask: ret & DO_TRACE
+*/
+#define DO_TRACE 1
+#define DONT_TRACE 2
+#define ENABLE_TRACE 3
+#define DISABLE_TRACE 4
/* Test to see if file is writable */
-#if !(!defined(HAVE_ACCESS) || defined(MSDOS))
+#if defined(HAVE_ACCESS) && !defined(MSDOS)
static BOOLEAN Writable(const char *pathname);
/* Change file owner and group */
static void ChangeOwner(CODE_STATE *cs, char *pathname);
@@ -275,10 +321,10 @@ static void DoPrefix(CODE_STATE *cs, uint line);
static char *DbugMalloc(size_t size);
static const char *BaseName(const char *pathname);
static void Indent(CODE_STATE *cs, int indent);
-static BOOLEAN InList(struct link *linkp,const char *cp);
-static void dbug_flush(CODE_STATE *);
+static void DbugFlush(CODE_STATE *);
static void DbugExit(const char *why);
static const char *DbugStrTok(const char *s);
+static void DbugVfprintf(FILE *stream, const char* format, va_list args);
#ifndef THREAD
/* Open profile output stream */
@@ -293,7 +339,7 @@ static unsigned long Clock(void);
* Miscellaneous printf format strings.
*/
-#define ERR_MISSING_RETURN "%s: missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
+#define ERR_MISSING_RETURN "missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
#define ERR_OPEN "%s: can't open debug output stream \"%s\": "
#define ERR_CLOSE "%s: can't close debug file: "
#define ERR_ABORT "%s: debugger aborting because %s\n"
@@ -322,34 +368,39 @@ static unsigned long Clock(void);
#ifdef THREAD
#include <my_pthread.h>
-pthread_mutex_t THR_LOCK_dbug;
+static pthread_mutex_t THR_LOCK_dbug;
static CODE_STATE *code_state(void)
{
- CODE_STATE *cs=0;
- struct st_my_thread_var *tmp;
+ CODE_STATE *cs, **cs_ptr;
+
+ /*
+ _dbug_on_ is reset if we don't plan to use any debug commands at all and
+ we want to run on maximum speed
+ */
+ if (!_dbug_on_)
+ return 0;
if (!init_done)
{
+ init_done=TRUE;
pthread_mutex_init(&THR_LOCK_dbug,MY_MUTEX_INIT_FAST);
bzero(&init_settings, sizeof(init_settings));
init_settings.out_file=stderr;
init_settings.flags=OPEN_APPEND;
- init_done=TRUE;
}
- if ((tmp=my_thread_var))
+ if (!(cs_ptr= (CODE_STATE**) my_thread_var_dbug()))
+ return 0; /* Thread not initialised */
+ if (!(cs= *cs_ptr))
{
- if (!(cs=(CODE_STATE *) tmp->dbug))
- {
- cs=(CODE_STATE*) DbugMalloc(sizeof(*cs));
- bzero((uchar*) cs,sizeof(*cs));
- cs->process= db_process ? db_process : "dbug";
- cs->func="?func";
- cs->file="?file";
- cs->stack=&init_settings;
- tmp->dbug= (void*) cs;
- }
+ cs=(CODE_STATE*) DbugMalloc(sizeof(*cs));
+ bzero((uchar*) cs,sizeof(*cs));
+ cs->process= db_process ? db_process : "dbug";
+ cs->func="?func";
+ cs->file="?file";
+ cs->stack=&init_settings;
+ *cs_ptr= cs;
}
return cs;
}
@@ -403,20 +454,19 @@ static CODE_STATE *code_state(void)
void _db_process_(const char *name)
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
if (!db_process)
db_process= name;
-
+
get_code_state_or_return;
cs->process= name;
}
-
/*
* FUNCTION
*
- * DbugParse parse control string and set current debugger setting
+ * DbugParse parse control string and set current debugger settings
*
* DESCRIPTION
*
@@ -438,15 +488,17 @@ void _db_process_(const char *name)
*
* For convenience, any leading "-#" is stripped off.
*
+ * RETURN
+ * 1 - a list of functions ("f" flag) was possibly changed
+ * 0 - a list of functions was not changed
*/
-static void DbugParse(CODE_STATE *cs, const char *control)
+int DbugParse(CODE_STATE *cs, const char *control)
{
const char *end;
- int rel=0;
+ int rel, f_used=0;
struct settings *stack;
- get_code_state_or_return;
stack= cs->stack;
if (control[0] == '-' && control[1] == '#')
@@ -455,6 +507,7 @@ static void DbugParse(CODE_STATE *cs, const char *control)
rel= control[0] == '+' || control[0] == '-';
if ((!rel || (!stack->out_file && !stack->next)))
{
+ FreeState(cs, stack, 0);
stack->flags= 0;
stack->delay= 0;
stack->maxdepth= 0;
@@ -497,7 +550,6 @@ static void DbugParse(CODE_STATE *cs, const char *control)
{
int c, sign= (*control == '+') ? 1 : (*control == '-') ? -1 : 0;
if (sign) control++;
- if (!rel) sign=0;
c= *control++;
if (*control == ',') control++;
/* XXX when adding new cases here, don't forget _db_explain_ ! */
@@ -526,6 +578,7 @@ static void DbugParse(CODE_STATE *cs, const char *control)
stack->delay= atoi(control);
break;
case 'f':
+ f_used= 1;
if (sign < 0 && control == end)
{
if (!is_shared(stack,functions))
@@ -664,8 +717,111 @@ static void DbugParse(CODE_STATE *cs, const char *control)
control=end+1;
end= DbugStrTok(control);
}
+ return !rel || f_used;
}
+#define framep_trace_flag(cs, frp) (frp ? \
+ frp->level & TRACE_ON : \
+ (ListFlags(cs->stack->functions) & INCLUDE) ? \
+ 0 : (uint)TRACE_ON)
+
+void FixTraceFlags_helper(CODE_STATE *cs, const char *func,
+ struct _db_stack_frame_ *framep)
+{
+ if (framep->prev)
+ FixTraceFlags_helper(cs, framep->func, framep->prev);
+
+ cs->func= func;
+ cs->level= framep->level & ~TRACE_ON;
+ framep->level= cs->level | framep_trace_flag(cs, framep->prev);
+ /*
+ we don't set cs->framep correctly, even though DoTrace uses it.
+ It's ok, because cs->framep may only affect DO_TRACE/DONT_TRACE return
+ values, but we ignore them here anyway
+ */
+ switch(DoTrace(cs)) {
+ case ENABLE_TRACE:
+ framep->level|= TRACE_ON;
+ break;
+ case DISABLE_TRACE:
+ framep->level&= ~TRACE_ON;
+ break;
+ }
+}
+
+#define fflags(cs) cs->stack->out_file ? ListFlags(cs->stack->functions) : TRACE_ON;
+
+void FixTraceFlags(uint old_fflags, CODE_STATE *cs)
+{
+ const char *func;
+ uint new_fflags, traceon, level;
+ struct _db_stack_frame_ *framep;
+
+ /*
+ first (a.k.a. safety) check:
+ if we haven't started tracing yet, no call stack at all - we're safe.
+ */
+ framep=cs->framep;
+ if (framep == 0)
+ return;
+
+ /*
+ Ok, the tracing has started, call stack isn't empty.
+
+ second check: does the new list have a SUBDIR rule ?
+ */
+ new_fflags=fflags(cs);
+ if (new_fflags & SUBDIR)
+ goto yuck;
+
+ /*
+ Ok, new list doesn't use SUBDIR.
+
+ third check: we do NOT need to re-scan if
+ neither old nor new lists used SUBDIR flag and if a default behavior
+ (whether an unlisted function is traced) hasn't changed.
+ Default behavior depends on whether there're INCLUDE elements in the list.
+ */
+ if (!(old_fflags & SUBDIR) && !((new_fflags^old_fflags) & INCLUDE))
+ return;
+
+ /*
+ Ok, old list may've used SUBDIR, or defaults could've changed.
+
+ fourth check: are we inside a currently active SUBDIR rule ?
+ go up the call stack, if TRACE_ON flag ever changes its value - we are.
+ */
+ for (traceon=framep->level; framep; framep=framep->prev)
+ if ((traceon ^ framep->level) & TRACE_ON)
+ goto yuck;
+
+ /*
+ Ok, TRACE_ON flag doesn't change in the call stack.
+
+ fifth check: but is the top-most value equal to a default one ?
+ */
+ if (((traceon & TRACE_ON) != 0) == ((new_fflags & INCLUDE) == 0))
+ return;
+
+yuck:
+ /*
+ Yuck! function list was changed, and one of the currently active rules
+ was possibly affected. For example, a tracing could've been enabled or
+ disabled for a function somewhere up the call stack.
+ To react correctly, we must go up the call stack all the way to
+ the top and re-match rules to set TRACE_ON bit correctly.
+
+ We must traverse the stack forwards, not backwards.
+ That's what a recursive helper is doing.
+ It'll destroy two CODE_STATE fields, save them now.
+ */
+ func= cs->func;
+ level= cs->level;
+ FixTraceFlags_helper(cs, func, cs->framep);
+ /* now we only need to restore CODE_STATE fields, and we're done */
+ cs->func= func;
+ cs->level= level;
+}
/*
* FUNCTION
@@ -683,19 +839,21 @@ static void DbugParse(CODE_STATE *cs, const char *control)
* parses the control string, and sets up a current debug
* settings. Pushes a new debug settings if the current is
* set to the initial debugger settings.
+ *
*/
-void _db_set_(CODE_STATE *cs, const char *control)
+void _db_set_(const char *control)
{
+ CODE_STATE *cs;
+ uint old_fflags;
get_code_state_or_return;
-
+ old_fflags=fflags(cs);
if (cs->stack == &init_settings)
PushState(cs);
-
- DbugParse(cs, control);
+ if (DbugParse(cs, control))
+ FixTraceFlags(old_fflags, cs);
}
-
/*
* FUNCTION
*
@@ -716,10 +874,25 @@ void _db_set_(CODE_STATE *cs, const char *control)
void _db_push_(const char *control)
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
+ uint old_fflags;
get_code_state_or_return;
+ old_fflags=fflags(cs);
PushState(cs);
- DbugParse(cs, control);
+ if (DbugParse(cs, control))
+ FixTraceFlags(old_fflags, cs);
+}
+
+
+/**
+ Returns TRUE if session-local settings have been set.
+*/
+
+int _db_is_pushed_()
+{
+ CODE_STATE *cs= NULL;
+ get_code_state_or_return FALSE;
+ return (cs->stack != &init_settings);
}
/*
@@ -765,15 +938,18 @@ void _db_set_init_(const char *control)
void _db_pop_()
{
struct settings *discard;
- CODE_STATE *cs=0;
+ uint old_fflags;
+ CODE_STATE *cs;
get_code_state_or_return;
discard= cs->stack;
- if (discard->next != NULL)
+ if (discard != &init_settings)
{
+ old_fflags=fflags(cs);
cs->stack= discard->next;
FreeState(cs, discard, 1);
+ FixTraceFlags(old_fflags, cs);
}
}
@@ -798,11 +974,16 @@ void _db_pop_()
buf=strnmov(buf, (S), len+1); \
if (buf >= end) goto overflow; \
} while (0)
-#define list_to_buf(l) do { \
+#define list_to_buf(l, f) do { \
struct link *listp=(l); \
while (listp) \
{ \
- str_to_buf(listp->str); \
+ if (listp->flags & (f)) \
+ { \
+ str_to_buf(listp->str); \
+ if (listp->flags & SUBDIR) \
+ char_to_buf('/'); \
+ } \
listp=listp->next_link; \
} \
} while (0)
@@ -842,9 +1023,18 @@ void _db_pop_()
#define op_list_to_buf(C, val, cond) do { \
if ((cond)) \
{ \
+ int f=ListFlags(val); \
colon_to_buf; \
char_to_buf((C)); \
- list_to_buf(val); \
+ if (f & INCLUDE) \
+ list_to_buf(val, INCLUDE); \
+ if (f & EXCLUDE) \
+ { \
+ colon_to_buf; \
+ char_to_buf('-'); \
+ char_to_buf((C)); \
+ list_to_buf(val, EXCLUDE); \
+ } \
} \
} while (0)
#define op_bool_to_buf(C, cond) do { \
@@ -859,7 +1049,7 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len)
{
char *start=buf, *end=buf+len-4;
- get_code_state_or_return *buf=0;
+ get_code_state_if_not_set_or_return *buf=0;
op_list_to_buf('d', cs->stack->keywords, DEBUGGING);
op_int_to_buf ('D', cs->stack->delay, 0);
@@ -927,15 +1117,11 @@ int _db_explain_init_(char *buf, size_t len)
*
* SYNOPSIS
*
- * VOID _db_enter_(_func_, _file_, _line_,
- * _sfunc_, _sfile_, _slevel_, _sframep_)
+ * VOID _db_enter_(_func_, _file_, _line_, _stack_frame_)
* char *_func_; points to current function name
* char *_file_; points to current file name
* int _line_; called from source line number
- * char **_sfunc_; save previous _func_
- * char **_sfile_; save previous _file_
- * int *_slevel_; save previous nesting level
- * char ***_sframep_; save previous frame pointer
+ * struct _db_stack_frame_ allocated on the caller's stack
*
* DESCRIPTION
*
@@ -959,55 +1145,66 @@ int _db_explain_init_(char *buf, size_t len)
*/
void _db_enter_(const char *_func_, const char *_file_,
- uint _line_, const char **_sfunc_, const char **_sfile_,
- uint *_slevel_, char ***_sframep_ __attribute__((unused)))
+ uint _line_, struct _db_stack_frame_ *_stack_frame_)
{
- int save_errno=errno;
- CODE_STATE *cs=0;
- get_code_state_or_return;
+ int save_errno;
+ CODE_STATE *cs;
+ if (!((cs=code_state())))
+ {
+ _stack_frame_->level= 0; /* Set to avoid valgrind warnings if dbug is enabled later */
+ _stack_frame_->prev= 0;
+ return;
+ }
+ save_errno= errno;
- *_sfunc_= cs->func;
- *_sfile_= cs->file;
+ _stack_frame_->func= cs->func;
+ _stack_frame_->file= cs->file;
cs->func= _func_;
cs->file= _file_;
- *_slevel_= ++cs->level;
+ _stack_frame_->prev= cs->framep;
+ _stack_frame_->level= ++cs->level | framep_trace_flag(cs, cs->framep);
+ cs->framep= _stack_frame_;
#ifndef THREAD
- *_sframep_= cs->framep;
- cs->framep= (char **) _sframep_;
if (DoProfile(cs))
{
long stackused;
- if (*cs->framep == NULL)
+ if (cs->framep->prev == NULL)
stackused= 0;
else
{
- stackused= ((long)(*cs->framep)) - ((long)(cs->framep));
+ stackused= (char*)(cs->framep->prev) - (char*)(cs->framep);
stackused= stackused > 0 ? stackused : -stackused;
}
(void) fprintf(cs->stack->prof_file, PROF_EFMT , Clock(), cs->func);
-#ifdef AUTOS_REVERSE
- (void) fprintf(cs->stack->prof_file, PROF_SFMT, cs->framep, stackused, *_sfunc_);
-#else
(void) fprintf(cs->stack->prof_file, PROF_SFMT, (ulong) cs->framep, stackused,
- cs->func);
-#endif
+ AUTOS_REVERSE ? _stack_frame_->func : cs->func);
(void) fflush(cs->stack->prof_file);
}
#endif
- if (DoTrace(cs))
- {
- if (!cs->locked)
- pthread_mutex_lock(&THR_LOCK_dbug);
- DoPrefix(cs, _line_);
- Indent(cs, cs->level);
- (void) fprintf(cs->stack->out_file, ">%s\n", cs->func);
- dbug_flush(cs); /* This does a unlock */
- }
-#ifdef SAFEMALLOC
- if (cs->stack->flags & SANITY_CHECK_ON)
- if (_sanity(_file_,_line_)) /* Check of safemalloc */
+ switch (DoTrace(cs)) {
+ case ENABLE_TRACE:
+ cs->framep->level|= TRACE_ON;
+ if (!TRACING) break;
+ /* fall through */
+ case DO_TRACE:
+ if ((cs->stack->flags & SANITY_CHECK_ON) && _sanity(_file_,_line_))
cs->stack->flags &= ~SANITY_CHECK_ON;
-#endif
+ if (TRACING)
+ {
+ if (!cs->locked)
+ pthread_mutex_lock(&THR_LOCK_dbug);
+ DoPrefix(cs, _line_);
+ Indent(cs, cs->level);
+ (void) fprintf(cs->stack->out_file, ">%s\n", cs->func);
+ DbugFlush(cs); /* This does a unlock */
+ }
+ break;
+ case DISABLE_TRACE:
+ cs->framep->level&= ~TRACE_ON;
+ /* fall through */
+ case DONT_TRACE:
+ break;
+ }
errno=save_errno;
}
@@ -1018,11 +1215,9 @@ void _db_enter_(const char *_func_, const char *_file_,
*
* SYNOPSIS
*
- * VOID _db_return_(_line_, _sfunc_, _sfile_, _slevel_)
+ * VOID _db_return_(_line_, _stack_frame_)
* int _line_; current source line number
- * char **_sfunc_; where previous _func_ is to be retrieved
- * char **_sfile_; where previous _file_ is to be retrieved
- * int *_slevel_; where previous level was stashed
+ * struct _db_stack_frame_ allocated on the caller's stack
*
* DESCRIPTION
*
@@ -1033,52 +1228,47 @@ void _db_enter_(const char *_func_, const char *_file_,
*
*/
-/* helper macro */
-void _db_return_(uint _line_, const char **_sfunc_,
- const char **_sfile_, uint *_slevel_)
+void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_)
{
int save_errno=errno;
- CODE_STATE *cs=0;
+ uint _slevel_= _stack_frame_->level & ~TRACE_ON;
+ CODE_STATE *cs;
get_code_state_or_return;
- if (cs->level != (int) *_slevel_)
+ if (cs->framep != _stack_frame_)
{
- if (!cs->locked)
- pthread_mutex_lock(&THR_LOCK_dbug);
- (void) fprintf(cs->stack->out_file, ERR_MISSING_RETURN, cs->process,
- cs->func);
- dbug_flush(cs);
+ char buf[512];
+ my_snprintf(buf, sizeof(buf), ERR_MISSING_RETURN, cs->func);
+ DbugExit(buf);
}
- else
- {
-#ifdef SAFEMALLOC
- if (cs->stack->flags & SANITY_CHECK_ON)
- {
- if (_sanity(*_sfile_,_line_))
- cs->stack->flags &= ~SANITY_CHECK_ON;
- }
-#endif
#ifndef THREAD
- if (DoProfile(cs))
- (void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func);
+ if (DoProfile(cs))
+ (void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func);
#endif
- if (DoTrace(cs))
+ if (DoTrace(cs) & DO_TRACE)
+ {
+ if ((cs->stack->flags & SANITY_CHECK_ON) &&
+ _sanity(_stack_frame_->file,_line_))
+ cs->stack->flags &= ~SANITY_CHECK_ON;
+ if (TRACING)
{
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
DoPrefix(cs, _line_);
Indent(cs, cs->level);
(void) fprintf(cs->stack->out_file, "<%s\n", cs->func);
- dbug_flush(cs);
+ DbugFlush(cs);
}
}
- cs->level= *_slevel_-1;
- cs->func= *_sfunc_;
- cs->file= *_sfile_;
-#ifndef THREAD
+ /*
+ Check to not set level < 0. This can happen if DBUG was disabled when
+ function was entered and enabled in function.
+ */
+ cs->level= _slevel_ != 0 ? _slevel_ - 1 : 0;
+ cs->func= _stack_frame_->func;
+ cs->file= _stack_frame_->file;
if (cs->framep != NULL)
- cs->framep= (char **) *cs->framep;
-#endif
+ cs->framep= cs->framep->prev;
errno=save_errno;
}
@@ -1105,7 +1295,7 @@ void _db_return_(uint _line_, const char **_sfunc_,
void _db_pargs_(uint _line_, const char *keyword)
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
cs->u_line= _line_;
cs->u_keyword= keyword;
@@ -1141,13 +1331,12 @@ void _db_pargs_(uint _line_, const char *keyword)
void _db_doprnt_(const char *format,...)
{
va_list args;
-
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
va_start(args,format);
- if (_db_keyword_(cs, cs->u_keyword))
+ if (_db_keyword_(cs, cs->u_keyword, 0))
{
int save_errno=errno;
if (!cs->locked)
@@ -1158,14 +1347,25 @@ void _db_doprnt_(const char *format,...)
else
(void) fprintf(cs->stack->out_file, "%s: ", cs->func);
(void) fprintf(cs->stack->out_file, "%s: ", cs->u_keyword);
- (void) vfprintf(cs->stack->out_file, format, args);
- (void) fputc('\n',cs->stack->out_file);
- dbug_flush(cs);
+ DbugVfprintf(cs->stack->out_file, format, args);
+ DbugFlush(cs);
errno=save_errno;
}
va_end(args);
}
+/*
+ * vfprintf clone with consistent, platform independent output for
+ * problematic formats like %p, %zd and %lld.
+ */
+static void DbugVfprintf(FILE *stream, const char* format, va_list args)
+{
+ char cvtbuf[1024];
+ size_t len;
+ len = my_vsnprintf(cvtbuf, sizeof(cvtbuf), format, args);
+ (void) fprintf(stream, "%s\n", cvtbuf);
+}
+
/*
* FUNCTION
@@ -1182,19 +1382,17 @@ void _db_doprnt_(const char *format,...)
*
* DESCRIPTION
* Dump N characters in a binary array.
- * Is used to examine corrputed memory or arrays.
+ * Is used to examine corrupted memory or arrays.
*/
void _db_dump_(uint _line_, const char *keyword,
const unsigned char *memory, size_t length)
{
int pos;
- char dbuff[90];
-
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
- if (_db_keyword_(cs, keyword))
+ if (_db_keyword_(cs, keyword, 0))
{
if (!cs->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
@@ -1208,9 +1406,8 @@ void _db_dump_(uint _line_, const char *keyword,
{
fprintf(cs->stack->out_file, "%s: ", cs->func);
}
- sprintf(dbuff,"%s: Memory: 0x%lx Bytes: (%ld)\n",
+ (void) fprintf(cs->stack->out_file, "%s: Memory: 0x%lx Bytes: (%ld)\n",
keyword, (ulong) memory, (long) length);
- (void) fputs(dbuff,cs->stack->out_file);
pos=0;
while (length-- > 0)
@@ -1226,7 +1423,7 @@ void _db_dump_(uint _line_, const char *keyword,
fputc(' ',cs->stack->out_file);
}
(void) fputc('\n',cs->stack->out_file);
- dbug_flush(cs);
+ DbugFlush(cs);
}
}
@@ -1234,93 +1431,75 @@ void _db_dump_(uint _line_, const char *keyword,
/*
* FUNCTION
*
- * ListAdd add to the list modifiers from debug control string
- *
- * SYNOPSIS
- *
- * static struct link *ListAdd(listp, ctlp, end)
- * struct link *listp;
- * char *ctlp;
- * char *end;
+ * ListAddDel modify the list according to debug control string
*
* DESCRIPTION
*
* Given pointer to a comma separated list of strings in "cltp",
- * parses the list, and adds it to listp, returning a pointer
- * to the new list
+ * parses the list, and modifies "listp", returning a pointer
+ * to the new list.
*
- * Note that since each link is added at the head of the list,
- * the final list will be in "reverse order", which is not
- * significant for our usage here.
+ * The mode of operation is defined by "todo" parameter.
*
- */
-
-static struct link *ListAdd(struct link *head,
- const char *ctlp, const char *end)
-{
- const char *start;
- struct link *new_malloc;
- int len;
-
- while (ctlp < end)
- {
- start= ctlp;
- while (ctlp < end && *ctlp != ',')
- ctlp++;
- len=ctlp-start;
- new_malloc= (struct link *) DbugMalloc(sizeof(struct link)+len);
- memcpy(new_malloc->str, start, len);
- new_malloc->str[len]=0;
- new_malloc->next_link= head;
- head= new_malloc;
- ctlp++;
- }
- return head;
-}
-
-/*
- * FUNCTION
- *
- * ListDel remove from the list modifiers in debug control string
- *
- * SYNOPSIS
- *
- * static struct link *ListDel(listp, ctlp, end)
- * struct link *listp;
- * char *ctlp;
- * char *end;
- *
- * DESCRIPTION
- *
- * Given pointer to a comma separated list of strings in "cltp",
- * parses the list, and removes these strings from the listp,
- * returning a pointer to the new list.
+ * If it is INCLUDE, elements (strings from "cltp") are added to the
+ * list, they will have INCLUDE flag set. If the list already contains
+ * the string in question, new element is not added, but a flag of
+ * the existing element is adjusted (INCLUDE bit is set, EXCLUDE bit
+ * is removed).
*
+ * If it is EXCLUDE, elements are added to the list with the EXCLUDE
+ * flag set. If the list already contains the string in question,
+ * it is removed, new element is not added.
*/
-static struct link *ListDel(struct link *head,
- const char *ctlp, const char *end)
+static struct link *ListAddDel(struct link *head, const char *ctlp,
+ const char *end, int todo)
{
const char *start;
struct link **cur;
- int len;
+ size_t len;
+ int subdir;
- while (ctlp < end)
+ ctlp--;
+next:
+ while (++ctlp < end)
{
start= ctlp;
+ subdir=0;
while (ctlp < end && *ctlp != ',')
ctlp++;
len=ctlp-start;
- cur=&head;
- do
+ if (start[len-1] == '/')
{
- while (*cur && !strncmp((*cur)->str, start, len))
+ len--;
+ subdir=SUBDIR;
+ }
+ if (len == 0) continue;
+ for (cur=&head; *cur; cur=&((*cur)->next_link))
+ {
+ if (!strncmp((*cur)->str, start, len))
{
- struct link *delme=*cur;
- *cur=(*cur)->next_link;
- free((void*) delme);
+ if ((*cur)->flags & todo) /* same action ? */
+ (*cur)->flags|= subdir; /* just merge the SUBDIR flag */
+ else if (todo == EXCLUDE)
+ {
+ struct link *delme=*cur;
+ *cur=(*cur)->next_link;
+ free((void*) delme);
+ }
+ else
+ {
+ (*cur)->flags&=~(EXCLUDE & SUBDIR);
+ (*cur)->flags|=INCLUDE | subdir;
+ }
+ goto next;
}
- } while (*cur && *(cur=&((*cur)->next_link)));
+ }
+ *cur= (struct link *) DbugMalloc(sizeof(struct link)+len);
+ memcpy((*cur)->str, start, len);
+ (*cur)->str[len]=0;
+ (*cur)->flags=todo | subdir;
+ (*cur)->next_link=0;
}
return head;
}
@@ -1352,7 +1531,7 @@ static struct link *ListCopy(struct link *orig)
{
struct link *new_malloc;
struct link *head;
- int len;
+ size_t len;
head= NULL;
while (orig != NULL)
@@ -1361,6 +1540,7 @@ static struct link *ListCopy(struct link *orig)
new_malloc= (struct link *) DbugMalloc(sizeof(struct link)+len);
memcpy(new_malloc->str, orig->str, len);
new_malloc->str[len]= 0;
+ new_malloc->flags=orig->flags;
new_malloc->next_link= head;
head= new_malloc;
orig= orig->next_link;
@@ -1373,47 +1553,52 @@ static struct link *ListCopy(struct link *orig)
*
* InList test a given string for member of a given list
*
- * SYNOPSIS
- *
- * static BOOLEAN InList(linkp, cp)
- * struct link *linkp;
- * char *cp;
- *
* DESCRIPTION
*
* Tests the string pointed to by "cp" to determine if it is in
* the list pointed to by "linkp". Linkp points to the first
- * link in the list. If linkp is NULL then the string is treated
- * as if it is in the list (I.E all strings are in the null list).
+ * link in the list. If linkp is NULL or contains only EXCLUDE
+ * elements then the string is treated as if it is in the list.
* This may seem rather strange at first but leads to the desired
* operation if no list is given. The net effect is that all
* strings will be accepted when there is no list, and when there
* is a list, only those strings in the list will be accepted.
*
+ * RETURN
+ * combination of SUBDIR, INCLUDE, EXCLUDE, MATCHED flags
+ *
*/
-static BOOLEAN InList(struct link *linkp, const char *cp)
+static int InList(struct link *linkp, const char *cp)
{
- REGISTER struct link *scan;
- REGISTER BOOLEAN result;
+ int result;
- if (linkp == NULL)
- result= TRUE;
- else
+ for (result=MATCHED; linkp != NULL; linkp= linkp->next_link)
{
- result= FALSE;
- for (scan= linkp; scan != NULL; scan= scan->next_link)
- {
- if (!strcmp(scan->str, cp))
- {
- result= TRUE;
- break;
- }
- }
+ if (!fnmatch(linkp->str, cp, 0))
+ return linkp->flags;
+ if (!(linkp->flags & EXCLUDE))
+ result=NOT_MATCHED;
+ if (linkp->flags & SUBDIR)
+ result|=SUBDIR;
}
return result;
}
+/*
+ * FUNCTION
+ *
+ * ListFlags returns aggregated list flags (ORed over all elements)
+ *
+ */
+
+static uint ListFlags(struct link *linkp)
+{
+ uint f;
+ for (f=0; linkp != NULL; linkp= linkp->next_link)
+ f|= linkp->flags;
+ return f;
+}
/*
* FUNCTION
@@ -1440,8 +1625,8 @@ static void PushState(CODE_STATE *cs)
struct settings *new_malloc;
new_malloc= (struct settings *) DbugMalloc(sizeof(struct settings));
+ bzero(new_malloc, sizeof(*new_malloc));
new_malloc->next= cs->stack;
- new_malloc->out_file= NULL;
cs->stack= new_malloc;
}
@@ -1472,11 +1657,17 @@ static void FreeState(CODE_STATE *cs, struct settings *state, int free_state)
FreeList(state->processes);
if (!is_shared(state, p_functions))
FreeList(state->p_functions);
+
if (!is_shared(state, out_file))
DBUGCloseFile(cs, state->out_file);
- (void) fflush(cs->stack->out_file);
- if (state->prof_file)
+ else
+ (void) fflush(state->out_file);
+
+ if (!is_shared(state, prof_file))
DBUGCloseFile(cs, state->prof_file);
+ else
+ (void) fflush(state->prof_file);
+
if (free_state)
free((void*) state);
}
@@ -1503,8 +1694,12 @@ void _db_end_()
{
struct settings *discard;
static struct settings tmp;
- CODE_STATE *cs=0;
-
+ CODE_STATE *cs;
+ /*
+ Set _dbug_on_ to be able to do full reset even when DEBUGGER_OFF was
+ called after dbug was initialized
+ */
+ _dbug_on_= 1;
get_code_state_or_return;
while ((discard= cs->stack))
@@ -1538,25 +1733,30 @@ void _db_end_()
*
* DoTrace check to see if tracing is current enabled
*
- * SYNOPSIS
- *
- * static BOOLEAN DoTrace(stack)
- *
* DESCRIPTION
*
- * Checks to see if tracing is enabled based on whether the
- * user has specified tracing, the maximum trace depth has
- * not yet been reached, the current function is selected,
- * and the current process is selected. Returns TRUE if
- * tracing is enabled, FALSE otherwise.
+ * Checks to see if dbug in this function is enabled based on
+ * whether the maximum trace depth has been reached, the current
+ * function is selected, and the current process is selected.
*
*/
-static BOOLEAN DoTrace(CODE_STATE *cs)
+static int DoTrace(CODE_STATE *cs)
{
- return (TRACING && cs->level <= cs->stack->maxdepth &&
- InList(cs->stack->functions, cs->func) &&
- InList(cs->stack->processes, cs->process));
+ if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
+ InList(cs->stack->processes, cs->process) & (MATCHED|INCLUDE))
+ switch(InList(cs->stack->functions, cs->func)) {
+ case INCLUDE|SUBDIR: return ENABLE_TRACE;
+ case INCLUDE: return DO_TRACE;
+ case MATCHED|SUBDIR:
+ case NOT_MATCHED|SUBDIR:
+ case MATCHED: return framep_trace_flag(cs, cs->framep) ?
+ DO_TRACE : DONT_TRACE;
+ case EXCLUDE:
+ case NOT_MATCHED: return DONT_TRACE;
+ case EXCLUDE|SUBDIR: return DISABLE_TRACE;
+ }
+ return DONT_TRACE;
}
@@ -1584,62 +1784,27 @@ static BOOLEAN DoProfile(CODE_STATE *cs)
{
return PROFILING &&
cs->level <= cs->stack->maxdepth &&
- InList(cs->stack->p_functions, cs->func) &&
- InList(cs->stack->processes, cs->process);
+ InList(cs->stack->p_functions, cs->func) & (INCLUDE|MATCHED) &&
+ InList(cs->stack->processes, cs->process) & (INCLUDE|MATCHED);
}
#endif
FILE *_db_fp_(void)
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return NULL;
return cs->stack->out_file;
}
-
-/*
- * FUNCTION
- *
- * _db_strict_keyword_ test keyword for member of keyword list
- *
- * SYNOPSIS
- *
- * BOOLEAN _db_strict_keyword_(keyword)
- * char *keyword;
- *
- * DESCRIPTION
- *
- * Similar to _db_keyword_, but keyword is NOT accepted if keyword list
- * is empty. Used in DBUG_EXECUTE_IF() - for actions that must not be
- * executed by default.
- *
- * Returns TRUE if keyword accepted, FALSE otherwise.
- *
- */
-
-BOOLEAN _db_strict_keyword_(const char *keyword)
-{
- CODE_STATE *cs=0;
- get_code_state_or_return FALSE;
- if (!DEBUGGING || cs->stack->keywords == NULL)
- return FALSE;
- return _db_keyword_(cs, keyword);
-}
-
/*
* FUNCTION
*
* _db_keyword_ test keyword for member of keyword list
*
- * SYNOPSIS
- *
- * BOOLEAN _db_keyword_(keyword)
- * char *keyword;
- *
* DESCRIPTION
*
* Test a keyword to determine if it is in the currently active
- * keyword list. As with the function list, a keyword is accepted
+ * keyword list. If strict=0, a keyword is accepted
* if the list is null, otherwise it must match one of the list
* members. When debugging is not on, no keywords are accepted.
* After the maximum trace level is exceeded, no keywords are
@@ -1651,36 +1816,13 @@ BOOLEAN _db_strict_keyword_(const char *keyword)
*
*/
-BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword)
-{
- get_code_state_or_return FALSE;
-
- return (DEBUGGING &&
- (!TRACING || cs->level <= cs->stack->maxdepth) &&
- InList(cs->stack->functions, cs->func) &&
- InList(cs->stack->keywords, keyword) &&
- InList(cs->stack->processes, cs->process));
-}
-
-/*
- * FUNCTION
- *
- * _db_keywords_ test keyword formed by a set of strings for member
- * of keyword list
- *
- * DESCRIPTION
- *
- * This function is similar to _db_keyword but receives a set of strings to
- * be concatenated in order to make the keyword to be compared.
- */
-
-BOOLEAN _db_keywords_(const char *function, const char *type)
+BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict)
{
- char dest[_DBUG_MAX_FUNC_NAME_ + 1];
-
- strxnmov(dest, _DBUG_MAX_FUNC_NAME_, function, type, NULL);
+ get_code_state_if_not_set_or_return FALSE;
+ strict=strict ? INCLUDE : INCLUDE|MATCHED;
- return _db_strict_keyword_(dest);
+ return DEBUGGING && DoTrace(cs) & DO_TRACE &&
+ InList(cs->stack->keywords, keyword) & strict;
}
/*
@@ -1848,7 +1990,7 @@ static void DBUGOpenFile(CODE_STATE *cs,
{
if (end)
{
- int len=end-name;
+ size_t len=end-name;
memcpy(cs->stack->name, name, len);
cs->stack->name[len]=0;
}
@@ -1971,12 +2113,12 @@ static FILE *OpenProfile(CODE_STATE *cs, const char *name)
static void DBUGCloseFile(CODE_STATE *cs, FILE *fp)
{
- if (fp != stderr && fp != stdout && fclose(fp) == EOF)
+ if (fp && fp != stderr && fp != stdout && fclose(fp) == EOF)
{
pthread_mutex_lock(&THR_LOCK_dbug);
(void) fprintf(cs->stack->out_file, ERR_CLOSE, cs->process);
perror("");
- dbug_flush(cs);
+ DbugFlush(cs);
}
}
@@ -2005,7 +2147,7 @@ static void DbugExit(const char *why)
CODE_STATE *cs=code_state();
(void) fprintf(stderr, ERR_ABORT, cs ? cs->process : "(null)", why);
(void) fflush(stderr);
- exit(1);
+ DBUG_ABORT();
}
@@ -2193,7 +2335,7 @@ static void ChangeOwner(CODE_STATE *cs, char *pathname)
EXPORT void _db_setjmp_()
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
cs->jmplevel= cs->level;
@@ -2220,7 +2362,7 @@ EXPORT void _db_setjmp_()
EXPORT void _db_longjmp_()
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
cs->level= cs->jmplevel;
@@ -2271,11 +2413,9 @@ char *s;
/* This is because some systems (MSDOS!!) dosn't flush fileheader */
/* and dbug-file isn't readable after a system crash !! */
-static void dbug_flush(CODE_STATE *cs)
+static void DbugFlush(CODE_STATE *cs)
{
-#ifndef THREAD
if (cs->stack->flags & FLUSH_ON_WRITE)
-#endif
{
(void) fflush(cs->stack->out_file);
if (cs->stack->delay)
@@ -2283,12 +2423,22 @@ static void dbug_flush(CODE_STATE *cs)
}
if (!cs->locked)
pthread_mutex_unlock(&THR_LOCK_dbug);
-} /* dbug_flush */
+} /* DbugFlush */
+
+
+/* For debugging */
+
+void _db_flush_()
+{
+ CODE_STATE *cs;
+ get_code_state_or_return;
+ (void) fflush(cs->stack->out_file);
+}
void _db_lock_file_()
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
pthread_mutex_lock(&THR_LOCK_dbug);
cs->locked=1;
@@ -2296,7 +2446,7 @@ void _db_lock_file_()
void _db_unlock_file_()
{
- CODE_STATE *cs=0;
+ CODE_STATE *cs;
get_code_state_or_return;
cs->locked=0;
pthread_mutex_unlock(&THR_LOCK_dbug);
@@ -2304,7 +2454,7 @@ void _db_unlock_file_()
const char* _db_get_func_(void)
{
- CODE_STATE *cs= 0;
+ CODE_STATE *cs;
get_code_state_or_return NULL;
return cs->func;
}
diff --git a/dbug/dbug_add_tags.pl b/dbug/dbug_add_tags.pl
index 141a2ed85f1..3e51a54c707 100755
--- a/dbug/dbug_add_tags.pl
+++ b/dbug/dbug_add_tags.pl
@@ -7,7 +7,7 @@ $ctags="exctags -x -f - --c-types=f -u";
sub get_tag {
local $.; local $_=<TAGS>;
($symbol, $line)= /^(.*\S)\s+function\s+(\d+)/;
- $symbol=$1 if /\s(\S+)\s*\(/;
+ $symbol=$1 if /[\s*]([^\s*]+)\s*\(/;
$line=1e50 unless $line;
}
@@ -51,7 +51,7 @@ while($src=shift)
$skip=!$semicolon;
$semicolon= /;\s*$/;
print && next if $skip ||
- (/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/ && !/^\s*return/);
+ (/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/ && !/^\s*return\b/);
last if /DBUG_ENTER/;
print "$tab DBUG_ENTER(\"$symbol\");\n";
print "\n" unless $_ eq "\n";
diff --git a/dbug/doinstall.sh b/dbug/doinstall.sh
deleted file mode 100644
index 707f193c761..00000000000
--- a/dbug/doinstall.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-
-# Warning - first line left blank for sh/csh/ksh compatibility. Do not
-# remove it. fnf@Unisoft
-
-# doinstall.sh --- figure out environment and do recursive make with
-# appropriate pathnames. Works under SV or BSD.
-
-if [ -r /usr/include/search.h ]
-then
- # System V
- $* LLIB=/usr/lib
-else
- # 4.2 BSD
- $* LLIB=/usr/lib/lint
-fi
diff --git a/dbug/install.sh b/dbug/install.sh
deleted file mode 100644
index 7226e01b1cf..00000000000
--- a/dbug/install.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-
-# WARNING -- first line intentionally left blank for sh/csh/ksh
-# compatibility. Do not remove it! FNF, UniSoft Systems.
-#
-# Usage is:
-# install <from> <to>
-#
-# The file <to> is replaced with the file <from>, after first
-# moving <to> to a backup file. The backup file name is created
-# by prepending the filename (after removing any leading pathname
-# components) with "OLD".
-#
-# This script is currently not real robust in the face of signals
-# or permission problems. It also does not do (by intention) all
-# the things that the System V or BSD install scripts try to do
-#
-
-if [ $# -ne 2 ]
-then
- echo "usage: $0 <from> <to>"
- exit 1
-fi
-
-# Now extract the dirname and basename components. Unfortunately, BSD does
-# not have dirname, so we do it the hard way.
-
-fd=`expr $1'/' : '\(/\)[^/]*/$' \| $1'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \| .`
-ff=`basename $1`
-td=`expr $2'/' : '\(/\)[^/]*/$' \| $2'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \| .`
-tf=`basename $2`
-
-# Now test to make sure that they are not the same files.
-
-if [ $fd/$ff = $td/$tf ]
-then
- echo "install: input and output are same files"
- exit 2
-fi
-
-# Save a copy of the "to" file as a backup.
-
-if test -f $td/$tf
-then
- if test -f $td/OLD$tf
- then
- rm -f $td/OLD$tf
- fi
- mv $td/$tf $td/OLD$tf
- if [ $? != 0 ]
- then
- exit 3
- fi
-fi
-
-# Now do the copy and return appropriate status
-
-cp $fd/$ff $td/$tf
-if [ $? != 0 ]
-then
- exit 4
-else
- exit 0
-fi
-
diff --git a/dbug/mklintlib.sh b/dbug/mklintlib.sh
deleted file mode 100644
index 6963016f334..00000000000
--- a/dbug/mklintlib.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-
-# Warning - first line left blank for sh/csh/ksh compatibility. Do not
-# remove it. fnf@Unisoft
-
-# mklintlib --- make a lint library, under either System V or 4.2 BSD
-#
-# usage: mklintlib <infile> <outfile>
-#
-
-if test $# -ne 2
-then
- echo "usage: mklintlib <infile> <outfile>"
- exit 1
-fi
-
-if grep SIGTSTP /usr/include/signal.h >/dev/null
-then # BSD
- if test -r /usr/include/whoami.h # 4.1
- then
- /lib/cpp -C -Dlint $1 >hlint
- (/usr/lib/lint/lint1 <hlint >$2) 2>&1 | grep -v warning
- else # 4.2
- lint -Cxxxx $1
- mv llib-lxxxx.ln $2
- fi
-else # USG
- cc -E -C -Dlint $1 | /usr/lib/lint1 -vx -Hhlint >$2
- rm -f hlint
-fi
-exit 0 # don't kill make
diff --git a/dbug/qmake.cmd b/dbug/qmake.cmd
deleted file mode 100644
index ebd4432f7fc..00000000000
--- a/dbug/qmake.cmd
+++ /dev/null
@@ -1,4 +0,0 @@
-CL -I\my\include -AL -Gsm2 -FPi -DDBUG_OFF *.c
-rm \my\lib\dbug.lib
-lib.exe \my\lib\dbug dbug.obj sanity.obj;
-link /NOD /STACK:8000 main factoria,factoria,,DBUG+STRINGS+LLIBCEP+DOSCALLS;
diff --git a/dbug/remove_function_from_trace.pl b/dbug/remove_function_from_trace.pl
new file mode 100755
index 00000000000..1da9e25f9ba
--- /dev/null
+++ b/dbug/remove_function_from_trace.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+
+die <<EEE unless @ARGV;
+Usage: $0 func1 [func2 [ ...] ]
+
+This filter (stdin->stdout) removes lines from dbug trace that were generated
+by specified functions and all functions down the call stack. Produces the
+same effect as if the original source had DBUG_PUSH(""); right after
+DBUG_ENTER() and DBUG_POP(); right before DBUG_RETURN in every such a function.
+EEE
+
+$re=join('|', @ARGV);
+$skip='';
+
+while(<STDIN>) {
+ print unless $skip;
+ next unless /^(?:.*: )*((?:\| )*)([<>])($re)\n/o;
+ if ($2 eq '>') {
+ $skip=$1.$3 unless $skip;
+ next;
+ }
+ next if $skip ne $1.$3;
+ $skip='';
+ print;
+}
diff --git a/dbug/tests-t.pl b/dbug/tests-t.pl
new file mode 100755
index 00000000000..de9ed6f6ab9
--- /dev/null
+++ b/dbug/tests-t.pl
@@ -0,0 +1,496 @@
+#!/usr/bin/env perl
+
+#
+# A driver program to test DBUG features - runs tests (shell commands)
+# from the end of file to invoke tests.c, which does the real dbug work.
+#
+
+use Test::More;
+
+$exe=$0;
+
+die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /;
+
+# load tests
+@tests=();
+while (<DATA>) {
+ if (/^% \.\/tests /) {
+ push @tests, [ $' ]
+ } elsif (/^#/) {
+ next;
+ } else {
+ push @{$tests[$#tests]}, $_
+ }
+}
+
+plan skip_all => "because dbug is disabled" if system $exe;
+
+plan tests => scalar(@tests);
+
+for (@tests) {
+ $t=$exe . shift @$_;
+ chomp($t);
+ open F, '-|', $t or die "open($t|): $!";
+ local $";
+ $out=join($", <F>); close(F);
+ # special cases are handled here:
+ $out =~ s/Memory: 0x[0-9A-Fa-f]+/Memory: 0x####/g if $t =~ /dump/;
+ # compare ("\n" at the beginning makes better output in case of errors)
+ is("\n$out","\n@$_", $t);
+}
+
+__DATA__
+% ./tests -#d
+func2: info: s=ok
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+main: explain: dbug explained: d
+func2: info: s=ok
+% ./tests d,ret3
+=> evaluate: OFF
+=> evaluate_if: OFF
+#
+## Testing negative lists
+#
+% ./tests d:-d,ret3
+func2: info: s=ko
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+main: explain: dbug explained: d:-d,ret3
+func2: info: s=ko
+% ./tests t:-d,ret3
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| <func2
+<main
+% ./tests t:d,info:-d,ret3
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | | info: s=ko
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| | info: s=ko
+| <func2
+<main
+% ./tests t:d,info:-d,ret3:-f,func2
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| | >func3
+| | <func3
+<main
+% ./tests t:d,info:-d,ret3:-f,func2 d,evaluate
+=> evaluate: ON
+=> evaluate_if: OFF
+% ./tests t:d,info:-d,ret3:-f,func2 d,evaluate_if
+=> evaluate: OFF
+=> evaluate_if: ON
+% ./tests t:d:-d,ret3:-f,func2 d,evaluate_if
+=> evaluate: OFF
+=> evaluate_if: ON
+% ./tests t:d:-d,ret3:-f,func2
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+| explain: dbug explained: d:-d,ret3:f:-f,func2:t
+| | >func3
+| | <func3
+<main
+#
+## Adding incremental settings to the brew
+#
+% ./tests t:d:-d,ret3:-f,func2 +d,evaluate_if
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+=> evaluate: OFF
+=> evaluate_if: ON
+| | >func3
+| | <func3
+<main
+#
+## DBUG_DUMP
+#
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+| dump: Memory: 0x#### Bytes: (27)
+64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
+74
+=> evaluate: OFF
+=> evaluate_if: OFF
+| | >func3
+| | <func3
+<main
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+| dump: Memory: 0x#### Bytes: (27)
+64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
+74
+=> evaluate: OFF
+=> evaluate_if: OFF
+| | >func3
+| | <func3
+<main
+% ./tests t:d:-d,ret3:f:-f,func2:+d,dump
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+| dump: Memory: 0x#### Bytes: (27)
+64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
+74
+=> evaluate: OFF
+=> evaluate_if: OFF
+| | >func3
+| | <func3
+<main
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+| dump: Memory: 0x#### Bytes: (35)
+64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
+66 2C 66 75 6E 63 32 3A 74
+=> evaluate: OFF
+=> evaluate_if: OFF
+| explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:t
+| | >func3
+| | <func3
+<main
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P
+dbug: >main
+dbug-tests: | >func1
+dbug-tests: | | | >func3
+dbug-tests: | | | <func3
+dbug-tests: | <func1
+dbug-tests: | dump: Memory: 0x#### Bytes: (37)
+64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
+66 2C 66 75 6E 63 32 3A 50 3A 74
+=> evaluate: OFF
+=> evaluate_if: OFF
+dbug-tests: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:P:t
+dbug-tests: | | >func3
+dbug-tests: | | <func3
+dbug-tests: <main
+% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P:F
+dbug: tests.c: >main
+dbug-tests: tests.c: | >func1
+dbug-tests: tests.c: | | | >func3
+dbug-tests: tests.c: | | | <func3
+dbug-tests: tests.c: | <func1
+dbug-tests: tests.c: | dump: Memory: 0x#### Bytes: (39)
+64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
+66 2C 66 75 6E 63 32 3A 46 3A 50 3A 74
+=> evaluate: OFF
+=> evaluate_if: OFF
+dbug-tests: tests.c: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:F:P:t
+dbug-tests: tests.c: | | >func3
+dbug-tests: tests.c: | | <func3
+dbug-tests: tests.c: <main
+#
+## DBUG_EXPLAIN, DBUG_PUSH, DBUG_POP, DBUG_SET
+#
+% ./tests t:d:-d,ret3:f:-f,func2
+>main
+| >func1
+| | | >func3
+| | | <func3
+| <func1
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+| explain: dbug explained: d:-d,ret3:f:-f,func2:t
+| | >func3
+| | <func3
+<main
+% ./tests t:d:-d,ret3
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | | info: s=ko
+| | <func2
+| <func1
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+| explain: dbug explained: d:-d,ret3:t
+| >func2
+| | >func3
+| | <func3
+| | info: s=ko
+| <func2
+<main
+% ./tests d,info:-d,ret3:d,push
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| | info: s=ko
+| <func2
+<main
+% ./tests d,info:-d,ret3:d,push,explain
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
+| explain: dbug explained: d,info,push,explain:-d,ret3:t
+| >func2
+| | >func3
+| | <func3
+| | info: s=ko
+| <func2
+<main
+% ./tests d,info:-d,ret3:d,explain
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
+main: explain: dbug explained: d,info,explain:-d,ret3
+func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,pop
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
+% ./tests d,info:-d,ret3:d,explain t:d,pop
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+main: explain: dbug explained: d,info,explain:-d,ret3
+func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,pop +t
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | | info: s=ko
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+main: explain: dbug explained: d,info,explain,pop:-d,ret3
+func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,set
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
+ tests.c: main: explain: dbug explained: d,info,explain,set:-d,ret3:F
+ tests.c: func2: info: s=ko
+% ./tests d,info:-d,ret3:d,explain,set:t
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | | info: s=ko
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+ tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
+ tests.c: | >func2
+ tests.c: | | >func3
+ tests.c: | | <func3
+ tests.c: | | info: s=ko
+ tests.c: | <func2
+ tests.c: <main
+% ./tests t d,info:-d,ret3:d,explain,set:t
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | | info: s=ko
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+ tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
+ tests.c: | >func2
+ tests.c: | | >func3
+ tests.c: | | <func3
+ tests.c: | | info: s=ko
+ tests.c: | <func2
+ tests.c: <main
+% ./tests t d,info:-d,ret3:d,explain,set,pop
+func2: info: s=ko
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| <func2
+<main
+% ./tests t:f,func2
+| | >func2
+| | <func2
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| <func2
+#
+## Testing SUBDIR rules
+#
+% ./tests t:-f,func2/:d
+>main
+| >func1
+| <func1
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+| explain: dbug explained: d:f:-f,func2/:t
+<main
+% ./tests t:f,func1/:d
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | | info: s=ok
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+% ./tests t:f,main/:d,pop
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | <func2
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+% ./tests f,main/:d,push
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| <func2
+<main
+#
+## Testing FixTraceFlags() - when we need to traverse the call stack
+# (these tests fail with FixTraceFlags() disabled)
+#
+# delete the INCLUDE rule up the stack
+% ./tests t:f,func1/ --push1=t:f,func3/
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | <func2
+=> push1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| | >func3
+| | <func3
+# delete the EXCLUDE rule up the stack
+% ./tests t:-f,func1/ --push1=t
+>main
+=> push1
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| <func2
+<main
+# add the INCLUDE rule up the stack
+% ./tests t:f,func3 --push1=t:f,main/
+| | | >func3
+| | | <func3
+=> push1
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| <func2
+<main
+# add the EXCLUDE rule up the stack
+% ./tests t --push1=t:-f,main/
+>main
+| >func1
+| | >func2
+| | | >func3
+| | | <func3
+| | <func2
+=> push1
+=> evaluate: OFF
+=> evaluate_if: OFF
+# change the defaults
+% ./tests t:f,func3 --push1=t
+| | | >func3
+| | | <func3
+=> push1
+| <func1
+=> evaluate: OFF
+=> evaluate_if: OFF
+| >func2
+| | >func3
+| | <func3
+| <func2
+<main
+# repeated keyword
+% ./tests d:-d,info,info
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+main: explain: dbug explained: d:-d,info
+% ./tests d:-d,info/,info
+=> execute
+=> evaluate: ON
+=> evaluate_if: OFF
+main: explain: dbug explained: d:-d,info/
diff --git a/dbug/tests.c b/dbug/tests.c
new file mode 100644
index 00000000000..d76266d34a3
--- /dev/null
+++ b/dbug/tests.c
@@ -0,0 +1,87 @@
+/*
+ A program to test DBUG features. Used by tests-t.pl
+*/
+
+char *push1=0;
+
+#include <my_global.h> /* This includes dbug.h */
+#include <my_pthread.h>
+#include <string.h>
+
+const char *func3()
+{
+ DBUG_ENTER("func3");
+ DBUG_RETURN(DBUG_EVALUATE("ret3", "ok", "ko"));
+}
+
+void func2()
+{
+ const char *s;
+ DBUG_ENTER("func2");
+ s=func3();
+ DBUG_PRINT("info", ("s=%s", s));
+ DBUG_VOID_RETURN;
+}
+
+int func1()
+{
+ DBUG_ENTER("func1");
+ func2();
+ if (push1)
+ {
+ DBUG_PUSH(push1);
+ fprintf(DBUG_FILE, "=> push1\n");
+ }
+ DBUG_RETURN(10);
+}
+
+int main (int argc, char *argv[])
+{
+ int i;
+#ifdef DBUG_OFF
+ return 1;
+#endif
+ if (argc == 1)
+ return 0;
+
+#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
+ pthread_init(); /* Must be called before DBUG_ENTER */
+#endif
+#ifdef THREAD
+ my_thread_global_init();
+#endif
+ dup2(1, 2);
+ for (i = 1; i < argc; i++)
+ {
+ if (strncmp(argv[i], "--push1=", 8) == 0)
+ push1=argv[i]+8;
+ else
+ DBUG_PUSH (argv[i]);
+ }
+ {
+ DBUG_ENTER ("main");
+ DBUG_PROCESS ("dbug-tests");
+ func1();
+ DBUG_EXECUTE_IF("dump",
+ {
+ char s[1000];
+ DBUG_EXPLAIN(s, sizeof(s)-1);
+ DBUG_DUMP("dump", (uchar*)s, strlen(s));
+ });
+ DBUG_EXECUTE_IF("push", DBUG_PUSH("+t"); );
+ DBUG_EXECUTE("execute", fprintf(DBUG_FILE, "=> execute\n"); );
+ DBUG_EXECUTE_IF("set", DBUG_SET("+F"); );
+ fprintf(DBUG_FILE, "=> evaluate: %s\n",
+ DBUG_EVALUATE("evaluate", "ON", "OFF"));
+ fprintf(DBUG_FILE, "=> evaluate_if: %s\n",
+ DBUG_EVALUATE_IF("evaluate_if", "ON", "OFF"));
+ DBUG_EXECUTE_IF("pop", DBUG_POP(); );
+ {
+ char s[1000] __attribute__((unused));
+ DBUG_EXPLAIN(s, sizeof(s)-1);
+ DBUG_PRINT("explain", ("dbug explained: %s", s));
+ }
+ func2();
+ DBUG_RETURN (0);
+ }
+}
diff --git a/dbug/user.r b/dbug/user.r
index ef67ef7a7cf..847ad80b30f 100644
--- a/dbug/user.r
+++ b/dbug/user.r
@@ -512,7 +512,7 @@ possible since all code preceding the first call to
.B DBUG_PUSH
is
essentially invisible to
-.B dbug
+.I dbug
(this can be worked around by
inserting a temporary
.B DBUG_PUSH(argv[1])
@@ -708,7 +708,7 @@ EX:\ \fCDBUG_PROCESS\ (argv[0]);\fR
.SP 1
.LI DBUG_PUSH\
Sets a new debugger state by pushing the current
-.B dbug
+.I dbug
state onto an internal stack and setting up the new state using the
debug control string passed as the macro argument. The most common
usage is to set the state specified by a debug control string
@@ -769,14 +769,14 @@ the 'd' flag. Used to conditionally execute "dangerous" actions, e.g
to crash the program testing how recovery works, or to introduce an
artificial delay checking for race conditions.
.SP 1
-EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ abort\ ());\fR
+EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ DBUG_ABORT()\ ());\fR
.SP 1
.LI DBUG_EVALUATE\
The DBUG_EVALUATE macro is similar to DBUG_EXECUTE, but it can be used in
the expression context. The first argument is the debug keyword that is used to
choose whether the second (keyword is enabled) or the third (keyword is not
enabled) argument is evaluated. When
-.B dbug
+.I dbug
is compiled off, the third argument is evaluated.
.SP 1
EX:\fC
@@ -796,7 +796,7 @@ EX:\fC
.br
if (prepare_transaction () ||
.br
- DBUG_EVALUATE ("crashme", (abort (), 0), 0) ||
+ DBUG_EVALUATE ("crashme", (DBUG_ABORT(), 0), 0) ||
.br
commit_transaction () )\fR
.SP 1
@@ -875,6 +875,12 @@ library. So there will be no need to disable asserts separately with NDEBUG.
.SP 1
EX:\ \fCDBUG_ASSERT(\ a\ >\ 0\ );\fR
.SP 1
+.LI DBUG_ABORT\
+This macro could be used instead of abort(). It flushes DBUG_FILE stream
+to ensure that no
+.I dbug
+output is lost and then calls abort().
+.SP 1
.LI DBUG_EXPLAIN\
Generates control string corresponding to the current debug state.
The macro takes two arguments - a buffer to store the result string
@@ -910,17 +916,17 @@ via the
.B DBUG_PUSH
or
.B DBUG_SET
-macros. Control string consists of colon separate flags. Colons
+macros. Control string consists of colon separated flags. Colons
that are part of ':\\', ':/', or '::' are not considered flag
separators. A flag may take an argument or a list of arguments.
If a control string starts from a '+' sign it works
.I incrementally,
-that is, it can modify existing state without overriding it. In such a
-string every flag may be preceded by a '+' or '-' to enable or disable
-a corresponding option in the debugger state. This section summarizes
-the currently available debugger options and the flag characters which
-enable or disable them. Argument lists enclosed in '[' and ']' are
-optional.
+that is, it can modify existing state without overriding it. Every
+flag may be preceded by a '+' or '-' to enable or disable a
+corresponding option in the debugger state or to add or remove
+arguments to the list. This section summarizes the currently available
+debugger options and the flag characters which enable or disable them.
+Argument lists enclosed in '[' and ']' are optional.
.SP 2
.BL 22
.LI a[,file]
@@ -936,6 +942,9 @@ a complete log file in case of crashes. This mode is implicit in
multi-threaded environment.
.LI d[,keywords]
Enable output from macros with specified keywords.
+Every keyword can be a
+.I glob(7)
+pattern.
An empty list of keywords implies that all keywords are selected.
.LI D[,time]
Delay for specified time after each output line, to let output drain.
@@ -943,7 +952,19 @@ Time is given in tenths of a second (value of 10 is one second).
Default is zero.
.LI f[,functions]
Limit debugger actions to the specified list of functions.
+Every function can be a
+.I glob(7)
+pattern.
An empty list of functions implies that all functions are selected.
+Every function in the list may optionally be followed by a '/' -
+this will implicitly select all the functions down the call stack.
+.SP 1
+EX: \fCf,func1,func2/:-f,func3,func4/\fR
+.SP 1
+This would enable debugger in functions 'func1()', 'func2()' and all
+functions called from it (directly or indirectly). But not in
+functions 'func3()' or 'func4()' and all functions called from
+it.
.LI F
Mark each debugger output line with the name of the source file
containing the macro causing the output.
@@ -952,6 +973,9 @@ Mark each debugger output line with the PID (or thread ID) of the
current process.
.LI g,[functions]
Enable profiling for the specified list of functions.
+Every function can be a
+.I glob(7)
+pattern.
An empty list of functions enables profiling for all functions.
See
.B PROFILING\ WITH\ DBUG
@@ -970,7 +994,11 @@ Like 'a[,file]' but overwrite old file, do not append.
.LI O[,file]
Like 'A[,file]' but overwrite old file, do not append.
.LI p[,processes]
-Limit debugger actions to the specified processes. An empty list
+Limit debugger actions to the specified processes.
+Every name can be a
+.I glob(7)
+pattern.
+An empty list
implies all processes. This is useful for processes which run child
processes. Note that each debugger output line can be marked with the
name of the current process via the 'P' flag. The process name must
diff --git a/dbug/vargs.h b/dbug/vargs.h
deleted file mode 100644
index 4609c8301bb..00000000000
--- a/dbug/vargs.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/******************************************************************************
- * *
- * N O T I C E *
- * *
- * Copyright Abandoned, 1987, Fred Fish *
- * *
- * *
- * This previously copyrighted work has been placed into the public *
- * domain by the author and may be freely used for any purpose, *
- * private or commercial. *
- * *
- * Because of the number of inquiries I was receiving about the use *
- * of this product in commercially developed works I have decided to *
- * simply make it public domain to further its unrestricted use. I *
- * specifically would be most happy to see this material become a *
- * part of the standard Unix distributions by AT&T and the Berkeley *
- * Computer Science Research Group, and a standard part of the GNU *
- * system from the Free Software Foundation. *
- * *
- * I would appreciate it, as a courtesy, if this notice is left in *
- * all copies and derivative works. Thank you. *
- * *
- * The author makes no warranty of any kind with respect to this *
- * product and explicitly disclaims any implied warranties of mer- *
- * chantability or fitness for any particular purpose. *
- * *
- ******************************************************************************
- */
-
-
-/*
- * FILE
- *
- * vargs.h include file for environments without varargs.h
- *
- * SCCS
- *
- * @(#)vargs.h 1.2 5/8/88
- *
- * SYNOPSIS
- *
- * #include "vargs.h"
- *
- * DESCRIPTION
- *
- * This file implements a varargs macro set for use in those
- * environments where there is no system supplied varargs. This
- * generally works because systems which don't supply a varargs
- * package are precisely those which don't strictly need a varargs
- * package. Using this one then allows us to minimize source
- * code changes. So in some sense, this is a "portable" varargs
- * since it is only used for convenience, when it is not strictly
- * needed.
- *
- */
-
-/*
- * These macros allow us to rebuild an argument list on the stack
- * given only a va_list. We can use these to fake a function like
- * vfprintf, which gets a fixed number of arguments, the last of
- * which is a va_list, by rebuilding a stack and calling the variable
- * argument form fprintf. Of course this only works when vfprintf
- * is not available in the host environment, and thus is not available
- * for fprintf to call (which would give us an infinite loop).
- *
- * Note that ARGS_TYPE is a long, which lets us get several bytes
- * at a time while also preventing lots of "possible pointer alignment
- * problem" messages from lint. The messages are valid, because this
- * IS nonportable, but then we should only be using it in very
- * nonrestrictive environments, and using the real varargs where it
- * really counts.
- *
- */
-
-#define ARG0 a0
-#define ARG1 a1
-#define ARG2 a2
-#define ARG3 a3
-#define ARG4 a4
-#define ARG5 a5
-#define ARG6 a6
-#define ARG7 a7
-#define ARG8 a8
-#define ARG9 a9
-
-#define ARGS_TYPE long
-#define ARGS_LIST ARG0,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8,ARG9
-#define ARGS_DCL auto ARGS_TYPE ARGS_LIST
-
-/*
- * A pointer of type "va_list" points to a section of memory
- * containing an array of variable sized arguments of unknown
- * number. This pointer is initialized by the va_start
- * macro to point to the first byte of the first argument.
- * We can then use it to walk through the argument list by
- * incrementing it by the size of the argument being referenced.
- */
-
-typedef char *va_list;
-
-/*
- * The first variable argument overlays va_alist, which is
- * nothing more than a "handle" which allows us to get the
- * address of the first argument on the stack. Note that
- * by definition, the va_dcl macro includes the terminating
- * semicolon, which makes use of va_dcl in the source code
- * appear to be missing a semicolon.
- */
-
-#define va_dcl ARGS_TYPE va_alist;
-
-/*
- * The va_start macro takes a variable of type "va_list" and
- * initializes it. In our case, it initializes a local variable
- * of type "pointer to char" to point to the first argument on
- * the stack.
- */
-
-#define va_start(list) list = (char *) &va_alist
-
-/*
- * The va_end macro is a null operation for our use.
- */
-
-#define va_end(list)
-
-/*
- * The va_arg macro is the tricky one. This one takes
- * a va_list as the first argument, and a type as the second
- * argument, and returns a value of the appropriate type
- * while advancing the va_list to the following argument.
- * For our case, we first increment the va_list arg by the
- * size of the type being recovered, cast the result to
- * a pointer of the appropriate type, and then dereference
- * that pointer as an array to get the previous arg (which
- * is the one we wanted.
- */
-
-#define va_arg(list,type) ((type *) (list += sizeof (type)))[-1]
diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c
index 42a5cbd6877..2614946a712 100644
--- a/extra/my_print_defaults.c
+++ b/extra/my_print_defaults.c
@@ -189,6 +189,7 @@ int main(int argc, char **argv)
config_file);
}
error= 2;
+ exit(error);
}
for (argument= arguments+1 ; *argument ; argument++)
@@ -197,5 +198,5 @@ int main(int argc, char **argv)
my_free((char*) load_default_groups,MYF(0));
free_defaults(arguments);
- exit(error);
+ exit(0);
}
diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp
index 89fd5f7c7bc..2bbc0a85e8b 100644
--- a/extra/yassl/taocrypt/src/random.cpp
+++ b/extra/yassl/taocrypt/src/random.cpp
@@ -27,7 +27,6 @@
#include <time.h>
#if defined(_WIN32)
- #define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
#else
diff --git a/include/Makefile.am b/include/Makefile.am
index dd6f53f7ca2..0a7a35bd6fa 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -21,7 +21,8 @@ HEADERS_GEN_MAKE = my_config.h
HEADERS_ABI = mysql.h mysql_com.h mysql_time.h \
my_list.h my_alloc.h typelib.h mysql/plugin.h
pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \
- my_xml.h mysql_embed.h \
+ my_xml.h mysql_embed.h mysql/services.h \
+ mysql/service_my_snprintf.h mysql/service_thd_alloc.h \
my_pthread.h my_no_pthread.h \
decimal.h errmsg.h my_global.h my_net.h \
my_getopt.h sslopt-longopts.h my_dir.h \
@@ -36,7 +37,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \
my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \
my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
- my_handler.h my_time.h \
+ my_handler.h my_time.h service_versions.h \
my_vle.h my_user.h my_atomic.h atomic/nolock.h \
atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \
atomic/solaris.h \
diff --git a/include/config-win.h b/include/config-win.h
index 702c6bcdeae..364c4f92134 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -356,7 +356,6 @@ inline ulonglong double2ulonglong(double d)
#define HAVE_OPENSSL 1
#define HAVE_YASSL 1
-#define COMMUNITY_SERVER 1
#define ENABLED_PROFILING 1
/*
diff --git a/include/errmsg.h b/include/errmsg.h
index 5754e99ba5e..c55c94af169 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -100,7 +100,8 @@ extern const char *client_errors[]; /* Error messages */
#define CR_SERVER_LOST_EXTENDED 2055
#define CR_STMT_CLOSED 2056
#define CR_NEW_STMT_METADATA 2057
-#define CR_ERROR_LAST /*Copy last error nr:*/ 2057
+#define CR_ALREADY_CONNECTED 2058
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2058
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
#endif /* ERRMSG_INCLUDED */
diff --git a/include/hash.h b/include/hash.h
index 629b404e8a7..d870e17c341 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -22,40 +22,6 @@ extern "C" {
#endif
/*
- There was a problem on MacOSX with a shared object ha_example.so.
- It used hash_search(). During build of ha_example.so no libmysys
- was specified. Since MacOSX had a hash_search() in the system
- library, it built the shared object so that the dynamic linker
- linked hash_search() to the system library, which caused a crash
- when called. To come around this, we renamed hash_search() to
- my_hash_search(), as we did long ago with hash_insert() and
- hash_reset(). However, this time we made the move complete with
- all names. To keep compatibility, we redefine the old names.
- Since every C and C++ file, that uses HASH, needs to include
- this file, the change is complete. Both names could be used
- in the code, but the my_* versions are recommended now.
-*/
-#define hash_get_key my_hash_get_key
-#define hash_free_key my_hash_free_key
-#define hash_init my_hash_init
-#define hash_init2 my_hash_init2
-#define _hash_init _my_hash_init
-#define hash_free my_hash_free
-#define hash_reset my_hash_reset
-#define hash_element my_hash_element
-#define hash_search my_hash_search
-#define hash_first my_hash_first
-#define hash_next my_hash_next
-#define hash_insert my_hash_insert
-#define hash_delete my_hash_delete
-#define hash_update my_hash_update
-#define hash_replace my_hash_replace
-#define hash_check my_hash_check
-#define hash_clear my_hash_clear
-#define hash_inited my_hash_inited
-#define hash_init_opt my_hash_init_opt
-
-/*
Overhead to store an element in hash
Can be used to approximate memory consumption for a hash
*/
diff --git a/include/m_string.h b/include/m_string.h
index c24bfd7aa6c..3c4c6ea088a 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -250,16 +250,10 @@ extern size_t my_snprintf(char *to, size_t n, const char *fmt, ...)
/*
LEX_STRING -- a pair of a C-string and its length.
+ (it's part of the plugin API as a MYSQL_LEX_STRING)
*/
-#ifndef _my_plugin_h
-/* This definition must match the one given in mysql/plugin.h */
-struct st_mysql_lex_string
-{
- char *str;
- size_t length;
-};
-#endif
+#include <mysql/plugin.h>
typedef struct st_mysql_lex_string LEX_STRING;
#define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1))
diff --git a/include/my_base.h b/include/my_base.h
index a01b2ec9b82..70bd9b5e073 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -255,7 +255,17 @@ enum ha_base_keytype {
HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \
HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY)
-#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */
+/*
+ Key contains partial segments.
+
+ This flag is internal to the MySQL server by design. It is not supposed
+ neither to be saved in FRM-files, nor to be passed to storage engines.
+ It is intended to pass information into internal static sort_keys(KEY *,
+ KEY *) function.
+
+ This flag can be calculated -- it's based on key lengths comparison.
+*/
+#define HA_KEY_HAS_PART_KEY_SEG 65536
/* Automatic bits in key-flag */
diff --git a/include/my_dbug.h b/include/my_dbug.h
index 0451a868aa4..956a5504e86 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -16,103 +16,64 @@
#ifndef _dbug_h
#define _dbug_h
-#if defined(__cplusplus) && !defined(DBUG_OFF)
-class Dbug_violation_helper
-{
-public:
- inline Dbug_violation_helper() :
- _entered(TRUE)
- { }
-
- inline ~Dbug_violation_helper()
- {
- assert(!_entered);
- }
-
- inline void leave()
- {
- _entered= FALSE;
- }
-
-private:
- bool _entered;
-};
-#endif /* C++ */
-
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
#if !defined(DBUG_OFF) && !defined(_lint)
-struct _db_code_state_;
-extern int _db_keyword_(struct _db_code_state_ *cs, const char *keyword);
-extern int _db_keywords_(const char *, const char *);
-extern int _db_strict_keyword_(const char *keyword);
+
+struct _db_stack_frame_ {
+ const char *func; /* function name of the previous stack frame */
+ const char *file; /* filename of the function of previous frame */
+ uint level; /* this nesting level, highest bit enables tracing */
+ struct _db_stack_frame_ *prev; /* pointer to the previous frame */
+};
+
+struct _db_code_state_;
+extern my_bool _dbug_on_;
+extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int);
extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len);
extern int _db_explain_init_(char *buf, size_t len);
-extern void _db_setjmp_(void);
-extern void _db_longjmp_(void);
+extern int _db_is_pushed_(void);
+extern void _db_setjmp_(void);
+extern void _db_longjmp_(void);
extern void _db_process_(const char *name);
-extern void _db_push_(const char *control);
-extern void _db_pop_(void);
-extern void _db_set_(struct _db_code_state_ *cs, const char *control);
+extern void _db_push_(const char *control);
+extern void _db_pop_(void);
+extern void _db_set_(const char *control);
extern void _db_set_init_(const char *control);
-extern void _db_enter_(const char *_func_,const char *_file_,uint _line_,
- const char **_sfunc_,const char **_sfile_,
- uint *_slevel_, char ***);
-extern void _db_return_(uint _line_,const char **_sfunc_,const char **_sfile_,
- uint *_slevel_);
-extern void _db_pargs_(uint _line_,const char *keyword);
-extern void _db_doprnt_ _VARARGS((const char *format,...))
+extern void _db_enter_(const char *_func_, const char *_file_, uint _line_,
+ struct _db_stack_frame_ *_stack_frame_);
+extern void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_);
+extern void _db_pargs_(uint _line_,const char *keyword);
+extern void _db_doprnt_ _VARARGS((const char *format,...))
ATTRIBUTE_FORMAT(printf, 1, 2);
-extern void _db_dump_(uint _line_,const char *keyword,
+extern void _db_dump_(uint _line_,const char *keyword,
const unsigned char *memory, size_t length);
-extern void _db_end_(void);
-extern void _db_lock_file_(void);
-extern void _db_unlock_file_(void);
-extern FILE *_db_fp_(void);
+extern void _db_end_(void);
+extern void _db_lock_file_(void);
+extern void _db_unlock_file_(void);
+extern FILE *_db_fp_(void);
+extern void _db_flush_();
extern const char* _db_get_func_(void);
-#ifdef __cplusplus
-
-#define DBUG_ENTER(a) \
- const char *_db_func_, *_db_file_; \
- uint _db_level_; \
- char **_db_framep_; \
- Dbug_violation_helper dbug_violation_helper; \
- _db_enter_ (a, __FILE__, __LINE__, &_db_func_, &_db_file_, \
- &_db_level_, &_db_framep_)
-#define DBUG_VIOLATION_HELPER_LEAVE dbug_violation_helper.leave()
-
-#else /* C */
-
-#define DBUG_ENTER(a) \
- const char *_db_func_, *_db_file_; \
- uint _db_level_; \
- char **_db_framep_; \
- _db_enter_ (a, __FILE__, __LINE__, &_db_func_, &_db_file_, \
- &_db_level_, &_db_framep_)
-#define DBUG_VIOLATION_HELPER_LEAVE do { } while(0)
-
-#endif /* C++ */
-
-#define DBUG_LEAVE \
- DBUG_VIOLATION_HELPER_LEAVE; \
- _db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_)
+#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \
+ _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
+#define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_)
#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
#define DBUG_EXECUTE(keyword,a1) \
- do {if (_db_keyword_(0, (keyword))) { a1 }} while(0)
+ do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0)
#define DBUG_EXECUTE_IF(keyword,a1) \
- do {if (_db_strict_keyword_ (keyword)) { a1 } } while(0)
+ do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0)
#define DBUG_EVALUATE(keyword,a1,a2) \
- (_db_keyword_(0,(keyword)) ? (a1) : (a2))
+ (_db_keyword_(0,(keyword), 0) ? (a1) : (a2))
#define DBUG_EVALUATE_IF(keyword,a1,a2) \
- (_db_strict_keyword_((keyword)) ? (a1) : (a2))
+ (_db_keyword_(0,(keyword), 1) ? (a1) : (a2))
#define DBUG_PRINT(keyword,arglist) \
do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0)
#define DBUG_PUSH(a1) _db_push_ (a1)
#define DBUG_POP() _db_pop_ ()
-#define DBUG_SET(a1) _db_set_ (0, (a1))
+#define DBUG_SET(a1) _db_set_ (a1)
#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1)
#define DBUG_PROCESS(a1) _db_process_(a1)
#define DBUG_FILE _db_fp_()
@@ -125,54 +86,66 @@ extern const char* _db_get_func_(void);
#define DBUG_ASSERT(A) assert(A)
#define DBUG_EXPLAIN(buf,len) _db_explain_(0, (buf),(len))
#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len))
-#define IF_DBUG(A) A
-#define _DBUG_MAX_FUNC_NAME_ 255
+#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0)
+#define DEBUGGER_ON do { _dbug_on_= 1; } while(0)
+#ifndef __WIN__
+#define DBUG_ABORT() (_db_flush_(), abort())
+#else
+/*
+ Avoid popup with abort/retry/ignore buttons. When BUG#31745 is fixed we can
+ call abort() instead of _exit(3) (now it would cause a "test signal" popup).
+*/
+#include <crtdbg.h>
+#define DBUG_ABORT() (_db_flush_(),\
+ (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE),\
+ (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR),\
+ _exit(3))
+#endif
#define DBUG_CHECK_CRASH(func, op) \
- do { \
- if (_db_keywords_((func), (op))) \
- { abort(); } \
- } while (0)
+ do { char _dbuf_[255]; strxnmov(_dbuf_, sizeof(_dbuf_)-1, (func), (op)); \
+ DBUG_EXECUTE_IF(_dbuf_, DBUG_ABORT()); } while(0)
#define DBUG_CRASH_ENTER(func) \
DBUG_ENTER(func); DBUG_CHECK_CRASH(func, "_crash_enter")
#define DBUG_CRASH_RETURN(val) \
- do {DBUG_CHECK_CRASH(_db_get_func_(), "_crash_return"); \
- DBUG_RETURN(val);} while(0)
+ DBUG_CHECK_CRASH(_db_get_func_(), "_crash_return")
#define DBUG_CRASH_VOID_RETURN \
- do {DBUG_CHECK_CRASH (_db_get_func_(), "_crash_return"); \
- DBUG_VOID_RETURN;} while(0)
-#else /* No debugger */
+ DBUG_CHECK_CRASH (_db_get_func_(), "_crash_return")
+
+#else /* No debugger */
#define DBUG_ENTER(a1)
#define DBUG_LEAVE
-#define DBUG_VIOLATION_HELPER_LEAVE
-#define DBUG_RETURN(a1) do { return(a1); } while(0)
-#define DBUG_VOID_RETURN do { return; } while(0)
-#define DBUG_EXECUTE(keyword,a1) do { } while(0)
-#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0)
+#define DBUG_RETURN(a1) do { return(a1); } while(0)
+#define DBUG_VOID_RETURN do { return; } while(0)
+#define DBUG_EXECUTE(keyword,a1) do { } while(0)
+#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0)
#define DBUG_EVALUATE(keyword,a1,a2) (a2)
#define DBUG_EVALUATE_IF(keyword,a1,a2) (a2)
-#define DBUG_PRINT(keyword,arglist) do { } while(0)
-#define DBUG_PUSH(a1)
-#define DBUG_SET(a1) do { } while(0)
-#define DBUG_SET_INITIAL(a1) do { } while(0)
-#define DBUG_POP()
-#define DBUG_PROCESS(a1)
+#define DBUG_PRINT(keyword,arglist) do { } while(0)
+#define DBUG_PUSH(a1) do { } while(0)
+#define DBUG_SET(a1) do { } while(0)
+#define DBUG_SET_INITIAL(a1) do { } while(0)
+#define DBUG_POP() do { } while(0)
+#define DBUG_PROCESS(a1) do { } while(0)
#define DBUG_SETJMP(a1) setjmp(a1)
#define DBUG_LONGJMP(a1) longjmp(a1)
-#define DBUG_DUMP(keyword,a1,a2) do { } while(0)
-#define DBUG_END()
-#define DBUG_ASSERT(A) do { } while(0)
-#define DBUG_LOCK_FILE
+#define DBUG_DUMP(keyword,a1,a2) do { } while(0)
+#define DBUG_END() do { } while(0)
+#define DBUG_ASSERT(A) do { } while(0)
+#define DBUG_LOCK_FILE do { } while(0)
#define DBUG_FILE (stderr)
-#define DBUG_UNLOCK_FILE
+#define DBUG_UNLOCK_FILE do { } while(0)
#define DBUG_EXPLAIN(buf,len)
#define DBUG_EXPLAIN_INITIAL(buf,len)
-#define IF_DBUG(A)
+#define DEBUGGER_OFF do { } while(0)
+#define DEBUGGER_ON do { } while(0)
+#define DBUG_ABORT() abort()
#define DBUG_CRASH_ENTER(func)
-#define DBUG_CRASH_RETURN(val) do { return(val); } while(0)
-#define DBUG_CRASH_VOID_RETURN do { return; } while(0)
+#define DBUG_CRASH_RETURN(val) do { return(val); } while(0)
+#define DBUG_CRASH_VOID_RETURN do { return; } while(0)
+
#endif
-#ifdef __cplusplus
+#ifdef __cplusplus
}
#endif
#endif
diff --git a/include/my_global.h b/include/my_global.h
index ca1e1a9d845..f6d1592fc6f 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -649,8 +649,6 @@ C_MODE_END
# endif
#endif
-#include <my_dbug.h>
-
#define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/
#define ASCII_BITS_USED 8 /* Bit char used */
#define NEAR_F /* No near function handling */
@@ -1177,6 +1175,8 @@ typedef char bool; /* Ordinary boolean values 0 1 */
#define reg16 register
#endif
+#include <my_dbug.h>
+
/*
Sometimes we want to make sure that the variable is not put into
a register in debugging mode so we can see its value in the core
diff --git a/include/my_pthread.h b/include/my_pthread.h
index b4fe1203d2b..b6d9feae067 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -670,6 +670,7 @@ struct st_my_thread_var
};
extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
+extern void **my_thread_var_dbug();
extern uint my_thread_end_wait_time;
#define my_thread_var (_my_thread_var())
#define my_errno my_thread_var->thr_errno
diff --git a/include/my_sys.h b/include/my_sys.h
index b4366a4cd3d..3c8df28b151 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -60,7 +60,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_WME 16 /* Write message on error */
#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */
#define MY_IGNORE_BADFD 32 /* my_sync: ignore 'bad descriptor' errors */
-#define MY_SYNC_DIR 1024 /* my_create/delete/rename: sync directory */
+#define MY_SYNC_DIR 8192 /* my_create/delete/rename: sync directory */
#define MY_RAID 64 /* Support for RAID */
#define MY_FULL_IO 512 /* For my_read - loop intil I/O is complete */
#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
@@ -683,6 +683,8 @@ extern void my_error _VARARGS((int nr,myf MyFlags, ...));
extern void my_printf_error _VARARGS((uint my_err, const char *format,
myf MyFlags, ...))
ATTRIBUTE_FORMAT(printf, 2, 4);
+extern void my_printv_error(uint error, const char *format, myf MyFlags,
+ va_list ap);
extern int my_error_register(const char** (*get_errmsgs) (),
int first, int last);
extern const char **my_error_unregister(int first, int last);
diff --git a/include/myisam.h b/include/myisam.h
index 70c6f33f118..2df7ccf6dfa 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -432,6 +432,10 @@ typedef struct st_mi_check_param
const char *db_name, *table_name;
const char *op_name;
enum_mi_stats_method stats_method;
+#ifdef THREAD
+ pthread_mutex_t print_msg_mutex;
+ my_bool need_print_msg_lock;
+#endif
} MI_CHECK;
typedef struct st_sort_ft_buf
diff --git a/include/mysql.h b/include/mysql.h
index 70faf3cb2c1..13060264ee7 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -188,24 +188,10 @@ struct st_mysql_options {
unsigned long max_allowed_packet;
my_bool use_ssl; /* if to use SSL or not */
my_bool compress,named_pipe;
- /*
- On connect, find out the replication role of the server, and
- establish connections to all the peers
- */
- my_bool rpl_probe;
- /*
- Each call to mysql_real_query() will parse it to tell if it is a read
- or a write, and direct it to the slave or the master
- */
- my_bool rpl_parse;
- /*
- If set, never read from a master, only from slave, when doing
- a read that is replication-aware
- */
- my_bool no_master_reads;
-#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
- my_bool separate_thread;
-#endif
+ my_bool unused1;
+ my_bool unused2;
+ my_bool unused3;
+ my_bool unused4;
enum mysql_option methods_to_use;
char *client_ip;
/* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
@@ -232,15 +218,6 @@ enum mysql_protocol_type
MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET,
MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
};
-/*
- There are three types of queries - the ones that have to go to
- the master, the ones that go to a slave, and the adminstrative
- type which must happen on the pivot connectioin
-*/
-enum mysql_rpl_type
-{
- MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
-};
typedef struct character_set
{
@@ -285,21 +262,8 @@ typedef struct st_mysql
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
-
- /*
- Set if this is the original connection, not a master or a slave we have
- added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
- */
- my_bool rpl_pivot;
- /*
- Pointers to the master, and the next slave connections, points to
- itself if lone connection.
- */
- struct st_mysql* master, *next_slave;
-
- struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
- /* needed for send/read/store/use result to work correctly with replication */
- struct st_mysql* last_used_con;
+ my_bool unused1;
+ void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; /* list of all statements */
const struct st_mysql_methods *methods;
@@ -333,35 +297,12 @@ typedef struct st_mysql_res {
void *extension;
} MYSQL_RES;
-#define MAX_MYSQL_MANAGER_ERR 256
-#define MAX_MYSQL_MANAGER_MSG 256
-
-#define MANAGER_OK 200
-#define MANAGER_INFO 250
-#define MANAGER_ACCESS 401
-#define MANAGER_CLIENT_ERR 450
-#define MANAGER_INTERNAL_ERR 500
#if !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT)
#define MYSQL_CLIENT
#endif
-typedef struct st_mysql_manager
-{
- NET net;
- char *host, *user, *passwd;
- char *net_buf, *net_buf_pos, *net_data_end;
- unsigned int port;
- int cmd_status;
- int last_errno;
- int net_buf_size;
- my_bool free_me;
- my_bool eof;
- char last_error[MAX_MYSQL_MANAGER_ERR];
- void *extension;
-} MYSQL_MANAGER;
-
typedef struct st_mysql_parameters
{
unsigned long *p_max_allowed_packet;
@@ -454,16 +395,6 @@ int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql);
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql);
-/* perform query on master */
-my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
- unsigned long length);
-my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
-/* perform query on slave */
-my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length);
-my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
void STDCALL mysql_get_character_set_info(MYSQL *mysql,
MY_CHARSET_INFO *charset);
@@ -485,37 +416,6 @@ mysql_set_local_infile_handler(MYSQL *mysql,
void
mysql_set_local_infile_default(MYSQL *mysql);
-
-/*
- enable/disable parsing of all queries to decide if they go on master or
- slave
-*/
-void STDCALL mysql_enable_rpl_parse(MYSQL* mysql);
-void STDCALL mysql_disable_rpl_parse(MYSQL* mysql);
-/* get the value of the parse flag */
-int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
-
-/* enable/disable reads from master */
-void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
-void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
-/* get the value of the master read flag */
-my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
-
-enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
-
-/* discover the master and its slaves */
-my_bool STDCALL mysql_rpl_probe(MYSQL* mysql);
-
-/* set the master, close/free the old one, if it is not a pivot */
-int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd);
-int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd);
-
int STDCALL mysql_shutdown(MYSQL *mysql,
enum mysql_enum_shutdown_level
shutdown_level);
@@ -559,21 +459,19 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from,
unsigned long length);
void STDCALL mysql_debug(const char *debug);
+char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
+ char *to,
+ unsigned long to_length,
+ const char *from,
+ unsigned long from_length,
+ void *param,
+ char *
+ (*extend_buffer)
+ (void *, char *to,
+ unsigned long *length));
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int STDCALL mysql_thread_safe(void);
my_bool STDCALL mysql_embedded(void);
-MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con);
-MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
- const char* host,
- const char* user,
- const char* passwd,
- unsigned int port);
-void STDCALL mysql_manager_close(MYSQL_MANAGER* con);
-int STDCALL mysql_manager_command(MYSQL_MANAGER* con,
- const char* cmd, int cmd_len);
-int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
- char* res_buf,
- int res_buf_size);
my_bool STDCALL mysql_read_query_result(MYSQL *mysql);
@@ -768,7 +666,7 @@ typedef struct st_mysql_methods
MYSQL_RES * (*use_result)(MYSQL *mysql);
void (*fetch_lengths)(unsigned long *to,
MYSQL_ROW column, unsigned int field_count);
- void (*flush_use_result)(MYSQL *mysql);
+ void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results);
#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
@@ -828,6 +726,7 @@ my_bool STDCALL mysql_rollback(MYSQL * mysql);
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool STDCALL mysql_more_results(MYSQL *mysql);
int STDCALL mysql_next_result(MYSQL *mysql);
+int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt);
void STDCALL mysql_close(MYSQL *sock);
@@ -842,7 +741,6 @@ MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host,
const char *user, const char *passwd);
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
-#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
#endif
#define HAVE_MYSQL_REAL_CONNECT
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 633cde41130..78f026215b9 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -28,15 +28,15 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
- my_bool unused0;
- my_bool unused;
- my_bool compress;
my_bool unused1;
- unsigned char *query_cache_query;
+ my_bool unused2;
+ my_bool compress;
+ my_bool unused3;
+ unsigned char *unused;
unsigned int last_errno;
unsigned char error;
- my_bool unused2;
- my_bool return_errno;
+ my_bool unused4;
+ my_bool unused5;
char last_error[512];
char sqlstate[5 +1];
void *extension;
@@ -277,10 +277,10 @@ struct st_mysql_options {
unsigned long max_allowed_packet;
my_bool use_ssl;
my_bool compress,named_pipe;
- my_bool rpl_probe;
- my_bool rpl_parse;
- my_bool no_master_reads;
- my_bool separate_thread;
+ my_bool unused1;
+ my_bool unused2;
+ my_bool unused3;
+ my_bool unused4;
enum mysql_option methods_to_use;
char *client_ip;
my_bool secure_auth;
@@ -301,10 +301,6 @@ enum mysql_protocol_type
MYSQL_PROTOCOL_DEFAULT, MYSQL_PROTOCOL_TCP, MYSQL_PROTOCOL_SOCKET,
MYSQL_PROTOCOL_PIPE, MYSQL_PROTOCOL_MEMORY
};
-enum mysql_rpl_type
-{
- MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
-};
typedef struct character_set
{
unsigned int number;
@@ -344,10 +340,8 @@ typedef struct st_mysql
my_bool free_me;
my_bool reconnect;
char scramble[20 +1];
- my_bool rpl_pivot;
- struct st_mysql* master, *next_slave;
- struct st_mysql* last_used_slave;
- struct st_mysql* last_used_con;
+ my_bool unused1;
+ void *unused2, *unused3, *unused4, *unused5;
LIST *stmts;
const struct st_mysql_methods *methods;
void *thd;
@@ -371,20 +365,6 @@ typedef struct st_mysql_res {
my_bool unbuffered_fetch_cancelled;
void *extension;
} MYSQL_RES;
-typedef struct st_mysql_manager
-{
- NET net;
- char *host, *user, *passwd;
- char *net_buf, *net_buf_pos, *net_data_end;
- unsigned int port;
- int cmd_status;
- int last_errno;
- int net_buf_size;
- my_bool free_me;
- my_bool eof;
- char last_error[256];
- void *extension;
-} MYSQL_MANAGER;
typedef struct st_mysql_parameters
{
unsigned long *p_max_allowed_packet;
@@ -437,14 +417,6 @@ int mysql_real_query(MYSQL *mysql, const char *q,
unsigned long length);
MYSQL_RES * mysql_store_result(MYSQL *mysql);
MYSQL_RES * mysql_use_result(MYSQL *mysql);
-my_bool mysql_master_query(MYSQL *mysql, const char *q,
- unsigned long length);
-my_bool mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
-my_bool mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length);
-my_bool mysql_slave_send_query(MYSQL *mysql, const char *q,
- unsigned long length);
void mysql_get_character_set_info(MYSQL *mysql,
MY_CHARSET_INFO *charset);
void
@@ -459,22 +431,6 @@ mysql_set_local_infile_handler(MYSQL *mysql,
void *);
void
mysql_set_local_infile_default(MYSQL *mysql);
-void mysql_enable_rpl_parse(MYSQL* mysql);
-void mysql_disable_rpl_parse(MYSQL* mysql);
-int mysql_rpl_parse_enabled(MYSQL* mysql);
-void mysql_enable_reads_from_master(MYSQL* mysql);
-void mysql_disable_reads_from_master(MYSQL* mysql);
-my_bool mysql_reads_from_master_enabled(MYSQL* mysql);
-enum mysql_rpl_type mysql_rpl_query_type(const char* q, int len);
-my_bool mysql_rpl_probe(MYSQL* mysql);
-int mysql_set_master(MYSQL* mysql, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd);
-int mysql_add_slave(MYSQL* mysql, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd);
int mysql_shutdown(MYSQL *mysql,
enum mysql_enum_shutdown_level
shutdown_level);
@@ -518,21 +474,19 @@ unsigned long mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from,
unsigned long length);
void mysql_debug(const char *debug);
+char * mysql_odbc_escape_string(MYSQL *mysql,
+ char *to,
+ unsigned long to_length,
+ const char *from,
+ unsigned long from_length,
+ void *param,
+ char *
+ (*extend_buffer)
+ (void *, char *to,
+ unsigned long *length));
void myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int mysql_thread_safe(void);
my_bool mysql_embedded(void);
-MYSQL_MANAGER* mysql_manager_init(MYSQL_MANAGER* con);
-MYSQL_MANAGER* mysql_manager_connect(MYSQL_MANAGER* con,
- const char* host,
- const char* user,
- const char* passwd,
- unsigned int port);
-void mysql_manager_close(MYSQL_MANAGER* con);
-int mysql_manager_command(MYSQL_MANAGER* con,
- const char* cmd, int cmd_len);
-int mysql_manager_fetch_line(MYSQL_MANAGER* con,
- char* res_buf,
- int res_buf_size);
my_bool mysql_read_query_result(MYSQL *mysql);
enum enum_mysql_stmt_state
{
@@ -616,7 +570,7 @@ typedef struct st_mysql_methods
MYSQL_RES * (*use_result)(MYSQL *mysql);
void (*fetch_lengths)(unsigned long *to,
MYSQL_ROW column, unsigned int field_count);
- void (*flush_use_result)(MYSQL *mysql);
+ void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results);
MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
int (*stmt_execute)(MYSQL_STMT *stmt);
@@ -671,4 +625,5 @@ my_bool mysql_rollback(MYSQL * mysql);
my_bool mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool mysql_more_results(MYSQL *mysql);
int mysql_next_result(MYSQL *mysql);
+int mysql_stmt_next_result(MYSQL_STMT *stmt);
void mysql_close(MYSQL *sock);
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index 45d0234cb67..f158dc20999 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 MySQL AB
+/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,12 +16,6 @@
#ifndef _my_plugin_h
#define _my_plugin_h
-/* size_t */
-#include <stdlib.h>
-
-typedef struct st_mysql MYSQL;
-
-
/*
On Windows, exports from DLL need to be declared
*/
@@ -39,15 +33,7 @@ class Item;
#define MYSQL_THD void*
#endif
-#ifndef _m_string_h
-/* This definition must match the one given in m_string.h */
-struct st_mysql_lex_string
-{
- char *str;
- unsigned int length;
-};
-#endif /* _m_string_h */
-typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+#include <mysql/services.h>
#define MYSQL_XIDDATASIZE 128
/**
@@ -70,7 +56,7 @@ typedef struct st_mysql_xid MYSQL_XID;
Plugin API. Common for all plugin types.
*/
-#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0100
+#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
/*
The allowable types of plugins
@@ -126,7 +112,8 @@ enum enum_mysql_show_type
{
SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
- SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE
+ SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
+ SHOW_always_last
};
struct st_mysql_show_var {
@@ -750,54 +737,6 @@ int thd_killed(const MYSQL_THD thd);
*/
unsigned long thd_get_thread_id(const MYSQL_THD thd);
-
-/**
- Allocate memory in the connection's local memory pool
-
- @details
- When properly used in place of @c my_malloc(), this can significantly
- improve concurrency. Don't use this or related functions to allocate
- large chunks of memory. Use for temporary storage only. The memory
- will be freed automatically at the end of the statement; no explicit
- code is required to prevent memory leaks.
-
- @see alloc_root()
-*/
-void *thd_alloc(MYSQL_THD thd, unsigned int size);
-/**
- @see thd_alloc()
-*/
-void *thd_calloc(MYSQL_THD thd, unsigned int size);
-/**
- @see thd_alloc()
-*/
-char *thd_strdup(MYSQL_THD thd, const char *str);
-/**
- @see thd_alloc()
-*/
-char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size);
-/**
- @see thd_alloc()
-*/
-void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size);
-
-/**
- Create a LEX_STRING in this connection's local memory pool
-
- @param thd user thread connection handle
- @param lex_str pointer to LEX_STRING object to be initialized
- @param str initializer to be copied into lex_str
- @param size length of str, in bytes
- @param allocate_lex_string flag: if TRUE, allocate new LEX_STRING object,
- instead of using lex_str value
- @return NULL on failure, or pointer to the LEX_STRING object
-
- @see thd_alloc()
-*/
-MYSQL_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
-
/**
Get the XID for this connection's transaction
@@ -818,64 +757,6 @@ void mysql_query_cache_invalidate4(MYSQL_THD thd,
const char *key, unsigned int key_length,
int using_trx);
-/**
- Get the value of user variable as an integer.
-
- This function will return the value of variable @a name as an
- integer. If the original value of the variable is not an integer,
- the value will be converted into an integer.
-
- @param name user variable name
- @param value pointer to return the value
- @param null_value if not NULL, the function will set it to true if
- the value of variable is null, set to false if not
-
- @retval 0 Success
- @retval 1 Variable not found
-*/
-int get_user_var_int(const char *name,
- long long int *value, int *null_value);
-
-/**
- Get the value of user variable as a double precision float number.
-
- This function will return the value of variable @a name as real
- number. If the original value of the variable is not a real number,
- the value will be converted into a real number.
-
- @param name user variable name
- @param value pointer to return the value
- @param null_value if not NULL, the function will set it to true if
- the value of variable is null, set to false if not
-
- @retval 0 Success
- @retval 1 Variable not found
-*/
-int get_user_var_real(const char *name,
- double *value, int *null_value);
-
-/**
- Get the value of user variable as a string.
-
- This function will return the value of variable @a name as
- string. If the original value of the variable is not a string,
- the value will be converted into a string.
-
- @param name user variable name
- @param value pointer to the value buffer
- @param len length of the value buffer
- @param precision precision of the value if it is a float number
- @param null_value if not NULL, the function will set it to true if
- the value of variable is null, set to false if not
-
- @retval 0 Success
- @retval 1 Variable not found
-*/
-int get_user_var_str(const char *name,
- char *value, unsigned long len,
- unsigned int precision, int *null_value);
-
-
#ifdef __cplusplus
}
#endif
diff --git a/include/mysql/plugin.h.pp b/include/mysql/plugin.h.pp
index d864140333b..b7dd7bc0032 100644
--- a/include/mysql/plugin.h.pp
+++ b/include/mysql/plugin.h.pp
@@ -1,11 +1,38 @@
+#include <mysql/services.h>
+#include <mysql/service_my_snprintf.h>
+#include <stdarg.h>
+#include <stdlib.h>
+extern struct my_snprintf_service_st {
+ size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
+ size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
+} *my_snprintf_service;
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
+#include <mysql/service_thd_alloc.h>
#include <stdlib.h>
-typedef struct st_mysql MYSQL;
struct st_mysql_lex_string
{
char *str;
- unsigned int length;
+ size_t length;
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+extern struct thd_alloc_service_st {
+ void *(*thd_alloc_func)(void*, unsigned int);
+ void *(*thd_calloc_func)(void*, unsigned int);
+ char *(*thd_strdup_func)(void*, const char *);
+ char *(*thd_strmake_func)(void*, const char *, unsigned int);
+ void *(*thd_memdup_func)(void*, const void*, unsigned int);
+ MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ const char *, unsigned int, int);
+} *thd_alloc_service;
+void *thd_alloc(void* thd, unsigned int size);
+void *thd_calloc(void* thd, unsigned int size);
+char *thd_strdup(void* thd, const char *str);
+char *thd_strmake(void* thd, const char *str, unsigned int size);
+void *thd_memdup(void* thd, const void* str, unsigned int size);
+MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
struct st_mysql_xid {
long formatID;
long gtrid_length;
@@ -17,7 +44,8 @@ enum enum_mysql_show_type
{
SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
- SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE
+ SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
+ SHOW_always_last
};
struct st_mysql_show_var {
const char *name;
@@ -107,9 +135,9 @@ struct st_mysql_information_schema
{
int interface_version;
};
-struct Mysql_replication {
- int interface_version;
-};
+ struct Mysql_replication {
+ int interface_version;
+ };
struct st_mysql_value
{
int (*value_type)(struct st_mysql_value *);
@@ -130,22 +158,7 @@ void thd_inc_row_count(void* thd);
int mysql_tmpfile(const char *prefix);
int thd_killed(const void* thd);
unsigned long thd_get_thread_id(const void* thd);
-void *thd_alloc(void* thd, unsigned int size);
-void *thd_calloc(void* thd, unsigned int size);
-char *thd_strdup(void* thd, const char *str);
-char *thd_strmake(void* thd, const char *str, unsigned int size);
-void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
void thd_get_xid(const void* thd, MYSQL_XID *xid);
void mysql_query_cache_invalidate4(void* thd,
const char *key, unsigned int key_length,
int using_trx);
-int get_user_var_int(const char *name,
- long long int *value, int *null_value);
-int get_user_var_real(const char *name,
- double *value, int *null_value);
-int get_user_var_str(const char *name,
- char *value, unsigned long len,
- unsigned int precision, int *null_value);
diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h
new file mode 100644
index 00000000000..ad344864c34
--- /dev/null
+++ b/include/mysql/service_my_snprintf.h
@@ -0,0 +1,98 @@
+#ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+ my_snprintf service
+
+ Portable and limited vsnprintf() implementation.
+
+ This is a portable, limited vsnprintf() implementation, with some
+ extra features. "Portable" means that it'll produce identical result
+ on all platforms (for example, on Windows and Linux system printf %e
+ formats the exponent differently, on different systems %p either
+ prints leading 0x or not, %s may accept null pointer or crash on
+ it). "Limited" means that it does not support all the C89 features.
+ But it supports few extensions, not in any standard.
+
+ my_vsnprintf(to, n, fmt, ap)
+
+ @param[out] to A buffer to store the result in
+ @param[in] n Store up to n-1 characters, followed by an end 0
+ @param[in] fmt printf-like format string
+ @param[in] ap Arguments
+
+ @return a number of bytes written to a buffer *excluding* terminating '\0'
+
+ @post
+ The syntax of a format string is generally the same:
+ % <flag> <width> <precision> <length modifier> <format>
+ where everithing but the format is optional.
+
+ Three one-character flags are recognized:
+ '0' has the standard zero-padding semantics;
+ '-' is parsed, but silently ignored;
+ '`' (backtick) is only supported for strings (%s) and means that the
+ string will be quoted according to MySQL identifier quoting rules.
+
+ Both <width> and <precision> can be specified as numbers or '*'.
+
+ <length modifier> can be 'l', 'll', or 'z'.
+
+ Supported formats are 's' (null pointer is accepted, printed as
+ "(null)"), 'b' (extension, see below), 'c', 'd', 'u', 'x',
+ 'X', 'p' (works as 0x%x).
+
+ Standard syntax for positional arguments $n is supported.
+
+ Extensions:
+
+ Flag '`' (backtick): see above.
+
+ Format 'b': binary buffer, prints exactly <precision> bytes from the
+ argument, without stopping at '\0'.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+extern struct my_snprintf_service_st {
+ size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
+ size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
+} *my_snprintf_service;
+
+#ifdef MYSQL_DYNAMIC_PLUGIN
+
+#define my_vsnprintf my_snprintf_service->my_vsnprintf_type
+#define my_snprintf my_snprintf_service->my_snprintf_type
+
+#else
+
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED
+#endif
+
diff --git a/include/mysql/service_thd_alloc.h b/include/mysql/service_thd_alloc.h
new file mode 100644
index 00000000000..86158ba1359
--- /dev/null
+++ b/include/mysql/service_thd_alloc.h
@@ -0,0 +1,128 @@
+#ifndef MYSQL_SERVICE_THD_ALLOC_INCLUDED
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/**
+ @file
+ This service provdes functions to allocate memory in a connection local
+ memory pool. The memory allocated there will be automatically freed at the
+ end of the statement, don't use it for allocations that should live longer
+ than that. For short living allocations this is more efficient than
+ using my_malloc and friends, and automatic "garbage collection" allows not
+ to think about memory leaks.
+
+ The pool is best for small to medium objects, don't use it for large
+ allocations - they are better served with my_malloc.
+*/
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct st_mysql_lex_string
+{
+ char *str;
+ size_t length;
+};
+typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+
+extern struct thd_alloc_service_st {
+ void *(*thd_alloc_func)(MYSQL_THD, unsigned int);
+ void *(*thd_calloc_func)(MYSQL_THD, unsigned int);
+ char *(*thd_strdup_func)(MYSQL_THD, const char *);
+ char *(*thd_strmake_func)(MYSQL_THD, const char *, unsigned int);
+ void *(*thd_memdup_func)(MYSQL_THD, const void*, unsigned int);
+ MYSQL_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD, MYSQL_LEX_STRING *,
+ const char *, unsigned int, int);
+} *thd_alloc_service;
+
+#ifdef MYSQL_DYNAMIC_PLUGIN
+
+#define thd_alloc(thd,size) (thd_alloc_service->thd_alloc_func((thd), (size)))
+
+#define thd_calloc(thd,size) (thd_alloc_service->thd_calloc_func((thd), (size)))
+
+#define thd_strdup(thd,str) (thd_alloc_service->thd_strdup_func((thd), (str)))
+
+#define thd_strmake(thd,str,size) \
+ (thd_alloc_service->thd_strmake_func((thd), (str), (size)))
+
+#define thd_memdup(thd,str,size) \
+ (thd_alloc_service->thd_memdup_func((thd), (str), (size)))
+
+#define thd_make_lex_string(thd, lex_str, str, size, allocate_lex_string) \
+ (thd_alloc_service->thd_make_lex_string_func((thd), (lex_str), (str), \
+ (size), (allocate_lex_string)))
+
+#else
+
+/**
+ Allocate memory in the connection's local memory pool
+
+ @details
+ When properly used in place of @c my_malloc(), this can significantly
+ improve concurrency. Don't use this or related functions to allocate
+ large chunks of memory. Use for temporary storage only. The memory
+ will be freed automatically at the end of the statement; no explicit
+ code is required to prevent memory leaks.
+
+ @see alloc_root()
+*/
+void *thd_alloc(MYSQL_THD thd, unsigned int size);
+/**
+ @see thd_alloc()
+*/
+void *thd_calloc(MYSQL_THD thd, unsigned int size);
+/**
+ @see thd_alloc()
+*/
+char *thd_strdup(MYSQL_THD thd, const char *str);
+/**
+ @see thd_alloc()
+*/
+char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size);
+/**
+ @see thd_alloc()
+*/
+void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size);
+
+/**
+ Create a LEX_STRING in this connection's local memory pool
+
+ @param thd user thread connection handle
+ @param lex_str pointer to LEX_STRING object to be initialized
+ @param str initializer to be copied into lex_str
+ @param size length of str, in bytes
+ @param allocate_lex_string flag: if TRUE, allocate new LEX_STRING object,
+ instead of using lex_str value
+ @return NULL on failure, or pointer to the LEX_STRING object
+
+ @see thd_alloc()
+*/
+MYSQL_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define MYSQL_SERVICE_THD_ALLOC_INCLUDED
+#endif
+
diff --git a/include/mysql/services.h b/include/mysql/services.h
new file mode 100644
index 00000000000..19003e66b96
--- /dev/null
+++ b/include/mysql/services.h
@@ -0,0 +1,30 @@
+#ifndef MYSQL_SERVICES_INCLUDED
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mysql/service_my_snprintf.h>
+#include <mysql/service_thd_alloc.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#define MYSQL_SERVICES_INCLUDED
+#endif
+
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 4ffcd658d7b..345ecd5dd93 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -146,6 +146,7 @@ enum enum_server_command
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
+#define CLIENT_PS_MULTI_RESULTS (1UL << 18) /* Multi-results in PS-protocol */
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
@@ -169,6 +170,7 @@ enum enum_server_command
CLIENT_SECURE_CONNECTION | \
CLIENT_MULTI_STATEMENTS | \
CLIENT_MULTI_RESULTS | \
+ CLIENT_PS_MULTI_RESULTS | \
CLIENT_SSL_VERIFY_SERVER_CERT | \
CLIENT_REMEMBER_OPTIONS)
@@ -208,6 +210,11 @@ enum enum_server_command
#define SERVER_QUERY_WAS_SLOW 2048
/**
+ To mark ResultSet containing output parameter values.
+*/
+#define SERVER_PS_OUT_PARAMS 4096
+
+/**
Server status flags that must be cleared when starting
execution of a new SQL statement.
Flags from this set are only added to the
@@ -257,24 +264,23 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
- my_bool unused0; /* Please remove with the next incompatible ABI change. */
- my_bool unused; /* Please remove with the next incompatible ABI change */
- my_bool compress;
my_bool unused1; /* Please remove with the next incompatible ABI change. */
+ my_bool unused2; /* Please remove with the next incompatible ABI change */
+ my_bool compress;
+ my_bool unused3; /* Please remove with the next incompatible ABI change. */
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
*/
#endif
/*
- 'query_cache_query' should be accessed only via query cache
- functions and methods to maintain proper locking.
+ Unused, please remove with the next incompatible ABI change.
*/
- unsigned char *query_cache_query;
+ unsigned char *unused;
unsigned int last_errno;
unsigned char error;
- my_bool unused2; /* Please remove with the next incompatible ABI change. */
- my_bool return_errno;
+ my_bool unused4; /* Please remove with the next incompatible ABI change. */
+ my_bool unused5; /* Please remove with the next incompatible ABI change. */
/** Client library error message buffer. Actually belongs to struct MYSQL. */
char last_error[MYSQL_ERRMSG_SIZE];
/** Client library sqlstate buffer. Set along with the error message. */
@@ -412,10 +418,6 @@ void my_net_set_write_timeout(NET *net, uint timeout);
void my_net_set_read_timeout(NET *net, uint timeout);
#endif
-/*
- The following function is not meant for normal usage
- Currently it's used internally by manager.c
-*/
struct sockaddr;
int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
unsigned int timeout);
diff --git a/include/service_versions.h b/include/service_versions.h
new file mode 100644
index 00000000000..114957cdd86
--- /dev/null
+++ b/include/service_versions.h
@@ -0,0 +1,24 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef _WIN32
+#define SERVICE_VERSION __declspec(dllexport) void *
+#else
+#define SERVICE_VERSION void *
+#endif
+
+#define VERSION_my_snprintf 0x0100
+#define VERSION_thd_alloc 0x0100
+
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index 805551b7ee3..84ad50e03e3 100755
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -73,7 +73,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c
../mysys/hash.c ../mysys/my_sleep.c ../mysys/default_modify.c
get_password.c ../strings/int2str.c ../strings/is_prefix.c
libmysql.c ../mysys/list.c ../strings/llstr.c
- ../strings/longlong2str.c manager.c ../mysys/mf_arr_appstr.c ../mysys/mf_cache.c
+ ../strings/longlong2str.c ../mysys/mf_arr_appstr.c ../mysys/mf_cache.c
../mysys/mf_dirname.c ../mysys/mf_fn_ext.c ../mysys/mf_format.c
../mysys/mf_iocache.c ../mysys/mf_iocache2.c ../mysys/mf_loadpath.c
../mysys/mf_pack.c ../mysys/mf_path.c ../mysys/mf_tempfile.c ../mysys/mf_unixpath.c
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index eb4fd75ed11..acc709bfb89 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -31,7 +31,7 @@ pkglib_LTLIBRARIES = $(target)
noinst_PROGRAMS = conf_to_src
-target_sources = libmysql.c password.c manager.c \
+target_sources = libmysql.c password.c \
get_password.c errmsg.c
mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index 1fd8619a746..aaec08d1b1e 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -22,9 +22,13 @@
extern uint mysql_port;
extern char * mysql_unix_port;
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
- CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
+ CLIENT_LONG_FLAG | \
+ CLIENT_TRANSACTIONS | \
+ CLIENT_PROTOCOL_41 | \
+ CLIENT_SECURE_CONNECTION | \
+ CLIENT_MULTI_RESULTS | \
+ CLIENT_PS_MULTI_RESULTS)
sig_handler my_pipe_sig_handler(int sig);
void read_user_name(char *name);
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 6e7f3ef48d3..d0ed44bd7aa 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -85,6 +85,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "This handle is already connected. Use a separate handle for each connection."
""
};
@@ -151,6 +152,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "This handle is already connected. Use a separate handle for each connection."
""
};
@@ -215,6 +217,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
+ "This handle is already connected. Use a separate handle for each connection."
""
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 1264f2765ba..477830a6ebd 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -131,7 +131,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
mysql_port = MYSQL_PORT;
#ifndef MSDOS
{
- struct servent *serv_ptr;
+ struct servent *serv_ptr __attribute__((unused));
char *env;
/*
@@ -249,16 +249,6 @@ void STDCALL mysql_thread_end()
#endif
}
-/*
- Let the user specify that we don't want SIGPIPE; This doesn't however work
- with threaded applications as we can have multiple read in progress.
-*/
-static MYSQL* spawn_init(MYSQL* parent, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd);
-
-
/*
Expand wildcard to a sql string
@@ -320,7 +310,7 @@ mysql_debug(const char *debug __attribute__((unused)))
/**************************************************************************
- Close the server connection if we get a SIGPIPE
+ Ignore SIGPIPE handler
ARGSUSED
**************************************************************************/
@@ -333,305 +323,6 @@ my_pipe_sig_handler(int sig __attribute__((unused)))
#endif
}
-/* perform query on master */
-my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
- unsigned long length)
-{
- DBUG_ENTER("mysql_master_query");
- if (mysql_master_send_query(mysql, q, length))
- DBUG_RETURN(1);
- DBUG_RETURN((*mysql->methods->read_query_result)(mysql));
-}
-
-my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
- unsigned long length)
-{
- MYSQL *master = mysql->master;
- DBUG_ENTER("mysql_master_send_query");
- if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0))
- DBUG_RETURN(1);
- master->reconnect= 1;
- mysql->last_used_con = master;
- DBUG_RETURN(simple_command(master, COM_QUERY, (const uchar*) q, length, 1));
-}
-
-
-/* perform query on slave */
-my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
- unsigned long length)
-{
- DBUG_ENTER("mysql_slave_query");
- if (mysql_slave_send_query(mysql, q, length))
- DBUG_RETURN(1);
- DBUG_RETURN((*mysql->methods->read_query_result)(mysql));
-}
-
-
-my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
- unsigned long length)
-{
- MYSQL* last_used_slave, *slave_to_use = 0;
- DBUG_ENTER("mysql_slave_send_query");
-
- if ((last_used_slave = mysql->last_used_slave))
- slave_to_use = last_used_slave->next_slave;
- else
- slave_to_use = mysql->next_slave;
- /*
- Next_slave is always safe to use - we have a circular list of slaves
- if there are no slaves, mysql->next_slave == mysql
- */
- mysql->last_used_con = mysql->last_used_slave = slave_to_use;
- if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0,
- 0,0,0,0))
- DBUG_RETURN(1);
- slave_to_use->reconnect= 1;
- DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, (const uchar*) q,
- length, 1));
-}
-
-
-/* enable/disable parsing of all queries to decide
- if they go on master or slave */
-void STDCALL mysql_enable_rpl_parse(MYSQL* mysql)
-{
- mysql->options.rpl_parse = 1;
-}
-
-void STDCALL mysql_disable_rpl_parse(MYSQL* mysql)
-{
- mysql->options.rpl_parse = 0;
-}
-
-/* get the value of the parse flag */
-int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql)
-{
- return mysql->options.rpl_parse;
-}
-
-/* enable/disable reads from master */
-void STDCALL mysql_enable_reads_from_master(MYSQL* mysql)
-{
- mysql->options.no_master_reads = 0;
-}
-
-void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
-{
- mysql->options.no_master_reads = 1;
-}
-
-/* get the value of the master read flag */
-my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
-{
- return !(mysql->options.no_master_reads);
-}
-
-
-/*
- We may get an error while doing replication internals.
- In this case, we add a special explanation to the original
- error
-*/
-
-static void expand_error(MYSQL* mysql, int error)
-{
- char tmp[MYSQL_ERRMSG_SIZE];
- char *p;
- uint err_length;
- strmake(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE-1);
- p = strmake(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE-1);
- err_length= (uint) (p - mysql->net.last_error);
- strmake(p, tmp, MYSQL_ERRMSG_SIZE-1 - err_length);
- mysql->net.last_errno = error;
-}
-
-/*
- This function assumes we have just called SHOW SLAVE STATUS and have
- read the given result and row
-*/
-
-static my_bool get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
-{
- MYSQL* master;
- DBUG_ENTER("get_master");
- if (mysql_num_fields(res) < 3)
- DBUG_RETURN(1); /* safety */
-
- /* use the same username and password as the original connection */
- if (!(master = spawn_init(mysql, row[0], atoi(row[2]), 0, 0)))
- DBUG_RETURN(1);
- mysql->master = master;
- DBUG_RETURN(0);
-}
-
-
-/*
- Assuming we already know that mysql points to a master connection,
- retrieve all the slaves
-*/
-
-static my_bool get_slaves_from_master(MYSQL* mysql)
-{
- MYSQL_RES* res = 0;
- MYSQL_ROW row;
- my_bool error = 1;
- int has_auth_info;
- int port_ind;
- DBUG_ENTER("get_slaves_from_master");
-
- if (!mysql->net.vio && !mysql_real_connect(mysql,0,0,0,0,0,0,0))
- {
- expand_error(mysql, CR_PROBE_MASTER_CONNECT);
- DBUG_RETURN(1);
- }
- mysql->reconnect= 1;
-
- if (mysql_query(mysql, "SHOW SLAVE HOSTS") ||
- !(res = mysql_store_result(mysql)))
- {
- expand_error(mysql, CR_PROBE_SLAVE_HOSTS);
- DBUG_RETURN(1);
- }
-
- switch (mysql_num_fields(res)) {
- case 5:
- has_auth_info = 0;
- port_ind=2;
- break;
- case 7:
- has_auth_info = 1;
- port_ind=4;
- break;
- default:
- goto err;
- }
-
- while ((row = mysql_fetch_row(res)))
- {
- MYSQL* slave;
- const char* tmp_user, *tmp_pass;
-
- if (has_auth_info)
- {
- tmp_user = row[2];
- tmp_pass = row[3];
- }
- else
- {
- tmp_user = mysql->user;
- tmp_pass = mysql->passwd;
- }
-
- if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]),
- tmp_user, tmp_pass)))
- goto err;
-
- /* Now add slave into the circular linked list */
- slave->next_slave = mysql->next_slave;
- mysql->next_slave = slave;
- }
- error = 0;
-err:
- if (res)
- mysql_free_result(res);
- DBUG_RETURN(error);
-}
-
-
-my_bool STDCALL mysql_rpl_probe(MYSQL* mysql)
-{
- MYSQL_RES *res= 0;
- MYSQL_ROW row;
- my_bool error= 1;
- DBUG_ENTER("mysql_rpl_probe");
-
- /*
- First determine the replication role of the server we connected to
- the most reliable way to do this is to run SHOW SLAVE STATUS and see
- if we have a non-empty master host. This is still not fool-proof -
- it is not a sin to have a master that has a dormant slave thread with
- a non-empty master host. However, it is more reliable to check
- for empty master than whether the slave thread is actually running
- */
- if (mysql_query(mysql, "SHOW SLAVE STATUS") ||
- !(res = mysql_store_result(mysql)))
- {
- expand_error(mysql, CR_PROBE_SLAVE_STATUS);
- DBUG_RETURN(1);
- }
-
- row= mysql_fetch_row(res);
- /*
- Check master host for emptiness/NULL
- For MySQL 4.0 it's enough to check for row[0]
- */
- if (row && row[0] && *(row[0]))
- {
- /* this is a slave, ask it for the master */
- if (get_master(mysql, res, row) || get_slaves_from_master(mysql))
- goto err;
- }
- else
- {
- mysql->master = mysql;
- if (get_slaves_from_master(mysql))
- goto err;
- }
-
- error = 0;
-err:
- if (res)
- mysql_free_result(res);
- DBUG_RETURN(error);
-}
-
-
-/*
- Make a not so fool-proof decision on where the query should go, to
- the master or the slave. Ideally the user should always make this
- decision himself with mysql_master_query() or mysql_slave_query().
- However, to be able to more easily port the old code, we support the
- option of an educated guess - this should work for most applications,
- however, it may make the wrong decision in some particular cases. If
- that happens, the user would have to change the code to call
- mysql_master_query() or mysql_slave_query() explicitly in the place
- where we have made the wrong decision
-*/
-
-enum mysql_rpl_type
-STDCALL mysql_rpl_query_type(const char* q, int len)
-{
- const char *q_end= q + len;
- for (; q < q_end; ++q)
- {
- char c;
- if (my_isalpha(&my_charset_latin1, (c= *q)))
- {
- switch (my_tolower(&my_charset_latin1,c)) {
- case 'i': /* insert */
- case 'u': /* update or unlock tables */
- case 'l': /* lock tables or load data infile */
- case 'd': /* drop or delete */
- case 'a': /* alter */
- return MYSQL_RPL_MASTER;
- case 'c': /* create or check */
- return my_tolower(&my_charset_latin1,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
- MYSQL_RPL_MASTER;
- case 's': /* select or show */
- return my_tolower(&my_charset_latin1,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
- MYSQL_RPL_SLAVE;
- case 'f': /* flush */
- case 'r': /* repair */
- case 'g': /* grant */
- return MYSQL_RPL_ADMIN;
- default:
- return MYSQL_RPL_SLAVE;
- }
- }
- }
- return MYSQL_RPL_MASTER; /* By default, send to master */
-}
-
/**************************************************************************
Connect to sql server
@@ -1093,68 +784,6 @@ mysql_query(MYSQL *mysql, const char *query)
}
-static MYSQL* spawn_init(MYSQL* parent, const char* host,
- unsigned int port, const char* user,
- const char* passwd)
-{
- MYSQL* child;
- DBUG_ENTER("spawn_init");
- if (!(child= mysql_init(0)))
- DBUG_RETURN(0);
-
- child->options.user= my_strdup((user) ? user :
- (parent->user ? parent->user :
- parent->options.user), MYF(0));
- child->options.password= my_strdup((passwd) ? passwd :
- (parent->passwd ?
- parent->passwd :
- parent->options.password), MYF(0));
- child->options.port= port;
- child->options.host= my_strdup((host) ? host :
- (parent->host ?
- parent->host :
- parent->options.host), MYF(0));
- if (parent->db)
- child->options.db= my_strdup(parent->db, MYF(0));
- else if (parent->options.db)
- child->options.db= my_strdup(parent->options.db, MYF(0));
-
- /*
- rpl_pivot is set to 1 in mysql_init(); Reset it as we are not doing
- replication here
- */
- child->rpl_pivot= 0;
- DBUG_RETURN(child);
-}
-
-
-int
-STDCALL mysql_set_master(MYSQL* mysql, const char* host,
- unsigned int port, const char* user,
- const char* passwd)
-{
- if (mysql->master != mysql && !mysql->master->rpl_pivot)
- mysql_close(mysql->master);
- if (!(mysql->master = spawn_init(mysql, host, port, user, passwd)))
- return 1;
- return 0;
-}
-
-
-int
-STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd)
-{
- MYSQL* slave;
- if (!(slave = spawn_init(mysql, host, port, user, passwd)))
- return 1;
- slave->next_slave = mysql->next_slave;
- mysql->next_slave = slave;
- return 0;
-}
-
/**************************************************************************
Return next field of the query results
**************************************************************************/
@@ -1483,17 +1112,17 @@ MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res)
unsigned int STDCALL mysql_field_count(MYSQL *mysql)
{
- return mysql->last_used_con->field_count;
+ return mysql->field_count;
}
my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
{
- return mysql->last_used_con->affected_rows;
+ return mysql->affected_rows;
}
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
{
- return mysql->last_used_con->insert_id;
+ return mysql->insert_id;
}
const char *STDCALL mysql_sqlstate(MYSQL *mysql)
@@ -1629,6 +1258,20 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length);
}
+
+char * STDCALL
+mysql_odbc_escape_string(MYSQL *mysql __attribute__((unused)),
+ char *to __attribute__((unused)),
+ ulong to_length __attribute__((unused)),
+ const char *from __attribute__((unused)),
+ ulong from_length __attribute__((unused)),
+ void *param __attribute__((unused)),
+ char * (*extend_buffer)(void *, char *, ulong *)
+ __attribute__((unused)))
+{
+ return NULL;
+}
+
void STDCALL
myodbc_remove_escape(MYSQL *mysql,char *name)
{
@@ -1858,7 +1501,6 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
MYSQL_DATA *fields_data;
DBUG_ENTER("cli_read_prepare_result");
- mysql= mysql->last_used_con;
if ((packet_length= cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1);
mysql->warning_count= 0;
@@ -2092,7 +1734,9 @@ static void alloc_stmt_fields(MYSQL_STMT *stmt)
{
MYSQL_FIELD *fields, *field, *end;
MEM_ROOT *alloc= &stmt->mem_root;
- MYSQL *mysql= stmt->mysql->last_used_con;
+ MYSQL *mysql= stmt->mysql;
+
+ DBUG_ASSERT(mysql->field_count);
stmt->field_count= mysql->field_count;
@@ -2115,18 +1759,21 @@ static void alloc_stmt_fields(MYSQL_STMT *stmt)
field= stmt->fields;
field && fields < end; fields++, field++)
{
- field->db = strdup_root(alloc,fields->db);
- field->table = strdup_root(alloc,fields->table);
- field->org_table= strdup_root(alloc,fields->org_table);
- field->name = strdup_root(alloc,fields->name);
- field->org_name = strdup_root(alloc,fields->org_name);
- field->charsetnr= fields->charsetnr;
- field->length = fields->length;
- field->type = fields->type;
- field->flags = fields->flags;
- field->decimals = fields->decimals;
- field->def = fields->def ? strdup_root(alloc,fields->def): 0;
- field->max_length= 0;
+ *field= *fields; /* To copy all numeric parts. */
+ field->catalog= strmake_root(alloc, fields->catalog,
+ fields->catalog_length);
+ field->db= strmake_root(alloc, fields->db, fields->db_length);
+ field->table= strmake_root(alloc, fields->table, fields->table_length);
+ field->org_table= strmake_root(alloc, fields->org_table,
+ fields->org_table_length);
+ field->name= strmake_root(alloc, fields->name, fields->name_length);
+ field->org_name= strmake_root(alloc, fields->org_name,
+ fields->org_name_length);
+ field->def= fields->def ? strmake_root(alloc, fields->def,
+ fields->def_length) : 0;
+ field->def_length= field->def ? fields->def_length : 0;
+ field->extension= 0; /* Avoid dangling links. */
+ field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */
}
}
@@ -2479,7 +2126,6 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
DBUG_ENTER("execute");
DBUG_DUMP("packet", (uchar *) packet, length);
- mysql->last_used_con= mysql;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
buff[4]= (char) stmt->flags;
int4store(buff+5, 1); /* iteration count */
@@ -2854,6 +2500,33 @@ static void reinit_result_set_metadata(MYSQL_STMT *stmt)
}
+static void prepare_to_fetch_result(MYSQL_STMT *stmt)
+{
+ if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
+ {
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ stmt->read_row_func= stmt_read_row_from_cursor;
+ }
+ else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
+ {
+ /*
+ This is a single-row result set, a result set with no rows, EXPLAIN,
+ SHOW VARIABLES, or some other command which either a) bypasses the
+ cursors framework in the server and writes rows directly to the
+ network or b) is more efficient if all (few) result set rows are
+ precached on client and server's resources are freed.
+ */
+ mysql_stmt_store_result(stmt);
+ }
+ else
+ {
+ stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
+ stmt->unbuffered_fetch_cancelled= FALSE;
+ stmt->read_row_func= stmt_read_row_unbuffered;
+ }
+}
+
+
/*
Send placeholders data to server (if there are placeholders)
and execute prepared statement.
@@ -2921,28 +2594,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
if (mysql->field_count)
{
reinit_result_set_metadata(stmt);
- if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
- {
- mysql->status= MYSQL_STATUS_READY;
- stmt->read_row_func= stmt_read_row_from_cursor;
- }
- else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
- {
- /*
- This is a single-row result set, a result set with no rows, EXPLAIN,
- SHOW VARIABLES, or some other command which either a) bypasses the
- cursors framework in the server and writes rows directly to the
- network or b) is more efficient if all (few) result set rows are
- precached on client and server's resources are freed.
- */
- mysql_stmt_store_result(stmt);
- }
- else
- {
- stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
- stmt->unbuffered_fetch_cancelled= FALSE;
- stmt->read_row_func= stmt_read_row_unbuffered;
- }
+ prepare_to_fetch_result(stmt);
}
DBUG_RETURN(test(stmt->last_errno));
}
@@ -4407,7 +4059,6 @@ static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
field->max_length= 10; /* 2003-11-11 */
param->skip_result= skip_result_with_length;
break;
- break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
param->skip_result= skip_result_with_length;
@@ -4689,7 +4340,6 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
}
net = &mysql->net;
- mysql= mysql->last_used_con;
while ((pkt_len= cli_safe_read(mysql)) != packet_error)
{
@@ -4787,8 +4437,6 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
DBUG_RETURN(1);
}
- mysql= mysql->last_used_con;
-
if (!stmt->field_count)
DBUG_RETURN(0);
@@ -4990,7 +4638,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
{
/* There is a result set and it belongs to this statement */
- (*mysql->methods->flush_use_result)(mysql);
+ (*mysql->methods->flush_use_result)(mysql, FALSE);
if (mysql->unbuffered_fetch_owner)
*mysql->unbuffered_fetch_owner= TRUE;
mysql->status= MYSQL_STATUS_READY;
@@ -5074,7 +4722,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
Flush result set of the connection. If it does not belong
to this statement, set a warning.
*/
- (*mysql->methods->flush_use_result)(mysql);
+ (*mysql->methods->flush_use_result)(mysql, TRUE);
if (mysql->unbuffered_fetch_owner)
*mysql->unbuffered_fetch_owner= TRUE;
mysql->status= MYSQL_STATUS_READY;
@@ -5193,8 +4841,7 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql)
my_bool res;
DBUG_ENTER("mysql_more_results");
- res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
- 1: 0);
+ res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? 1: 0);
DBUG_PRINT("exit",("More results exists ? %d", res));
DBUG_RETURN(res);
}
@@ -5216,13 +4863,56 @@ int STDCALL mysql_next_result(MYSQL *mysql)
net_clear_error(&mysql->net);
mysql->affected_rows= ~(my_ulonglong) 0;
- if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)
+ if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
DBUG_RETURN((*mysql->methods->next_result)(mysql));
DBUG_RETURN(-1); /* No more results */
}
+int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ int rc;
+ DBUG_ENTER("mysql_stmt_next_result");
+
+ if (!mysql)
+ DBUG_RETURN(1);
+
+ if (stmt->last_errno)
+ DBUG_RETURN(stmt->last_errno);
+
+ if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
+ {
+ if (reset_stmt_handle(stmt, RESET_STORE_RESULT))
+ DBUG_RETURN(1);
+ }
+
+ rc= mysql_next_result(mysql);
+
+ if (rc)
+ {
+ set_stmt_errmsg(stmt, &mysql->net);
+ DBUG_RETURN(rc);
+ }
+
+ stmt->state= MYSQL_STMT_EXECUTE_DONE;
+ stmt->bind_result_done= FALSE;
+
+ if (mysql->field_count)
+ {
+ alloc_stmt_fields(stmt);
+ prepare_to_fetch_result(stmt);
+ }
+ else
+ {
+ stmt->field_count= mysql->field_count;
+ }
+
+ DBUG_RETURN(0);
+}
+
+
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql)
{
return (*mysql->methods->use_result)(mysql);
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 81f86dc8726..e435a14b005 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -78,6 +78,7 @@ EXPORTS
mysql_next_result
mysql_num_fields
mysql_num_rows
+ mysql_odbc_escape_string
mysql_options
mysql_stmt_param_count
mysql_stmt_param_metadata
@@ -135,15 +136,6 @@ EXPORTS
client_errors
mysql_set_local_infile_default
mysql_set_local_infile_handler
- mysql_disable_reads_from_master
- mysql_disable_rpl_parse
- mysql_enable_reads_from_master
- mysql_enable_rpl_parse
- mysql_master_query
- mysql_rpl_parse_enabled
- mysql_rpl_probe
- mysql_rpl_query_type
- mysql_slave_query
mysql_embedded
mysql_server_init
mysql_server_end
diff --git a/libmysql/manager.c b/libmysql/manager.c
deleted file mode 100644
index 53ffffa55c0..00000000000
--- a/libmysql/manager.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Copyright (C) 2000-2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation.
-
- There are special exceptions to the terms and conditions of the GPL as it
- is applied to this software. View the full text of the exception in file
- EXCEPTIONS-CLIENT in the directory of this software distribution.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include <my_global.h>
-#if defined(THREAD)
-#include <my_pthread.h> /* because of signal() */
-#endif
-#include "mysql.h"
-#include "mysql_version.h"
-#include "mysqld_error.h"
-#include <my_sys.h>
-#include <mysys_err.h>
-#include <m_string.h>
-#include <m_ctype.h>
-#include <my_net.h>
-#include <errmsg.h>
-#include <violite.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <errno.h>
-
-#if defined(__NETWARE__)
-#include <netdb.h>
-#include <sys/select.h>
-#include <sys/utsname.h>
-#elif !defined( __WIN__)
-#include <sys/resource.h>
-#ifdef HAVE_SYS_UN_H
-# include <sys/un.h>
-#endif
-#include <netdb.h>
-#ifdef HAVE_SELECT_H
-# include <select.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <sys/utsname.h>
-#endif /* __WIN__ */
-
-#ifndef INADDR_NONE
-#define INADDR_NONE -1
-#endif
-
-#define RES_BUF_SHIFT 5
-#define NET_BUF_SIZE 2048
-
-MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con)
-{
- int net_buf_size=NET_BUF_SIZE;
- if (!con)
- {
- if (!(con=(MYSQL_MANAGER*)my_malloc(sizeof(*con)+net_buf_size,
- MYF(MY_WME|MY_ZEROFILL))))
- return 0;
- con->free_me=1;
- con->net_buf=(char*)con+sizeof(*con);
- }
- else
- {
- bzero((char*)con,sizeof(*con));
- if (!(con->net_buf=my_malloc(net_buf_size,MYF(0))))
- return 0;
- }
- con->net_buf_pos=con->net_data_end=con->net_buf;
- con->net_buf_size=net_buf_size;
- return con;
-}
-
-MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
- const char* host,
- const char* user,
- const char* passwd,
- unsigned int port)
-{
- my_socket sock;
- struct sockaddr_in sock_addr;
- in_addr_t ip_addr;
- char msg_buf[MAX_MYSQL_MANAGER_MSG];
- int msg_len;
- Vio* vio;
- my_bool not_used;
-
- if (!host)
- host="localhost";
- if (!user)
- user="root";
- if (!passwd)
- passwd="";
-
- if ((sock=(my_socket)socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
- {
- con->last_errno=errno;
- strmov(con->last_error,"Cannot create socket");
- goto err;
- }
- if (!(vio=vio_new(sock,VIO_TYPE_TCPIP,FALSE)))
- {
- con->last_errno=ENOMEM;
- strmov(con->last_error,"Cannot create network I/O object");
- goto err;
- }
- vio_blocking(vio, TRUE, &not_used);
- my_net_init(&con->net,vio);
- bzero((char*) &sock_addr,sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE)
- {
- memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr));
- }
- else
- {
- int tmp_errno;
- struct hostent tmp_hostent,*hp;
- char buff2[GETHOSTBYNAME_BUFF_SIZE];
- hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2),
- &tmp_errno);
- if (!hp)
- {
- con->last_errno=tmp_errno;
- sprintf(con->last_error,"Could not resolve host '%-.64s'",host);
- my_gethostbyname_r_free();
- goto err;
- }
- memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
- my_gethostbyname_r_free();
- }
- sock_addr.sin_port = (ushort) htons((ushort) port);
- if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
- 0))
- {
- con->last_errno=errno;
- sprintf(con->last_error ,"Could not connect to %-.64s", host);
- goto err;
- }
- /* read the greating */
- if (my_net_read(&con->net) == packet_error)
- {
- con->last_errno=errno;
- strmov(con->last_error,"Read error on socket");
- goto err;
- }
- sprintf(msg_buf,"%-.16s %-.16s\n",user,passwd);
- msg_len=strlen(msg_buf);
- if (my_net_write(&con->net,(uchar*) msg_buf,msg_len) || net_flush(&con->net))
- {
- con->last_errno=con->net.last_errno;
- strmov(con->last_error,"Write error on socket");
- goto err;
- }
- if (my_net_read(&con->net) == packet_error)
- {
- con->last_errno=errno;
- strmov(con->last_error,"Read error on socket");
- goto err;
- }
- if ((con->cmd_status=atoi((char*) con->net.read_pos)) != MANAGER_OK)
- {
- strmov(con->last_error,"Access denied");
- goto err;
- }
- if (!my_multi_malloc(MYF(0), &con->host, (uint)strlen(host)+1,
- &con->user, (uint)strlen(user)+1,
- &con->passwd, (uint)strlen(passwd)+1,
- NullS))
- {
- con->last_errno=ENOMEM;
- strmov(con->last_error,"Out of memory");
- goto err;
- }
- strmov(con->host,host);
- strmov(con->user,user);
- strmov(con->passwd,passwd);
- return con;
-
-err:
- {
- my_bool free_me=con->free_me;
- con->free_me=0;
- mysql_manager_close(con);
- con->free_me=free_me;
- }
- return 0;
-}
-
-void STDCALL mysql_manager_close(MYSQL_MANAGER* con)
-{
- /*
- No need to free con->user and con->passwd, because they were
- allocated in my_multimalloc() along with con->host, freeing
- con->hosts frees the whole block
- */
- my_free((uchar*)con->host,MYF(MY_ALLOW_ZERO_PTR));
- net_end(&con->net);
- if (con->free_me)
- my_free((uchar*)con,MYF(0));
-}
-
-
-int STDCALL mysql_manager_command(MYSQL_MANAGER* con,const char* cmd,
- int cmd_len)
-{
- if (!cmd_len)
- cmd_len=strlen(cmd);
- if (my_net_write(&con->net,(const uchar*)cmd,cmd_len) || net_flush(&con->net))
- {
- con->last_errno=errno;
- strmov(con->last_error,"Write error on socket");
- return 1;
- }
- con->eof=0;
- return 0;
-}
-
-
-int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf,
- int res_buf_size)
-{
- char* res_buf_end=res_buf+res_buf_size;
- char* net_buf=(char*) con->net.read_pos, *net_buf_end;
- int res_buf_shift=RES_BUF_SHIFT;
- ulong num_bytes;
-
- if (res_buf_size<RES_BUF_SHIFT)
- {
- con->last_errno=ENOMEM;
- strmov(con->last_error,"Result buffer too small");
- return 1;
- }
-
- if ((num_bytes=my_net_read(&con->net)) == packet_error)
- {
- con->last_errno=errno;
- strmov(con->last_error,"socket read failed");
- return 1;
- }
-
- net_buf_end=net_buf+num_bytes;
-
- if ((con->eof=(net_buf[3]==' ')))
- res_buf_shift--;
- net_buf+=res_buf_shift;
- res_buf_end[-1]=0;
- for (;net_buf<net_buf_end && res_buf < res_buf_end;res_buf++,net_buf++)
- {
- if ((*res_buf=*net_buf) == '\r')
- {
- *res_buf=0;
- break;
- }
- }
- return 0;
-}
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index ccf3d0a847b..f032aae0d18 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -98,7 +98,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
thd= (THD *) mysql->thd;
}
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.start_new_query();
#endif
@@ -119,7 +119,6 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
thd->current_stmt= stmt;
thd->store_globals(); // Fix if more than one connect
- lex_start(thd);
/*
We have to call free_old_query before we start to fill mysql->fields
for new query. In the case of embedded server we collect field data
@@ -144,13 +143,13 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
thd->mysys_var= 0;
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
#endif
return result;
}
-static void emb_flush_use_result(MYSQL *mysql)
+static void emb_flush_use_result(MYSQL *mysql, my_bool)
{
THD *thd= (THD*) mysql->thd;
if (thd->cur_data)
@@ -656,7 +655,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
- net_end_statement(thd);
+ thd->protocol->end_statement();
emb_read_query_result(mysql);
return result;
}
@@ -882,7 +881,7 @@ void Protocol_text::remove_last_row()
}
-bool Protocol::send_fields(List<Item> *list, uint flags)
+bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
@@ -891,7 +890,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
CHARSET_INFO *thd_cs= thd->variables.character_set_results;
CHARSET_INFO *cs= system_charset_info;
MYSQL_DATA *data;
- DBUG_ENTER("send_fields");
+ DBUG_ENTER("send_result_set_metadata");
if (!thd->mysql) // bootstrap file handling
DBUG_RETURN(0);
@@ -985,7 +984,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
write_eof_packet(thd, thd->server_status,
thd->warning_info->statement_warn_count());
- DBUG_RETURN(prepare_for_send(list));
+ DBUG_RETURN(prepare_for_send(list->elements));
err:
my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index c7b37d98f2b..bca076fa938 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -28,6 +28,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
+#include <sql_common.h>
#include "client_settings.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -77,17 +78,6 @@ static my_bool is_NT(void)
}
#endif
-/**************************************************************************
-** Shut down connection
-**************************************************************************/
-
-static void end_server(MYSQL *mysql)
-{
- DBUG_ENTER("end_server");
- free_old_query(mysql);
- DBUG_VOID_RETURN;
-}
-
int mysql_init_character_set(MYSQL *mysql);
@@ -104,6 +94,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
db ? db : "(Null)",
user ? user : "(Null)"));
+ /* Test whether we're already connected */
+ if (mysql->server_version)
+ {
+ set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
+ DBUG_RETURN(0);
+ }
+
if (!host || !host[0])
host= mysql->options.host;
@@ -216,7 +213,7 @@ error:
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;
- end_server(mysql);
+ free_old_query(mysql);
mysql->free_me=0;
mysql_close(mysql);
mysql->free_me=free_me;
diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def
index 047cfe0fe57..706f6ba945d 100644
--- a/libmysqld/libmysqld.def
+++ b/libmysqld/libmysqld.def
@@ -13,9 +13,7 @@ EXPORTS
mysql_commit
mysql_data_seek
mysql_debug
- mysql_disable_rpl_parse
mysql_dump_debug_info
- mysql_enable_rpl_parse
mysql_eof
mysql_errno
mysql_error
@@ -50,6 +48,7 @@ EXPORTS
mysql_next_result
mysql_num_fields
mysql_num_rows
+ mysql_odbc_escape_string
mysql_options
mysql_ping
mysql_query
@@ -61,8 +60,6 @@ EXPORTS
mysql_rollback
mysql_row_seek
mysql_row_tell
- mysql_rpl_parse_enabled
- mysql_rpl_probe
mysql_select_db
mysql_send_query
mysql_shutdown
diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt
new file mode 100644
index 00000000000..ddfa2495ade
--- /dev/null
+++ b/libservices/CMakeLists.txt
@@ -0,0 +1,20 @@
+# Copyright (C) 2006 MySQL AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c)
+
+ADD_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
diff --git a/libservices/HOWTO b/libservices/HOWTO
new file mode 100644
index 00000000000..b4960cb11dc
--- /dev/null
+++ b/libservices/HOWTO
@@ -0,0 +1,100 @@
+How to create a new service
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A "service" is a set of C functions in a structure that a
+service dynamic linker uses when a dynamic plugin is loaded.
+
+If you want to export C++ class you need to provide an
+extern "C" function that will create a new instance of your class,
+and put it in a service.
+
+Data structures are not part of the service structure, but they are part
+of the API you create and usually need to be declared in the same
+service_*.h file.
+
+To turn a set of functions (foo_func1, foo_func2)
+into a service "foo" you need to
+
+1. create a new file include/mysql/service_foo.h
+
+2. the template is
+==================================================================
+ #ifndef MYSQL_SERVICE_FOO_INCLUDED
+ /* standard GPL header */
+
+ /**
+ @file
+ *exhaustive* description of the interface you provide.
+ This file is the main user documentation of the new service
+ */
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ extern struct foo_service_st {
+ int (*foo_func1_type)(...); /* fix the prototype as appropriate */
+ void (*foo_func2_type)(...); /* fix the prototype as appropriate */
+ } *foo_service;
+
+ #ifdef MYSQL_DYNAMIC_PLUGIN
+
+ #define foo_func1(...) foo_service->foo_func1_type(...)
+ #define foo_func2(...) foo_service->foo_func2_type(...)
+
+ #else
+
+ int foo_func1_type(...); /* fix the prototype as appropriate */
+ void foo_func2_type(...); /* fix the prototype as appropriate */
+
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #define MYSQL_SERVICE_FOO_INCLUDED
+ #endif
+==================================================================
+
+the service_foo.h file should be self-contained, if it needs system headers -
+include them in it, e.g. if you use size_t - #include <stdlib.h>
+
+it should also declare all the accompanying data structures, as necessary
+(e.g. thd_alloc_service declares MYSQL_LEX_STRING).
+
+3. add the new file to include/Makefile.am (pkginclude_HEADERS)
+4. add the new file to include/mysql/services.h
+5. increase the minor plugin ABI version in include/mysql/plugin.h
+ (MYSQL_PLUGIN_INTERFACE_VERSION = MYSQL_PLUGIN_INTERFACE_VERSION+1)
+6. add the version of your service to include/service_versions.h:
+==================================================================
+ #define VERSION_foo 0x0100
+==================================================================
+
+7. create a new file libservices/foo_service.h using the following template:
+==================================================================
+ /* GPL header */
+ #include <service_versions.h>
+ SERVICE_VERSION *foo_service= (void*)VERSION_foo;
+==================================================================
+
+8. add the new file to libservices/CMakeLists.txt (MYSQLSERVICES_SOURCES)
+9. add the new file to libservices/Makefile.am (libmysqlservices_a_SOURCES)
+10. and finally, register your service for dynamic linking in
+ sql/sql_plugin_services.h
+10.1 fill in the service structure:
+==================================================================
+ static struct foo_service_st foo_handler = {
+ foo_func1,
+ foo_func2
+ }
+==================================================================
+
+10.2 and add it to the list of services
+
+==================================================================
+ { "foo_service", VERSION_foo, &foo_handler }
+==================================================================
+
+that's all.
+
diff --git a/libservices/Makefile.am b/libservices/Makefile.am
new file mode 100644
index 00000000000..642081859c1
--- /dev/null
+++ b/libservices/Makefile.am
@@ -0,0 +1,19 @@
+# Copyright 2009 Sun Microsystems, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+AM_CPPFLAGS = -I$(top_srcdir)/include
+pkglib_LIBRARIES = libmysqlservices.a
+libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c
+EXTRA_DIST = CMakeLists.txt
diff --git a/libservices/my_snprintf_service.c b/libservices/my_snprintf_service.c
new file mode 100644
index 00000000000..40d778e4b8d
--- /dev/null
+++ b/libservices/my_snprintf_service.c
@@ -0,0 +1,17 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <service_versions.h>
+SERVICE_VERSION my_snprintf_service= (void*)VERSION_my_snprintf;
diff --git a/libservices/thd_alloc_service.c b/libservices/thd_alloc_service.c
new file mode 100644
index 00000000000..5d4d496774c
--- /dev/null
+++ b/libservices/thd_alloc_service.c
@@ -0,0 +1,17 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <service_versions.h>
+SERVICE_VERSION *thd_alloc_service= (void*)VERSION_thd_alloc;
diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental
index 2d113972b45..3bb66c0eb1a 100644
--- a/mysql-test/collections/default.experimental
+++ b/mysql-test/collections/default.experimental
@@ -6,8 +6,6 @@ binlog.binlog_multi_engine # joro : NDB tests marked as experiment
funcs_1.charset_collation_1 # depends on compile-time decisions
-innodb.innodb_information_schema # Bug#47449 2009-09-19 alik main.information_schema and innodb.innodb_information_schema fail sporadically
-
main.ctype_gbk_binlog @solaris # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists
main.information_schema # Bug#47449 2009-09-19 alik main.information_schema and innodb.innodb_information_schema fail sporadically
main.innodb-autoinc* # Bug#47809 2009-10-04 joro innodb-autoinc.test fails with valgrind errors with the innodb plugin
@@ -17,11 +15,12 @@ main.log_tables # Bug#47924 2009-10-08 alik main.log_ta
main.plugin # Bug#47146 Linking problem with example plugin when dtrace enabled
main.plugin_load # Bug#47146
+rpl.rpl_cross_version* # Bug #43913 2009-10-26 joro rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm
rpl.rpl_innodb_bug28430* # Bug#46029
rpl.rpl_innodb_bug30888* @solaris # Bug#47646 2009-09-25 alik rpl.rpl_innodb_bug30888 fails sporadically on Solaris
+rpl.rpl_log_pos* # Bug#47743 2009-10-02 alik rpl.rpl_log_pos fails sporadically
rpl.rpl_plugin_load* @solaris # Bug#47146
rpl.rpl_row_create_table* # Bug#45576: rpl_row_create_table fails on PB2
-rpl.rpl_log_pos* # Bug#47743 2009-10-02 alik rpl.rpl_log_pos fails sporadically
rpl.rpl_timezone* # Bug#47017 2009-10-27 alik rpl_timezone fails on PB-2 with mismatch error
rpl.rpl_trigger* # Bug#46656 2009-09-25 alik InnoDB plugin: memory leaks (Valgrind)
rpl.rpl_heartbeat_basic # BUG#43828 2009-10-22 luis fails sporadically
diff --git a/mysql-test/extra/binlog_tests/drop_temp_table.test b/mysql-test/extra/binlog_tests/drop_temp_table.test
index 5616fb4a643..63833c10c14 100644
--- a/mysql-test/extra/binlog_tests/drop_temp_table.test
+++ b/mysql-test/extra/binlog_tests/drop_temp_table.test
@@ -48,6 +48,16 @@ DROP TABLE IF EXISTS tmp2, t;
--enable_warnings
SELECT GET_LOCK("a",10);
+
+#
+# BUG48216 Replication fails on all slaves after upgrade to 5.0.86 on master
+#
+# When the session is closed, any temporary tables of the session are dropped
+# and are binlogged. But it will be binlogged with a wrong database name when
+# the length of the database name('drop-temp-table-test') is greater than the
+# current database name('test').
+#
+USE test;
disconnect con1;
connection con2;
diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test
index 129a39ac509..e159242ed10 100644
--- a/mysql-test/extra/rpl_tests/rpl_loaddata.test
+++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test
@@ -158,4 +158,65 @@ LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1;
DROP TABLE IF EXISTS t1;
+# BUG#48297: Schema name is ignored when LOAD DATA is written into binlog,
+# replication aborts
+-- source include/master-slave-reset.inc
+
+-- let $db1= b48297_db1
+-- let $db2= b42897_db2
+
+-- connection master
+
+-- disable_warnings
+-- eval drop database if exists $db1
+-- eval drop database if exists $db2
+-- enable_warnings
+
+-- eval create database $db1
+-- eval create database $db2
+
+-- eval use $db1
+-- eval CREATE TABLE t1 (c1 VARCHAR(256)) engine=$engine_type;
+
+-- eval use $db2
+
+-- echo ### assertion: works with cross-referenced database
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
+
+-- eval use $db1
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- echo ### assertion: works with fully qualified name on current database
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
+
+-- echo ### assertion: works without fully qualified name on current database
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1
+
+-- echo ### create connection without default database
+-- echo ### connect (conn2,localhost,root,,*NO-ONE*);
+connect (conn2,localhost,root,,*NO-ONE*);
+-- connection conn2
+-- echo ### assertion: works without stating the default database
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
+-- echo ### disconnect and switch back to master connection
+-- disconnect conn2
+-- connection master
+
+-- sync_slave_with_master
+-- eval use $db1
+
+let $diff_table_1=master:$db1.t1;
+let $diff_table_2=slave:$db1.t1;
+source include/diff_tables.inc;
+
+-- connection master
+
+-- eval DROP DATABASE $db1
+-- eval DROP DATABASE $db2
+
+-- sync_slave_with_master
+
# End of 4.1 tests
diff --git a/mysql-test/extra/rpl_tests/rpl_stm_000001.test b/mysql-test/extra/rpl_tests/rpl_stm_000001.test
index 1f5eb5786dd..869a9e3b07c 100644
--- a/mysql-test/extra/rpl_tests/rpl_stm_000001.test
+++ b/mysql-test/extra/rpl_tests/rpl_stm_000001.test
@@ -93,7 +93,7 @@ kill @id;
# We don't drop t3 as this is a temporary table
drop table t2;
connection master;
---error 1053,2013
+--error 1317,2013
reap;
connection slave;
# The SQL slave thread should now have stopped because the query was killed on
diff --git a/mysql-test/include/bug38347.inc b/mysql-test/include/bug38347.inc
new file mode 100644
index 00000000000..ca1dbfa1bd2
--- /dev/null
+++ b/mysql-test/include/bug38347.inc
@@ -0,0 +1,21 @@
+
+--echo
+SHOW GRANTS FOR mysqltest_u1@localhost;
+
+--echo
+--echo # connection: con1 (mysqltest_u1@mysqltest_db1)
+--connect (con1,localhost,mysqltest_u1,,mysqltest_db1)
+--connection con1
+
+--echo
+SHOW CREATE TABLE t1;
+
+--echo
+--echo # connection: default
+--connection default
+
+--disconnect con1
+
+--echo
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
diff --git a/mysql-test/include/have_case_insensitive_fs.inc b/mysql-test/include/have_case_insensitive_fs.inc
new file mode 100644
index 00000000000..de4ad73d780
--- /dev/null
+++ b/mysql-test/include/have_case_insensitive_fs.inc
@@ -0,0 +1,4 @@
+--require r/case_insensitive_fs.require
+--disable_query_log
+show variables like 'lower_case_file_system';
+--enable_query_log
diff --git a/mysql-test/include/have_community_features.inc b/mysql-test/include/have_community_features.inc
deleted file mode 100644
index 66697d8dd00..00000000000
--- a/mysql-test/include/have_community_features.inc
+++ /dev/null
@@ -1,4 +0,0 @@
---require r/have_community_features.require
---disable_query_log
-show variables like 'have_community_features';
---enable_query_log
diff --git a/mysql-test/include/have_profiling.inc b/mysql-test/include/have_profiling.inc
new file mode 100644
index 00000000000..48f6668ff92
--- /dev/null
+++ b/mysql-test/include/have_profiling.inc
@@ -0,0 +1,4 @@
+--require r/have_profiling.require
+--disable_query_log
+show variables like 'have_profiling';
+--enable_query_log
diff --git a/mysql-test/include/query_cache_sql_prepare.inc b/mysql-test/include/query_cache_sql_prepare.inc
index 1842d5412bb..baa041aa058 100644
--- a/mysql-test/include/query_cache_sql_prepare.inc
+++ b/mysql-test/include/query_cache_sql_prepare.inc
@@ -1,11 +1,13 @@
############### include/query_cache_sql_prepare.inc ################
#
# This is to see how statements prepared via the PREPARE SQL command
-# go into the query cache: if using parameters they cannot; if not
-# using parameters they can.
+# go into the query cache.
# Query cache is abbreviated as "QC"
#
# Last update:
+# 2008-05-26 Kostja
+# - Add test coverage for automatic statement reprepare
+#
# 2007-05-03 ML - Move t/query_cache_sql_prepare.test
# to include/query_cache_sql_prepare.inc
# - Create two toplevel tests sourcing this routine
@@ -490,6 +492,37 @@ use test;
--echo
--echo ########################################################################
+--echo #
+--echo # Bug#27430 Crash in subquery code when in PS and table DDL changed
+--echo # after PREPARE
+--echo # Check the effect of automatic reprepare on query cache
+--echo #
+--echo ########################################################################
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a varchar(255));
+insert into t1 (a) values ("Pack my box with five dozen liquor jugs.");
+flush status;
+prepare stmt from "select a from t1";
+execute stmt;
+set @@global.query_cache_size=0;
+alter table t1 add column b int;
+execute stmt;
+set @@global.query_cache_size=100000;
+execute stmt;
+execute stmt;
+--echo #
+--echo # Sic: ALTER TABLE caused an automatic reprepare
+--echo # of the prepared statement. Since the query cache was disabled
+--echo # at the time of reprepare, the new prepared statement doesn't
+--echo # work with it.
+--echo #
+show status like 'Qcache_hits';
+show status like 'Qcache_queries_in_cache';
+--echo # Cleanup
+deallocate prepare stmt;
+drop table t1;
###############################################################################
diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc
index 455262b29f5..aa9093fb2b4 100755
--- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc
+++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc
@@ -50,9 +50,6 @@
is killed.
*/
-/* Requires Windows 2000 or higher */
-#define _WIN32_WINNT 0x0500
-
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index db7173d0b47..15171798279 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -1330,4 +1330,20 @@ ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9',
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
DROP TABLE t1;
+CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL,
+f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2);
+this should affect no rows as there is no real change
+ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
End of 5.1 tests
+CREATE TABLE t1(c CHAR(10),
+i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY);
+INSERT INTO t1 VALUES('a',2),('b',4),('c',6);
+ALTER TABLE t1
+DROP i,
+ADD i INT UNSIGNED NOT NULL AUTO_INCREMENT,
+AUTO_INCREMENT = 1;
+DROP TABLE t1;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index 6eaa8731dc6..1820782d2f8 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -19,81 +19,10 @@ test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
create table t2 select * from t1 procedure analyse();
-select * from t2;
-Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
-test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
-test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
-test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
-test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
-drop table t1,t2;
+ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT
+drop table t1;
EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
ERROR HY000: Incorrect usage of PROCEDURE and subquery
-create table t1 (a int not null);
-create table t2 select * from t1 where 0=1 procedure analyse();
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `Field_name` varbinary(255) NOT NULL DEFAULT '',
- `Min_value` varbinary(255) DEFAULT NULL,
- `Max_value` varbinary(255) DEFAULT NULL,
- `Min_length` bigint(11) NOT NULL DEFAULT '0',
- `Max_length` bigint(11) NOT NULL DEFAULT '0',
- `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0',
- `Nulls` bigint(11) NOT NULL DEFAULT '0',
- `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '',
- `Std` varbinary(255) DEFAULT NULL,
- `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT ''
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-select * from t1 where 0=1 procedure analyse();
-Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-insert into t1 values(1);
-drop table t2;
-create table t2 select * from t1 where 0=1 procedure analyse();
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `Field_name` varbinary(255) NOT NULL DEFAULT '',
- `Min_value` varbinary(255) DEFAULT NULL,
- `Max_value` varbinary(255) DEFAULT NULL,
- `Min_length` bigint(11) NOT NULL DEFAULT '0',
- `Max_length` bigint(11) NOT NULL DEFAULT '0',
- `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0',
- `Nulls` bigint(11) NOT NULL DEFAULT '0',
- `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '',
- `Std` varbinary(255) DEFAULT NULL,
- `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT ''
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-select * from t2;
-Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-insert into t2 select * from t1 procedure analyse();
-select * from t2;
-Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-test.t1.a 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL
-insert into t1 values(2);
-drop table t2;
-create table t2 select * from t1 where 0=1 procedure analyse();
-show create table t2;
-Table Create Table
-t2 CREATE TABLE `t2` (
- `Field_name` varbinary(255) NOT NULL DEFAULT '',
- `Min_value` varbinary(255) DEFAULT NULL,
- `Max_value` varbinary(255) DEFAULT NULL,
- `Min_length` bigint(11) NOT NULL DEFAULT '0',
- `Max_length` bigint(11) NOT NULL DEFAULT '0',
- `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0',
- `Nulls` bigint(11) NOT NULL DEFAULT '0',
- `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '',
- `Std` varbinary(255) DEFAULT NULL,
- `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT ''
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-select * from t2;
-Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-insert into t2 select * from t1 procedure analyse();
-select * from t2;
-Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-test.t1.a 1 2 1 1 0 0 1.5000 0.5000 ENUM('1','2') NOT NULL
-drop table t1,t2;
create table t1 (v varchar(128));
insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),('a\0'),('b\''),('c\"'),('d\\'),('\'b'),('\"c'),('\\d'),('a\0\0\0b'),('a\'\'\'\'b'),('a\"\"\"\"b'),('a\\\\\\\\b'),('\'\0\\\"'),('\'\''),('\"\"'),('\\\\'),('The\ZEnd');
select * from t1 procedure analyse();
@@ -157,3 +86,40 @@ SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE();
ERROR HY000: Incorrect usage of PROCEDURE and subquery
DROP TABLE t1;
End of 4.1 tests
+#
+# Bug #48293: crash with procedure analyse, view with > 10 columns,
+# having clause...
+#
+CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT,
+f INT, g INT, h INT, i INT, j INT,k INT);
+INSERT INTO t1 VALUES (),();
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+#should have a derived table
+EXPLAIN SELECT * FROM v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 2
+#should not crash
+SELECT * FROM v1 PROCEDURE analyse();
+ERROR HY000: Incorrect usage of PROCEDURE and view
+#should not crash
+SELECT * FROM t1 a, v1, t1 b PROCEDURE analyse();
+ERROR HY000: Incorrect usage of PROCEDURE and view
+#should not crash
+SELECT * FROM (SELECT * FROM t1 having a > 1) x PROCEDURE analyse();
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
+#should not crash
+SELECT * FROM t1 a, (SELECT * FROM t1 having a > 1) x, t1 b PROCEDURE analyse();
+ERROR HY000: Incorrect usage of PROCEDURE and subquery
+#should not crash
+SELECT 1 FROM t1 group by a having a > 1 order by 1 PROCEDURE analyse();
+ERROR HY000: Can't use ORDER clause with this procedure
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1),(2);
+# should not crash
+CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE();
+ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT
+DROP TABLE t1;
+End of 5.0 tests
diff --git a/mysql-test/r/bug40113.result b/mysql-test/r/bug40113.result
deleted file mode 100644
index 289037a3f35..00000000000
--- a/mysql-test/r/bug40113.result
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout
-# without error
-#
-CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB;
-INSERT INTO t1 (a,b) VALUES (1070109,99);
-CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB;
-INSERT INTO t2 (b,a) VALUES (7,1070109);
-SELECT * FROM t1;
-a b
-1070109 99
-BEGIN;
-SELECT b FROM t2 WHERE b=7 FOR UPDATE;
-b
-7
-BEGIN;
-SELECT b FROM t2 WHERE b=7 FOR UPDATE;
-ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7));
-ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7);
-ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7);
-ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-SELECT * FROM t1;
-a b
-1070109 99
-DROP TABLE t2, t1;
-End of 5.0 tests
diff --git a/mysql-test/r/case_insensitive_fs.require b/mysql-test/r/case_insensitive_fs.require
new file mode 100644
index 00000000000..062ac610ddd
--- /dev/null
+++ b/mysql-test/r/case_insensitive_fs.require
@@ -0,0 +1,2 @@
+Variable_name Value
+lower_case_file_system ON
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index b829ef30fb1..471cc6e9a3d 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1922,3 +1922,37 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
# -- End of Bug#45829
End of 5.1 tests
+
+# --
+# -- Bug #43054 Assertion `!table->auto_increment_field_not_null'
+# -- failed when redefining trigger
+
+CREATE TABLE B (
+pk INTEGER AUTO_INCREMENT,
+int_key INTEGER NOT NULL,
+PRIMARY KEY (pk),
+KEY (int_key)
+);
+INSERT IGNORE INTO B VALUES ('9', '9');
+CREATE TABLE IF NOT EXISTS t1 (
+`pk` INTEGER NOT NULL AUTO_INCREMENT ,
+`int` INTEGER ,
+PRIMARY KEY ( `pk` )
+) SELECT `pk` , `int_key` FROM B ;
+CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+INSERT INTO t1 ( `int` ) VALUES (4 ),( 8 ),( 2 ) ;
+END ; |
+CREATE TABLE IF NOT EXISTS t1 (
+`pk` INTEGER NOT NULL AUTO_INCREMENT ,
+`int` INTEGER ,
+PRIMARY KEY ( `pk` )
+) SELECT `pk` , `int_key` FROM B ;
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+UPDATE A SET `pk`=1 WHERE `pk`=0 ;
+END ;|
+ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table'
+DROP TABLE t1;
+DROP TABLE B;
diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index b42094550bd..67262a4935d 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -548,6 +548,36 @@ SELECT * FROM t1 WHERE s2 = s3;
s1 s2 s3
a A A
DROP TABLE t1;
+create table t1 (a varchar(1) character set latin1 collate latin1_general_ci);
+insert into t1 values ('A'),('a'),('B'),('b'),('C'),('c');
+select * from t1 where a > 'B' collate latin1_bin;
+a
+a
+b
+C
+c
+select * from t1 where a <> 'B' collate latin1_bin;
+a
+A
+a
+b
+C
+c
+create index i on t1 (a);
+select * from t1 where a > 'B' collate latin1_bin;
+a
+a
+b
+C
+c
+select * from t1 where a <> 'B' collate latin1_bin;
+a
+A
+a
+b
+C
+c
+drop table t1;
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
diff --git a/mysql-test/r/ctype_ldml.result b/mysql-test/r/ctype_ldml.result
index 388b1373cf9..222351cd5e2 100644
--- a/mysql-test/r/ctype_ldml.result
+++ b/mysql-test/r/ctype_ldml.result
@@ -73,6 +73,14 @@ efgh efgh
ijkl ijkl
DROP TABLE t1;
#
+# Bug#45645 Mysql server close all connection and restart using lower function
+#
+CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 COLLATE utf8_test_ci;
+INSERT INTO t1 (a) VALUES ('hello!');
+SELECT * FROM t1 WHERE LOWER(a)=LOWER('N');
+a
+DROP TABLE t1;
+#
# Bug#43827 Server closes connections and restarts
#
CREATE TABLE t1 (c1 VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_test_ci);
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index b26b029759c..0645be35b10 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -311,3 +311,25 @@ a b
drop table t1;
set global low_priority_updates = @old_delayed_updates;
End of 5.1 tests
+#
+# Bug #47274 assert in open_table on CREATE TABLE <already existing>
+#
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1 ( f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1));
+# The following CREATE TABLEs before gave an assert.
+INSERT DELAYED t1 VALUES (4);
+CREATE TABLE t1 AS SELECT 1 AS f1;
+ERROR 42S01: Table 't1' already exists
+REPLACE DELAYED t1 VALUES (5);
+CREATE TABLE t1 AS SELECT 1 AS f1;
+ERROR 42S01: Table 't1' already exists
+INSERT DELAYED t1 VALUES (6);
+CREATE TABLE t1 (f1 INTEGER);
+ERROR 42S01: Table 't1' already exists
+CREATE TABLE t2 (f1 INTEGER);
+INSERT DELAYED t1 VALUES (7);
+CREATE TABLE t1 LIKE t2;
+ERROR 42S01: Table 't1' already exists
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index b798b49dd34..42739b10d50 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -121,3 +121,17 @@ ERROR 42000: Incorrect table name '#mysql50#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
use test;
drop database mysqltestbug26703;
End of 5.1 tests
+
+# --
+# -- Bug#37431 (DROP TABLE does not report errors correctly).
+# --
+DROP TABLE IF EXISTS t1;
+DROP TABLE t1;
+ERROR 42S02: Unknown table 't1'
+SHOW WARNINGS;
+Level Code Message
+Error 1051 Unknown table 't1'
+
+# --
+# -- End of Bug#37431.
+# --
diff --git a/mysql-test/r/drop_debug.result b/mysql-test/r/drop_debug.result
new file mode 100644
index 00000000000..75346b88bc6
--- /dev/null
+++ b/mysql-test/r/drop_debug.result
@@ -0,0 +1,21 @@
+
+# --
+# -- Bug#43138: DROP DATABASE failure does not clean up message list.
+# --
+
+DROP DATABASE IF EXISTS mysql_test;
+
+CREATE DATABASE mysql_test;
+CREATE TABLE mysql_test.t1(a INT);
+
+SET SESSION DEBUG = "+d,bug43138";
+
+DROP DATABASE mysql_test;
+Warnings:
+Error 1051 Unknown table 't1'
+
+SET SESSION DEBUG = "-d,bug43138";
+
+# --
+# -- End of Bug#43138.
+# --
diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result
index bb177fe3475..efe6df41ac6 100644
--- a/mysql-test/r/events_bugs.result
+++ b/mysql-test/r/events_bugs.result
@@ -77,7 +77,7 @@ set sql_mode='traditional';
alter event e_16407 do select 1;
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
event_schema event_name sql_mode
-events_test e_16407 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+events_test e_16407 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
drop event e_16407;
set sql_mode="ansi";
select get_lock('ee_16407_2', 60);
@@ -114,8 +114,8 @@ insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956');
end|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
event_schema event_name sql_mode
-events_test ee_16407_2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
-events_test ee_16407_3 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+events_test ee_16407_2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
+events_test ee_16407_3 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
events_test ee_16407_4
select /*2*/ user, host, db, info from information_schema.processlist
where state = 'User lock' and info = 'select get_lock(\'ee_16407_2\', 60)';
@@ -138,8 +138,8 @@ ee_16407_4 0000-00-00
"OK, last check before we drop them"
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
event_schema event_name sql_mode
-events_test ee_16407_2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
-events_test ee_16407_3 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+events_test ee_16407_2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
+events_test ee_16407_3 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
events_test ee_16407_4
drop event ee_16407_2;
drop event ee_16407_3;
@@ -185,8 +185,8 @@ ee_16407_6 2004-02-29
"And here we check one more time before we drop the events"
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
event_schema event_name sql_mode
-events_test ee_16407_5 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
-events_test ee_16407_6 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+events_test ee_16407_5 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
+events_test ee_16407_6 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
drop event ee_16407_5;
drop event ee_16407_6;
drop procedure ee_16407_5_pendant;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index fbeea8bab45..3c449cf11a1 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -195,6 +195,22 @@ dt
2001-01-01 01:01:01
drop tables t1, t2;
#
+# Bug#48295:
+# explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode
+#
+CREATE TABLE t1 (f1 INT);
+SELECT @@session.sql_mode INTO @old_sql_mode;
+SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
+EXPLAIN EXTENDED SELECT 1 FROM t1
+WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
+ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
+SHOW WARNINGS;
+Level Code Message
+Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
+Note 1003 select 1 AS `1` from `test`.`t1` where <not>(<exists>(...))
+SET SESSION sql_mode=@old_sql_mode;
+DROP TABLE t1;
+#
# Bug#30302: Tables that were optimized away are printed in the
# EXPLAIN EXTENDED warning.
#
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index d8b8a14afc6..33ae2e0a5a4 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -382,6 +382,9 @@ y
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'
SELECT c DIV 900 y FROM t1 GROUP BY y;
y
0
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 779a125c5cc..35ce190feb3 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1151,6 +1151,9 @@ INSERT INTO t2 VALUES (0), (1);
SELECT * FROM t1, t2 WHERE num=str;
str num
notnumber 0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'notnumber'
+Warning 1292 Truncated incorrect DOUBLE value: 'notnumber'
SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6);
str num
notnumber 0
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index b030139e40e..68c4a6a13e5 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -1487,4 +1487,43 @@ MBRINTERSECTS(b, GEOMFROMTEXT('LINESTRING(1 1,1102219 2)') );
COUNT(*)
2
DROP TABLE t1;
+#
+# Bug #48258: Assertion failed when using a spatial index
+#
+CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a));
+INSERT INTO t1 VALUES
+(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')),
+(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'));
+EXPLAIN SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where
+SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+1
+1
+1
+EXPLAIN SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where
+SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+1
+EXPLAIN SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where
+SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+1
+1
+1
+EXPLAIN SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where
+SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+1
+EXPLAIN SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where
+SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+1
+1
+1
+DROP TABLE t1;
End of 5.0 tests.
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index a3708d06a1c..b40ff6be160 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -972,6 +972,18 @@ select min(`col002`) from t1 union select `col002` from t1;
min(`col002`)
NULL
drop table t1;
+#
+# Bug #47780: crash when comparing GIS items from subquery
+#
+CREATE TABLE t1(a INT, b MULTIPOLYGON);
+INSERT INTO t1 VALUES
+(0,
+GEOMFROMTEXT(
+'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))'));
+# must not crash
+SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
+1
+DROP TABLE t1;
End of 5.0 tests
create table t1 (f1 tinyint(1), f2 char(1), f3 varchar(1), f4 geometry, f5 datetime);
create view v1 as select * from t1;
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index 70181987c74..542a056c68c 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -13,8 +13,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -44,15 +44,15 @@ delete from mysql.user where user='mysqltest_1';
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 0 0 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
select * from mysql.user where user="mysqltest_1";
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
@@ -483,6 +483,7 @@ Show view Tables To see views with SHOW CREATE VIEW
Shutdown Server Admin To shut down the server
Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
Trigger Tables To use triggers
+Create tablespace Server Admin To create/alter/drop tablespaces
Update Tables To update existing rows
Usage Server Admin No privileges - allow connect only
create database mysqltest;
@@ -914,13 +915,13 @@ SHOW CREATE VIEW mysqltest2.v_ny;
View Create View character_set_client collation_connection
v_ny CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v_ny` AS select `mysqltest2`.`t_nn`.`c1` AS `c1` from `mysqltest2`.`t_nn` latin1 latin1_swedish_ci
SHOW CREATE TABLE mysqltest3.t_nn;
-ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
+ERROR 42000: SHOW command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
SHOW CREATE VIEW mysqltest3.t_nn;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't_nn'
SHOW CREATE VIEW mysqltest3.v_nn;
ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
SHOW CREATE TABLE mysqltest3.v_nn;
-ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
+ERROR 42000: SHOW command denied to user 'mysqltest_1'@'localhost' for table 'v_nn'
SHOW CREATE TABLE mysqltest2.t_nn;
Table Create Table
t_nn CREATE TABLE `t_nn` (
@@ -1007,8 +1008,8 @@ DROP TABLE mysqltest1.t2;
SHOW GRANTS;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
-GRANT SELECT, INSERT, CREATE, DROP, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost'
GRANT SELECT, INSERT, CREATE, DROP, ALTER ON `mysqltest1`.`t1` TO 'mysqltest_1'@'localhost'
+GRANT SELECT, INSERT, CREATE, DROP, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost'
RENAME TABLE t1 TO t2;
RENAME TABLE t2 TO t1;
ALTER TABLE t1 RENAME TO t2;
@@ -1018,8 +1019,8 @@ REVOKE DROP, INSERT ON mysqltest1.t2 FROM mysqltest_1@localhost;
SHOW GRANTS;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
-GRANT SELECT, CREATE, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost'
GRANT SELECT, CREATE, ALTER ON `mysqltest1`.`t1` TO 'mysqltest_1'@'localhost'
+GRANT SELECT, CREATE, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost'
RENAME TABLE t1 TO t2;
ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1'
ALTER TABLE t1 RENAME TO t2;
@@ -1413,3 +1414,713 @@ DROP USER 'user1';
DROP USER 'user1'@'localhost';
DROP USER 'user2';
DROP DATABASE db1;
+#
+# Bug #25863 No database selected error, but documentation
+# says * for global allowed
+#
+GRANT ALL ON * TO mysqltest_1;
+ERROR 3D000: No database selected
+GRANT ALL ON *.* TO mysqltest_1;
+SHOW GRANTS FOR mysqltest_1;
+Grants for mysqltest_1@%
+GRANT ALL PRIVILEGES ON *.* TO 'mysqltest_1'@'%'
+DROP USER mysqltest_1;
+USE test;
+GRANT ALL ON * TO mysqltest_1;
+SHOW GRANTS FOR mysqltest_1;
+Grants for mysqltest_1@%
+GRANT USAGE ON *.* TO 'mysqltest_1'@'%'
+GRANT ALL PRIVILEGES ON `test`.* TO 'mysqltest_1'@'%'
+DROP USER mysqltest_1;
+GRANT ALL ON *.* TO mysqltest_1;
+SHOW GRANTS FOR mysqltest_1;
+Grants for mysqltest_1@%
+GRANT ALL PRIVILEGES ON *.* TO 'mysqltest_1'@'%'
+DROP USER mysqltest_1;
+#########################################################################
+#
+# Bug#38347: ALTER ROUTINE privilege allows SHOW CREATE TABLE.
+#
+#########################################################################
+
+# --
+# -- Prepare the environment.
+# --
+DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%';
+FLUSH PRIVILEGES;
+DROP DATABASE IF EXISTS mysqltest_db1;
+CREATE DATABASE mysqltest_db1;
+CREATE TABLE mysqltest_db1.t1(a INT);
+
+# --
+# -- Check that global privileges don't allow SHOW CREATE TABLE.
+# --
+GRANT EVENT ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT LOCK TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT ALTER ROUTINE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT CREATE ROUTINE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT FILE ON *.* TO mysqltest_u1@localhost;
+GRANT CREATE USER ON *.* TO mysqltest_u1@localhost;
+GRANT PROCESS ON *.* TO mysqltest_u1@localhost;
+GRANT RELOAD ON *.* TO mysqltest_u1@localhost;
+GRANT REPLICATION CLIENT ON *.* TO mysqltest_u1@localhost;
+GRANT REPLICATION SLAVE ON *.* TO mysqltest_u1@localhost;
+GRANT SHOW DATABASES ON *.* TO mysqltest_u1@localhost;
+GRANT SHUTDOWN ON *.* TO mysqltest_u1@localhost;
+GRANT USAGE ON *.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE ROUTINE, ALTER ROUTINE, EVENT ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global SELECT allows SHOW CREATE TABLE.
+# --
+
+GRANT SELECT ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT SELECT ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global INSERT allows SHOW CREATE TABLE.
+# --
+
+GRANT INSERT ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT INSERT ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global UPDATE allows SHOW CREATE TABLE.
+# --
+
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT UPDATE ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global DELETE allows SHOW CREATE TABLE.
+# --
+
+GRANT DELETE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT DELETE ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global CREATE allows SHOW CREATE TABLE.
+# --
+
+GRANT CREATE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT CREATE ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global DROP allows SHOW CREATE TABLE.
+# --
+
+GRANT DROP ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT DROP ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global ALTER allows SHOW CREATE TABLE.
+# --
+
+GRANT ALTER ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT ALTER ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global INDEX allows SHOW CREATE TABLE.
+# --
+
+GRANT INDEX ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT INDEX ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global REFERENCES allows SHOW CREATE TABLE.
+# --
+
+GRANT REFERENCES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT REFERENCES ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global GRANT OPTION allows SHOW CREATE TABLE.
+# --
+
+GRANT GRANT OPTION ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT USAGE ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost' WITH GRANT OPTION
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global CREATE VIEW allows SHOW CREATE TABLE.
+# --
+
+GRANT CREATE VIEW ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT CREATE VIEW ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that global SHOW VIEW allows SHOW CREATE TABLE.
+# --
+
+GRANT SHOW VIEW ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT SHOW VIEW ON `mysqltest_db1`.* TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level SELECT allows SHOW CREATE TABLE.
+# --
+
+GRANT SELECT ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT SELECT ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level INSERT allows SHOW CREATE TABLE.
+# --
+
+GRANT INSERT ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT INSERT ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level UPDATE allows SHOW CREATE TABLE.
+# --
+
+GRANT UPDATE ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT UPDATE ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level DELETE allows SHOW CREATE TABLE.
+# --
+
+GRANT DELETE ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT DELETE ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level CREATE allows SHOW CREATE TABLE.
+# --
+
+GRANT CREATE ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT CREATE ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level DROP allows SHOW CREATE TABLE.
+# --
+
+GRANT DROP ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT DROP ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level ALTER allows SHOW CREATE TABLE.
+# --
+
+GRANT ALTER ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT ALTER ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level INDEX allows SHOW CREATE TABLE.
+# --
+
+GRANT INDEX ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT INDEX ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level REFERENCES allows SHOW CREATE TABLE.
+# --
+
+GRANT REFERENCES ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT REFERENCES ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level GRANT OPTION allows SHOW CREATE TABLE.
+# --
+
+GRANT GRANT OPTION ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT USAGE ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost' WITH GRANT OPTION
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level CREATE VIEW allows SHOW CREATE TABLE.
+# --
+
+GRANT CREATE VIEW ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT CREATE VIEW ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Check that table-level SHOW VIEW allows SHOW CREATE TABLE.
+# --
+
+GRANT SHOW VIEW ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+GRANT SHOW VIEW ON `mysqltest_db1`.`t1` TO 'mysqltest_u1'@'localhost'
+
+# connection: con1 (mysqltest_u1@mysqltest_db1)
+
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+# connection: default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+Grants for mysqltest_u1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# --
+# -- Cleanup.
+# --
+
+DROP DATABASE mysqltest_db1;
+DROP USER mysqltest_u1@localhost;
+
+# End of Bug#38347.
+
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 461ad78bbb6..eae12491a4d 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -391,7 +391,7 @@ grant all on mysqltest_1.* to mysqltest_u1@localhost;
use mysqltest_2;
create table t1 (i int);
show create table mysqltest_2.t1;
-ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't1'
create table t1 like mysqltest_2.t1;
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result
index f38848111ad..59c64ee84ae 100644
--- a/mysql-test/r/grant3.result
+++ b/mysql-test/r/grant3.result
@@ -154,4 +154,42 @@ SELECT * FROM mysqltest_1.t1;
a
DROP USER 'mysqltest1'@'%';
DROP DATABASE mysqltest_1;
+#
+# Bug#41597 - After rename of user, there are additional grants
+# when grants are reapplied.
+#
+CREATE DATABASE temp;
+CREATE TABLE temp.t1(a INT, b VARCHAR(10));
+INSERT INTO temp.t1 VALUES(1, 'name1');
+INSERT INTO temp.t1 VALUES(2, 'name2');
+INSERT INTO temp.t1 VALUES(3, 'name3');
+CREATE USER 'user1'@'%';
+RENAME USER 'user1'@'%' TO 'user2'@'%';
+# Show privileges after rename and BEFORE grant
+SHOW GRANTS FOR 'user2'@'%';
+Grants for user2@%
+GRANT USAGE ON *.* TO 'user2'@'%'
+GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%';
+# Show privileges after rename and grant
+SHOW GRANTS FOR 'user2'@'%';
+Grants for user2@%
+GRANT USAGE ON *.* TO 'user2'@'%'
+GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%'
+# Connect as the renamed user
+SHOW GRANTS;
+Grants for user2@%
+GRANT USAGE ON *.* TO 'user2'@'%'
+GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%'
+SELECT a FROM temp.t1;
+a
+1
+2
+3
+# Check for additional privileges by accessing a
+# non privileged column. We shouldn't be able to
+# access this column.
+SELECT b FROM temp.t1;
+ERROR 42000: SELECT command denied to user 'user2'@'localhost' for column 'b' in table 't1'
+DROP USER 'user2'@'%';
+DROP DATABASE temp;
End of 5.0 tests
diff --git a/mysql-test/r/grant4.result b/mysql-test/r/grant4.result
new file mode 100644
index 00000000000..28ad9d04151
--- /dev/null
+++ b/mysql-test/r/grant4.result
@@ -0,0 +1,123 @@
+drop database if exists mysqltest_db1;
+create database mysqltest_db1;
+use mysqltest_db1;
+create table t_column_priv_only (a int, b int);
+create table t_select_priv like t_column_priv_only;
+create table t_no_priv like t_column_priv_only;
+grant all privileges on test.* to mysqltest_u1@localhost;
+grant insert (a) on mysqltest_db1.t_column_priv_only to mysqltest_u1@localhost;
+grant select on mysqltest_db1.t_select_priv to mysqltest_u1@localhost;
+** Connect as restricted user mysqltest_u1.
+
+** Test column level privileges only. No SELECT privileges on the table.
+** INSERT INTO ... VALUES ...
+** Attempting to insert values to a table with only column privileges
+** should work.
+insert into mysqltest_db1.t_column_priv_only (a) VALUES (1);
+
+** SHOW COLUMNS
+** Should succeed because we have privileges (any) on at least one of the columns.
+select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_column_priv_only';
+Field Type Null Key Default Extra
+a int(11) YES NULL
+show columns from mysqltest_db1.t_column_priv_only;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+** SHOW COLUMNS
+** Should fail because there are no privileges on any column combination.
+show columns from mysqltest_db1.t_no_priv;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't_no_priv'
+** However, select from I_S.COLUMNS will succeed but not show anything:
+select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_no_priv';
+Field Type Null Key Default Extra
+
+** CREATE TABLE ... LIKE ... require SELECT privleges and will fail.
+create table test.t_no_priv like mysqltest_db1.column_priv_only;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'column_priv_only'
+
+** Just to be sure... SELECT also fails.
+select * from mysqltest_db1.t_column_priv_only;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't_column_priv_only'
+
+** SHOW CREATE TABLE ... require any privileges on all columns (the entire table).
+** First we try and fail on a table with only one column privilege.
+show create table mysqltest_db1.t_column_priv_only;
+ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't_column_priv_only'
+
+** Now we do the same on a table with SELECT privileges.
+
+** SHOW COLUMNS
+** Success because we got some privileges on the table (SELECT_ACL)
+show columns from mysqltest_db1.t_select_priv;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL
+
+** CREATE TABLE ... LIKE ... require SELECT privleges and will SUCCEED.
+drop table if exists test.t_duplicated;
+create table test.t_duplicated like mysqltest_db1.t_select_priv;
+drop table test.t_duplicated;
+
+** SHOW CREATE TABLE will succeed because we have a privilege on all columns in the table (table-level privilege).
+show create table mysqltest_db1.t_select_priv;
+Table Create Table
+t_select_priv CREATE TABLE `t_select_priv` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+** SHOW CREATE TABLE will fail if there is no grants at all:
+show create table mysqltest_db1.t_no_priv;
+ERROR 42000: SHOW command denied to user 'mysqltest_u1'@'localhost' for table 't_no_priv'
+
+use mysqltest_db1;
+CREATE TABLE t5 (s1 INT);
+CREATE INDEX i ON t5 (s1);
+CREATE TABLE t6 (s1 INT, s2 INT);
+CREATE VIEW v5 AS SELECT * FROM t5;
+CREATE VIEW v6 AS SELECT * FROM t6;
+CREATE VIEW v2 AS SELECT * FROM t_select_priv;
+CREATE VIEW v3 AS SELECT * FROM t_select_priv;
+CREATE INDEX i ON t6 (s1);
+GRANT UPDATE (s2) ON t6 to mysqltest_u1@localhost;
+GRANT UPDATE (s2) ON v6 to mysqltest_u1@localhost;
+GRANT SHOW VIEW ON v2 to mysqltest_u1@localhost;
+GRANT SHOW VIEW, SELECT ON v3 to mysqltest_u1@localhost;
+use mysqltest_db1;
+** Connect as restricted user mysqltest_u1.
+** SELECT FROM INFORMATION_SCHEMA.STATISTICS will succeed because any privileges will do (authentication is enough).
+SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name='t5';
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT
+def mysqltest_db1 t5 1 mysqltest_db1 i 1 s1 A NULL NULL NULL YES BTREE
+** SHOW INDEX FROM t5 will fail because we don't have any privileges on any column combination.
+SHOW INDEX FROM t5;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't5'
+** SHOW INDEX FROM t6 will succeed because there exist a privilege on a column combination on t6.
+SHOW INDEX FROM t6;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t6 1 i 1 s1 A NULL NULL NULL YES BTREE
+** CHECK TABLE requires any privilege on any column combination and should succeed for t6:
+CHECK TABLE t6;
+Table Op Msg_type Msg_text
+mysqltest_db1.t6 check status OK
+** With no privileges access is naturally denied:
+CHECK TABLE t5;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't5'
+** CHECKSUM TABLE requires SELECT privileges on the table. The following should fail:
+CHECKSUM TABLE t6;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't6'
+** And this should work:
+CHECKSUM TABLE t_select_priv;
+Table Checksum
+mysqltest_db1.t_select_priv 0
+SHOW CREATE VIEW v5;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'v5'
+SHOW CREATE VIEW v6;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'v6'
+SHOW CREATE VIEW v2;
+ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 'v2'
+SHOW CREATE VIEW v3;
+View Create View character_set_client collation_connection
+v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t_select_priv`.`a` AS `a`,`t_select_priv`.`b` AS `b` from `t_select_priv` latin1 latin1_swedish_ci
+drop database mysqltest_db1;
+drop user mysqltest_u1@localhost;
diff --git a/mysql-test/r/grant_lowercase_fs.result b/mysql-test/r/grant_lowercase_fs.result
new file mode 100644
index 00000000000..5a3087ed5cd
--- /dev/null
+++ b/mysql-test/r/grant_lowercase_fs.result
@@ -0,0 +1,16 @@
+create database db1;
+GRANT CREATE ON db1.* to user_1@localhost;
+GRANT SELECT ON db1.* to USER_1@localhost;
+CREATE TABLE t1(f1 int);
+SELECT * FROM t1;
+ERROR 42000: SELECT command denied to user 'user_1'@'localhost' for table 't1'
+SELECT * FROM t1;
+f1
+CREATE TABLE t2(f1 int);
+ERROR 42000: CREATE command denied to user 'USER_1'@'localhost' for table 't2'
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost;
+DROP USER user_1@localhost;
+DROP USER USER_1@localhost;
+DROP DATABASE db1;
+use test;
diff --git a/mysql-test/r/have_community_features.require b/mysql-test/r/have_community_features.require
deleted file mode 100644
index 9233bba91e1..00000000000
--- a/mysql-test/r/have_community_features.require
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable_name Value
-have_community_features YES
diff --git a/mysql-test/r/have_profiling.require b/mysql-test/r/have_profiling.require
new file mode 100644
index 00000000000..453ee5bb084
--- /dev/null
+++ b/mysql-test/r/have_profiling.require
@@ -0,0 +1,2 @@
+Variable_name Value
+have_profiling YES
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 79e97b7a06d..04234eb3cc4 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -592,7 +592,7 @@ proc definer char(77)
proc created timestamp
proc modified timestamp
proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
-proc comment char(64)
+proc comment text
proc character_set_client char(32)
proc collation_connection char(32)
proc db_collation char(32)
@@ -771,6 +771,7 @@ information_schema PARTITIONS PARTITION_DESCRIPTION
information_schema PLUGINS PLUGIN_DESCRIPTION
information_schema PROCESSLIST INFO
information_schema ROUTINES ROUTINE_DEFINITION
+information_schema ROUTINES ROUTINE_COMMENT
information_schema TRIGGERS ACTION_CONDITION
information_schema TRIGGERS ACTION_STATEMENT
information_schema VIEWS VIEW_DEFINITION
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index 34a413afc1b..bed73d9faf7 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -3,7 +3,7 @@ drop view if exists v1,v2;
drop function if exists f1;
drop function if exists f2;
use INFORMATION_SCHEMA;
-show tables where Tables_in_information_schema not like "Innodb%";
+show tables where Tables_in_information_schema NOT LIKE 'Innodb%';
Tables_in_information_schema
CHARACTER_SETS
COLLATIONS
@@ -119,12 +119,12 @@ create table t1 (f1 char(4));
create view v1 as select f1 from t1;
grant insert on v1 to testdb_2@localhost;
create view v5 as select f1 from t1;
-grant show view on v5 to testdb_2@localhost;
+grant select, show view on v5 to testdb_2@localhost;
create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
use testdb_1;
create view v6 as select f1 from t1;
-grant show view on v6 to testdb_2@localhost;
+grant select, show view on v6 to testdb_2@localhost;
create table t2 (f1 char(4));
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
Warnings:
@@ -152,11 +152,13 @@ create view v2 as select f1 from testdb_1.v1;
create view v4 as select f1,f2 from testdb_1.v3;
show fields from testdb_1.v5;
Field Type Null Key Default Extra
+f1 char(4) YES NULL
show create view testdb_1.v5;
View Create View character_set_client collation_connection
v5 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_1`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v5` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` latin1 latin1_swedish_ci
show fields from testdb_1.v6;
Field Type Null Key Default Extra
+f1 char(4) YES NULL
show create view testdb_1.v6;
View Create View character_set_client collation_connection
v6 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v6` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` latin1 latin1_swedish_ci
@@ -171,9 +173,9 @@ v7 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such_user`@`no_such_host` SQL SECURITY
Warnings:
Note 1449 The user specified as a definer ('no_such_user'@'no_such_host') does not exist
revoke insert(f1) on v3 from testdb_2@localhost;
-revoke show view on v5 from testdb_2@localhost;
+revoke select,show view on v5 from testdb_2@localhost;
use testdb_1;
-revoke show view on v6 from testdb_2@localhost;
+revoke select,show view on v6 from testdb_2@localhost;
show fields from testdb_1.v5;
ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v5'
show create view testdb_1.v5;
@@ -203,7 +205,7 @@ show create view v2;
View Create View character_set_client collation_connection
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_2`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `v1`.`f1` AS `f1` from `testdb_1`.`v1` latin1 latin1_swedish_ci
show create view testdb_1.v1;
-ERROR 42000: SHOW VIEW command denied to user 'testdb_2'@'localhost' for table 'v1'
+ERROR 42000: SELECT command denied to user 'testdb_2'@'localhost' for table 'v1'
select table_name from information_schema.columns a
where a.table_name = 'v2';
table_name
diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result
index d2e8eb19e0c..abb8f3da072 100644
--- a/mysql-test/r/innodb-autoinc.result
+++ b/mysql-test/r/innodb-autoinc.result
@@ -867,6 +867,7 @@ INSERT INTO t2 SELECT NULL FROM t1;
Got one of the listed errors
DROP TABLE t1;
DROP TABLE t2;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (null);
INSERT INTO t1 VALUES (null);
@@ -874,18 +875,254 @@ ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;
SELECT * FROM t1;
d1
1
-3
+2
SELECT * FROM t1;
d1
1
-3
+2
INSERT INTO t1 VALUES(null);
Got one of the listed errors
ALTER TABLE t1 AUTO_INCREMENT = 3;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d1` int(11) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`d1`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
d1
1
+2
3
-4
DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name Value
+auto_increment_increment 1
+auto_increment_offset 1
+CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-127, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` tinyint(4) NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+-127 innodb
+-1 innodb
+1 NULL
+2 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (-127, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+1 NULL
+2 innodb
+3 innodb
+4 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-32767, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` smallint(6) NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+-32767 innodb
+-1 innodb
+1 NULL
+2 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (-32757, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+1 NULL
+2 innodb
+3 innodb
+4 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-8388607, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` mediumint(9) NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+-8388607 innodb
+-1 innodb
+1 NULL
+2 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (-8388607, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+1 NULL
+2 innodb
+3 innodb
+4 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-2147483647, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` int(11) NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+-2147483647 innodb
+-1 innodb
+1 NULL
+2 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (-2147483647, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+1 NULL
+2 innodb
+3 innodb
+4 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-9223372036854775807, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` bigint(20) NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+-9223372036854775807 innodb
+-1 innodb
+1 NULL
+2 NULL
+DROP TABLE t1;
+CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (-9223372036854775807, 'innodb');
+Warnings:
+Warning 1264 Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `c2` varchar(10) DEFAULT NULL,
+ PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+1 NULL
+2 innodb
+3 innodb
+4 NULL
+DROP TABLE t1;
+CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB;
+CREATE INDEX i1 on T1(c2);
+SHOW CREATE TABLE T1;
+Table Create Table
+T1 CREATE TABLE `T1` (
+ `c1` int(11) NOT NULL AUTO_INCREMENT,
+ `c2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`c1`),
+ KEY `i1` (`c2`)
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1
+INSERT INTO T1 (c2) values (0);
+SELECT * FROM T1;
+c1 c2
+10 0
+DROP TABLE T1;
diff --git a/mysql-test/r/innodb_bug46000.result b/mysql-test/r/innodb_bug46000.result
index ccff888a48d..c8e3db8d641 100644
--- a/mysql-test/r/innodb_bug46000.result
+++ b/mysql-test/r/innodb_bug46000.result
@@ -1,17 +1,19 @@
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
-ERROR HY000: Can't create table 'test.bug46000' (errno: -1)
+ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX'
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
-ERROR HY000: Can't create table 'test.bug46000' (errno: -1)
-show errors;
+ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX'
+show warnings;
Level Code Message
-Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
+Warning 1280 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
+Error 1280 Incorrect index name 'GEN_CLUST_INDEX'
Error 1005 Can't create table 'test.bug46000' (errno: -1)
create table bug46000(id int) engine=innodb;
create index GEN_CLUST_INDEX on bug46000(id);
-ERROR HY000: Can't create table '#sql-temporary' (errno: -1)
-show errors;
+ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX'
+show warnings;
Level Code Message
-Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
-Error 1005 Can't create table '#sql-temporary' (errno: -1)
+Warning 1280 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
+Error 1280 Incorrect index name 'GEN_CLUST_INDEX'
+Error 1030 Got error -1 from storage engine
create index idx on bug46000(id);
drop table bug46000;
diff --git a/mysql-test/r/innodb_bug47777.result b/mysql-test/r/innodb_bug47777.result
new file mode 100644
index 00000000000..fbba47edcfc
--- /dev/null
+++ b/mysql-test/r/innodb_bug47777.result
@@ -0,0 +1,13 @@
+create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb;
+insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'));
+select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)');
+count(*)
+1
+update bug47777 set c2=GeomFromText('POINT(1 1)');
+select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)');
+count(*)
+0
+select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)');
+count(*)
+1
+drop table bug47777;
diff --git a/mysql-test/r/innodb_lock_wait_timeout_1.result b/mysql-test/r/innodb_lock_wait_timeout_1.result
new file mode 100644
index 00000000000..a635b0d527a
--- /dev/null
+++ b/mysql-test/r/innodb_lock_wait_timeout_1.result
@@ -0,0 +1,357 @@
+#
+# Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout
+# without error
+#
+CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB;
+INSERT INTO t1 (a,b) VALUES (1070109,99);
+CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB;
+INSERT INTO t2 (b,a) VALUES (7,1070109);
+SELECT * FROM t1;
+a b
+1070109 99
+BEGIN;
+SELECT b FROM t2 WHERE b=7 FOR UPDATE;
+b
+7
+BEGIN;
+SELECT b FROM t2 WHERE b=7 FOR UPDATE;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7));
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+SELECT * FROM t1;
+a b
+1070109 99
+DROP TABLE t2, t1;
+# End of 5.0 tests
+#
+# Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT
+# FOR UPDATE
+#
+drop table if exists t1;
+create table t1 (a int primary key auto_increment,
+b int, index(b)) engine=innodb;
+insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+set autocommit=0;
+begin;
+select * from t1 where b=5 for update;
+a b
+5 5
+insert ignore into t1 (b) select a as b from t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+# Cleanup
+#
+commit;
+set autocommit=default;
+drop table t1;
+#
+# Bug#41756 Strange error messages about locks from InnoDB
+#
+drop table if exists t1;
+# In the default transaction isolation mode, and/or with
+# innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row()
+# in InnoDB does nothing.
+# Thus in order to reproduce the condition that led to the
+# warning, one needs to relax isolation by either
+# setting a weaker tx_isolation value, or by turning on
+# the unsafe replication switch.
+# For testing purposes, choose to tweak the isolation level,
+# since it's settable at runtime, unlike
+# innodb_locks_unsafe_for_binlog, which is
+# only a command-line switch.
+#
+set @@session.tx_isolation="read-committed";
+# Prepare data. We need a table with a unique index,
+# for join_read_key to be used. The other column
+# allows to control what passes WHERE clause filter.
+create table t1 (a int primary key, b int) engine=innodb;
+# Let's make sure t1 has sufficient amount of rows
+# to exclude JT_ALL access method when reading it,
+# i.e. make sure that JT_EQ_REF(a) is always preferred.
+insert into t1 values (1,1), (2,null), (3,1), (4,1),
+(5,1), (6,1), (7,1), (8,1), (9,1), (10,1),
+(11,1), (12,1), (13,1), (14,1), (15,1),
+(16,1), (17,1), (18,1), (19,1), (20,1);
+#
+# Demonstrate that for the SELECT statement
+# used later in the test JT_EQ_REF access method is used.
+#
+explain
+select 1 from t1 natural join (select 2 as a, 1 as b union all
+select 2 as a, 2 as b) as t2 for update;
+id 1
+select_type PRIMARY
+table <derived2>
+type ALL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows 2
+Extra
+id 1
+select_type PRIMARY
+table t1
+type eq_ref
+possible_keys PRIMARY
+key PRIMARY
+key_len 4
+ref t2.a
+rows 1
+Extra Using where
+id 2
+select_type DERIVED
+table NULL
+type NULL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows NULL
+Extra No tables used
+id 3
+select_type UNION
+table NULL
+type NULL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows NULL
+Extra No tables used
+id NULL
+select_type UNION RESULT
+table <union2,3>
+type ALL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows NULL
+Extra
+#
+# Demonstrate that the reported SELECT statement
+# no longer produces warnings.
+#
+select 1 from t1 natural join (select 2 as a, 1 as b union all
+select 2 as a, 2 as b) as t2 for update;
+1
+commit;
+#
+# Demonstrate that due to lack of inter-sweep "reset" function,
+# we keep some non-matching records locked, even though we know
+# we could unlock them.
+# To do that, show that if there is only one distinct value
+# for a in t2 (a=2), we will keep record (2,null) in t1 locked.
+# But if we add another value for "a" to t2, say 6,
+# join_read_key cache will be pruned at least once,
+# and thus record (2, null) in t1 will get unlocked.
+#
+begin;
+select 1 from t1 natural join (select 2 as a, 1 as b union all
+select 2 as a, 2 as b) as t2 for update;
+1
+#
+# Switching to connection con1
+# We should be able to delete all records from t1 except (2, null),
+# since they were not locked.
+begin;
+# Delete in series of 3 records so that full scan
+# is not used and we're not blocked on record (2,null)
+delete from t1 where a in (1,3,4);
+delete from t1 where a in (5,6,7);
+delete from t1 where a in (8,9,10);
+delete from t1 where a in (11,12,13);
+delete from t1 where a in (14,15,16);
+delete from t1 where a in (17,18);
+delete from t1 where a in (19,20);
+#
+# Record (2, null) is locked. This is actually unnecessary,
+# because the previous select returned no rows.
+# Just demonstrate the effect.
+#
+delete from t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+rollback;
+#
+# Switching to connection default
+#
+# Show that the original contents of t1 is intact:
+select * from t1;
+a b
+1 1
+2 NULL
+3 1
+4 1
+5 1
+6 1
+7 1
+8 1
+9 1
+10 1
+11 1
+12 1
+13 1
+14 1
+15 1
+16 1
+17 1
+18 1
+19 1
+20 1
+commit;
+#
+# Have a one more record in t2 to show that
+# if join_read_key cache is purned, the current
+# row under the cursor is unlocked (provided, this row didn't
+# match the partial WHERE clause, of course).
+# Sic: the result of this test dependent on the order of retrieval
+# of records --echo # from the derived table, if !
+# We use DELETE to disable the JOIN CACHE. This DELETE modifies no
+# records. It also should leave no InnoDB row locks.
+#
+begin;
+delete t1.* from t1 natural join (select 2 as a, 2 as b union all
+select 0 as a, 0 as b) as t2;
+# Demonstrate that nothing was deleted form t1
+select * from t1;
+a b
+1 1
+2 NULL
+3 1
+4 1
+5 1
+6 1
+7 1
+8 1
+9 1
+10 1
+11 1
+12 1
+13 1
+14 1
+15 1
+16 1
+17 1
+18 1
+19 1
+20 1
+#
+# Switching to connection con1
+begin;
+# Since there is another distinct record in the derived table
+# the previous matching record in t1 -- (2,null) -- was unlocked.
+delete from t1;
+# We will need the contents of the table again.
+rollback;
+select * from t1;
+a b
+1 1
+2 NULL
+3 1
+4 1
+5 1
+6 1
+7 1
+8 1
+9 1
+10 1
+11 1
+12 1
+13 1
+14 1
+15 1
+16 1
+17 1
+18 1
+19 1
+20 1
+commit;
+#
+# Switching to connection default
+rollback;
+begin;
+#
+# Before this patch, we could wrongly unlock a record
+# that was cached and later used in a join. Demonstrate that
+# this is no longer the case.
+# Sic: this test is also order-dependent (i.e. the
+# the bug would show up only if the first record in the union
+# is retreived and processed first.
+#
+# Verify that JT_EQ_REF is used.
+explain
+select 1 from t1 natural join (select 3 as a, 2 as b union all
+select 3 as a, 1 as b) as t2 for update;
+id 1
+select_type PRIMARY
+table <derived2>
+type ALL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows 2
+Extra
+id 1
+select_type PRIMARY
+table t1
+type eq_ref
+possible_keys PRIMARY
+key PRIMARY
+key_len 4
+ref t2.a
+rows 1
+Extra Using where
+id 2
+select_type DERIVED
+table NULL
+type NULL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows NULL
+Extra No tables used
+id 3
+select_type UNION
+table NULL
+type NULL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows NULL
+Extra No tables used
+id NULL
+select_type UNION RESULT
+table <union2,3>
+type ALL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows NULL
+Extra
+# Lock the record.
+select 1 from t1 natural join (select 3 as a, 2 as b union all
+select 3 as a, 1 as b) as t2 for update;
+1
+1
+# Switching to connection con1
+#
+# We should not be able to delete record (3,1) from t1,
+# (previously it was possible).
+#
+delete from t1 where a=3;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+# Switching to connection default
+commit;
+set @@session.tx_isolation=default;
+drop table t1;
+#
+# End of 5.1 tests
+#
diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result
index b112bde4f27..d6aa6a02468 100644
--- a/mysql-test/r/innodb_mysql.result
+++ b/mysql-test/r/innodb_mysql.result
@@ -2209,4 +2209,66 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 4 NULL 128 Using where
DROP TABLE t1;
+#
+# Bug #47963: Wrong results when index is used
+#
+CREATE TABLE t1(
+a VARCHAR(5) NOT NULL,
+b VARCHAR(5) NOT NULL,
+c DATETIME NOT NULL,
+KEY (c)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00');
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00';
+a b c
+TEST TEST 2009-10-09 00:00:00
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0';
+a b c
+TEST TEST 2009-10-09 00:00:00
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00';
+a b c
+TEST TEST 2009-10-09 00:00:00
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0';
+a b c
+TEST TEST 2009-10-09 00:00:00
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000';
+a b c
+TEST TEST 2009-10-09 00:00:00
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001';
+a b c
+TEST TEST 2009-10-09 00:00:00
+SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00';
+a b c
+EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND
+c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+DROP TABLE t1;
End of 5.1 tests
+#
+# Test for bug #39932 "create table fails if column for FK is in different
+# case than in corr index".
+#
+drop tables if exists t1, t2;
+create table t1 (pk int primary key) engine=InnoDB;
+# Even although the below statement uses uppercased field names in
+# foreign key definition it still should be able to find explicitly
+# created supporting index. So it should succeed and should not
+# create any additional supporting indexes.
+create table t2 (fk int, key x (fk),
+constraint x foreign key (FK) references t1 (PK)) engine=InnoDB;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `fk` int(11) DEFAULT NULL,
+ KEY `x` (`fk`),
+ CONSTRAINT `x` FOREIGN KEY (`fk`) REFERENCES `t1` (`pk`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2, t1;
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 4ed56bf3c56..36d2b9ef348 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -639,3 +639,43 @@ CREATE TABLE t2(f1 CHAR(1));
INSERT INTO t2 SELECT f1 FROM t1;
DROP TABLE t1, t2;
End of 5.0 tests.
+#
+# Bug#34898 "mysql_info() reports 0 warnings while
+# mysql_warning_count() reports 1"
+# Check that the number of warnings reported by
+# mysql_info() is correct.
+#
+drop table if exists t1;
+create table t1 (data varchar(4) not null);
+set sql_mode='error_for_division_by_zero';
+#
+# Demonstrate that the number of warnings matches
+# the information in mysql_info().
+#
+insert t1 (data) values ('letter'), (1/0);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 3
+Warnings:
+Warning 1265 Data truncated for column 'data' at row 1
+Warning 1365 Division by 0
+Warning 1048 Column 'data' cannot be null
+update t1 set data='envelope' where 1/0 or 1;
+affected rows: 2
+info: Rows matched: 2 Changed: 2 Warnings: 3
+Warnings:
+Warning 1365 Division by 0
+Warning 1265 Data truncated for column 'data' at row 1
+Warning 1265 Data truncated for column 'data' at row 2
+insert t1 (data) values (default), (1/0), ('dead beef');
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 4
+Warnings:
+Warning 1364 Field 'data' doesn't have a default value
+Warning 1365 Division by 0
+Warning 1048 Column 'data' cannot be null
+Warning 1265 Data truncated for column 'data' at row 3
+set sql_mode=default;
+drop table t1;
+#
+# End of 5.4 tests
+#
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index e589bdac48e..d443e20df76 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -1063,6 +1063,60 @@ a b c d
127 NULL 127 NULL
128 NULL 128 NULL
DROP TABLE IF EXISTS t1,t2;
+#
+# Bug #42116: Mysql crash on specific query
+#
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+CREATE TABLE t3 (a INT, INDEX (a));
+CREATE TABLE t4 (a INT);
+CREATE TABLE t5 (a INT);
+CREATE TABLE t6 (a INT);
+INSERT INTO t1 VALUES (1), (1), (1);
+INSERT INTO t2 VALUES
+(2), (2), (2), (2), (2), (2), (2), (2), (2), (2);
+INSERT INTO t3 VALUES
+(3), (3), (3), (3), (3), (3), (3), (3), (3), (3);
+EXPLAIN
+SELECT *
+FROM
+t1 JOIN t2 ON t1.a = t2.a
+LEFT JOIN
+(
+(
+t3 LEFT JOIN t4 ON t3.a = t4.a
+)
+LEFT JOIN
+(
+t5 LEFT JOIN t6 ON t5.a = t6.a
+)
+ON t4.a = t5.a
+)
+ON t1.a = t3.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t3 ref a a 5 test.t1.a 2 Using index
+1 SIMPLE t4 ALL NULL NULL NULL NULL 0
+1 SIMPLE t5 ALL NULL NULL NULL NULL 0
+1 SIMPLE t6 ALL NULL NULL NULL NULL 0
+1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where; Using join buffer
+SELECT *
+FROM
+t1 JOIN t2 ON t1.a = t2.a
+LEFT JOIN
+(
+(
+t3 LEFT JOIN t4 ON t3.a = t4.a
+)
+LEFT JOIN
+(
+t5 LEFT JOIN t6 ON t5.a = t6.a
+)
+ON t4.a = t5.a
+)
+ON t1.a = t3.a;
+a a a a a a
+DROP TABLE t1,t2,t3,t4,t5,t6;
End of 5.0 tests.
CREATE TABLE t1 (f1 int);
CREATE TABLE t2 (f1 int);
diff --git a/mysql-test/r/loadxml.result b/mysql-test/r/loadxml.result
index d7967a105f8..55e6759748a 100644
--- a/mysql-test/r/loadxml.result
+++ b/mysql-test/r/loadxml.result
@@ -58,11 +58,7 @@ select 1 as xml;
xml
1
create table t2(fl text);
-LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<person>';;
-show processlist;
-Id User Host db Command Time State Info
-# root localhost test Query # NULL show processlist
-# root localhost test Query # Reading from net LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<p
+LOAD XML LOCAL INFILE "MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<person>';;
drop table t1;
drop table t2;
create table t1 (
diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result
index 30c4c928a96..af7f9e3c132 100644
--- a/mysql-test/r/locale.result
+++ b/mysql-test/r/locale.result
@@ -49,11 +49,44 @@ DROP TABLE t1;
#
# Bug#46633 Obsolete Serbian locale name
#
-set lc_messages=sr_YU;
-ERROR HY000: Unknown locale: 'sr_YU'
-set lc_messages=sr_RS;
-set lc_time_names=sr_RS;
-select format(123456.789, 3, 'sr_RS');
+SET lc_messages=sr_YU;
+Warnings:
+Warning 1287 'sr_YU' is deprecated; use 'sr_RS' instead
+SHOW VARIABLES LIKE 'lc_messages';
+Variable_name Value
+lc_messages sr_RS
+SET lc_messages=sr_RS;
+SHOW VARIABLES LIKE 'lc_messages';
+Variable_name Value
+lc_messages sr_RS
+SET lc_time_names=sr_RS;
+SELECT format(123456.789, 3, 'sr_RS');
format(123456.789, 3, 'sr_RS')
123456.789
+#
+# Bug#43207 wrong LC_TIME names for romanian locale
+#
+SET NAMES utf8;
+SET lc_time_names=ro_RO;
+SELECT DATE_FORMAT('2001-01-01', '%w %a %W');
+DATE_FORMAT('2001-01-01', '%w %a %W')
+1 Lu Luni
+SELECT DATE_FORMAT('2001-01-02', '%w %a %W');
+DATE_FORMAT('2001-01-02', '%w %a %W')
+2 Ma Marţi
+SELECT DATE_FORMAT('2001-01-03', '%w %a %W');
+DATE_FORMAT('2001-01-03', '%w %a %W')
+3 Mi Miercuri
+SELECT DATE_FORMAT('2001-01-04', '%w %a %W');
+DATE_FORMAT('2001-01-04', '%w %a %W')
+4 Jo Joi
+SELECT DATE_FORMAT('2001-01-05', '%w %a %W');
+DATE_FORMAT('2001-01-05', '%w %a %W')
+5 Vi Vineri
+SELECT DATE_FORMAT('2001-01-06', '%w %a %W');
+DATE_FORMAT('2001-01-06', '%w %a %W')
+6 Sâ Sâmbătă
+SELECT DATE_FORMAT('2001-01-07', '%w %a %W');
+DATE_FORMAT('2001-01-07', '%w %a %W')
+0 Du Duminică
End of 5.4 tests
diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result
index 5c3e3d789a1..56e30ac59f8 100644
--- a/mysql-test/r/log_state.result
+++ b/mysql-test/r/log_state.result
@@ -309,6 +309,30 @@ SET @@global.general_log_file = @old_general_log_file;
SET @@global.slow_query_log = @old_slow_query_log;
SET @@global.slow_query_log_file = @old_slow_query_log_file;
End of 5.1 tests
+
+# --
+# -- Bug#38124: "general_log_file" variable silently unset when
+# -- using expression
+# --
+SET GLOBAL general_log_file = DEFAULT;
+SELECT @@general_log_file INTO @my_glf;
+SET GLOBAL general_log_file = 'BUG38124.LOG';
+SELECT @@general_log_file;
+@@general_log_file
+BUG38124.LOG
+SET GLOBAL general_log_file = concat('BUG38124-2.LOG');
+SELECT @@general_log_file;
+@@general_log_file
+BUG38124-2.LOG
+SET GLOBAL general_log_file = substr('BUG38124-2.LOG',3,6);
+SELECT @@general_log_file;
+@@general_log_file
+G38124
+SET GLOBAL general_log_file = DEFAULT;
+SELECT @@general_log_file = @my_glf;
+@@general_log_file = @my_glf
+1
+SET GLOBAL general_log_file = @old_general_log_file;
# Close connection con1
SET global general_log = @old_general_log;
SET global general_log_file = @old_general_log_file;
diff --git a/mysql-test/r/log_state_bug33693.result b/mysql-test/r/log_state_bug33693.result
new file mode 100644
index 00000000000..abf20fc7aa7
--- /dev/null
+++ b/mysql-test/r/log_state_bug33693.result
@@ -0,0 +1,3 @@
+SELECT INSTR(@@general_log_file, 'MYSQLTEST_VARDIR/run');;
+INSTR(@@general_log_file, 'MYSQLTEST_VARDIR/run')
+0
diff --git a/mysql-test/r/lowercase_fs_off.result b/mysql-test/r/lowercase_fs_off.result
index ecb21261987..30f835a8ea3 100644
--- a/mysql-test/r/lowercase_fs_off.result
+++ b/mysql-test/r/lowercase_fs_off.result
@@ -10,3 +10,48 @@ create database D1;
ERROR 42000: Access denied for user 'sample'@'localhost' to database 'D1'
drop user 'sample'@'localhost';
drop database if exists d1;
+CREATE DATABASE d1;
+USE d1;
+CREATE TABLE T1(f1 INT);
+CREATE TABLE t1(f1 INT);
+GRANT SELECT ON T1 to user_1@localhost;
+select * from t1;
+ERROR 42000: SELECT command denied to user 'user_1'@'localhost' for table 't1'
+select * from T1;
+f1
+GRANT SELECT ON t1 to user_1@localhost;
+select * from information_schema.table_privileges;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'user_1'@'localhost' def d1 T1 SELECT NO
+'user_1'@'localhost' def d1 t1 SELECT NO
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
+DROP USER user_1@localhost;
+DROP DATABASE d1;
+USE test;
+CREATE DATABASE db1;
+USE db1;
+CREATE PROCEDURE p1() BEGIN END;
+CREATE FUNCTION f1(i INT) RETURNS INT RETURN i+1;
+GRANT USAGE ON db1.* to user_1@localhost;
+GRANT EXECUTE ON PROCEDURE db1.P1 to user_1@localhost;
+GRANT EXECUTE ON FUNCTION db1.f1 to user_1@localhost;
+GRANT UPDATE ON db1.* to USER_1@localhost;
+call p1();
+call P1();
+select f1(1);
+f1(1)
+2
+call p1();
+ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1'
+call P1();
+ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1'
+select f1(1);
+ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1'
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost;
+DROP FUNCTION f1;
+DROP PROCEDURE p1;
+DROP USER user_1@localhost;
+DROP USER USER_1@localhost;
+DROP DATABASE db1;
+use test;
diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result
index 51c2ac0faf5..cf87fd1b5a4 100644
--- a/mysql-test/r/lowercase_table2.result
+++ b/mysql-test/r/lowercase_table2.result
@@ -174,3 +174,74 @@ TABLE_SCHEMA TABLE_NAME
mysqltest_LC2 myUC
use test;
drop database mysqltest_LC2;
+# End of 5.1 tests
+#
+# Test for bug #44738 "fill_schema_table_from_frm() opens tables without
+# lowercasing table name". Due to not properly normalizing table names
+# in lower_case_table_names modes in this function queries to I_S which
+# were executed through it left entries with incorrect key in table
+# definition cache. As result further queries to I_S that used this
+# function produced stale results in cases when table definition was
+# changed by a DDL statement. Also combination of this issue and a
+# similar problem in CREATE TABLE (it also has peeked into table
+# definition cache using non-normalized key) led to spurious
+# ER_TABLE_EXISTS_ERROR errors when one tried to create table with the
+# same name as a previously existing but dropped table.
+#
+drop database if exists mysqltest_UPPERCASE;
+drop table if exists t_bug44738_UPPERCASE;
+create database mysqltest_UPPERCASE;
+use mysqltest_UPPERCASE;
+create table t_bug44738_UPPERCASE (i int) comment='Old comment';
+create table t_bug44738_lowercase (i int) comment='Old comment';
+select table_schema, table_name, table_comment from information_schema.tables
+where table_schema like 'mysqltest_%' and table_name like 't_bug44738_%'
+ order by table_name;
+table_schema table_name table_comment
+mysqltest_UPPERCASE t_bug44738_lowercase Old comment
+mysqltest_UPPERCASE t_bug44738_UPPERCASE Old comment
+alter table t_bug44738_UPPERCASE comment='New comment';
+alter table t_bug44738_lowercase comment='New comment';
+# There should be no stale entries in TDC for our tables after the
+# above ALTER TABLE statements so new version of comments should be
+# returned by the below query to I_S.
+select table_schema, table_name, table_comment from information_schema.tables
+where table_schema like 'mysqltest_%' and table_name like 't_bug44738_%'
+ order by table_name;
+table_schema table_name table_comment
+mysqltest_UPPERCASE t_bug44738_lowercase New comment
+mysqltest_UPPERCASE t_bug44738_UPPERCASE New comment
+drop database mysqltest_UPPERCASE;
+use test;
+# Let us check that the original test case which led to discovery
+# of this problem also works.
+create table t_bug44738_UPPERCASE (i int);
+select table_schema, table_name, table_comment from information_schema.tables
+where table_schema = 'test' and table_name like 't_bug44738_%';
+table_schema table_name table_comment
+test t_bug44738_UPPERCASE
+drop table t_bug44738_UPPERCASE;
+# After the above DROP TABLE there are no entries in TDC which correspond
+# to our table and therefore the below statement should succeed.
+create table t_bug44738_UPPERCASE (i int);
+drop table t_bug44738_UPPERCASE;
+# Finally, let us check that another issue which was exposed by
+# the original test case is solved. I.e. that fuse in CREATE TABLE
+# which ensures that table is not created if there is an entry for
+# it in TDC even though it was removed from disk uses normalized
+# version of the table name.
+create table t_bug44738_UPPERCASE (i int) engine = myisam;
+# Load table definition in TDC.
+select table_schema, table_name, table_comment from information_schema.tables
+where table_schema = 'test' and table_name like 't_bug44738_%';
+table_schema table_name table_comment
+test t_bug44738_UPPERCASE
+# Simulate manual removal of the table.
+# After manual removal of table still there should be an entry for table
+# in TDC so attempt to create table with the same name should fail.
+create table t_bug44738_UPPERCASE (i int);
+ERROR 42S01: Table 't_bug44738_uppercase' already exists
+# And should succeed after FLUSH TABLES.
+flush tables;
+create table t_bug44738_UPPERCASE (i int);
+drop table t_bug44738_UPPERCASE;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 297eb3b9c58..83152a0dd8d 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -2220,3 +2220,39 @@ tr1 CREATE DEFINER=`root`@`localhost` TRIGGER tr1 AFTER INSERT ON t3 FOR EACH R
DROP TRIGGER tr1;
DROP TABLE t1, t2, t3;
End of 5.1 tests
+#
+# An additional test case for Bug#27430 Crash in subquery code
+# when in PS and table DDL changed after PREPARE
+#
+# Test merge table with too many merge children.
+#
+drop table if exists t_parent;
+set @save_table_definition_cache=@@global.table_definition_cache;
+#
+# Set @@global.table_definition_cache to minimum
+#
+set @@global.table_definition_cache=400;
+set @a=null;
+#
+# Create 400 merge children
+#
+set @a=concat("create table t_parent (a int) union(", @a,
+") insert_method=first engine=mrg_myisam");
+prepare stmt from @a;
+execute stmt;
+prepare stmt from "select * from t_parent";
+execute stmt;
+ERROR HY000: Prepared statement needs to be re-prepared
+execute stmt;
+ERROR HY000: Prepared statement needs to be re-prepared
+execute stmt;
+ERROR HY000: Prepared statement needs to be re-prepared
+deallocate prepare stmt;
+#
+# Create merge parent
+#
+#
+# Cleanup
+#
+drop table t_parent;
+set @@global.table_definition_cache=@save_table_definition_cache;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index f5050ccf1c0..95fdc4fb93d 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -2290,6 +2290,12 @@ Table Op Msg_type Msg_text
test.t1 repair error myisam_sort_buffer_size is too small
test.t1 repair warning Number of rows changed from 0 to 7168
test.t1 repair status OK
+SET myisam_repair_threads=2;
+REPAIR TABLE t1;
+SET myisam_repair_threads=@@global.myisam_repair_threads;
SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size;
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
DROP TABLE t1;
End of 5.1 tests
diff --git a/mysql-test/r/myisam_crash_before_flush_keys.result b/mysql-test/r/myisam_crash_before_flush_keys.result
index 372f2e41590..d3545ea47d0 100644
--- a/mysql-test/r/myisam_crash_before_flush_keys.result
+++ b/mysql-test/r/myisam_crash_before_flush_keys.result
@@ -15,31 +15,13 @@ SET SESSION debug="d,crash_before_flush_keys";
# Run the crashing query
FLUSH TABLE t1;
ERROR HY000: Lost connection to MySQL server during query
-# Run MYISAMCHK tool to check the table t1 and repair
-myisamchk: MyISAM file MYSQLD_DATADIR/test/t1
-myisamchk: warning: 1 client is using or hasn't closed the table properly
-myisamchk: error: Size of indexfile is: 1024 Should be: 3072
-MYISAMCHK: Unknown error 126
-myisamchk: error: Can't read indexpage from filepos: 1024
-MyISAM-table 'MYSQLD_DATADIR/test/t1' is corrupted
-Fix it using switch "-r" or "-o"
# Write file to make mysql-test-run.pl start the server
# Turn on reconnect
# Call script that will poll the server waiting for
# it to be back online again
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` int(11) NOT NULL DEFAULT '0',
- `b` int(11) NOT NULL DEFAULT '0',
- PRIMARY KEY (`a`,`b`),
- KEY `b` (`b`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
-SELECT * FROM t1 FORCE INDEX (PRIMARY);
-a b
-1 2
-2 3
-3 4
-4 5
-5 6
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check warning 1 client is using or hasn't closed the table properly
+test.t1 check error Size of indexfile is: 1024 Should be: 3072
+test.t1 check error Corrupt
DROP TABLE t1;
diff --git a/mysql-test/r/mysqlbinlog_row.result b/mysql-test/r/mysqlbinlog_row.result
index 9b562ac0fff..85416138c6d 100644
--- a/mysql-test/r/mysqlbinlog_row.result
+++ b/mysql-test/r/mysqlbinlog_row.result
@@ -339,7 +339,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C latin1 *//*!*/;
diff --git a/mysql-test/r/mysqlbinlog_row_innodb.result b/mysql-test/r/mysqlbinlog_row_innodb.result
index 86f0b67ebb3..cf59d23bcf1 100644
--- a/mysql-test/r/mysqlbinlog_row_innodb.result
+++ b/mysql-test/r/mysqlbinlog_row_innodb.result
@@ -2256,7 +2256,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
@@ -3879,7 +3879,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
@@ -4246,7 +4246,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
@@ -4807,7 +4807,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
diff --git a/mysql-test/r/mysqlbinlog_row_myisam.result b/mysql-test/r/mysqlbinlog_row_myisam.result
index b9366d941f8..973786d698e 100644
--- a/mysql-test/r/mysqlbinlog_row_myisam.result
+++ b/mysql-test/r/mysqlbinlog_row_myisam.result
@@ -2256,7 +2256,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
@@ -3901,7 +3901,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
@@ -4274,7 +4274,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
@@ -4845,7 +4845,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
diff --git a/mysql-test/r/mysqlbinlog_row_trans.result b/mysql-test/r/mysqlbinlog_row_trans.result
index 9c3348a9e76..43a9a6182f8 100644
--- a/mysql-test/r/mysqlbinlog_row_trans.result
+++ b/mysql-test/r/mysqlbinlog_row_trans.result
@@ -135,7 +135,7 @@ ROLLBACK/*!*/;
use test/*!*/;
SET TIMESTAMP=1000000000/*!*/;
SET @@session.pseudo_thread_id=#/*!*/;
-SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C latin1 *//*!*/;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index cf79a970033..13d36fab2f1 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -2391,7 +2391,7 @@ trg3 UPDATE t1 begin
if new.a = -1 then
set @fired:= "Yes";
end if;
-end AFTER 0000-00-00 00:00:00 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
+end AFTER 0000-00-00 00:00:00 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
INSERT INTO t1 (a) VALUES (1),(2),(3),(22);
update t1 set a = 4 where a=3;
@@ -2468,7 +2468,7 @@ DELIMITER ;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
-/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER' */ ;
+/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 trigger trg3 after update on t1 for each row
begin
@@ -2500,7 +2500,7 @@ UNLOCK TABLES;
/*!50003 SET character_set_results = latin1 */ ;
/*!50003 SET collation_connection = latin1_swedish_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
-/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER' */ ;
+/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 trigger trg4 before insert on t2 for each row
begin
@@ -2594,12 +2594,12 @@ trg3 UPDATE t1 begin
if new.a = -1 then
set @fired:= "Yes";
end if;
-end AFTER # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
+end AFTER # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
trg4 INSERT t2 begin
if new.a > 10 then
set @fired:= "No";
end if;
-end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
+end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
DROP TABLE t1, t2;
#
# Bug#9136 my_print_defaults changed behaviour between 4.1.7 and 4.1.10a
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 4540c9d5218..a7516d97888 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -733,4 +733,24 @@ SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP;
1
1
DROP TABLE t1;
+#
+# Bug #48131: crash group by with rollup, distinct,
+# filesort, with temporary tables
+#
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY);
+INSERT INTO t1 VALUES (1), (2);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (100);
+SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
+a b
+1 100
+1 NULL
+2 100
+2 NULL
+NULL NULL
+SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
+b
+100
+NULL
+DROP TABLE t1, t2;
End of 5.0 tests
diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result
index e5f5a53c1f3..84ef17857f4 100644
--- a/mysql-test/r/outfile.result
+++ b/mysql-test/r/outfile.result
Binary files differ
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index 065c427bfd3..065e46dbf92 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -420,14 +420,12 @@ create table t1 (a bigint)
partition by range (a)
(partition p0 values less than (0xFFFFFFFFFFFFFFFF),
partition p1 values less than (10));
-ERROR 42000: VALUES value must be of same type as partition function near '),
-partition p1 values less than (10))' at line 3
+ERROR HY000: VALUES value must be of same type as partition function
create table t1 (a bigint)
partition by list (a)
(partition p0 values in (0xFFFFFFFFFFFFFFFF),
partition p1 values in (10));
-ERROR 42000: VALUES value must be of same type as partition function near '),
-partition p1 values in (10))' at line 3
+ERROR HY000: VALUES value must be of same type as partition function
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (100),
@@ -1421,7 +1419,7 @@ DROP TABLE t1;
CREATE TABLE t1 (a int)
PARTITION BY RANGE(a)
(PARTITION p0 VALUES LESS THAN (NULL));
-ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '))' at line 3
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
create table t1 (s1 int auto_increment primary key)
partition by list (s1)
(partition p1 values in (1),
diff --git a/mysql-test/r/partition_column.result b/mysql-test/r/partition_column.result
new file mode 100644
index 00000000000..249de9f3496
--- /dev/null
+++ b/mysql-test/r/partition_column.result
@@ -0,0 +1,568 @@
+drop table if exists t1;
+create table t1 (a varchar(1) character set latin1 collate latin1_general_ci)
+partition by range columns(a)
+( partition p0 values less than ('a'),
+partition p1 values less than ('b'),
+partition p2 values less than ('c'),
+partition p3 values less than ('d'));
+insert into t1 values ('A'),('a'),('B'),('b'),('C'),('c');
+select * from t1 where a > 'B' collate latin1_bin;
+a
+a
+b
+C
+c
+select * from t1 where a <> 'B' collate latin1_bin;
+a
+A
+a
+b
+C
+c
+alter table t1 remove partitioning;
+select * from t1 where a > 'B' collate latin1_bin;
+a
+a
+b
+C
+c
+select * from t1 where a <> 'B' collate latin1_bin;
+a
+A
+a
+b
+C
+c
+drop table t1;
+create table t1 (a varchar(2) character set latin1,
+b varchar(2) character set latin1)
+partition by list columns(a,b)
+(partition p0 values in (('a','a')));
+insert into t1 values ('A','A');
+select * from t1 where b <> 'a' collate latin1_bin AND
+a = 'A' collate latin1_bin;
+a b
+A A
+alter table t1 remove partitioning;
+select * from t1 where b <> 'a' collate latin1_bin AND
+a = 'A' collate latin1_bin;
+a b
+A A
+drop table t1;
+create table t1 (a varchar(5))
+partition by list columns(a)
+( partition p0 values in ('\''),
+ partition p1 values in ('\\'),
+ partition p2 values in ('\0'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a)
+(PARTITION p0 VALUES IN ('''') ENGINE = MyISAM,
+ PARTITION p1 VALUES IN ('\\') ENGINE = MyISAM,
+ PARTITION p2 VALUES IN ('\0') ENGINE = MyISAM) */
+drop table t1;
+set @@sql_mode=allow_invalid_dates;
+create table t1 (a char, b char, c date)
+partition by range columns (a,b,c)
+( partition p0 values less than (0,0,to_days('3000-11-31')));
+ERROR HY000: Partition column values of incorrect type
+create table t1 (a char, b char, c date)
+partition by range columns (a,b,c)
+( partition p0 values less than (0,0,'3000-11-31'));
+ERROR HY000: Partition column values of incorrect type
+set @@sql_mode='';
+create table t1 (a int, b char(10), c varchar(25), d datetime)
+partition by range columns(a,b,c,d)
+subpartition by hash (to_seconds(d))
+subpartitions 4
+( partition p0 values less than (1, 0, MAXVALUE, '1900-01-01'),
+partition p1 values less than (1, 'a', MAXVALUE, '1999-01-01'),
+partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
+ERROR HY000: Partition column values of incorrect type
+create table t1 (a int, b char(10), c varchar(25), d datetime)
+partition by range columns(a,b,c,d)
+subpartition by hash (to_seconds(d))
+subpartitions 4
+( partition p0 values less than (1, '0', MAXVALUE, '1900-01-01'),
+partition p1 values less than (1, 'a', MAXVALUE, '1999-01-01'),
+partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+RANGE COLUMNS a,b,c,d 1,'0',MAXVALUE,'1900-01-01'
+RANGE COLUMNS a,b,c,d 1,'0',MAXVALUE,'1900-01-01'
+RANGE COLUMNS a,b,c,d 1,'0',MAXVALUE,'1900-01-01'
+RANGE COLUMNS a,b,c,d 1,'0',MAXVALUE,'1900-01-01'
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,'1999-01-01'
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,'a',MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+RANGE COLUMNS a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL,
+ `c` varchar(25) DEFAULT NULL,
+ `d` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE COLUMNS(a,b,c,d)
+SUBPARTITION BY HASH (to_seconds(d))
+SUBPARTITIONS 4
+(PARTITION p0 VALUES LESS THAN (1,'0',MAXVALUE,'1900-01-01') ENGINE = MyISAM,
+ PARTITION p1 VALUES LESS THAN (1,'a',MAXVALUE,'1999-01-01') ENGINE = MyISAM,
+ PARTITION p2 VALUES LESS THAN (1,'a',MAXVALUE,MAXVALUE) ENGINE = MyISAM,
+ PARTITION p3 VALUES LESS THAN (1,MAXVALUE,MAXVALUE,MAXVALUE) ENGINE = MyISAM) */
+drop table t1;
+create table t1 (a int, b int)
+partition by range columns (a,b)
+(partition p0 values less than (NULL, maxvalue));
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
+create table t1 (a int, b int)
+partition by list columns(a,b)
+( partition p0 values in ((maxvalue, 0)));
+Got one of the listed errors
+create table t1 (a int, b int)
+partition by list columns (a,b)
+( partition p0 values in ((0,0)));
+alter table t1 add partition
+(partition p1 values in (maxvalue, maxvalue));
+Got one of the listed errors
+drop table t1;
+create table t1 (a int, b int)
+partition by key (a,a);
+ERROR HY000: Duplicate partition field name 'a'
+create table t1 (a int, b int)
+partition by list columns(a,a)
+( partition p values in ((1,1)));
+ERROR HY000: Duplicate partition field name 'a'
+create table t1 (a int signed)
+partition by list (a)
+( partition p0 values in (1, 3, 5, 7, 9, NULL),
+partition p1 values in (2, 4, 6, 8, 0));
+insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
+select * from t1 where NULL <= a;
+a
+select * from t1 where a is null;
+a
+NULL
+explain partitions select * from t1 where a is null;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
+select * from t1 where a <= 1;
+a
+1
+0
+drop table t1;
+create table t1 (a int signed)
+partition by list columns(a)
+( partition p0 values in (1, 3, 5, 7, 9, NULL),
+partition p1 values in (2, 4, 6, 8, 0));
+insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
+select * from t1 where a <= NULL;
+a
+select * from t1 where a is null;
+a
+NULL
+explain partitions select * from t1 where a is null;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
+select * from t1 where a <= 1;
+a
+1
+0
+drop table t1;
+create table t1 (a int, b int)
+partition by list columns(a,b)
+( partition p0 values in ((1, NULL), (2, NULL), (NULL, NULL)),
+partition p1 values in ((1,1), (2,2)),
+partition p2 values in ((3, NULL), (NULL, 1)));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+LIST COLUMNS a,b (1,NULL),(2,NULL),(NULL,NULL)
+LIST COLUMNS a,b (1,1),(2,2)
+LIST COLUMNS a,b (3,NULL),(NULL,1)
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a,b)
+(PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM,
+ PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */
+insert into t1 values (3, NULL);
+insert into t1 values (NULL, 1);
+insert into t1 values (NULL, NULL);
+insert into t1 values (1, NULL);
+insert into t1 values (2, NULL);
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+select * from t1 where a = 1;
+a b
+1 NULL
+1 1
+select * from t1 where a = 2;
+a b
+2 NULL
+2 2
+select * from t1 where a > 8;
+a b
+select * from t1 where a not between 8 and 8;
+a b
+2 NULL
+2 2
+3 NULL
+1 NULL
+1 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a,b)
+(PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM,
+ PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */
+drop table t1;
+create table t1 (a int)
+partition by list (a)
+( partition p0 values in (1),
+partition p1 values in (1));
+ERROR HY000: Multiple definition of same constant in list partitioning
+create table t1 (a int)
+partition by list (a)
+( partition p0 values in (2, 1),
+partition p1 values in (4, NULL, 3));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+LIST a 2,1
+LIST a NULL,4,3
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST (a)
+(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN (NULL,4,3) ENGINE = MyISAM) */
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+insert into t1 values (4);
+insert into t1 values (NULL);
+insert into t1 values (5);
+ERROR HY000: Table has no partition for value 5
+drop table t1;
+create table t1 (a int)
+partition by list columns(a)
+( partition p0 values in (2, 1),
+partition p1 values in ((4), (NULL), (3)));
+ERROR 42000: Row expressions in VALUES IN only allowed for multi-field column partitioning near '))' at line 4
+create table t1 (a int)
+partition by list columns(a)
+( partition p0 values in (2, 1),
+partition p1 values in (4, NULL, 3));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+LIST COLUMNS a 2,1
+LIST COLUMNS a 4,NULL,3
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a)
+(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+insert into t1 values (4);
+insert into t1 values (NULL);
+insert into t1 values (5);
+ERROR HY000: Table has no partition for value from column_list
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a)
+(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
+ PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */
+drop table t1;
+create table t1 (a int, b char(10), c varchar(5), d int)
+partition by range columns(a,b,c)
+subpartition by key (c,d)
+subpartitions 3
+( partition p0 values less than (1,'abc','abc'),
+partition p1 values less than (2,'abc','abc'),
+partition p2 values less than (3,'abc','abc'),
+partition p3 values less than (4,'abc','abc'));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+RANGE COLUMNS a,b,c 1,'abc','abc'
+RANGE COLUMNS a,b,c 1,'abc','abc'
+RANGE COLUMNS a,b,c 1,'abc','abc'
+RANGE COLUMNS a,b,c 2,'abc','abc'
+RANGE COLUMNS a,b,c 2,'abc','abc'
+RANGE COLUMNS a,b,c 2,'abc','abc'
+RANGE COLUMNS a,b,c 3,'abc','abc'
+RANGE COLUMNS a,b,c 3,'abc','abc'
+RANGE COLUMNS a,b,c 3,'abc','abc'
+RANGE COLUMNS a,b,c 4,'abc','abc'
+RANGE COLUMNS a,b,c 4,'abc','abc'
+RANGE COLUMNS a,b,c 4,'abc','abc'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(10) DEFAULT NULL,
+ `c` varchar(5) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE COLUMNS(a,b,c)
+SUBPARTITION BY KEY (c,d)
+SUBPARTITIONS 3
+(PARTITION p0 VALUES LESS THAN (1,'abc','abc') ENGINE = MyISAM,
+ PARTITION p1 VALUES LESS THAN (2,'abc','abc') ENGINE = MyISAM,
+ PARTITION p2 VALUES LESS THAN (3,'abc','abc') ENGINE = MyISAM,
+ PARTITION p3 VALUES LESS THAN (4,'abc','abc') ENGINE = MyISAM) */
+insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
+insert into t1 values (1,'b','c',1),(2,'b','c',2),(3,'b','c',3);
+insert into t1 values (1,'c','d',1),(2,'c','d',2),(3,'c','d',3);
+insert into t1 values (1,'d','e',1),(2,'d','e',2),(3,'d','e',3);
+select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR
+(a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2))));
+a b c d
+1 a b 1
+1 b c 1
+drop table t1;
+create table t1 (a int, b varchar(2), c int)
+partition by range columns (a, b, c)
+(partition p0 values less than (1, 'A', 1),
+partition p1 values less than (1, 'B', 1));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+RANGE COLUMNS a,b,c 1,'A',1
+RANGE COLUMNS a,b,c 1,'B',1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(2) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE COLUMNS(a,b,c)
+(PARTITION p0 VALUES LESS THAN (1,'A',1) ENGINE = MyISAM,
+ PARTITION p1 VALUES LESS THAN (1,'B',1) ENGINE = MyISAM) */
+insert into t1 values (1, 'A', 1);
+explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 1;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1 system NULL NULL NULL NULL 1
+select * from t1 where a = 1 AND b <= 'A' and c = 1;
+a b c
+1 A 1
+drop table t1;
+create table t1 (a char, b char, c char)
+partition by list columns(a)
+( partition p0 values in ('a'));
+insert into t1 (a) values ('a');
+select * from t1 where a = 'a';
+a b c
+a NULL NULL
+drop table t1;
+create table t1 (d time)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+partition p1 values less than ('2040-01-01'));
+ERROR HY000: Partition column values of incorrect type
+create table t1 (d timestamp)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+partition p1 values less than ('2040-01-01'));
+ERROR HY000: Field 'd' is of a not allowed type for this type of partitioning
+create table t1 (d bit(1))
+partition by range columns(d)
+( partition p0 values less than (0),
+partition p1 values less than (1));
+ERROR HY000: Field 'd' is of a not allowed type for this type of partitioning
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (maxvalue, 10));
+drop table t1;
+create table t1 (d date)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+partition p1 values less than ('2009-01-01'));
+drop table t1;
+create table t1 (d date)
+partition by range columns(d)
+( partition p0 values less than ('1999-01-01'),
+partition p1 values less than ('2000-01-01'));
+drop table t1;
+create table t1 (d date)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+partition p1 values less than ('3000-01-01'));
+drop table t1;
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p2 values less than (99,99),
+partition p1 values less than (99,999));
+insert into t1 values (99,998);
+select * from t1 where b = 998;
+a b
+99 998
+drop table t1;
+create table t1 as select to_seconds(null) as to_seconds;
+select data_type from information_schema.columns
+where column_name='to_seconds';
+data_type
+int
+drop table t1;
+create table t1 (a int, b int)
+partition by list columns(a,b)
+(partition p0 values in ((maxvalue,maxvalue)));
+ERROR 42000: Cannot use MAXVALUE as value in VALUES IN near 'maxvalue,maxvalue)))' at line 3
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (maxvalue,maxvalue));
+drop table t1;
+create table t1 (a int)
+partition by list columns(a)
+(partition p0 values in (0));
+select partition_method from information_schema.partitions where table_name='t1';
+partition_method
+LIST COLUMNS
+drop table t1;
+create table t1 (a char(6))
+partition by range columns(a)
+(partition p0 values less than ('H23456'),
+partition p1 values less than ('M23456'));
+insert into t1 values ('F23456');
+select * from t1;
+a
+F23456
+drop table t1;
+create table t1 (a char(6))
+partition by range columns(a)
+(partition p0 values less than (H23456),
+partition p1 values less than (M23456));
+ERROR 42S22: Unknown column 'H23456' in 'field list'
+create table t1 (a char(6))
+partition by range columns(a)
+(partition p0 values less than (23456),
+partition p1 values less than (23456));
+ERROR HY000: Partition column values of incorrect type
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (10));
+ERROR 42000: Inconsistency in usage of column lists for partitioning near '))' at line 3
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (1,1,1);
+ERROR HY000: Inconsistency in usage of column lists for partitioning
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (1, 0),
+partition p1 values less than (2, maxvalue),
+partition p2 values less than (3, 3),
+partition p3 values less than (10, maxvalue));
+insert into t1 values (11,0);
+ERROR HY000: Table has no partition for value from column_list
+insert into t1 values (0,1),(1,1),(2,1),(3,1),(3,4),(4,9),(9,1);
+select * from t1;
+a b
+0 1
+1 1
+2 1
+3 1
+3 4
+4 9
+9 1
+alter table t1
+partition by range columns(b,a)
+(partition p0 values less than (1,2),
+partition p1 values less than (3,3),
+partition p2 values less than (9,5));
+explain partitions select * from t1 where b < 2;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 7 Using where
+select * from t1 where b < 2;
+a b
+0 1
+1 1
+2 1
+3 1
+9 1
+explain partitions select * from t1 where b < 4;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 7 Using where
+select * from t1 where b < 4;
+a b
+0 1
+1 1
+2 1
+3 1
+9 1
+alter table t1 reorganize partition p1 into
+(partition p11 values less than (2,2),
+partition p12 values less than (3,3));
+alter table t1 reorganize partition p0 into
+(partition p01 values less than (0,3),
+partition p02 values less than (1,1));
+ERROR HY000: Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range
+alter table t1 reorganize partition p2 into
+(partition p2 values less than(9,6,1));
+ERROR HY000: Inconsistency in usage of column lists for partitioning
+alter table t1 reorganize partition p2 into
+(partition p2 values less than (10));
+ERROR HY000: Inconsistency in usage of column lists for partitioning
+alter table t1 reorganize partition p2 into
+(partition p21 values less than (4,7),
+partition p22 values less than (9,5));
+explain partitions select * from t1 where b < 4;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p11,p12,p21 ALL NULL NULL NULL NULL 7 Using where
+select * from t1 where b < 4;
+a b
+0 1
+1 1
+2 1
+3 1
+9 1
+drop table t1;
+create table t1 (a int, b int)
+partition by list columns(a,b)
+subpartition by hash (b)
+subpartitions 2
+(partition p0 values in ((0,0), (1,1)),
+partition p1 values in ((1000,1000)));
+insert into t1 values (1000,1000);
+drop table t1;
+create table t1 (a char, b char, c char)
+partition by range columns(a,b,c)
+( partition p0 values less than ('a','b','c'));
+alter table t1 add partition
+(partition p1 values less than ('b','c','d'));
+drop table t1;
diff --git a/mysql-test/r/partition_column_prune.result b/mysql-test/r/partition_column_prune.result
new file mode 100644
index 00000000000..82c49453d43
--- /dev/null
+++ b/mysql-test/r/partition_column_prune.result
@@ -0,0 +1,66 @@
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+create table t1 (a char, b char, c char)
+partition by range columns(a,b,c)
+( partition p0 values less than ('a','b','c'));
+insert into t1 values ('a', NULL, 'd');
+explain partitions select * from t1 where a = 'a' AND c = 'd';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
+select * from t1 where a = 'a' AND c = 'd';
+a b c
+a NULL d
+drop table t1;
+create table t1 (a int not null) partition by range columns(a) (
+partition p0 values less than (10),
+partition p1 values less than (20),
+partition p2 values less than (30),
+partition p3 values less than (40),
+partition p4 values less than (50),
+partition p5 values less than (60),
+partition p6 values less than (70)
+);
+insert into t1 values (5),(15),(25),(35),(45),(55),(65);
+insert into t1 values (5),(15),(25),(35),(45),(55),(65);
+create table t2 (a int not null) partition by range(a) (
+partition p0 values less than (10),
+partition p1 values less than (20),
+partition p2 values less than (30),
+partition p3 values less than (40),
+partition p4 values less than (50),
+partition p5 values less than (60),
+partition p6 values less than (70)
+);
+insert into t2 values (5),(15),(25),(35),(45),(55),(65);
+insert into t2 values (5),(15),(25),(35),(45),(55),(65);
+explain partitions select * from t1 where a > 35 and a < 45;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 4 Using where
+explain partitions select * from t2 where a > 35 and a < 45;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 4 Using where
+drop table t1, t2;
+create table t1 (a int not null, b int not null )
+partition by range columns(a,b) (
+partition p01 values less than (2,10),
+partition p02 values less than (2,20),
+partition p03 values less than (2,30),
+partition p11 values less than (4,10),
+partition p12 values less than (4,20),
+partition p13 values less than (4,30),
+partition p21 values less than (6,10),
+partition p22 values less than (6,20),
+partition p23 values less than (6,30)
+);
+insert into t1 values (2,5), (2,15), (2,25),
+(4,5), (4,15), (4,25), (6,5), (6,15), (6,25);
+insert into t1 select * from t1;
+explain partitions select * from t1 where a=2;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p01,p02,p03,p11 ALL NULL NULL NULL NULL 13 Using where
+explain partitions select * from t1 where a=4;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p11,p12,p13,p21 ALL NULL NULL NULL NULL 16 Using where
+explain partitions select * from t1 where a=2 and b < 22;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p01,p02,p03 ALL NULL NULL NULL NULL 16 Using where
+drop table t1;
diff --git a/mysql-test/r/partition_datatype.result b/mysql-test/r/partition_datatype.result
index 607afb71da5..47ea799f497 100644
--- a/mysql-test/r/partition_datatype.result
+++ b/mysql-test/r/partition_datatype.result
@@ -273,7 +273,7 @@ select * from t1 where a = 'y';
a
y
drop table t1;
-create table t1 (a varchar(65531)) partition by key (a);
+create table t1 (a varchar(3068)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
@@ -286,7 +286,7 @@ select * from t1 where a = 'bbbb';
a
bbbb
drop table t1;
-create table t1 (a varchar(65532)) partition by key (a);
+create table t1 (a varchar(3069)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
@@ -299,7 +299,7 @@ select * from t1 where a = 'bbbb';
a
bbbb
drop table t1;
-create table t1 (a varchar(65533) not null) partition by key (a);
+create table t1 (a varchar(3070) not null) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
@@ -312,6 +312,8 @@ select * from t1 where a = 'bbbb';
a
bbbb
drop table t1;
+create table t1 (a varchar(3070)) partition by key (a);
+ERROR HY000: The total length of the partitioning fields is too large
create table t1 (a varchar(65533)) partition by key (a);
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
create table t1 (a varchar(65534) not null) partition by key (a);
diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result
index 511806d64bd..d24c3de3cc0 100644
--- a/mysql-test/r/partition_error.result
+++ b/mysql-test/r/partition_error.result
@@ -361,8 +361,7 @@ partition by range (a)
partitions 2
(partition x1 values less than (4.0) tablespace ts1,
partition x2 values less than (8) tablespace ts2);
-ERROR 42000: VALUES value must be of same type as partition function near ') tablespace ts1,
-partition x2 values less than (8) tablespace ts2)' at line 8
+ERROR HY000: VALUES value must be of same type as partition function
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -412,8 +411,7 @@ partition by list (a)
partitions 2
(partition x1 values less than 4,
partition x2 values less than (5));
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '4,
-partition x2 values less than (5))' at line 8
+ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -423,7 +421,7 @@ partition by range (a)
partitions 2
(partition x1 values less than maxvalue,
partition x2 values less than (5));
-ERROR 42000: MAXVALUE can only be used in last partition definition near '))' at line 9
+ERROR HY000: MAXVALUE can only be used in last partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -433,7 +431,7 @@ partition by range (a)
partitions 2
(partition x1 values less than maxvalue,
partition x2 values less than maxvalue);
-ERROR 42000: MAXVALUE can only be used in last partition definition near 'maxvalue)' at line 9
+ERROR HY000: MAXVALUE can only be used in last partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -602,8 +600,7 @@ partition by list (a)
partitions 2
(partition x1 values in (4.0, 12+8),
partition x2 values in (3, 21));
-ERROR 42000: VALUES value must be of same type as partition function near ' 12+8),
-partition x2 values in (3, 21))' at line 8
+ERROR HY000: VALUES value must be of same type as partition function
CREATE TABLE t1 (
a int not null,
b int not null,
diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result
index 4323d167b10..d95e7dc43fd 100644
--- a/mysql-test/r/partition_innodb.result
+++ b/mysql-test/r/partition_innodb.result
@@ -1,4 +1,39 @@
drop table if exists t1;
+create table t1 (a varchar(5), b int signed, c varchar(10), d datetime)
+partition by range columns(b,c)
+subpartition by hash(to_seconds(d))
+( partition p0 values less than (2, 'b'),
+partition p1 values less than (4, 'd'),
+partition p2 values less than (10, 'za'));
+insert into t1 values ('a', 3, 'w', '2001-10-27 04:34:00');
+insert into t1 values ('r', 7, 'w', '2001-10-27 05:34:00');
+insert into t1 values ('g', 10, 'w', '2001-10-27 06:34:00');
+update t1 set a = 'c' where a > 'f';
+drop table t1;
+create table t1 (a varchar(5))
+engine=memory
+partition by range columns(a)
+( partition p0 values less than ('m'),
+partition p1 values less than ('za'));
+insert into t1 values ('j');
+update t1 set a = 'z' where (a >= 'j');
+drop table t1;
+create table t1 (a varchar(5))
+engine=myisam
+partition by range columns(a)
+( partition p0 values less than ('m'),
+partition p1 values less than ('za'));
+insert into t1 values ('j');
+update t1 set a = 'z' where (a >= 'j');
+drop table t1;
+create table t1 (a varchar(5))
+engine=innodb
+partition by range columns(a)
+( partition p0 values less than ('m'),
+partition p1 values less than ('za'));
+insert into t1 values ('j');
+update t1 set a = 'z' where (a >= 'j');
+drop table t1;
create table t1 (a int not null,
b datetime not null,
primary key (a,b))
diff --git a/mysql-test/r/partition_list.result b/mysql-test/r/partition_list.result
index a68a67c6386..e22fc11e5bb 100644
--- a/mysql-test/r/partition_list.result
+++ b/mysql-test/r/partition_list.result
@@ -54,6 +54,17 @@ subpartitions 2
partition p1 values in (1),
partition pnull values in (null, 2),
partition p3 values in (3));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+LIST a 0
+LIST a 0
+LIST a 1
+LIST a 1
+LIST a NULL,2
+LIST a NULL,2
+LIST a 3
+LIST a 3
insert into t1 values (0,0),(0,1),(1,0),(1,1),(null,0),(null,1);
insert into t1 values (2,0),(2,1),(3,0),(3,1);
explain partitions select * from t1 where a is null;
diff --git a/mysql-test/r/partition_mgm_err.result b/mysql-test/r/partition_mgm_err.result
index f8403988f47..a13278d724e 100644
--- a/mysql-test/r/partition_mgm_err.result
+++ b/mysql-test/r/partition_mgm_err.result
@@ -41,7 +41,7 @@ ERROR HY000: Reorganize of range partitions cannot change total ranges except fo
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (4),
PARTITION x11 VALUES LESS THAN (2));
-ERROR HY000: Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range
+ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (6),
PARTITION x11 VALUES LESS THAN (4));
diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result
index d8bff2cbe01..d7790cd8075 100644
--- a/mysql-test/r/partition_pruning.result
+++ b/mysql-test/r/partition_pruning.result
@@ -656,6 +656,335 @@ EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
DROP TABLE t1;
+# TO_SECONDS, test of LIST and index
+CREATE TABLE t1 (a DATE, KEY(a))
+PARTITION BY LIST (TO_SECONDS(a))
+(PARTITION `p0001-01-01` VALUES IN (TO_SECONDS('0001-01-01')),
+PARTITION `p2001-01-01` VALUES IN (TO_SECONDS('2001-01-01')),
+PARTITION `pNULL` VALUES IN (NULL),
+PARTITION `p0000-01-02` VALUES IN (TO_SECONDS('0000-01-02')),
+PARTITION `p1001-01-01` VALUES IN (TO_SECONDS('1001-01-01')));
+INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
+('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
+SELECT * FROM t1 WHERE a < '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-01-01';
+a
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-01-01';
+a
+1001-01-01
+SELECT * FROM t1 WHERE a < '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-00-00';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-00-00';
+a
+1001-00-00
+# Disabling warnings for the invalid date
+SELECT * FROM t1 WHERE a < '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a > '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a = '1999-02-31';
+a
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+a
+0001-01-01
+1001-00-00
+1001-01-01
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1001-01-01 system a NULL NULL NULL 1
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
+# Disabling warnings for the invalid date
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01 range a a 4 NULL 2 Using where; Using index
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 range a a 4 NULL 3 Using where; Using index
+# test without index
+ALTER TABLE t1 DROP KEY a;
+SELECT * FROM t1 WHERE a < '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a <= '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a >= '1001-01-01';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-01-01';
+a
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-01-01';
+a
+1001-01-01
+SELECT * FROM t1 WHERE a < '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+SELECT * FROM t1 WHERE a <= '1001-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+SELECT * FROM t1 WHERE a >= '1001-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a > '1001-00-00';
+a
+1001-01-01
+1002-00-00
+2001-01-01
+SELECT * FROM t1 WHERE a = '1001-00-00';
+a
+1001-00-00
+# Disabling warnings for the invalid date
+SELECT * FROM t1 WHERE a < '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a <= '1999-02-31';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a >= '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a > '1999-02-31';
+a
+2001-01-01
+SELECT * FROM t1 WHERE a = '1999-02-31';
+a
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+a
+0000-00-00
+0000-01-02
+0001-01-01
+1001-00-00
+1001-01-01
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+a
+1001-00-00
+1001-01-01
+1002-00-00
+SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+a
+0001-01-01
+1001-00-00
+1001-01-01
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p1001-01-01 system NULL NULL NULL NULL 1
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
+# Disabling warnings for the invalid date
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
+DROP TABLE t1;
# Test with DATETIME column NOT NULL
CREATE TABLE t1 (
a int(10) unsigned NOT NULL,
@@ -1272,10 +1601,9 @@ INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL);
# test with an invalid date, which lead to item->null_value is set.
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME);
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p20090401 ALL NULL NULL NULL NULL 2 Using where
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Warning 1292 Incorrect datetime value: '2009-04-99'
-Warning 1292 Incorrect datetime value: '2009-04-99'
DROP TABLE t1;
CREATE TABLE t1
(a INT NOT NULL AUTO_INCREMENT,
diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result
index 02d2f6359c5..87cb4fba306 100644
--- a/mysql-test/r/partition_range.result
+++ b/mysql-test/r/partition_range.result
@@ -1,6 +1,99 @@
drop table if exists t1, t2;
create table t1 (a int)
partition by range (a)
+( partition p0 values less than (NULL),
+partition p1 values less than (MAXVALUE));
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
+create table t1 (a datetime not null)
+partition by range (TO_SECONDS(a))
+( partition p0 VALUES LESS THAN (TO_SECONDS('2007-03-08 00:00:00')),
+partition p1 VALUES LESS THAN (TO_SECONDS('2007-04-01 00:00:00')));
+select partition_method, partition_expression, partition_description
+from information_schema.partitions where table_name = "t1";
+partition_method partition_expression partition_description
+RANGE TO_SECONDS(a) 63340531200
+RANGE TO_SECONDS(a) 63342604800
+INSERT INTO t1 VALUES ('2007-03-01 12:00:00'), ('2007-03-07 12:00:00');
+INSERT INTO t1 VALUES ('2007-03-08 12:00:00'), ('2007-03-15 12:00:00');
+explain partitions select * from t1 where a < '2007-03-08 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
+explain partitions select * from t1 where a < '2007-03-08 00:00:01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 4 Using where
+explain partitions select * from t1 where a <= '2007-03-08 00:00:00';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 4 Using where
+explain partitions select * from t1 where a <= '2007-03-07 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
+explain partitions select * from t1 where a < '2007-03-07 23:59:59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
+drop table t1;
+create table t1 (a date)
+partition by range(to_seconds(a))
+(partition p0 values less than (to_seconds('2004-01-01')),
+partition p1 values less than (to_seconds('2005-01-01')));
+insert into t1 values ('2003-12-30'),('2004-12-31');
+select * from t1;
+a
+2003-12-30
+2004-12-31
+explain partitions select * from t1 where a <= '2003-12-31';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
+select * from t1 where a <= '2003-12-31';
+a
+2003-12-30
+explain partitions select * from t1 where a <= '2005-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
+select * from t1 where a <= '2005-01-01';
+a
+2003-12-30
+2004-12-31
+drop table t1;
+create table t1 (a datetime)
+partition by range(to_seconds(a))
+(partition p0 values less than (to_seconds('2004-01-01 12:00:00')),
+partition p1 values less than (to_seconds('2005-01-01 12:00:00')));
+insert into t1 values ('2004-01-01 11:59:29'),('2005-01-01 11:59:59');
+select * from t1;
+a
+2004-01-01 11:59:29
+2005-01-01 11:59:59
+explain partitions select * from t1 where a <= '2004-01-01 11:59.59';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
+select * from t1 where a <= '2004-01-01 11:59:59';
+a
+2004-01-01 11:59:29
+explain partitions select * from t1 where a <= '2005-01-01';
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
+select * from t1 where a <= '2005-01-01';
+a
+2004-01-01 11:59:29
+drop table t1;
+create table t1 (a int, b char(20))
+partition by range columns(a,b)
+(partition p0 values less than (1));
+ERROR 42000: Inconsistency in usage of column lists for partitioning near '))' at line 3
+create table t1 (a int, b char(20))
+partition by range(a)
+(partition p0 values less than (1,"b"));
+ERROR HY000: Cannot have more than one value for this type of RANGE partitioning
+create table t1 (a int, b char(20))
+partition by range(a)
+(partition p0 values less than (1,"b"));
+ERROR HY000: Cannot have more than one value for this type of RANGE partitioning
+create table t1 (a int, b char(20))
+partition by range columns(b)
+(partition p0 values less than ("b"));
+drop table t1;
+create table t1 (a int)
+partition by range (a)
( partition p0 values less than (maxvalue));
alter table t1 add partition (partition p1 values less than (100000));
ERROR HY000: MAXVALUE can only be used in last partition definition
diff --git a/mysql-test/r/partition_utf8.result b/mysql-test/r/partition_utf8.result
new file mode 100644
index 00000000000..0fae7bb16b6
--- /dev/null
+++ b/mysql-test/r/partition_utf8.result
@@ -0,0 +1,53 @@
+set names utf8;
+create table t1 (a varchar(2) character set cp1250)
+partition by list columns (a)
+( partition p0 values in (0x81));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2) CHARACTER SET cp1250 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a)
+(PARTITION p0 VALUES IN (_cp1250 0x81) ENGINE = MyISAM) */
+drop table t1;
+create table t1 (a varchar(2) character set cp1250)
+partition by list columns (a)
+( partition p0 values in (0x80));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2) CHARACTER SET cp1250 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a)
+(PARTITION p0 VALUES IN ('€') ENGINE = MyISAM) */
+drop table t1;
+create table t1 (a varchar(1500), b varchar(1570))
+partition by list columns(a,b)
+( partition p0 values in (('a','b')));
+ERROR HY000: The total length of the partitioning fields is too large
+create table t1 (a varchar(1023) character set utf8 collate utf8_spanish2_ci)
+partition by range columns(a)
+( partition p0 values less than ('CZ'),
+partition p1 values less than ('CH'),
+partition p2 values less than ('D'));
+insert into t1 values ('czz'),('chi'),('ci'),('cg');
+select * from t1 where a between 'cg' AND 'ci';
+a
+ci
+cg
+drop table t1;
+create table t1 (a varchar(2) character set ucs2)
+partition by list columns (a)
+(partition p0 values in (0x2020),
+partition p1 values in (''));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST COLUMNS(a)
+(PARTITION p0 VALUES IN ('†') ENGINE = MyISAM,
+ PARTITION p1 VALUES IN ('') ENGINE = MyISAM) */
+insert into t1 values ('');
+insert into t1 values (_ucs2 0x2020);
+drop table t1;
diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
index 782d2a5a9a4..85fbd1353cc 100644
--- a/mysql-test/r/plugin.result
+++ b/mysql-test/r/plugin.result
@@ -12,6 +12,15 @@ CREATE TABLE t1(a int) ENGINE=EXAMPLE;
SELECT * FROM t1;
a
DROP TABLE t1;
+set global example_ulong_var=500;
+set global example_enum_var= e1;
+show status like 'example%';
+Variable_name Value
+example_func_example enum_var is 0, ulong_var is 500, really
+show variables like 'example%';
+Variable_name Value
+example_enum_var e1
+example_ulong_var 500
UNINSTALL PLUGIN example;
UNINSTALL PLUGIN EXAMPLE;
ERROR 42000: PLUGIN EXAMPLE does not exist
diff --git a/mysql-test/r/profiling.result b/mysql-test/r/profiling.result
index c96074eb830..f20c459d7dc 100644
--- a/mysql-test/r/profiling.result
+++ b/mysql-test/r/profiling.result
@@ -298,6 +298,13 @@ id
1
2
3
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'hello'
+Warning 1292 Truncated incorrect DOUBLE value: 'hello'
+Warning 1292 Truncated incorrect DOUBLE value: 'hello'
+Warning 1292 Truncated incorrect DOUBLE value: 'hello'
+Warning 1292 Truncated incorrect DOUBLE value: 'hello'
+Warning 1292 Truncated incorrect DOUBLE value: 'hello'
select @@profiling;
@@profiling
1
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 06e6b8167fd..6c7e83134d7 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1194,13 +1194,13 @@ SET @aux= "SELECT COUNT(*)
prepare my_stmt from @aux;
execute my_stmt;
COUNT(*)
-39
+40
execute my_stmt;
COUNT(*)
-39
+40
execute my_stmt;
COUNT(*)
-39
+40
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
@@ -2926,4 +2926,165 @@ execute stmt;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
drop table t1;
deallocate prepare stmt;
+
End of 5.1 tests.
+
+#
+# WL#4435: Support OUT-parameters in prepared statements.
+#
+
+DROP PROCEDURE IF EXISTS p_string;
+DROP PROCEDURE IF EXISTS p_double;
+DROP PROCEDURE IF EXISTS p_int;
+DROP PROCEDURE IF EXISTS p_decimal;
+
+CREATE PROCEDURE p_string(
+IN v0 INT,
+OUT v1 CHAR(32),
+IN v2 CHAR(32),
+INOUT v3 CHAR(32))
+BEGIN
+SET v0 = -1;
+SET v1 = 'test_v1';
+SET v2 = 'n/a';
+SET v3 = 'test_v3';
+END|
+
+CREATE PROCEDURE p_double(
+IN v0 INT,
+OUT v1 DOUBLE(4, 2),
+IN v2 DOUBLE(4, 2),
+INOUT v3 DOUBLE(4, 2))
+BEGIN
+SET v0 = -1;
+SET v1 = 12.34;
+SET v2 = 98.67;
+SET v3 = 56.78;
+END|
+
+CREATE PROCEDURE p_int(
+IN v0 CHAR(10),
+OUT v1 INT,
+IN v2 INT,
+INOUT v3 INT)
+BEGIN
+SET v0 = 'n/a';
+SET v1 = 1234;
+SET v2 = 9876;
+SET v3 = 5678;
+END|
+
+CREATE PROCEDURE p_decimal(
+IN v0 INT,
+OUT v1 DECIMAL(4, 2),
+IN v2 DECIMAL(4, 2),
+INOUT v3 DECIMAL(4, 2))
+BEGIN
+SET v0 = -1;
+SET v1 = 12.34;
+SET v2 = 98.67;
+SET v3 = 56.78;
+END|
+
+PREPARE stmt_str FROM 'CALL p_string(?, ?, ?, ?)';
+PREPARE stmt_dbl FROM 'CALL p_double(?, ?, ?, ?)';
+PREPARE stmt_int FROM 'CALL p_int(?, ?, ?, ?)';
+PREPARE stmt_dec FROM 'CALL p_decimal(?, ?, ?, ?)';
+
+SET @x_str_1 = NULL;
+SET @x_str_2 = NULL;
+SET @x_str_3 = NULL;
+SET @x_dbl_1 = NULL;
+SET @x_dbl_2 = NULL;
+SET @x_dbl_3 = NULL;
+SET @x_int_1 = NULL;
+SET @x_int_2 = NULL;
+SET @x_int_3 = NULL;
+SET @x_dec_1 = NULL;
+SET @x_dec_2 = NULL;
+SET @x_dec_3 = NULL;
+
+-- Testing strings...
+
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+@x_int_1 @x_str_1 @x_str_2 @x_str_3
+NULL test_v1 NULL test_v3
+
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+@x_int_1 @x_str_1 @x_str_2 @x_str_3
+NULL test_v1 NULL test_v3
+
+-- Testing doubles...
+
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+@x_int_1 @x_dbl_1 @x_dbl_2 @x_dbl_3
+NULL 12.34 NULL 56.78
+
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+@x_int_1 @x_dbl_1 @x_dbl_2 @x_dbl_3
+NULL 12.34 NULL 56.78
+
+-- Testing ints...
+
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+@x_str_1 @x_int_1 @x_int_2 @x_int_3
+test_v1 1234 NULL 5678
+
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+@x_str_1 @x_int_1 @x_int_2 @x_int_3
+test_v1 1234 NULL 5678
+
+-- Testing decs...
+
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+@x_int_1 @x_dec_1 @x_dec_2 @x_dec_3
+1234 12.34 NULL 56.78
+
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+@x_int_1 @x_dec_1 @x_dec_2 @x_dec_3
+1234 12.34 NULL 56.78
+
+DEALLOCATE PREPARE stmt_str;
+DEALLOCATE PREPARE stmt_dbl;
+DEALLOCATE PREPARE stmt_int;
+DEALLOCATE PREPARE stmt_dec;
+
+DROP PROCEDURE p_string;
+DROP PROCEDURE p_double;
+DROP PROCEDURE p_int;
+DROP PROCEDURE p_decimal;
+
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+
+CREATE PROCEDURE p1(OUT v1 CHAR(10))
+SET v1 = 'test1';
+
+CREATE PROCEDURE p2(OUT v2 CHAR(10))
+BEGIN
+SET @query = 'CALL p1(?)';
+PREPARE stmt1 FROM @query;
+EXECUTE stmt1 USING @u1;
+DEALLOCATE PREPARE stmt1;
+SET v2 = @u1;
+END|
+
+CALL p2(@a);
+SELECT @a;
+@a
+test1
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+# End of WL#4435.
+
+End of 6.0 tests.
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 1b2a0cc50b2..3ab65c24040 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -279,6 +279,9 @@ b char(10) YES NULL
SET @arg00=1;
execute stmt4 using @arg00;
Field Type Null Key Default Extra
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'a'
+Warning 1292 Truncated incorrect DOUBLE value: 'b'
prepare stmt4 from ' show columns from t2 from test like ''a%'' ';
execute stmt4;
Field Type Null Key Default Extra
diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result
index 8b16123ccea..672db74d9c0 100644
--- a/mysql-test/r/ps_grant.result
+++ b/mysql-test/r/ps_grant.result
@@ -32,19 +32,19 @@ identified by 'looser' ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
drop table mysqltest.t9 ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
prepare s_t1 from 'select a as my_col from t1' ;
execute s_t1 ;
my_col
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 6c6d357a462..b67fa9322ee 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -1707,6 +1707,7 @@ Qcache_hits 2
DROP TABLE t1;
SET GLOBAL query_cache_size= default;
End of 5.0 tests
+SET GLOBAL query_cache_size=1024*1024*512;
CREATE TABLE t1 (a ENUM('rainbow'));
INSERT INTO t1 VALUES (),(),(),(),();
SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID()));
@@ -1721,4 +1722,5 @@ SELECT 1 FROM t1 GROUP BY
1
1
DROP TABLE t1;
+SET GLOBAL query_cache_size= default;
End of 5.1 tests
diff --git a/mysql-test/r/query_cache_disabled.result b/mysql-test/r/query_cache_disabled.result
new file mode 100644
index 00000000000..f2f58580ca2
--- /dev/null
+++ b/mysql-test/r/query_cache_disabled.result
@@ -0,0 +1,14 @@
+SHOW GLOBAL VARIABLES LIKE 'query_cache_type';
+Variable_name Value
+query_cache_type OFF
+SET GLOBAL query_cache_type=ON;
+ERROR HY000: Query cache is disabled; restart the server with query_cache_type=1 to enable it
+SET GLOBAL query_cache_type=DEMAND;
+ERROR HY000: Query cache is disabled; restart the server with query_cache_type=1 to enable it
+SET GLOBAL query_cache_type=OFF;
+ERROR HY000: Query cache is disabled; restart the server with query_cache_type=1 to enable it
+SET GLOBAL query_cache_size=1024*1024;
+SHOW GLOBAL VARIABLES LIKE 'query_cache_size';
+Variable_name Value
+query_cache_size 1048576
+SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/query_cache_ps_no_prot.result b/mysql-test/r/query_cache_ps_no_prot.result
index 0efb2540c64..f686e876a60 100644
--- a/mysql-test/r/query_cache_ps_no_prot.result
+++ b/mysql-test/r/query_cache_ps_no_prot.result
@@ -529,5 +529,46 @@ DROP DATABASE mysqltest1;
use test;
########################################################################
+#
+# Bug#27430 Crash in subquery code when in PS and table DDL changed
+# after PREPARE
+# Check the effect of automatic reprepare on query cache
+#
+########################################################################
+drop table if exists t1;
+create table t1 (a varchar(255));
+insert into t1 (a) values ("Pack my box with five dozen liquor jugs.");
+flush status;
+prepare stmt from "select a from t1";
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+set @@global.query_cache_size=0;
+alter table t1 add column b int;
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+set @@global.query_cache_size=100000;
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+#
+# Sic: ALTER TABLE caused an automatic reprepare
+# of the prepared statement. Since the query cache was disabled
+# at the time of reprepare, the new prepared statement doesn't
+# work with it.
+#
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 0
+show status like 'Qcache_queries_in_cache';
+Variable_name Value
+Qcache_queries_in_cache 0
+# Cleanup
+deallocate prepare stmt;
+drop table t1;
set @@global.query_cache_size=@initial_query_cache_size;
flush status;
diff --git a/mysql-test/r/query_cache_ps_ps_prot.result b/mysql-test/r/query_cache_ps_ps_prot.result
index dc0c4a0193a..e594161f2e9 100644
--- a/mysql-test/r/query_cache_ps_ps_prot.result
+++ b/mysql-test/r/query_cache_ps_ps_prot.result
@@ -529,5 +529,46 @@ DROP DATABASE mysqltest1;
use test;
########################################################################
+#
+# Bug#27430 Crash in subquery code when in PS and table DDL changed
+# after PREPARE
+# Check the effect of automatic reprepare on query cache
+#
+########################################################################
+drop table if exists t1;
+create table t1 (a varchar(255));
+insert into t1 (a) values ("Pack my box with five dozen liquor jugs.");
+flush status;
+prepare stmt from "select a from t1";
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+set @@global.query_cache_size=0;
+alter table t1 add column b int;
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+set @@global.query_cache_size=100000;
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+execute stmt;
+a
+Pack my box with five dozen liquor jugs.
+#
+# Sic: ALTER TABLE caused an automatic reprepare
+# of the prepared statement. Since the query cache was disabled
+# at the time of reprepare, the new prepared statement doesn't
+# work with it.
+#
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 0
+show status like 'Qcache_queries_in_cache';
+Variable_name Value
+Qcache_queries_in_cache 0
+# Cleanup
+deallocate prepare stmt;
+drop table t1;
set @@global.query_cache_size=@initial_query_cache_size;
flush status;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index c98a7696ea6..7ed8d23d533 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -1398,3 +1398,209 @@ a < 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 range a a 5 NULL 8 Using where; Using index
DROP TABLE t1, t2, t3;
+#
+# Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN
+#
+CREATE TABLE t1(a INT, KEY(a));
+INSERT INTO t1 VALUES (1), (NULL);
+SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL);
+a
+DROP TABLE t1;
+#
+# Bug#47925: regression of range optimizer and date comparison in 5.1.39!
+#
+CREATE TABLE t1 ( a DATE, KEY ( a ) );
+CREATE TABLE t2 ( a DATETIME, KEY ( a ) );
+# Make optimizer choose range scan
+INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22');
+INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23');
+INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'),
+('2009-09-22 12:00:00');
+INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'),
+('2009-09-23 12:00:00');
+# DATE vs DATE
+EXPLAIN
+SELECT * FROM t1 WHERE a >= '2009/09/23';
+id select_type table type possible_keys key key_len ref rows Extra
+X X X range a a X X X X
+SELECT * FROM t1 WHERE a >= '2009/09/23';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '20090923';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= 20090923;
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009-9-23';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009.09.23';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009:09:23';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+# DATE vs DATETIME
+EXPLAIN
+SELECT * FROM t2 WHERE a >= '2009/09/23';
+id select_type table type possible_keys key key_len ref rows Extra
+X X X range a a X X X X
+SELECT * FROM t2 WHERE a >= '2009/09/23';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009/09/23';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '20090923';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= 20090923;
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009-9-23';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009.09.23';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009:09:23';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+# DATETIME vs DATETIME
+EXPLAIN
+SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
+id select_type table type possible_keys key key_len ref rows Extra
+X X X range a a X X X X
+SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '20090923120000';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= 20090923120000;
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00';
+a
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+2009-09-23 12:00:00
+# DATETIME vs DATE
+EXPLAIN
+SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
+id select_type table type possible_keys key key_len ref rows Extra
+X X X range a a X X X X
+SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '20090923000000';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= 20090923000000;
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00';
+a
+2009-09-23
+2009-09-23
+2009-09-23
+# Test of the new get_date_from_str implementation
+# Behavior differs slightly between the trunk and mysql-pe.
+# The former may give errors for the truncated values, while the latter
+# gives warnings. The purpose of this test is not to interfere, and only
+# preserve existing behavior.
+SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND
+str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20';
+str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND
+str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: ''
+SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND
+str_to_date('2007-20-00', '%Y-%m-%d') <= '';
+str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND
+str_to_date('2007-20-00', '%Y-%m-%d') <= ''
+NULL
+Warnings:
+Warning 1292 Truncated incorrect date value: ''
+Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date
+Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date
+SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
+str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: ''
+SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '';
+str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''
+NULL
+Warnings:
+Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date
+SELECT str_to_date('', '%Y-%m-%d');
+str_to_date('', '%Y-%m-%d')
+0000-00-00
+DROP TABLE t1, t2;
+End of 5.1 tests
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 485bd4e5687..1944edf6ade 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -4386,6 +4386,47 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = `test`.`t1`.`b`) and (`test`.`t1`.`a` > 1)) limit 2
DROP TABLE t1;
+#
+# Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when
+# forcing a spatial index
+#
+CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a));
+INSERT INTO t1 VALUES
+(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')),
+(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'));
+EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL a NULL NULL NULL 2
+SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
+1
+1
+1
+1
+1
+EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL a NULL NULL NULL 2
+SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
+1
+1
+1
+1
+1
+DROP TABLE t1;
+#
+# Bug #48291 : crash with row() operator,select into @var, and
+# subquery returning multiple rows
+#
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (2),(3);
+# Should not crash
+SELECT 1 FROM t1 WHERE a <> 1 AND NOT
+ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1))
+INTO @var0;
+ERROR 21000: Subquery returns more than 1 row
+DROP TABLE t1;
End of 5.0 tests
create table t1(a INT, KEY (a));
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 442511de2b1..091d932a6fc 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -1126,7 +1126,7 @@ def information_schema ROUTINES ROUTINES SQL_DATA_ACCESS SQL_DATA_ACCESS 253 192
def information_schema ROUTINES ROUTINES SQL_PATH SQL_PATH 253 192 0 Y 0 0 33
def information_schema ROUTINES ROUTINES SECURITY_TYPE SECURITY_TYPE 253 21 7 N 1 0 33
def information_schema ROUTINES ROUTINES SQL_MODE SQL_MODE 253 24576 0 N 1 0 33
-def information_schema ROUTINES ROUTINES ROUTINE_COMMENT ROUTINE_COMMENT 253 192 0 N 1 0 33
+def information_schema ROUTINES ROUTINES ROUTINE_COMMENT ROUTINE_COMMENT 252 589815 0 N 17 0 33
def information_schema ROUTINES ROUTINES DEFINER DEFINER 253 231 14 N 1 0 33
SPECIFIC_NAME ROUTINE_CATALOG ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE DTD_IDENTIFIER ROUTINE_BODY ROUTINE_DEFINITION EXTERNAL_NAME EXTERNAL_LANGUAGE PARAMETER_STYLE IS_DETERMINISTIC SQL_DATA_ACCESS SQL_PATH SECURITY_TYPE SQL_MODE ROUTINE_COMMENT DEFINER
p1 def test p1 PROCEDURE NULL SQL SELECT 1 NULL NULL SQL NO CONTAINS SQL NULL DEFINER root@localhost
@@ -1181,7 +1181,7 @@ def information_schema ROUTINES ROUTINES SQL_DATA_ACCESS SQL_DATA_ACCESS 253 192
def information_schema ROUTINES ROUTINES SQL_PATH SQL_PATH 253 192 0 Y 0 0 33
def information_schema ROUTINES ROUTINES SECURITY_TYPE SECURITY_TYPE 253 21 7 N 1 0 33
def information_schema ROUTINES ROUTINES SQL_MODE SQL_MODE 253 24576 0 N 1 0 33
-def information_schema ROUTINES ROUTINES ROUTINE_COMMENT ROUTINE_COMMENT 253 192 0 N 1 0 33
+def information_schema ROUTINES ROUTINES ROUTINE_COMMENT ROUTINE_COMMENT 252 589815 0 N 17 0 33
def information_schema ROUTINES ROUTINES DEFINER DEFINER 253 231 14 N 1 0 33
SPECIFIC_NAME ROUTINE_CATALOG ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE DTD_IDENTIFIER ROUTINE_BODY ROUTINE_DEFINITION EXTERNAL_NAME EXTERNAL_LANGUAGE PARAMETER_STYLE IS_DETERMINISTIC SQL_DATA_ACCESS SQL_PATH SECURITY_TYPE SQL_MODE ROUTINE_COMMENT DEFINER
f1 def test f1 FUNCTION int(11) SQL RETURN 1 NULL NULL SQL NO CONTAINS SQL NULL DEFINER root@localhost
diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result
new file mode 100644
index 00000000000..14c5311bbe5
--- /dev/null
+++ b/mysql-test/r/sp-bugs.result
@@ -0,0 +1,47 @@
+#
+# Bug #47412: Valgrind warnings / user can read uninitalized memory
+# using SP variables
+#
+CREATE SCHEMA testdb;
+USE testdb;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg1 VARCHAR(32) )
+BEGIN
+CALL p_not_exists ( );
+END|
+# should not return valgrind warnings
+CALL p3 ( f2 () );
+ERROR 42000: PROCEDURE testdb.p_not_exists does not exist
+DROP SCHEMA testdb;
+CREATE SCHEMA testdb;
+USE testdb;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg2 INTEGER )
+BEGIN
+CALL p_not_exists ( );
+END|
+# should not return valgrind warnings
+CALL p3 ( f2 () );
+ERROR 42000: PROCEDURE testdb.p_not_exists does not exist
+DROP SCHEMA testdb;
+CREATE SCHEMA testdb;
+USE testdb;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+RETURN f_not_exists () ;
+END|
+# should not return valgrind warnings
+SELECT f2 ();
+f2 ()
+NULL
+DROP SCHEMA testdb;
+End of 5.1 tests
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 17ab2b79043..b3968ea7eb6 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -1670,3 +1670,19 @@ NULL
SELECT non_existent (a) FROM t1 WHERE b = 999999;
ERROR 42000: FUNCTION test.non_existent does not exist
DROP TABLE t1;
+#
+# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
+# SP + MERGE + ALTER
+#
+CREATE TABLE t1 (pk INT, b INT, KEY (b));
+CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a;
+CALL p1(5);
+ERROR HY000: The target table v1 of the UPDATE is not updatable
+ALTER TABLE t1 CHANGE COLUMN b b2 INT;
+CALL p1(7);
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+End of 5.1 tests
diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result
index f532a5284a9..f167986e82c 100644
--- a/mysql-test/r/sp-vars.result
+++ b/mysql-test/r/sp-vars.result
@@ -1158,3 +1158,30 @@ f1() @b
0 abc
drop function f1;
drop table t1;
+
+---------------------------------------------------------------
+BUG#28299
+---------------------------------------------------------------
+
+CREATE PROCEDURE ctest()
+BEGIN
+DECLARE i CHAR(16);
+DECLARE j INT;
+SET i= 'string';
+SET j= 1 + i;
+END|
+CALL ctest();
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'string '
+DROP PROCEDURE ctest;
+CREATE PROCEDURE vctest()
+BEGIN
+DECLARE i VARCHAR(16);
+DECLARE j INT;
+SET i= 'string';
+SET j= 1 + i;
+END|
+CALL vctest();
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'string'
+DROP PROCEDURE vctest;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index fce588f704c..45dac2f5523 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -6926,3 +6926,35 @@ DROP TABLE t1, t2;
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
+DROP FUNCTION IF EXISTS f1;
+DROP TABLE IF EXISTS t_non_existing;
+DROP TABLE IF EXISTS t1;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+DECLARE v INT;
+SELECT a INTO v FROM t_non_existing;
+RETURN 1;
+END|
+CREATE TABLE t1 (a INT) ENGINE = myisam;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1 WHERE a = f1();
+ERROR 42S02: Table 'test.t_non_existing' doesn't exist
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#34197: CREATE PROCEDURE fails when COMMENT truncated in non
+# strict SQL mode
+#
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1 ()
+COMMENT
+'12345678901234567890123456789012345678901234567890123456789012345678901234567890'
+BEGIN
+END;
+SELECT comment FROM mysql.proc WHERE name = "p1";
+comment
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+SELECT routine_comment FROM information_schema.routines WHERE routine_name = "p1";
+routine_comment
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+DROP PROCEDURE p1;
diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result
index 3cc251bc0a6..be45e5ff5d7 100644
--- a/mysql-test/r/sp_trans.result
+++ b/mysql-test/r/sp_trans.result
@@ -556,3 +556,30 @@ f1 bug13575(f1)
3 ccc
drop function bug13575|
drop table t3|
+#
+# End of 5.1 tests
+#
+#
+# Bug #35877 Update .. WHERE with function, constraint violation, crash
+#
+DROP TABLE IF EXISTS t1_aux|
+DROP TABLE IF EXISTS t1_not_null|
+DROP FUNCTION IF EXISTS f1_two_inserts|
+# MyISAM test
+CREATE TABLE t1_not_null (f1 BIGINT, f2 BIGINT NOT NULL)|
+CREATE TABLE t1_aux (f1 BIGINT, f2 BIGINT)|
+INSERT INTO t1_aux VALUES (1,1)|
+CREATE FUNCTION f1_two_inserts() returns INTEGER
+BEGIN
+INSERT INTO t1_not_null SET f1 = 10, f2 = NULL;
+RETURN 1;
+END|
+UPDATE t1_aux SET f2 = 2 WHERE f1 = f1_two_inserts()|
+ERROR 23000: Column 'f2' cannot be null
+# InnoDB test
+ALTER TABLE t1_not_null ENGINE = InnoDB|
+ALTER TABLE t1_aux ENGINE = InnoDB|
+UPDATE t1_aux SET f2 = 2 WHERE f1 = f1_two_inserts()|
+ERROR 23000: Column 'f2' cannot be null
+DROP TABLE t1_aux, t1_not_null|
+DROP FUNCTION f1_two_inserts|
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 0b0d5a38d0b..e83879274a1 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -506,6 +506,12 @@ mysqltest_32753@localhost
set session sql_mode=@OLD_SQL_MODE;
flush privileges;
drop user mysqltest_32753@localhost;
+SET @org_mode=@@sql_mode;
+SET @@sql_mode='traditional';
+SELECT @@sql_mode LIKE '%NO_ENGINE_SUBSTITUTION%';
+@@sql_mode LIKE '%NO_ENGINE_SUBSTITUTION%'
+1
+SET sql_mode=@org_mode;
DROP TABLE IF EXISTS t1,t2;
CREATE USER 'user_PCTFL'@'localhost' identified by 'PWD';
CREATE USER 'user_no_PCTFL'@'localhost' identified by 'PWD';
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
index a9e0d7f457d..897c9072203 100644
--- a/mysql-test/r/strict.result
+++ b/mysql-test/r/strict.result
@@ -2,7 +2,7 @@ set @org_mode=@@sql_mode;
set @@sql_mode='ansi,traditional';
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (col1 date);
INSERT INTO t1 VALUES('2004-01-01'),('2004-02-29');
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index e00946a1b9e..6325dc4f2fc 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-ERROR HY000: Incorrect usage of PROCEDURE and subquery
+ERROR HY000: Incorrect parameters to procedure 'ANALYSE'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
ERROR 42S22: Unknown column 'a' in 'field list'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -4412,8 +4412,7 @@ FROM t1
WHERE a = 230;
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
-2 DEPENDENT SUBQUERY st1 index NULL a 5 NULL 2 Using index
-2 DEPENDENT SUBQUERY st2 index b b 5 NULL 2 Using where; Using index; Using join buffer
+2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
FROM t1
WHERE a = 230;
@@ -4837,4 +4836,18 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INTO @v )' at line 1
DROP TABLE t1, t2;
+CREATE TABLE t1 (a ENUM('rainbow'));
+INSERT INTO t1 VALUES (),(),(),(),();
+SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID()));
+1
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGBLOB);
+INSERT INTO t1 SET a = 'aaaa';
+INSERT INTO t1 SET a = 'aaaa';
+SELECT 1 FROM t1 GROUP BY
+(SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1);
+1
+1
+DROP TABLE t1;
End of 5.1 tests.
diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result
index f20ae6a31be..3a0576768b2 100644
--- a/mysql-test/r/subselect3.result
+++ b/mysql-test/r/subselect3.result
@@ -895,3 +895,72 @@ 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;
+#
+# BUG#48177 - SELECTs with NOT IN subqueries containing NULL
+# values return too many records
+#
+CREATE TABLE t1 (
+i1 int DEFAULT NULL,
+i2 int DEFAULT NULL
+) ;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, 3);
+INSERT INTO t1 VALUES (4, NULL);
+INSERT INTO t1 VALUES (4, 0);
+INSERT INTO t1 VALUES (NULL, NULL);
+CREATE TABLE t2 (
+i1 int DEFAULT NULL,
+i2 int DEFAULT NULL
+) ;
+INSERT INTO t2 VALUES (4, NULL);
+INSERT INTO t2 VALUES (5, 0);
+
+Data in t1
+SELECT i1, i2 FROM t1;
+i1 i2
+1 NULL
+2 3
+4 NULL
+4 0
+NULL NULL
+
+Data in subquery (should be filtered out)
+SELECT i1, i2 FROM t2 ORDER BY i1;
+i1 i2
+4 NULL
+5 0
+FLUSH STATUS;
+
+SELECT i1, i2
+FROM t1
+WHERE (i1, i2)
+NOT IN (SELECT i1, i2 FROM t2);
+i1 i2
+1 NULL
+2 3
+
+# Check that the subquery only has to be evaluated once
+# for all-NULL values even though there are two (NULL,NULL) records
+# Baseline:
+SHOW STATUS LIKE '%Handler_read_rnd_next';
+Variable_name Value
+Handler_read_rnd_next 17
+
+INSERT INTO t1 VALUES (NULL, NULL);
+FLUSH STATUS;
+
+SELECT i1, i2
+FROM t1
+WHERE (i1, i2)
+NOT IN (SELECT i1, i2 FROM t2);
+i1 i2
+1 NULL
+2 3
+
+# Handler_read_rnd_next should be one more than baseline
+# (read record from t1, but do not read from t2)
+SHOW STATUS LIKE '%Handler_read_rnd_next';
+Variable_name Value
+Handler_read_rnd_next 18
+DROP TABLE t1,t2;
+End of 5.1 tests
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index e252331cd1a..679e50fcad9 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -110,6 +110,7 @@ user CREATE TABLE `user` (
`Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
+ `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '',
`ssl_cipher` blob NOT NULL,
`x509_issuer` blob NOT NULL,
@@ -161,7 +162,7 @@ procs_priv CREATE TABLE `procs_priv` (
`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
`User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '',
- `Routine_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',
+ `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
`Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL,
`Grantor` char(77) COLLATE utf8_bin NOT NULL DEFAULT '',
`Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '',
@@ -201,7 +202,7 @@ proc CREATE TABLE `proc` (
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
- `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
+ `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 000b08113c1..1a6494e03ad 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -2088,3 +2088,30 @@ SELECT * FROM t2;
a b
DROP TABLE t1, t2;
End of 5.1 tests.
+#
+# Bug#34453 Can't change size of file (Errcode: 1224)
+#
+DROP TRIGGER IF EXISTS t1_bi;
+DROP TRIGGER IF EXISTS t1_bd;
+DROP TABLE IF EXISTS t1;
+DROP TEMPORARY TABLE IF EXISTS t2;
+CREATE TABLE t1 (s1 INT);
+CREATE TEMPORARY TABLE t2 (s1 INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (0);
+CREATE TRIGGER t1_bd BEFORE DELETE ON t1 FOR EACH ROW DELETE FROM t2;
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 VALUES (0);
+SELECT * FROM t1;
+s1
+0
+0
+SELECT * FROM t2;
+s1
+0
+0
+# Reported to give ERROR 14 (HY000):
+# Can't change size of file (Errcode: 1224)
+# on Windows
+DELETE FROM t1;
+DROP TABLE t1;
+DROP TEMPORARY TABLE t2;
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 76c5ea8f756..67898b7f335 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -3,13 +3,13 @@ SET SQL_WARNINGS=1;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
datatype_id int(11) DEFAULT '0' NOT NULL,
-minvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
-maxvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
+min_value decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
+max_value decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
valuename varchar(20),
forecolor int(11),
backcolor int(11),
PRIMARY KEY (id),
-UNIQUE datatype_id (datatype_id, minvalue, maxvalue)
+UNIQUE datatype_id (datatype_id, min_value, max_value)
);
INSERT INTO t1 VALUES ( '1', '4', '0.0000000000', '0.0000000000', 'Ei saja', '0', '16776960');
INSERT INTO t1 VALUES ( '2', '4', '1.0000000000', '1.0000000000', 'Sajab', '16777215', '255');
@@ -143,12 +143,12 @@ INSERT INTO t1 VALUES ( '139', '21', '326.0000000000', '326.0000000000', 'Lumine
INSERT INTO t1 VALUES ( '143', '16', '-4.9000000000', '-0.1000000000', '', NULL, '15774720');
INSERT INTO t1 VALUES ( '145', '15', '0.0000000000', '1.9000000000', '', '0', '16769024');
INSERT INTO t1 VALUES ( '146', '16', '0.0000000000', '1.9000000000', '', '0', '16769024');
-select * from t1 where minvalue<=1 and maxvalue>=-1 and datatype_id=16;
-id datatype_id minvalue maxvalue valuename forecolor backcolor
+select * from t1 where min_value<=1 and max_value>=-1 and datatype_id=16;
+id datatype_id min_value max_value valuename forecolor backcolor
143 16 -4.9000000000 -0.1000000000 NULL 15774720
146 16 0.0000000000 1.9000000000 0 16769024
-select * from t1 where minvalue<=-1 and maxvalue>=-1 and datatype_id=16;
-id datatype_id minvalue maxvalue valuename forecolor backcolor
+select * from t1 where min_value<=-1 and max_value>=-1 and datatype_id=16;
+id datatype_id min_value max_value valuename forecolor backcolor
143 16 -4.9000000000 -0.1000000000 NULL 15774720
drop table t1;
create table t1 (a decimal(10,2));
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index 1ad46821bb7..ed10fa5d67f 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -1495,9 +1495,9 @@ CREATE TABLE t1 (a int DEFAULT NULL, b int DEFAULT NULL);
INSERT INTO t1 VALUES (3,30), (1,10), (2,10);
SELECT a+CAST(1 AS decimal(65,30)) AS aa, SUM(b) FROM t1 GROUP BY aa;
aa SUM(b)
-2.00000000000000000000000000000 10
-3.00000000000000000000000000000 10
-4.00000000000000000000000000000 30
+2.000000000000000000000000000000 10
+3.000000000000000000000000000000 10
+4.000000000000000000000000000000 30
SELECT a+CAST(1 AS decimal(65,31)) AS aa, SUM(b) FROM t1 GROUP BY aa;
ERROR 42000: Too big scale 31 specified for column '1'. Maximum is 30.
DROP TABLE t1;
@@ -1521,13 +1521,13 @@ f1
DROP TABLE t1;
CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1;
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
+Warning 1264 Out of range value for column 'f1' at row 1
DESC t1;
Field Type Null Key Default Extra
-f1 decimal(65,20) NO 0.00000000000000000000
+f1 decimal(65,30) NO 0.000000000000000000000000000000
SELECT f1 FROM t1;
f1
-123451234512345123451234512345123451234512345.67890678906789067891
+99999999999999999999999999999999999.999999999999999999999999999999
DROP TABLE t1;
select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 *
1.01500000 * 1.01500000 * 0.99500000);
@@ -1595,7 +1595,7 @@ Warnings:
Note 1265 Data truncated for column 'my_col' at row 1
DESCRIBE t1;
Field Type Null Key Default Extra
-my_col decimal(32,30) NO 0.000000000000000000000000000000
+my_col decimal(65,30) NO 0.000000000000000000000000000000
SELECT my_col FROM t1;
my_col
1.123456789123456789123456789123
@@ -1625,212 +1625,8 @@ Warnings:
Note 1265 Data truncated for column 'my_col' at row 1
DESCRIBE t1;
Field Type Null Key Default Extra
-my_col decimal(30,30) YES NULL
+my_col decimal(65,30) YES NULL
SELECT my_col FROM t1;
my_col
0.012345687012345687012345687012
DROP TABLE t1;
-#
-# Bug#45261: Crash, stored procedure + decimal
-#
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 SELECT
-/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001
-AS c1;
-Warnings:
-Warning 1264 Out of range value for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,0) NO 0
-SELECT * FROM t1;
-c1
-99999999999999999999999999999999999999999999999999999999999999999
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.
-AS c1;
-Warnings:
-Warning 1264 Out of range value for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,0) NO 0
-SELECT * FROM t1;
-c1
-99999999999999999999999999999999999999999999999999999999999999999
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */
-AS c1;
-Warnings:
-Warning 1264 Out of range value for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,0) NO 0
-SELECT * FROM t1;
-c1
-99999999999999999999999999999999999999999999999999999999999999999
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
-AS c1;
-Warnings:
-Warning 1292 Truncated incorrect DECIMAL value: ''
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,0) NO 0
-SELECT * FROM t1;
-c1
-99999999999999999999999999999999999999999999999999999999999999999
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */
-AS c1;
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,25) NO 0.0000000000000000000000000
-SELECT * FROM t1;
-c1
-1000000000000000000000000000000000000001.1000000000000000000000000
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */
-AS c1;
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(31,30) NO 0.000000000000000000000000000000
-SELECT * FROM t1;
-c1
-1.100000000000000000000000000000
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
-AS c1;
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(31,30) NO 0.000000000000000000000000000000
-SELECT * FROM t1;
-c1
-1.100000000000000000000000000000
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
-AS c1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(30,30) NO 0.000000000000000000000000000000
-SELECT * FROM t1;
-c1
-0.100000000000000000000000000000
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */
-AS c1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,20) NO 0.00000000000000000000
-SELECT * FROM t1;
-c1
-123456789012345678901234567890123456789012345.12345678901234567890
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */
-AS c1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,0) NO 0
-SELECT * FROM t1;
-c1
-12345678901234567890123456789012345678901234567890123456789012345
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */
-AS c1;
-Warnings:
-Warning 1264 Out of range value for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,0) NO 0
-SELECT * FROM t1;
-c1
-99999999999999999999999999999999999999999999999999999999999999999
-DROP TABLE t1;
-CREATE TABLE t1 SELECT
-.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */
-AS c1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(30,30) NO 0.000000000000000000000000000000
-SELECT * FROM t1;
-c1
-0.123456789012345678901234567890
-DROP TABLE t1;
-CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(33,30) NO 0.000000000000000000000000000000
-SELECT * FROM t1;
-c1
-123.123456789012345678901234567890
-DROP TABLE t1;
-CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1;
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,29) NO 0.00000000000000000000000000000
-SELECT * FROM t1;
-c1
-2.10000000000000000000000000000
-DROP TABLE t1;
-#
-# Test that the integer and decimal parts are properly calculated.
-#
-CREATE TABLE t1 (a DECIMAL(30,30));
-INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
-CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 4
-DESC t2;
-Field Type Null Key Default Extra
-c1 decimal(32,30) YES NULL
-DROP TABLE t1,t2;
-CREATE TABLE t1 (a DECIMAL(30,30));
-INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
-CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-Note 1265 Data truncated for column 'c1' at row 2
-Note 1265 Data truncated for column 'c1' at row 3
-DESC t2;
-Field Type Null Key Default Extra
-c1 decimal(32,30) YES NULL
-DROP TABLE t1,t2;
-CREATE TABLE t1 (a DECIMAL(30,30));
-INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
-CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1;
-Warnings:
-Note 1265 Data truncated for column 'c1' at row 1
-DESC t2;
-Field Type Null Key Default Extra
-c1 decimal(31,30) YES NULL
-DROP TABLE t1,t2;
-#
-# Test that variables get maximum precision.
-#
-SET @decimal= 1.1;
-CREATE TABLE t1 SELECT @decimal AS c1;
-DESC t1;
-Field Type Null Key Default Extra
-c1 decimal(65,30) YES NULL
-SELECT * FROM t1;
-c1
-1.100000000000000000000000000000
-DROP TABLE t1;
diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result
index 96042a91bae..6b614960422 100644
--- a/mysql-test/r/type_varchar.result
+++ b/mysql-test/r/type_varchar.result
@@ -489,3 +489,23 @@ Warnings:
Warning 1292 Truncated incorrect INTEGER value: '1a'
Warning 1292 Truncated incorrect INTEGER value: 't'
DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(16));
+INSERT INTO t1 VALUES ('5'), ('s'), ('');
+SELECT 5 = a FROM t1;
+5 = a
+1
+0
+0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 's'
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(16));
+INSERT INTO t1 VALUES ('5'), ('s'), ('');
+SELECT 5 = a FROM t1;
+5 = a
+1
+0
+0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 's '
+DROP TABLE t1;
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index 7a51649fac5..d859579e835 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -503,3 +503,14 @@ ERROR HY000: Recursive stored functions and triggers are not allowed.
DROP TABLE t1;
DROP FUNCTION f1;
End of 5.0 tests
+#
+# Bug #47919 assert in open_table during ALTER temporary table
+#
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1));
+CREATE TEMPORARY TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+ALTER TABLE t2 COMMENT = 'ABC';
+UPDATE t2, t1 SET t2.f1 = 2, t1.f1 = 9;
+ALTER TABLE t2 COMMENT = 'DEF';
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result
index a9d4164cda4..65fbf2d87b6 100644
--- a/mysql-test/r/view_grant.result
+++ b/mysql-test/r/view_grant.result
@@ -799,12 +799,12 @@ CREATE USER u29908_1@localhost;
CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1;
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
SELECT f1 FROM t1;
-GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
-GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
+GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
+GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
CREATE USER u29908_2@localhost;
-GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
-GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
+GRANT SELECT, DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
+GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
ALTER VIEW v1 AS SELECT f2 FROM t1;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
@@ -1218,3 +1218,22 @@ Warnings:
Note 1449 The user specified as a definer ('no_such_user'@'no_such_host') does not exist
DROP TABLE t1;
DROP VIEW v1;
+#
+# Bug #46019: ERROR 1356 When selecting from within another
+# view that has Group By
+#
+CREATE DATABASE mysqltest1;
+USE mysqltest1;
+CREATE TABLE t1 (a INT);
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT a FROM t1 GROUP BY a;
+CREATE SQL SECURITY INVOKER VIEW v2 AS SELECT a FROM v1;
+CREATE USER mysqluser1;
+GRANT SELECT ON TABLE t1 TO mysqluser1;
+GRANT SELECT, SHOW VIEW ON TABLE v1 TO mysqluser1;
+GRANT SELECT, SHOW VIEW ON TABLE v2 TO mysqluser1;
+SELECT a FROM v1;
+a
+SELECT a FROM v2;
+a
+DROP USER mysqluser1;
+DROP DATABASE mysqltest1;
diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result
index a597806d897..d23c8e672b0 100644
--- a/mysql-test/r/xa.result
+++ b/mysql-test/r/xa.result
@@ -89,3 +89,28 @@ xa start 'a';
xa end 'a';
xa prepare 'a';
xa commit 'a';
+CREATE TABLE t1(a INT, KEY(a)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1),(2);
+BEGIN;
+UPDATE t1 SET a=3 WHERE a=1;
+BEGIN;
+UPDATE t1 SET a=4 WHERE a=2;
+UPDATE t1 SET a=5 WHERE a=2;
+UPDATE t1 SET a=5 WHERE a=1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+ROLLBACK;
+ROLLBACK;
+BEGIN;
+UPDATE t1 SET a=3 WHERE a=1;
+XA START 'xid1';
+UPDATE t1 SET a=4 WHERE a=2;
+UPDATE t1 SET a=5 WHERE a=2;
+UPDATE t1 SET a=5 WHERE a=1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+XA END 'xid1';
+ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
+XA ROLLBACK 'xid1';
+XA START 'xid1';
+XA END 'xid1';
+XA ROLLBACK 'xid1';
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result b/mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result
new file mode 100644
index 00000000000..036ccf131bb
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result
@@ -0,0 +1,50 @@
+RESET MASTER;
+CREATE TABLE t1 (a int);
+### assertion: index file contains regular entries
+SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
+SELECT @index;
+@index
+master-bin.000001
+
+### assertion: show original binlogs
+show binary logs;
+Log_name File_size
+master-bin.000001 #
+### assertion: binlog contents from regular entries
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a int)
+FLUSH LOGS;
+### assertion: index file contains renamed binlog and the new one
+SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
+SELECT @index;
+@index
+master-bin-b34582.000001
+master-bin.000002
+
+### assertion: original binlog content still exists, despite we
+### renamed and changed the index file
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin-b34582.000001 # Query # # use `test`; CREATE TABLE t1 (a int)
+### assertion: user changed binlog index shows correct entries
+show binary logs;
+Log_name File_size
+master-bin-b34582.000001 #
+master-bin.000002 #
+DROP TABLE t1;
+### assertion: purging binlogs up to binlog created after instrumenting index file should work
+PURGE BINARY LOGS TO 'master-bin.000002';
+### assertion: show binary logs should only contain latest binlog
+show binary logs;
+Log_name File_size
+master-bin.000002 #
+### assertion: assert that binlog files were indeed purged (using file_exists calls)
+### assertion: assert that not purged binlog file exists
+### assertion: show index file contents and these should match show binary logs issued above
+SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index');
+SELECT @index;
+@index
+master-bin.000002
+
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
index 0a6ff1d4400..75c088e595d 100644
--- a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
+++ b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
@@ -19,6 +19,7 @@ DROP TABLE IF EXISTS tmp2, t;
SELECT GET_LOCK("a",10);
GET_LOCK("a",10)
1
+USE test;
SELECT GET_LOCK("a",10);
GET_LOCK("a",10)
1
diff --git a/mysql-test/suite/binlog/r/binlog_stm_do_db.result b/mysql-test/suite/binlog/r/binlog_stm_do_db.result
new file mode 100644
index 00000000000..ab4ba7cdca1
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_stm_do_db.result
@@ -0,0 +1,42 @@
+SET @old_isolation_level= @@session.tx_isolation;
+SET @@session.tx_isolation= 'READ-COMMITTED';
+CREATE DATABASE b42829;
+use b42829;
+CREATE TABLE t1 (x int, y int) engine=InnoDB;
+CREATE TABLE t2 (x int, y int) engine=InnoDB;
+CREATE DATABASE b42829_filtered;
+use b42829_filtered;
+CREATE TABLE t1 (x int, y int) engine=InnoDB;
+CREATE TABLE t2 (x int, y int) engine=InnoDB;
+SET @@session.sql_log_bin= 0;
+INSERT INTO b42829_filtered.t1 VALUES (100,100);
+INSERT INTO b42829.t1 VALUES (100,100);
+SET @@session.sql_log_bin= 1;
+### assertion: the inserts will not raise log error because
+### binlog-do-db is filtering used database
+INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
+INSERT INTO t1 SELECT * FROM t2;
+### assertion: assert that despite updating a not filtered
+### database this wont trigger an error as the
+### used database is the filtered one.
+UPDATE b42829_filtered.t1 ft1, b42829.t1 nft1 SET ft1.x=1, nft1.x=2;
+use b42829;
+### assertion: the statements *will* raise log error because
+### binlog-do-db is not filtering used database
+BEGIN;
+INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
+ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
+UPDATE b42829_filtered.t1 ft1, b42829.t1 nft1 SET ft1.x=1, nft1.x=2;
+ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
+INSERT INTO t1 SELECT * FROM t2;
+ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
+COMMIT;
+### assertion: filtered events did not make into the binlog
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # CREATE DATABASE b42829
+master-bin.000001 # Query # # use `b42829`; CREATE TABLE t1 (x int, y int) engine=InnoDB
+master-bin.000001 # Query # # use `b42829`; CREATE TABLE t2 (x int, y int) engine=InnoDB
+DROP DATABASE b42829;
+DROP DATABASE b42829_filtered;
+SET @@session.tx_isolation= @old_isolation_level;
diff --git a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
index 8bbf1bccc63..19ddcf49080 100644
--- a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
+++ b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
@@ -19,6 +19,7 @@ DROP TABLE IF EXISTS tmp2, t;
SELECT GET_LOCK("a",10);
GET_LOCK("a",10)
1
+USE test;
SELECT GET_LOCK("a",10);
GET_LOCK("a",10)
1
diff --git a/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test
new file mode 100644
index 00000000000..84c83687486
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test
@@ -0,0 +1,114 @@
+# BUG#34582: FLUSH LOGS does not close and reopen the binlog index
+# file
+#
+# WHAT
+# ====
+#
+# We want to test that FLUSH LOGS closes and reopens binlog index
+# file.
+#
+# HOW
+# ===
+#
+# PREPARE:
+# 1. create some binlog events
+# 2. show index content, binlog events and binlog contents
+# for mysql-bin.000001
+# 3. copy the mysql-bin.000001 to mysql-bin-b34582.000001
+# 4. change the index file so that mysql-bin.000001 is replaced
+# with mysql-bin-b34582.000001
+# 5. FLUSH the logs so that new index is closed and reopened
+#
+# ASSERTIONS:
+# 1. index file contents shows mysql-bin-b34582.000001 and
+# mysql-bin.000002
+# 1. show binary logs shows current index entries
+# 2. binlog contents for mysql-bin-b34582.000001 are displayed
+# 3. Purge binlogs up to the latest one succeeds
+# 4. SHOW BINARY LOGS presents the latest one only after purging
+# 5. Purged binlogs files don't exist in the filesystem
+# 6. Not purged binlog file exists in the filesystem
+#
+# CLEAN UP:
+# 1. RESET MASTER
+#
+
+-- source include/have_log_bin.inc
+
+RESET MASTER;
+
+-- let $datadir= `SELECT @@datadir`
+-- let $index=$datadir/master-bin.index
+-- chmod 0644 $index
+
+# action: issue one command so that binlog gets some event
+CREATE TABLE t1 (a int);
+
+-- echo ### assertion: index file contains regular entries
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
+--echo ### assertion: show original binlogs
+-- source include/show_binary_logs.inc
+
+--echo ### assertion: binlog contents from regular entries
+-- source include/show_binlog_events.inc
+
+# action: copy binlogs to other names and change entries in index file
+-- copy_file $datadir/master-bin.000001 $datadir/master-bin-b34582.000001
+let INDEX_FILE=$index;
+perl;
+$file= $ENV{'INDEX_FILE'};
+open(FILE, ">$file") || die "Unable to open $file.";
+truncate(FILE,0);
+close ($file);
+EOF
+
+-- append_file $index
+master-bin-b34582.000001
+EOF
+
+# action: should cause rotation, and creation of new binlogs
+FLUSH LOGS;
+
+# file is not used anymore - remove it (mysql closed on flush logs).
+-- remove_file $datadir/master-bin.000001
+
+-- echo ### assertion: index file contains renamed binlog and the new one
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
+-- echo ### assertion: original binlog content still exists, despite we
+-- echo ### renamed and changed the index file
+-- source include/show_binlog_events.inc
+
+-- echo ### assertion: user changed binlog index shows correct entries
+-- source include/show_binary_logs.inc
+
+DROP TABLE t1;
+
+-- echo ### assertion: purging binlogs up to binlog created after instrumenting index file should work
+-- let $current_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
+-- eval PURGE BINARY LOGS TO '$current_binlog'
+
+-- echo ### assertion: show binary logs should only contain latest binlog
+-- source include/show_binary_logs.inc
+
+-- echo ### assertion: assert that binlog files were indeed purged (using file_exists calls)
+-- error 1
+-- file_exists $datadir/master-bin-b34852.000001
+
+-- echo ### assertion: assert that not purged binlog file exists
+-- file_exists $datadir/$current_binlog
+
+-- echo ### assertion: show index file contents and these should match show binary logs issued above
+-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-- eval SET @index=LOAD_FILE('$index')
+-- replace_regex /\.[\\\/]master/master/
+SELECT @index;
+
+RESET MASTER;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt
new file mode 100644
index 00000000000..e2cfcb299cf
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt
@@ -0,0 +1 @@
+--binlog-do-db=b42829
diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db.test b/mysql-test/suite/binlog/t/binlog_stm_do_db.test
new file mode 100644
index 00000000000..858bc8cc683
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_do_db.test
@@ -0,0 +1,90 @@
+# BUG#42829: binlogging enabled for all schemas regardless of
+# binlog-db-db / binlog-ignore-db
+#
+# WHAT
+# ====
+#
+# We want to test whether filtered events from binlog will cause
+# raising an error mentioning that statement is unable to be logged or
+# not, when:
+#
+# 1. isolation level READ-COMMITTED; AND
+#
+# 2. using InnoDB engine; AND
+#
+# 3. using SBL (in which case InnoDB will only allow RBL).
+#
+# HOW
+# ===
+#
+# The test is implemented as follows:
+#
+# i) set tx_isolation to read-committed.
+#
+# ii) create two databases (one filtered other not - using
+# binlog-do-db)
+#
+# iii) Create statements that are to be filtered on filtered db
+#
+# - At this point, before fix, an error would be raised
+#
+# iv) do the same thing for not the filtered database and check
+# that events throw an error:
+#
+# - Error: ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+#
+
+-- source include/have_log_bin.inc
+-- source include/have_innodb.inc
+-- source include/have_binlog_format_statement.inc
+
+SET @old_isolation_level= @@session.tx_isolation;
+SET @@session.tx_isolation= 'READ-COMMITTED';
+
+-- let $engine= InnoDB
+-- let $filtered= b42829_filtered
+-- let $not_filtered= b42829
+
+-- eval CREATE DATABASE $not_filtered
+-- eval use $not_filtered
+-- eval CREATE TABLE t1 (x int, y int) engine=$engine
+-- eval CREATE TABLE t2 (x int, y int) engine=$engine
+
+-- eval CREATE DATABASE $filtered
+-- eval use $filtered
+-- eval CREATE TABLE t1 (x int, y int) engine=$engine
+-- eval CREATE TABLE t2 (x int, y int) engine=$engine
+
+SET @@session.sql_log_bin= 0;
+-- eval INSERT INTO $filtered.t1 VALUES (100,100)
+-- eval INSERT INTO $not_filtered.t1 VALUES (100,100)
+SET @@session.sql_log_bin= 1;
+
+-- echo ### assertion: the inserts will not raise log error because
+-- echo ### binlog-do-db is filtering used database
+INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
+INSERT INTO t1 SELECT * FROM t2;
+
+-- echo ### assertion: assert that despite updating a not filtered
+-- echo ### database this wont trigger an error as the
+-- echo ### used database is the filtered one.
+-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2
+
+-- eval use $not_filtered
+-- echo ### assertion: the statements *will* raise log error because
+-- echo ### binlog-do-db is not filtering used database
+BEGIN;
+-- error ER_BINLOG_LOGGING_IMPOSSIBLE
+INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
+-- error ER_BINLOG_LOGGING_IMPOSSIBLE
+-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2
+-- error ER_BINLOG_LOGGING_IMPOSSIBLE
+INSERT INTO t1 SELECT * FROM t2;
+COMMIT;
+
+-- echo ### assertion: filtered events did not make into the binlog
+source include/show_binlog_events.inc;
+
+-- eval DROP DATABASE $not_filtered
+-- eval DROP DATABASE $filtered
+SET @@session.tx_isolation= @old_isolation_level;
diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result
index ca68e92aaa9..b19252e4dd7 100644
--- a/mysql-test/suite/funcs_1/r/innodb_func_view.result
+++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result
@@ -2096,6 +2096,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varbinary_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varbinary_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2108,6 +2111,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -2158,6 +2164,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varchar_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varchar_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2170,6 +2179,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3373,8 +3385,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3390,8 +3405,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3455,8 +3473,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3472,8 +3493,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/innodb_storedproc_07.result b/mysql-test/suite/funcs_1/r/innodb_storedproc_07.result
index 5a2c0bb6bdf..a520bdfac36 100644
--- a/mysql-test/suite/funcs_1/r/innodb_storedproc_07.result
+++ b/mysql-test/suite/funcs_1/r/innodb_storedproc_07.result
@@ -80,7 +80,7 @@ CREATE TABLE result (f1 text(200), f2 char(20));
set @@sql_mode='traditional';
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp1()
BEGIN
declare a tinyint;
@@ -97,7 +97,7 @@ END if;
END//
SHOW CREATE PROCEDURE sp1;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
+sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
BEGIN
declare a tinyint;
declare count_ int default 1;
@@ -117,10 +117,10 @@ Variable_name Value
sql_mode
CALL sp1();
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
SELECT * from result;
f1 f2
-STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER value restored
+STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION value restored
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
sql_mode
@@ -142,7 +142,7 @@ DROP PROCEDURE IF EXISTS sp2;
... show initial value
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp2()
BEGIN
SET @@sql_mode='MAXDB';
@@ -150,7 +150,7 @@ SHOW VARIABLES LIKE 'sql_mode';
END//
SHOW CREATE PROCEDURE sp2;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
+sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
BEGIN
SET @@sql_mode='MAXDB';
SHOW VARIABLES LIKE 'sql_mode';
@@ -158,7 +158,7 @@ END latin1 latin1_swedish_ci latin1_swedish_ci
... show value prior calling procedure
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
... call procedure that changes sql_mode
CALL sp2();
Variable_name Value
@@ -166,7 +166,7 @@ sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,MAXDB,NO_KEY_OPTIONS,NO_TABLE_
... check whether old value is re-set
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
DROP PROCEDURE sp2;
--source suite/funcs_1/storedproc/cleanup_sp_tb.inc
diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_03.result b/mysql-test/suite/funcs_1/r/innodb_trig_03.result
index b02fba0f38d..012977ae4a3 100644
--- a/mysql-test/suite/funcs_1/r/innodb_trig_03.result
+++ b/mysql-test/suite/funcs_1/r/innodb_trig_03.result
@@ -77,7 +77,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke TRIGGER on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER on *.* to test_yesprivs@localhost;
grant SELECT on priv_db.t1 to test_yesprivs@localhost;
@@ -155,7 +155,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke UPDATE on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -169,7 +169,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
select f1 from t1 order by f1;
f1
insert 3.5.3.2-no
@@ -401,7 +401,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke SELECT on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, SELECT on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -415,7 +415,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
create trigger trg5a_1 before INSERT on t1 for each row
set @test_var = new.f1;
set @test_var = 'before trig 3.5.3.8-1a';
diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_03e.result b/mysql-test/suite/funcs_1/r/innodb_trig_03e.result
index 25edc0f68bb..bc3f7daf5bc 100644
--- a/mysql-test/suite/funcs_1/r/innodb_trig_03e.result
+++ b/mysql-test/suite/funcs_1/r/innodb_trig_03e.result
@@ -562,7 +562,7 @@ trig 1_1-yes
revoke TRIGGER on *.* from test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
connect(localhost,test_yesprivs,PWD,test,MASTER_MYPORT,MASTER_MYSOCK);
select current_user;
current_user
@@ -609,7 +609,7 @@ root@localhost
grant TRIGGER on priv_db.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost'
trigger privilege on db level for create:
diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result
index a335e135a4f..9511aa973e5 100644
--- a/mysql-test/suite/funcs_1/r/innodb_views.result
+++ b/mysql-test/suite/funcs_1/r/innodb_views.result
@@ -3546,11 +3546,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or REPLACE AS Select * from tb2 my_table' at line 1
CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH LOCAL CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
SELECT * FROM tb2 my_table CREATE VIEW As v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE VIEW As v1' at line 1
@@ -3580,7 +3580,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH CASCADED' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION;
@@ -3609,7 +3609,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH LOCAL' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION;
@@ -22843,6 +22843,9 @@ SELECT * FROM v1 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT SQRT('DEF');
SQRT('DEF')
0
@@ -22863,7 +22866,12 @@ SELECT * FROM v2 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -22871,6 +22879,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -22878,6 +22888,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v2;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result
index 47eb14a459f..e10c775c227 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result
@@ -137,7 +137,7 @@ def information_schema PARTITIONS NODEGROUP 24 NO varchar 12 36 NULL NULL utf8
def information_schema PARTITIONS PARTITION_COMMENT 23 NO varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
def information_schema PARTITIONS PARTITION_DESCRIPTION 12 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
def information_schema PARTITIONS PARTITION_EXPRESSION 10 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
-def information_schema PARTITIONS PARTITION_METHOD 8 NULL YES varchar 12 36 NULL NULL utf8 utf8_general_ci varchar(12) select
+def information_schema PARTITIONS PARTITION_METHOD 8 NULL YES varchar 18 54 NULL NULL utf8 utf8_general_ci varchar(18) select
def information_schema PARTITIONS PARTITION_NAME 4 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
def information_schema PARTITIONS PARTITION_ORDINAL_POSITION 6 NULL YES bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
def information_schema PARTITIONS SUBPARTITION_EXPRESSION 11 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
@@ -192,7 +192,7 @@ def information_schema ROUTINES LAST_ALTERED 17 0000-00-00 00:00:00 NO datetime
def information_schema ROUTINES PARAMETER_STYLE 11 NO varchar 8 24 NULL NULL utf8 utf8_general_ci varchar(8) select
def information_schema ROUTINES ROUTINE_BODY 7 NO varchar 8 24 NULL NULL utf8 utf8_general_ci varchar(8) select
def information_schema ROUTINES ROUTINE_CATALOG 2 NO varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
-def information_schema ROUTINES ROUTINE_COMMENT 19 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
+def information_schema ROUTINES ROUTINE_COMMENT 19 NULL NO longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
def information_schema ROUTINES ROUTINE_DEFINITION 8 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
def information_schema ROUTINES ROUTINE_NAME 4 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
def information_schema ROUTINES ROUTINE_SCHEMA 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
@@ -487,7 +487,7 @@ NULL information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT bigint NU
3.0000 information_schema PARTITIONS SUBPARTITION_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
NULL information_schema PARTITIONS PARTITION_ORDINAL_POSITION bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema PARTITIONS SUBPARTITION_ORDINAL_POSITION bigint NULL NULL NULL NULL bigint(21) unsigned
-3.0000 information_schema PARTITIONS PARTITION_METHOD varchar 12 36 utf8 utf8_general_ci varchar(12)
+3.0000 information_schema PARTITIONS PARTITION_METHOD varchar 18 54 utf8 utf8_general_ci varchar(18)
3.0000 information_schema PARTITIONS SUBPARTITION_METHOD varchar 12 36 utf8 utf8_general_ci varchar(12)
1.0000 information_schema PARTITIONS PARTITION_EXPRESSION longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
1.0000 information_schema PARTITIONS SUBPARTITION_EXPRESSION longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
@@ -552,7 +552,7 @@ NULL information_schema PROCESSLIST TIME int NULL NULL NULL NULL int(7)
NULL information_schema ROUTINES CREATED datetime NULL NULL NULL NULL datetime
NULL information_schema ROUTINES LAST_ALTERED datetime NULL NULL NULL NULL datetime
3.0000 information_schema ROUTINES SQL_MODE varchar 8192 24576 utf8 utf8_general_ci varchar(8192)
-3.0000 information_schema ROUTINES ROUTINE_COMMENT varchar 64 192 utf8 utf8_general_ci varchar(64)
+1.0000 information_schema ROUTINES ROUTINE_COMMENT longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
3.0000 information_schema ROUTINES DEFINER varchar 77 231 utf8 utf8_general_ci varchar(77)
3.0000 information_schema ROUTINES CHARACTER_SET_CLIENT varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema ROUTINES COLLATION_CONNECTION varchar 32 96 utf8 utf8_general_ci varchar(32)
diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
index a7f5c3ce52e..bd548ac0a25 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
@@ -110,7 +110,7 @@ def mysql proc body 11 NULL NO longblob 4294967295 4294967295 NULL NULL NULL NUL
def mysql proc body_utf8 20 NULL YES longblob 4294967295 4294967295 NULL NULL NULL NULL longblob select,insert,update,references
def mysql proc character_set_client 17 NULL YES char 32 96 NULL NULL utf8 utf8_bin char(32) select,insert,update,references
def mysql proc collation_connection 18 NULL YES char 32 96 NULL NULL utf8 utf8_bin char(32) select,insert,update,references
-def mysql proc comment 16 NO char 64 192 NULL NULL utf8 utf8_bin char(64) select,insert,update,references
+def mysql proc comment 16 NULL NO text 65535 65535 NULL NULL utf8 utf8_bin text select,insert,update,references
def mysql proc created 13 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL NULL NULL timestamp on update CURRENT_TIMESTAMP select,insert,update,references
def mysql proc db 1 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
def mysql proc db_collation 19 NULL YES char 32 96 NULL NULL utf8 utf8_bin char(32) select,insert,update,references
@@ -130,7 +130,7 @@ def mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI
def mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references
def mysql procs_priv Host 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references
def mysql procs_priv Proc_priv 7 NO set 27 81 NULL NULL utf8 utf8_general_ci set('Execute','Alter Routine','Grant') select,insert,update,references
-def mysql procs_priv Routine_name 4 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
+def mysql procs_priv Routine_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references
def mysql procs_priv Routine_type 5 NULL NO enum 9 27 NULL NULL utf8 utf8_bin enum('FUNCTION','PROCEDURE') PRI select,insert,update,references
def mysql procs_priv Timestamp 8 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL NULL NULL timestamp on update CURRENT_TIMESTAMP select,insert,update,references
def mysql procs_priv User 3 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references
@@ -180,6 +180,7 @@ def mysql user Alter_priv 17 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('
def mysql user Alter_routine_priv 28 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Create_priv 8 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Create_routine_priv 27 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
+def mysql user Create_tablespace_priv 32 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Create_tmp_table_priv 20 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Create_user_priv 29 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Create_view_priv 25 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -193,10 +194,10 @@ def mysql user Host 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI sele
def mysql user Index_priv 16 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Insert_priv 5 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Lock_tables_priv 21 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
-def mysql user max_connections 38 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
-def mysql user max_questions 36 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
-def mysql user max_updates 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
-def mysql user max_user_connections 39 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
+def mysql user max_connections 39 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
+def mysql user max_questions 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
+def mysql user max_updates 38 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
+def mysql user max_user_connections 40 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
def mysql user Password 3 NO char 41 41 NULL NULL latin1 latin1_bin char(41) select,insert,update,references
def mysql user Process_priv 12 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user References_priv 15 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -207,14 +208,14 @@ def mysql user Select_priv 4 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('
def mysql user Show_db_priv 18 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Show_view_priv 26 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Shutdown_priv 11 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
-def mysql user ssl_cipher 33 NULL NO blob 65535 65535 NULL NULL NULL NULL blob select,insert,update,references
-def mysql user ssl_type 32 NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED') select,insert,update,references
+def mysql user ssl_cipher 34 NULL NO blob 65535 65535 NULL NULL NULL NULL blob select,insert,update,references
+def mysql user ssl_type 33 NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED') select,insert,update,references
def mysql user Super_priv 19 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Trigger_priv 31 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user Update_priv 6 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user User 2 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references
-def mysql user x509_issuer 34 NULL NO blob 65535 65535 NULL NULL NULL NULL blob select,insert,update,references
-def mysql user x509_subject 35 NULL NO blob 65535 65535 NULL NULL NULL NULL blob select,insert,update,references
+def mysql user x509_issuer 35 NULL NO blob 65535 65535 NULL NULL NULL NULL blob select,insert,update,references
+def mysql user x509_subject 36 NULL NO blob 65535 65535 NULL NULL NULL NULL blob select,insert,update,references
##########################################################################
# Show the quotient of CHARACTER_OCTET_LENGTH and CHARACTER_MAXIMUM_LENGTH
##########################################################################
@@ -233,6 +234,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME
1.0000 char latin1 latin1_bin
1.0000 char latin1 latin1_swedish_ci
1.0000 varchar latin1 latin1_swedish_ci
+1.0000 text utf8 utf8_bin
1.0000 mediumtext utf8 utf8_general_ci
1.0000 text utf8 utf8_general_ci
SELECT DISTINCT
@@ -403,7 +405,7 @@ NULL mysql ndb_binlog_index schemaops bigint NULL NULL NULL NULL bigint(20) unsi
NULL mysql proc created timestamp NULL NULL NULL NULL timestamp
NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
3.0000 mysql proc sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
-3.0000 mysql proc comment char 64 192 utf8 utf8_bin char(64)
+1.0000 mysql proc comment text 65535 65535 utf8 utf8_bin text
3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32)
3.0000 mysql proc db_collation char 32 96 utf8 utf8_bin char(32)
@@ -411,7 +413,7 @@ NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp
3.0000 mysql procs_priv Host char 60 180 utf8 utf8_bin char(60)
3.0000 mysql procs_priv Db char 64 192 utf8 utf8_bin char(64)
3.0000 mysql procs_priv User char 16 48 utf8 utf8_bin char(16)
-3.0000 mysql procs_priv Routine_name char 64 192 utf8 utf8_bin char(64)
+3.0000 mysql procs_priv Routine_name char 64 192 utf8 utf8_general_ci char(64)
3.0000 mysql procs_priv Routine_type enum 9 27 utf8 utf8_bin enum('FUNCTION','PROCEDURE')
3.0000 mysql procs_priv Grantor char 77 231 utf8 utf8_bin char(77)
3.0000 mysql procs_priv Proc_priv set 27 81 utf8 utf8_general_ci set('Execute','Alter Routine','Grant')
@@ -489,6 +491,7 @@ NULL mysql time_zone_transition_type Is_DST tinyint NULL NULL NULL NULL tinyint(
3.0000 mysql user Create_user_priv enum 1 3 utf8 utf8_general_ci enum('N','Y')
3.0000 mysql user Event_priv enum 1 3 utf8 utf8_general_ci enum('N','Y')
3.0000 mysql user Trigger_priv enum 1 3 utf8 utf8_general_ci enum('N','Y')
+3.0000 mysql user Create_tablespace_priv enum 1 3 utf8 utf8_general_ci enum('N','Y')
3.0000 mysql user ssl_type enum 9 27 utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED')
1.0000 mysql user ssl_cipher blob 65535 65535 NULL NULL blob
1.0000 mysql user x509_issuer blob 65535 65535 NULL NULL blob
diff --git a/mysql-test/suite/funcs_1/r/is_routines.result b/mysql-test/suite/funcs_1/r/is_routines.result
index c362b6f59d4..8e37b995322 100644
--- a/mysql-test/suite/funcs_1/r/is_routines.result
+++ b/mysql-test/suite/funcs_1/r/is_routines.result
@@ -46,7 +46,7 @@ SECURITY_TYPE varchar(7) NO
CREATED datetime NO 0000-00-00 00:00:00
LAST_ALTERED datetime NO 0000-00-00 00:00:00
SQL_MODE varchar(8192) NO
-ROUTINE_COMMENT varchar(64) NO
+ROUTINE_COMMENT longtext NO NULL
DEFINER varchar(77) NO
CHARACTER_SET_CLIENT varchar(32) NO
COLLATION_CONNECTION varchar(32) NO
@@ -72,7 +72,7 @@ ROUTINES CREATE TEMPORARY TABLE `ROUTINES` (
`CREATED` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`LAST_ALTERED` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`SQL_MODE` varchar(8192) NOT NULL DEFAULT '',
- `ROUTINE_COMMENT` varchar(64) NOT NULL DEFAULT '',
+ `ROUTINE_COMMENT` longtext NOT NULL,
`DEFINER` varchar(77) NOT NULL DEFAULT '',
`CHARACTER_SET_CLIENT` varchar(32) NOT NULL DEFAULT '',
`COLLATION_CONNECTION` varchar(32) NOT NULL DEFAULT '',
@@ -98,7 +98,7 @@ SECURITY_TYPE varchar(7) NO
CREATED datetime NO 0000-00-00 00:00:00
LAST_ALTERED datetime NO 0000-00-00 00:00:00
SQL_MODE varchar(8192) NO
-ROUTINE_COMMENT varchar(64) NO
+ROUTINE_COMMENT longtext NO NULL
DEFINER varchar(77) NO
CHARACTER_SET_CLIENT varchar(32) NO
COLLATION_CONNECTION varchar(32) NO
diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result
index 6d8d6c664c1..cbb794a9a91 100644
--- a/mysql-test/suite/funcs_1/r/is_statistics.result
+++ b/mysql-test/suite/funcs_1/r/is_statistics.result
@@ -214,8 +214,8 @@ def db_datadict_2 t4 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH
SHOW GRANTS FOR 'testuser1'@'localhost';
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
-GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost'
GRANT SELECT ON `db_datadict`.`t1` TO 'testuser1'@'localhost' WITH GRANT OPTION
+GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost'
SHOW GRANTS FOR 'testuser2'@'localhost';
Grants for testuser2@localhost
GRANT USAGE ON *.* TO 'testuser2'@'localhost'
@@ -233,8 +233,8 @@ def db_datadict_2 t3 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH
SHOW GRANTS FOR 'testuser1'@'localhost';
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
-GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost'
GRANT SELECT ON `db_datadict`.`t1` TO 'testuser1'@'localhost' WITH GRANT OPTION
+GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost'
SHOW GRANTS FOR 'testuser2'@'localhost';
ERROR 42000: Access denied for user 'testuser1'@'localhost' to database 'mysql'
# Switch to connection testuser2
diff --git a/mysql-test/suite/funcs_1/r/is_user_privileges.result b/mysql-test/suite/funcs_1/r/is_user_privileges.result
index 1dc9694180e..8f68f8c802d 100644
--- a/mysql-test/suite/funcs_1/r/is_user_privileges.result
+++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result
@@ -76,10 +76,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
#
# Add GRANT OPTION db_datadict.* to testuser1;
GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
@@ -93,10 +93,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Establish connection testuser1 (user=testuser1)
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -105,10 +105,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser1'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -130,10 +130,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
#
# Here <SELECT YES> is shown correctly for testuser1;
@@ -147,10 +147,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -159,10 +159,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser1'@'localhost' def SELECT YES
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 Y N N N N N N N N N Y N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION
@@ -207,10 +207,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -253,10 +253,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -265,10 +265,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser1'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -284,10 +284,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser1'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -309,10 +309,10 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
'testuser3'@'localhost' def USAGE NO
SELECT * FROM mysql.user
WHERE user LIKE 'testuser%' ORDER BY host, user;
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
-localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
-localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections
+localhost testuser1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser2 N Y Y N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
+localhost testuser3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result
index 8b2c2be11e9..eb3d326808f 100644
--- a/mysql-test/suite/funcs_1/r/memory_func_view.result
+++ b/mysql-test/suite/funcs_1/r/memory_func_view.result
@@ -2097,6 +2097,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varbinary_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varbinary_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2109,6 +2112,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -2159,6 +2165,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varchar_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varchar_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2171,6 +2180,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3374,8 +3386,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3391,8 +3406,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3456,8 +3474,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3473,8 +3494,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/memory_storedproc_07.result b/mysql-test/suite/funcs_1/r/memory_storedproc_07.result
index 596b63316ce..2b8d41f963e 100644
--- a/mysql-test/suite/funcs_1/r/memory_storedproc_07.result
+++ b/mysql-test/suite/funcs_1/r/memory_storedproc_07.result
@@ -81,7 +81,7 @@ CREATE TABLE result (f1 text(200), f2 char(20));
set @@sql_mode='traditional';
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp1()
BEGIN
declare a tinyint;
@@ -98,7 +98,7 @@ END if;
END//
SHOW CREATE PROCEDURE sp1;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
+sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
BEGIN
declare a tinyint;
declare count_ int default 1;
@@ -118,10 +118,10 @@ Variable_name Value
sql_mode
CALL sp1();
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
SELECT * from result;
f1 f2
-STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER value restored
+STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION value restored
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
sql_mode
@@ -143,7 +143,7 @@ DROP PROCEDURE IF EXISTS sp2;
... show initial value
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp2()
BEGIN
SET @@sql_mode='MAXDB';
@@ -151,7 +151,7 @@ SHOW VARIABLES LIKE 'sql_mode';
END//
SHOW CREATE PROCEDURE sp2;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
+sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
BEGIN
SET @@sql_mode='MAXDB';
SHOW VARIABLES LIKE 'sql_mode';
@@ -159,7 +159,7 @@ END latin1 latin1_swedish_ci latin1_swedish_ci
... show value prior calling procedure
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
... call procedure that changes sql_mode
CALL sp2();
Variable_name Value
@@ -167,7 +167,7 @@ sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,MAXDB,NO_KEY_OPTIONS,NO_TABLE_
... check whether old value is re-set
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
DROP PROCEDURE sp2;
--source suite/funcs_1/storedproc/cleanup_sp_tb.inc
diff --git a/mysql-test/suite/funcs_1/r/memory_trig_03.result b/mysql-test/suite/funcs_1/r/memory_trig_03.result
index 7f38fd1f182..65bc7deef8c 100644
--- a/mysql-test/suite/funcs_1/r/memory_trig_03.result
+++ b/mysql-test/suite/funcs_1/r/memory_trig_03.result
@@ -78,7 +78,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke TRIGGER on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER on *.* to test_yesprivs@localhost;
grant SELECT on priv_db.t1 to test_yesprivs@localhost;
@@ -156,7 +156,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke UPDATE on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -170,7 +170,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
select f1 from t1 order by f1;
f1
insert 3.5.3.2-no
@@ -402,7 +402,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke SELECT on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, SELECT on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -416,7 +416,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
create trigger trg5a_1 before INSERT on t1 for each row
set @test_var = new.f1;
set @test_var = 'before trig 3.5.3.8-1a';
diff --git a/mysql-test/suite/funcs_1/r/memory_trig_03e.result b/mysql-test/suite/funcs_1/r/memory_trig_03e.result
index 462a8858029..cfbee5f27b7 100644
--- a/mysql-test/suite/funcs_1/r/memory_trig_03e.result
+++ b/mysql-test/suite/funcs_1/r/memory_trig_03e.result
@@ -563,7 +563,7 @@ trig 1_1-yes
revoke TRIGGER on *.* from test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
connect(localhost,test_yesprivs,PWD,test,MASTER_MYPORT,MASTER_MYSOCK);
select current_user;
current_user
@@ -610,7 +610,7 @@ root@localhost
grant TRIGGER on priv_db.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost'
trigger privilege on db level for create:
diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result
index ccbd086b71f..7f3a0efb8b8 100644
--- a/mysql-test/suite/funcs_1/r/memory_views.result
+++ b/mysql-test/suite/funcs_1/r/memory_views.result
@@ -3547,11 +3547,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or REPLACE AS Select * from tb2 my_table' at line 1
CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH LOCAL CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
SELECT * FROM tb2 my_table CREATE VIEW As v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE VIEW As v1' at line 1
@@ -3581,7 +3581,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH CASCADED' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION;
@@ -3610,7 +3610,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH LOCAL' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION;
@@ -22845,6 +22845,9 @@ SELECT * FROM v1 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT SQRT('DEF');
SQRT('DEF')
0
@@ -22865,7 +22868,12 @@ SELECT * FROM v2 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -22873,6 +22881,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -22880,6 +22890,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v2;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result
index 8b2c2be11e9..eb3d326808f 100644
--- a/mysql-test/suite/funcs_1/r/myisam_func_view.result
+++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result
@@ -2097,6 +2097,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varbinary_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varbinary_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2109,6 +2112,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -2159,6 +2165,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varchar_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varchar_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2171,6 +2180,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3374,8 +3386,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3391,8 +3406,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3456,8 +3474,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3473,8 +3494,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/myisam_storedproc_07.result b/mysql-test/suite/funcs_1/r/myisam_storedproc_07.result
index 596b63316ce..2b8d41f963e 100644
--- a/mysql-test/suite/funcs_1/r/myisam_storedproc_07.result
+++ b/mysql-test/suite/funcs_1/r/myisam_storedproc_07.result
@@ -81,7 +81,7 @@ CREATE TABLE result (f1 text(200), f2 char(20));
set @@sql_mode='traditional';
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp1()
BEGIN
declare a tinyint;
@@ -98,7 +98,7 @@ END if;
END//
SHOW CREATE PROCEDURE sp1;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
+sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
BEGIN
declare a tinyint;
declare count_ int default 1;
@@ -118,10 +118,10 @@ Variable_name Value
sql_mode
CALL sp1();
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
SELECT * from result;
f1 f2
-STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER value restored
+STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION value restored
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
sql_mode
@@ -143,7 +143,7 @@ DROP PROCEDURE IF EXISTS sp2;
... show initial value
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp2()
BEGIN
SET @@sql_mode='MAXDB';
@@ -151,7 +151,7 @@ SHOW VARIABLES LIKE 'sql_mode';
END//
SHOW CREATE PROCEDURE sp2;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
+sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
BEGIN
SET @@sql_mode='MAXDB';
SHOW VARIABLES LIKE 'sql_mode';
@@ -159,7 +159,7 @@ END latin1 latin1_swedish_ci latin1_swedish_ci
... show value prior calling procedure
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
... call procedure that changes sql_mode
CALL sp2();
Variable_name Value
@@ -167,7 +167,7 @@ sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,MAXDB,NO_KEY_OPTIONS,NO_TABLE_
... check whether old value is re-set
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
DROP PROCEDURE sp2;
--source suite/funcs_1/storedproc/cleanup_sp_tb.inc
diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_03.result b/mysql-test/suite/funcs_1/r/myisam_trig_03.result
index 7f38fd1f182..65bc7deef8c 100644
--- a/mysql-test/suite/funcs_1/r/myisam_trig_03.result
+++ b/mysql-test/suite/funcs_1/r/myisam_trig_03.result
@@ -78,7 +78,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke TRIGGER on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER on *.* to test_yesprivs@localhost;
grant SELECT on priv_db.t1 to test_yesprivs@localhost;
@@ -156,7 +156,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke UPDATE on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -170,7 +170,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
select f1 from t1 order by f1;
f1
insert 3.5.3.2-no
@@ -402,7 +402,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke SELECT on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, SELECT on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -416,7 +416,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
create trigger trg5a_1 before INSERT on t1 for each row
set @test_var = new.f1;
set @test_var = 'before trig 3.5.3.8-1a';
diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_03e.result b/mysql-test/suite/funcs_1/r/myisam_trig_03e.result
index 104db478638..d21bd176810 100644
--- a/mysql-test/suite/funcs_1/r/myisam_trig_03e.result
+++ b/mysql-test/suite/funcs_1/r/myisam_trig_03e.result
@@ -563,7 +563,7 @@ trig 1_1-yes
revoke TRIGGER on *.* from test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
connect(localhost,test_yesprivs,PWD,test,MASTER_MYPORT,MASTER_MYSOCK);
select current_user;
current_user
@@ -610,7 +610,7 @@ root@localhost
grant TRIGGER on priv_db.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost'
trigger privilege on db level for create:
diff --git a/mysql-test/suite/funcs_1/r/myisam_views.result b/mysql-test/suite/funcs_1/r/myisam_views.result
index 9b07a0ae45b..65ad319d642 100644
--- a/mysql-test/suite/funcs_1/r/myisam_views.result
+++ b/mysql-test/suite/funcs_1/r/myisam_views.result
@@ -4049,11 +4049,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or REPLACE AS Select * from tb2 my_table' at line 1
CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH LOCAL CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
SELECT * FROM tb2 my_table CREATE VIEW As v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE VIEW As v1' at line 1
@@ -4083,7 +4083,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH CASCADED' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION;
@@ -4112,7 +4112,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH LOCAL' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION;
@@ -24547,6 +24547,9 @@ SELECT * FROM v1 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT SQRT('DEF');
SQRT('DEF')
0
@@ -24567,7 +24570,12 @@ SELECT * FROM v2 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -24575,6 +24583,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -24582,6 +24592,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v2;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
diff --git a/mysql-test/suite/funcs_1/r/ndb_func_view.result b/mysql-test/suite/funcs_1/r/ndb_func_view.result
index ca68e92aaa9..b19252e4dd7 100644
--- a/mysql-test/suite/funcs_1/r/ndb_func_view.result
+++ b/mysql-test/suite/funcs_1/r/ndb_func_view.result
@@ -2096,6 +2096,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varbinary_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varbinary_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2108,6 +2111,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -2158,6 +2164,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_varchar_1000`,'IS TRUE','IS NOT TRUE') AS `IF(my_varchar_1000, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2170,6 +2179,9 @@ IS NOT TRUE 2
IS NOT TRUE <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3
IS NOT TRUE ---äÖüß@µ*$-- 4
IS TRUE -1 5
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
+Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3373,8 +3385,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3390,8 +3405,11 @@ NULL NULL 1
-3333.33 -3333.3333 29
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
@@ -3455,8 +3473,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3472,8 +3493,11 @@ NULL NULL 1
-3333.33 -3333.3333 27
Warnings:
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: '<---------1000 characters-------------------------------------------------------------------------------------------------------'
Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/ndb_storedproc_07.result b/mysql-test/suite/funcs_1/r/ndb_storedproc_07.result
index 5a2c0bb6bdf..a520bdfac36 100644
--- a/mysql-test/suite/funcs_1/r/ndb_storedproc_07.result
+++ b/mysql-test/suite/funcs_1/r/ndb_storedproc_07.result
@@ -80,7 +80,7 @@ CREATE TABLE result (f1 text(200), f2 char(20));
set @@sql_mode='traditional';
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp1()
BEGIN
declare a tinyint;
@@ -97,7 +97,7 @@ END if;
END//
SHOW CREATE PROCEDURE sp1;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
+sp1 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`()
BEGIN
declare a tinyint;
declare count_ int default 1;
@@ -117,10 +117,10 @@ Variable_name Value
sql_mode
CALL sp1();
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
SELECT * from result;
f1 f2
-STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER value restored
+STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION value restored
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
sql_mode
@@ -142,7 +142,7 @@ DROP PROCEDURE IF EXISTS sp2;
... show initial value
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
CREATE PROCEDURE sp2()
BEGIN
SET @@sql_mode='MAXDB';
@@ -150,7 +150,7 @@ SHOW VARIABLES LIKE 'sql_mode';
END//
SHOW CREATE PROCEDURE sp2;
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
-sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
+sp2 STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `sp2`()
BEGIN
SET @@sql_mode='MAXDB';
SHOW VARIABLES LIKE 'sql_mode';
@@ -158,7 +158,7 @@ END latin1 latin1_swedish_ci latin1_swedish_ci
... show value prior calling procedure
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
... call procedure that changes sql_mode
CALL sp2();
Variable_name Value
@@ -166,7 +166,7 @@ sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,MAXDB,NO_KEY_OPTIONS,NO_TABLE_
... check whether old value is re-set
SHOW VARIABLES LIKE 'sql_mode';
Variable_name Value
-sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+sql_mode STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
DROP PROCEDURE sp2;
--source suite/funcs_1/storedproc/cleanup_sp_tb.inc
diff --git a/mysql-test/suite/funcs_1/r/ndb_trig_03.result b/mysql-test/suite/funcs_1/r/ndb_trig_03.result
index b02fba0f38d..012977ae4a3 100644
--- a/mysql-test/suite/funcs_1/r/ndb_trig_03.result
+++ b/mysql-test/suite/funcs_1/r/ndb_trig_03.result
@@ -77,7 +77,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke TRIGGER on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER on *.* to test_yesprivs@localhost;
grant SELECT on priv_db.t1 to test_yesprivs@localhost;
@@ -155,7 +155,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke UPDATE on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, UPDATE on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -169,7 +169,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
select f1 from t1 order by f1;
f1
insert 3.5.3.2-no
@@ -401,7 +401,7 @@ grant ALL on *.* to test_noprivs@localhost;
revoke SELECT on *.* from test_noprivs@localhost;
show grants for test_noprivs@localhost;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
revoke ALL PRIVILEGES, GRANT OPTION FROM test_yesprivs@localhost;
grant TRIGGER, SELECT on *.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
@@ -415,7 +415,7 @@ test_noprivs@localhost
use priv_db;
show grants;
Grants for test_noprivs@localhost
-GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE ON *.* TO 'test_noprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
create trigger trg5a_1 before INSERT on t1 for each row
set @test_var = new.f1;
set @test_var = 'before trig 3.5.3.8-1a';
diff --git a/mysql-test/suite/funcs_1/r/ndb_trig_03e.result b/mysql-test/suite/funcs_1/r/ndb_trig_03e.result
index 73388680481..eea8df9a1fd 100644
--- a/mysql-test/suite/funcs_1/r/ndb_trig_03e.result
+++ b/mysql-test/suite/funcs_1/r/ndb_trig_03e.result
@@ -562,7 +562,7 @@ trig 1_1-yes
revoke TRIGGER on *.* from test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
connect(localhost,test_yesprivs,PWD,test,MASTER_MYPORT,MASTER_MYSOCK);
select current_user;
current_user
@@ -609,7 +609,7 @@ root@localhost
grant TRIGGER on priv_db.* to test_yesprivs@localhost;
show grants for test_yesprivs@localhost;
Grants for test_yesprivs@localhost
-GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, CREATE TABLESPACE ON *.* TO 'test_yesprivs'@'localhost' IDENTIFIED BY PASSWORD '*C49735D016A099C0CF104EF9183F374A54CA2576'
GRANT TRIGGER ON `priv_db`.* TO 'test_yesprivs'@'localhost'
trigger privilege on db level for create:
diff --git a/mysql-test/suite/funcs_1/r/ndb_views.result b/mysql-test/suite/funcs_1/r/ndb_views.result
index b75f4955986..79020adbc50 100644
--- a/mysql-test/suite/funcs_1/r/ndb_views.result
+++ b/mysql-test/suite/funcs_1/r/ndb_views.result
@@ -3546,11 +3546,11 @@ CREATE VIEW v1 or REPLACE AS Select * from tb2 my_table;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or REPLACE AS Select * from tb2 my_table' at line 1
CREATE VIEW v1 WITH CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
CREATE VIEW v1 WITH LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH LOCAL CHECK OPTION AS Select *
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LOCAL CHECK OPTION AS Select *
from tb2 my_table limit 50' at line 1
SELECT * FROM tb2 my_table CREATE VIEW As v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE VIEW As v1' at line 1
@@ -3580,7 +3580,7 @@ FROM test.tb2 my_table CHECK OPTION WITH CASCADED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH CASCADED' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH CASCADED CHECK OPTION;
@@ -3609,7 +3609,7 @@ FROM test.tb2 my_table CHECK OPTION WITH LOCAL;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK OPTION WITH LOCAL' at line 2
CREATE OR REPLACE VIEW v1 WITH CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WITH CASCADED CHECK OPTION
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CASCADED CHECK OPTION
AS SELECT F59, F60 FROM test.tb2 my_table' at line 1
CREATE OR REPLACE AS SELECT F59, F60
FROM test.tb2 my_table VIEW v1 WITH LOCAL CHECK OPTION;
@@ -22843,6 +22843,9 @@ SELECT * FROM v1 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT SQRT('DEF');
SQRT('DEF')
0
@@ -22863,7 +22866,12 @@ SELECT * FROM v2 order by 2;
f1 my_sqrt
ABC 0
ABC 1.73205080756888
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -22871,6 +22879,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v1;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
@@ -22878,6 +22888,8 @@ f1 ABC
my_sqrt 1.73205080756888
DROP TABLE t2;
CREATE TABLE t2 AS SELECT * FROM v2;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'DEF'
SELECT * FROM t2 order by 2;
f1 ABC
my_sqrt 0
diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result
index ab917fce339..cda55e92ac8 100644
--- a/mysql-test/suite/funcs_1/r/storedproc.result
+++ b/mysql-test/suite/funcs_1/r/storedproc.result
@@ -2806,7 +2806,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SELECT * from t1 where f2=f1' at line 1
CREATE PROCEDURE with()
SELECT * from t1 where f2=f1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'with()
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '()
SELECT * from t1 where f2=f1' at line 1
CREATE PROCEDURE write()
SELECT * from t1 where f2=f1;
@@ -5660,7 +5660,7 @@ CREATE PROCEDURE sp1()
with:BEGIN
SELECT @x;
END//
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'with:BEGIN
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':BEGIN
SELECT @x;
END' at line 2
DROP PROCEDURE IF EXISTS sp1;
@@ -9220,7 +9220,7 @@ CREATE PROCEDURE sp1()
BEGIN
declare with char;
END//
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'with char;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'char;
END' at line 3
DROP PROCEDURE IF EXISTS sp1;
Warnings:
@@ -11576,8 +11576,9 @@ BEGIN
declare with condition for sqlstate '02000';
declare exit handler for with set @var2 = 1;
END//
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'with condition for sqlstate '02000';
-declare exit handler for with set @var2 = 1' at line 3
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'condition for sqlstate '02000';
+declare exit handler for with set @var2 = 1;
+END' at line 3
DROP PROCEDURE IF EXISTS sp1;
Warnings:
Note 1305 PROCEDURE sp1 does not exist
@@ -13681,7 +13682,7 @@ CREATE PROCEDURE sp1( )
BEGIN
declare with handler for sqlstate '02000' set @var2 = 1;
END//
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'with handler for sqlstate '02000' set @var2 = 1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'handler for sqlstate '02000' set @var2 = 1;
END' at line 3
DROP PROCEDURE IF EXISTS sp1;
Warnings:
@@ -22115,7 +22116,7 @@ f1
2005-03-14 01:01:02
SELECT @@sql_mode;
@@sql_mode
-STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER
+STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
DROP PROCEDURE sp2;
drop table temp_table;
diff --git a/mysql-test/suite/innodb/r/innodb-zip.result b/mysql-test/suite/innodb/r/innodb-zip.result
index a59758c8673..21396d81ba8 100644
--- a/mysql-test/suite/innodb/r/innodb-zip.result
+++ b/mysql-test/suite/innodb/r/innodb-zip.result
@@ -196,13 +196,15 @@ drop table t1;
set innodb_strict_mode = on;
create table t1 (id int primary key) engine = innodb key_block_size = 0;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16]
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 9;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 1;
create table t4 (id int primary key) engine = innodb key_block_size = 2;
@@ -231,26 +233,30 @@ key_block_size = 8 row_format = compressed;
create table t2 (id int primary key) engine = innodb
key_block_size = 8 row_format = redundant;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb
key_block_size = 8 row_format = compact;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb
key_block_size = 8 row_format = dynamic;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb
key_block_size = 8 row_format = default;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t5' (errno: 1478)
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@@ -260,20 +266,26 @@ drop table t1;
create table t1 (id int primary key) engine = innodb
key_block_size = 9 row_format = redundant;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = compact;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = dynamic;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
+Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@@ -281,38 +293,45 @@ table_schema table_name row_format
set global innodb_file_per_table = off;
create table t1 (id int primary key) engine = innodb key_block_size = 1;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 2;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 4;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb key_block_size = 8;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb key_block_size = 16;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t5' (errno: 1478)
create table t6 (id int primary key) engine = innodb row_format = compressed;
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
Error 1005 Can't create table 'test.t6' (errno: 1478)
create table t7 (id int primary key) engine = innodb row_format = dynamic;
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
Error 1005 Can't create table 'test.t7' (errno: 1478)
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
@@ -326,38 +345,45 @@ set global innodb_file_per_table = on;
set global innodb_file_format = `0`;
create table t1 (id int primary key) engine = innodb key_block_size = 1;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 2;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 4;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb key_block_size = 8;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb key_block_size = 16;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t5' (errno: 1478)
create table t6 (id int primary key) engine = innodb row_format = compressed;
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t6' (errno: 1478)
create table t7 (id int primary key) engine = innodb row_format = dynamic;
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
-show errors;
+show warnings;
Level Code Message
+Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t7' (errno: 1478)
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def
index 9a188ac8a48..a1ccbbd3603 100644
--- a/mysql-test/suite/innodb/t/disabled.def
+++ b/mysql-test/suite/innodb/t/disabled.def
@@ -1,2 +1 @@
innodb-index : Bug#47563 2009-06-11 svoj InnoDB: Error: table `test`.`t1#1` already exists in InnoDB internal
-innodb_information_schema : Bug#47808 joro : innodb_information_schema.test fails when run under valgrind
diff --git a/mysql-test/suite/innodb/t/innodb-analyze.test b/mysql-test/suite/innodb/t/innodb-analyze.test
index 32eef7e742c..9bdb9db697c 100644
--- a/mysql-test/suite/innodb/t/innodb-analyze.test
+++ b/mysql-test/suite/innodb/t/innodb-analyze.test
@@ -11,6 +11,7 @@
-- disable_result_log
-- enable_warnings
+let $sample_pages=`select @@innodb_stats_sample_pages`;
SET GLOBAL innodb_stats_sample_pages=0;
# check that the value has been adjusted to 1
@@ -61,5 +62,4 @@ SET GLOBAL innodb_stats_sample_pages=16;
ANALYZE TABLE innodb_analyze;
DROP TABLE innodb_analyze;
-
-SET GLOBAL innodb_stats_sample_pages=DEFAULT;
+EVAL SET GLOBAL innodb_stats_sample_pages=$sample_pages;
diff --git a/mysql-test/suite/innodb/t/innodb-zip.test b/mysql-test/suite/innodb/t/innodb-zip.test
index 5bcd0e3c824..fdb9b89e37a 100644
--- a/mysql-test/suite/innodb/t/innodb-zip.test
+++ b/mysql-test/suite/innodb/t/innodb-zip.test
@@ -174,11 +174,11 @@ set innodb_strict_mode = on;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 0;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 9;
-show errors;
+show warnings;
create table t3 (id int primary key) engine = innodb key_block_size = 1;
@@ -204,22 +204,22 @@ key_block_size = 8 row_format = compressed;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 8 row_format = redundant;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb
key_block_size = 8 row_format = compact;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb
key_block_size = 8 row_format = dynamic;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb
key_block_size = 8 row_format = default;
-show errors;
+show warnings;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@@ -229,17 +229,17 @@ drop table t1;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb
key_block_size = 9 row_format = redundant;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = compact;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = dynamic;
-show errors;
+show warnings;
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@@ -249,25 +249,25 @@ set global innodb_file_per_table = off;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 1;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 2;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb key_block_size = 4;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb key_block_size = 8;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb key_block_size = 16;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t6 (id int primary key) engine = innodb row_format = compressed;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t7 (id int primary key) engine = innodb row_format = dynamic;
-show errors;
+show warnings;
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
@@ -281,25 +281,25 @@ set global innodb_file_format = `0`;
--error ER_CANT_CREATE_TABLE
create table t1 (id int primary key) engine = innodb key_block_size = 1;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t2 (id int primary key) engine = innodb key_block_size = 2;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t3 (id int primary key) engine = innodb key_block_size = 4;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t4 (id int primary key) engine = innodb key_block_size = 8;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t5 (id int primary key) engine = innodb key_block_size = 16;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t6 (id int primary key) engine = innodb row_format = compressed;
-show errors;
+show warnings;
--error ER_CANT_CREATE_TABLE
create table t7 (id int primary key) engine = innodb row_format = dynamic;
-show errors;
+show warnings;
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
diff --git a/mysql-test/suite/innodb/t/innodb_bug36169.test b/mysql-test/suite/innodb/t/innodb_bug36169.test
index f3869a31513..5bf55193b5c 100644
--- a/mysql-test/suite/innodb/t/innodb_bug36169.test
+++ b/mysql-test/suite/innodb/t/innodb_bug36169.test
@@ -5,6 +5,8 @@
-- source include/have_innodb.inc
+let $file_format=`select @@innodb_file_format`;
+let $file_per_table=`select @@innodb_file_per_table`;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;
@@ -1153,6 +1155,5 @@ DROP TABLE IF EXISTS table4;
DROP TABLE IF EXISTS table5;
DROP TABLE IF EXISTS table6;
-SET GLOBAL innodb_file_per_table=DEFAULT;
-SET GLOBAL innodb_file_format='Antelope';
-SET GLOBAL innodb_file_format_check='Antelope';
+EVAL SET GLOBAL innodb_file_format=$file_format;
+EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
diff --git a/mysql-test/suite/innodb/t/innodb_bug36172.test b/mysql-test/suite/innodb/t/innodb_bug36172.test
index 9d437b7d8cd..c6c4e6fae47 100644
--- a/mysql-test/suite/innodb/t/innodb_bug36172.test
+++ b/mysql-test/suite/innodb/t/innodb_bug36172.test
@@ -14,6 +14,9 @@ SET storage_engine=InnoDB;
-- disable_query_log
-- disable_result_log
+let $file_format=`select @@innodb_file_format`;
+let $file_format_check=`select @@innodb_file_format_check`;
+let $file_per_table=`select @@innodb_file_per_table`;
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=on;
@@ -24,7 +27,6 @@ CHECK TABLE table0 EXTENDED;
INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.9055146948, `col21` = 4293243420.5621204000, `col22` = '20511211123705', `col23` = 4289899778.6573381000, `col24` = 4293449279.0540481000, `col25` = 'emphysemic', `col26` = 'dentally', `col27` = '2347406', `col28` = 'eruct', `col30` = 1222, `col31` = 4294372994.9941406000, `col32` = 4291385574.1173744000, `col33` = 'borrowing\'s', `col34` = 'septics', `col35` = 'ratter\'s', `col36` = 'Kaye', `col37` = 'Florentia', `col38` = 'allium', `col39` = 'barkeep', `col40` = '19510407003441', `col41` = 4293559200.4215522000, `col42` = 22482, `col43` = 'decussate', `col44` = 'Brom\'s', `col45` = 'violated', `col46` = 4925506.4635456400, `col47` = 930549, `col48` = '51296066', `col49` = 'voluminously', `col50` = '29306676', `col51` = -88, `col52` = -2153690, `col53` = 4290250202.1464887000, `col54` = 'expropriation', `col55` = 'Aberdeen\'s', `col56` = 20343, `col58` = '19640415171532', `col59` = 'extern', `col60` = 'Ubana', `col61` = 4290487961.8539081000, `col62` = '2147', `col63` = -24271, `col64` = '20750801194548', `col65` = 'Cunaxa\'s', `col66` = 'pasticcio', `col67` = 2795817, `col68` = 'Indore\'s', `col70` = 6864127, `col71` = '1817832', `col72` = '20540506114211', `col73` = '20040101012300', `col74` = 'rationalized', `col75` = '45522', `col76` = 'indene', `col77` = -6964559, `col78` = 4247535.5266884370, `col79` = '20720416124357', `col80` = '2143', `col81` = 4292060102.4466386000, `col82` = 'striving', `col83` = 'boneblack\'s', `col84` = 'redolent', `col85` = 6489697.9009369183, `col86` = 4287473465.9731131000, `col87` = 7726015, `col88` = 'perplexed', `col89` = '17153791', `col90` = 5478587.1108127078, `col91` = 4287091404.7004304000, `col92` = 'Boulez\'s', `col93` = '2931278';
CHECK TABLE table0 EXTENDED;
DROP TABLE table0;
-
-SET GLOBAL innodb_file_per_table=DEFAULT;
-SET GLOBAL innodb_file_format='Antelope';
-SET GLOBAL innodb_file_format_check='Antelope';
+EVAL SET GLOBAL innodb_file_format=$file_format;
+EVAL SET GLOBAL innodb_file_format_check=$file_format_check;
+EVAL SET GLOBAL innodb_file_per_table=$file_per_table;
diff --git a/mysql-test/suite/innodb/t/innodb_information_schema.test b/mysql-test/suite/innodb/t/innodb_information_schema.test
index eaed653854a..fc1d38d8d14 100644
--- a/mysql-test/suite/innodb/t/innodb_information_schema.test
+++ b/mysql-test/suite/innodb/t/innodb_information_schema.test
@@ -109,14 +109,18 @@ SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE;
-- send
SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE;
-# Give time to the above 2 queries to execute before continuing.
-# Without this sleep it sometimes happens that the SELECT from innodb_locks
-# executes before some of them, resulting in less than expected number
-# of rows being selected from innodb_locks.
--- sleep 0.1
-
-- enable_result_log
-- connection con_verify_innodb_locks
+# Wait for the above queries to execute before continuing.
+# Without this, it sometimes happens that the SELECT from innodb_locks
+# executes before some of them, resulting in less than expected number
+# of rows being selected from innodb_locks. If there is a bug and there
+# are no 14 rows in innodb_locks then this test will fail with timeout.
+let $count = 14;
+let $table = INFORMATION_SCHEMA.INNODB_LOCKS;
+-- source include/wait_until_rows_count.inc
+# the above enables the query log, re-disable it
+-- disable_query_log
SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data
FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data;
diff --git a/mysql-test/suite/ndb/r/ndb_dd_ddl.result b/mysql-test/suite/ndb/r/ndb_dd_ddl.result
index 2bf30f5c7fc..9714a89c2ab 100644
--- a/mysql-test/suite/ndb/r/ndb_dd_ddl.result
+++ b/mysql-test/suite/ndb/r/ndb_dd_ddl.result
@@ -236,3 +236,79 @@ engine ndb;
ERROR HY000: Failed to drop TABLESPACE
drop logfile group lg1
engine ndb;
+
+# -----------------------------------------------------------------
+# End 5.1 test
+# -----------------------------------------------------------------
+
+# --
+# -- WL#4300: Define privileges for tablespaces.
+# --
+GRANT CREATE TABLESPACE ON *.* TO mysqltest_u1@localhost;
+
+DROP DATABASE IF EXISTS mysqltest2;
+CREATE DATABASE mysqltest2;
+GRANT ALL PRIVILEGES ON mysqltest2.* TO mysqltest_u2@localhost;
+
+# -- Connection: mysqltest_u1@localhost
+
+# -- Grants for mysqltest_u1@localhost:
+SHOW GRANTS;
+Grants for mysqltest_u1@localhost
+GRANT CREATE TABLESPACE ON *.* TO 'mysqltest_u1'@'localhost'
+
+# -- Check CREATE LOGFILE GROUP...
+CREATE LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile.dat'
+INITIAL_SIZE 1M
+UNDO_BUFFER_SIZE = 1M
+ENGINE = NDB;
+
+# -- Check ALTER LOGFILE GROUP...
+ALTER LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile02.dat'
+INITIAL_SIZE 1M
+ENGINE = NDB;
+
+# -- Check CREATE TABLESPACE...
+CREATE TABLESPACE ts1
+ADD DATAFILE 'datafile.dat'
+USE LOGFILE GROUP lg1
+INITIAL_SIZE 1M
+ENGINE = NDB;
+
+# -- Check ALTER TABLESPACE...
+ALTER TABLESPACE ts1
+DROP DATAFILE 'datafile.dat'
+INITIAL_SIZE 1M
+ENGINE = NDB;
+
+# -- Connection: mysqltest_u2@localhost
+
+# -- Grants for mysqltest_u2@localhost:
+SHOW GRANTS;
+Grants for mysqltest_u2@localhost
+GRANT USAGE ON *.* TO 'mysqltest_u2'@'localhost'
+GRANT ALL PRIVILEGES ON `mysqltest2`.* TO 'mysqltest_u2'@'localhost'
+CREATE TABLE t1(c INT) TABLESPACE ts1;
+DROP TABLE t1;
+
+# -- Connection: mysqltest_u1@localhost
+
+
+# -- Check DROP TABLESPACE...
+DROP TABLESPACE ts1
+ENGINE = NDB;
+
+# -- Check DROP LOGFILE GROUP...
+DROP LOGFILE GROUP lg1
+ENGINE = NDB;
+
+# -- Connection: root@localhost
+
+DROP USER mysqltest_u1@localhost;
+DROP USER mysqltest_u2@localhost;
+
+# -----------------------------------------------------------------
+# End 6.0 test
+# -----------------------------------------------------------------
diff --git a/mysql-test/suite/ndb/t/ndb_dd_ddl.test b/mysql-test/suite/ndb/t/ndb_dd_ddl.test
index d6de7c45326..e8db0730687 100644
--- a/mysql-test/suite/ndb/t/ndb_dd_ddl.test
+++ b/mysql-test/suite/ndb/t/ndb_dd_ddl.test
@@ -367,4 +367,103 @@ engine ndb;
--exec rm $MYSQLTEST_VARDIR/tmp/t1.frm
-# End 5.1 test
+--echo
+--echo # -----------------------------------------------------------------
+--echo # End 5.1 test
+--echo # -----------------------------------------------------------------
+
+--echo
+--echo # --
+--echo # -- WL#4300: Define privileges for tablespaces.
+--echo # --
+
+GRANT CREATE TABLESPACE ON *.* TO mysqltest_u1@localhost;
+
+--echo
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest2;
+--enable_warnings
+
+CREATE DATABASE mysqltest2;
+
+GRANT ALL PRIVILEGES ON mysqltest2.* TO mysqltest_u2@localhost;
+
+--echo
+--echo # -- Connection: mysqltest_u1@localhost
+--echo
+--connect(con1, localhost, mysqltest_u1,,)
+
+--echo # -- Grants for mysqltest_u1@localhost:
+SHOW GRANTS;
+
+--echo
+--echo # -- Check CREATE LOGFILE GROUP...
+CREATE LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile.dat'
+INITIAL_SIZE 1M
+UNDO_BUFFER_SIZE = 1M
+ENGINE = NDB;
+
+--echo
+--echo # -- Check ALTER LOGFILE GROUP...
+ALTER LOGFILE GROUP lg1
+ADD UNDOFILE 'undofile02.dat'
+INITIAL_SIZE 1M
+ENGINE = NDB;
+
+--echo
+--echo # -- Check CREATE TABLESPACE...
+CREATE TABLESPACE ts1
+ADD DATAFILE 'datafile.dat'
+USE LOGFILE GROUP lg1
+INITIAL_SIZE 1M
+ENGINE = NDB;
+
+--echo
+--echo # -- Check ALTER TABLESPACE...
+ALTER TABLESPACE ts1
+DROP DATAFILE 'datafile.dat'
+INITIAL_SIZE 1M
+ENGINE = NDB;
+
+--echo
+--echo # -- Connection: mysqltest_u2@localhost
+--echo
+--connect(con2, localhost, mysqltest_u2,,mysqltest2)
+
+--echo # -- Grants for mysqltest_u2@localhost:
+SHOW GRANTS;
+
+CREATE TABLE t1(c INT) TABLESPACE ts1;
+
+DROP TABLE t1;
+
+--echo
+--echo # -- Connection: mysqltest_u1@localhost
+--echo
+--connection con1
+
+--echo
+--echo # -- Check DROP TABLESPACE...
+DROP TABLESPACE ts1
+ENGINE = NDB;
+
+--echo
+--echo # -- Check DROP LOGFILE GROUP...
+DROP LOGFILE GROUP lg1
+ENGINE = NDB;
+
+--echo
+--echo # -- Connection: root@localhost
+--echo
+--connection default
+--disconnect con1
+
+DROP USER mysqltest_u1@localhost;
+DROP USER mysqltest_u2@localhost;
+
+--echo
+--echo # -----------------------------------------------------------------
+--echo # End 6.0 test
+--echo # -----------------------------------------------------------------
diff --git a/mysql-test/suite/parts/inc/partition_key_32col.inc b/mysql-test/suite/parts/inc/partition_key_32col.inc
index 74016d9b556..b0635ca0e9c 100644
--- a/mysql-test/suite/parts/inc/partition_key_32col.inc
+++ b/mysql-test/suite/parts/inc/partition_key_32col.inc
@@ -1,4 +1,4 @@
---error ER_TOO_MANY_KEY_PARTS
+--error ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
eval create table t1 (a date not null, b varchar(50) not null, c varchar(50) not null, d enum('m', 'w') not null, e int not null, f decimal (18,2) not null, g bigint not null, h tinyint not null, a1 date not null, b1 varchar(50) not null, c1 varchar(50) not null, d1 enum('m', 'w') not null, e1 int not null, f1 decimal (18,2) not null, g1 bigint not null, h1 tinyint not null, a2 date not null, b2 varchar(50) not null, c2 varchar(50) not null, d2 enum('m', 'w') not null, e2 int not null, f2 decimal (18,2) not null, g2 bigint not null, h2 tinyint not null, a3 date not null, b3 varchar(50) not null, c3 varchar(50) not null, d3 enum('m', 'w') not null, e3 int not null, f3 decimal (18,2) not null, g3 bigint not null, h3 tinyint not null, i char(255), primary key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a3,b3,c3,d3,e3,f3,g3,h3)) engine=$engine
partition by key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a3,b3,c3,d3,e3,f3,g3,h3) (
partition pa1 max_rows=20 min_rows=2,
diff --git a/mysql-test/suite/parts/inc/partition_syntax.inc b/mysql-test/suite/parts/inc/partition_syntax.inc
index e72aad80f0a..e7eea73325a 100644
--- a/mysql-test/suite/parts/inc/partition_syntax.inc
+++ b/mysql-test/suite/parts/inc/partition_syntax.inc
@@ -312,7 +312,7 @@ PARTITION BY RANGE(f_int1)
--echo #------------------------------------------------------------------------
--echo # 3.5.1 NULL in RANGE partitioning clause
--echo # 3.5.1.1 VALUE LESS THAN (NULL) is not allowed
---error ER_PARSE_ERROR
+--error ER_NULL_IN_VALUES_LESS_THAN
eval CREATE TABLE t1 (
$column_list
)
@@ -320,7 +320,7 @@ PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
--echo # 3.5.1.2 VALUE LESS THAN (NULL) is not allowed
---error ER_PARSE_ERROR
+--error ER_NULL_IN_VALUES_LESS_THAN
eval CREATE TABLE t1 (
$column_list
)
diff --git a/mysql-test/suite/parts/r/partition_special_innodb.result b/mysql-test/suite/parts/r/partition_special_innodb.result
index 8869f6d450c..26c1ac9356c 100644
--- a/mysql-test/suite/parts/r/partition_special_innodb.result
+++ b/mysql-test/suite/parts/r/partition_special_innodb.result
@@ -133,7 +133,7 @@ partition pa1 max_rows=20 min_rows=2,
partition pa2 max_rows=30 min_rows=3,
partition pa3 max_rows=30 min_rows=4,
partition pa4 max_rows=40 min_rows=2);
-ERROR 42000: Too many key parts specified; max 16 parts allowed
+ERROR HY000: Too many fields in 'list of partition fields'
create table t1 (a date not null, b varchar(50) not null, c varchar(50) not null, d enum('m', 'w') not null, e int not null, f decimal (18,2) not null, g bigint not null, h tinyint not null, a1 date not null, b1 varchar(50) not null, c1 varchar(50) not null, d1 enum('m', 'w') not null, e1 int not null, f1 decimal (18,2) not null, g1 bigint not null, h1 tinyint not null, a2 date not null, b2 varchar(50) not null, c2 varchar(50) not null, d2 enum('m', 'w') not null, e2 int not null, f2 decimal (18,2) not null, g2 bigint not null, h2 tinyint not null, a3 date not null, b3 varchar(50) not null, c3 varchar(50) not null, d3 enum('m', 'w') not null, e3 int not null, f3 decimal (18,2) not null, g3 bigint not null, h3 tinyint not null, i char(255), primary key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1)) engine='InnoDB'
partition by key(a,b,c,d,e,f,g,h) (
partition pa1 max_rows=20 min_rows=2,
diff --git a/mysql-test/suite/parts/r/partition_special_myisam.result b/mysql-test/suite/parts/r/partition_special_myisam.result
index 7167d6af39e..60c9f9666cd 100644
--- a/mysql-test/suite/parts/r/partition_special_myisam.result
+++ b/mysql-test/suite/parts/r/partition_special_myisam.result
@@ -133,7 +133,7 @@ partition pa1 max_rows=20 min_rows=2,
partition pa2 max_rows=30 min_rows=3,
partition pa3 max_rows=30 min_rows=4,
partition pa4 max_rows=40 min_rows=2);
-ERROR 42000: Too many key parts specified; max 16 parts allowed
+ERROR HY000: Too many fields in 'list of partition fields'
create table t1 (a date not null, b varchar(50) not null, c varchar(50) not null, d enum('m', 'w') not null, e int not null, f decimal (18,2) not null, g bigint not null, h tinyint not null, a1 date not null, b1 varchar(50) not null, c1 varchar(50) not null, d1 enum('m', 'w') not null, e1 int not null, f1 decimal (18,2) not null, g1 bigint not null, h1 tinyint not null, a2 date not null, b2 varchar(50) not null, c2 varchar(50) not null, d2 enum('m', 'w') not null, e2 int not null, f2 decimal (18,2) not null, g2 bigint not null, h2 tinyint not null, a3 date not null, b3 varchar(50) not null, c3 varchar(50) not null, d3 enum('m', 'w') not null, e3 int not null, f3 decimal (18,2) not null, g3 bigint not null, h3 tinyint not null, i char(255), primary key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1)) engine='MyISAM'
partition by key(a,b,c,d,e,f,g,h) (
partition pa1 max_rows=20 min_rows=2,
diff --git a/mysql-test/suite/parts/r/partition_syntax_innodb.result b/mysql-test/suite/parts/r/partition_syntax_innodb.result
index c27a1386409..848a30a13df 100644
--- a/mysql-test/suite/parts/r/partition_syntax_innodb.result
+++ b/mysql-test/suite/parts/r/partition_syntax_innodb.result
@@ -610,8 +610,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
-ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
-PARTITION part2 VALUES LESS THAN (1000))' at line 9
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.1.2 VALUE LESS THAN (NULL) is not allowed
CREATE TABLE t1 (
f_int1 INTEGER,
@@ -623,8 +622,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
-ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
-PARTITION part2 VALUES LESS THAN (1000))' at line 9
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.2 NULL in LIST partitioning clause
# 3.5.2.1 VALUE IN (NULL)
CREATE TABLE t1 (
diff --git a/mysql-test/suite/parts/r/partition_syntax_myisam.result b/mysql-test/suite/parts/r/partition_syntax_myisam.result
index 0cf98765797..f3b7f5b3025 100644
--- a/mysql-test/suite/parts/r/partition_syntax_myisam.result
+++ b/mysql-test/suite/parts/r/partition_syntax_myisam.result
@@ -610,8 +610,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
-ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
-PARTITION part2 VALUES LESS THAN (1000))' at line 9
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.1.2 VALUE LESS THAN (NULL) is not allowed
CREATE TABLE t1 (
f_int1 INTEGER,
@@ -623,8 +622,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
-ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
-PARTITION part2 VALUES LESS THAN (1000))' at line 9
+ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.2 NULL in LIST partitioning clause
# 3.5.2.1 VALUE IN (NULL)
CREATE TABLE t1 (
diff --git a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
index ae3554a5420..5f2a55b5e35 100644
--- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
+++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
@@ -4,8 +4,10 @@ reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
-call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'");
+call mtr.add_suppression("Get master clock failed with error: ");
+call mtr.add_suppression("Get master SERVER_ID failed with error: ");
call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again");
+call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*");
SELECT IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP");
IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP")
1
diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result
index 4c6fd43da13..4e81d90a970 100644
--- a/mysql-test/suite/rpl/r/rpl_loaddata.result
+++ b/mysql-test/suite/rpl/r/rpl_loaddata.result
@@ -200,3 +200,32 @@ CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB;
LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1;
ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY'
DROP TABLE IF EXISTS t1;
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop database if exists b48297_db1;
+drop database if exists b42897_db2;
+create database b48297_db1;
+create database b42897_db2;
+use b48297_db1;
+CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;;
+use b42897_db2;
+### assertion: works with cross-referenced database
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1;
+use b48297_db1;
+### assertion: works with fully qualified name on current database
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1;
+### assertion: works without fully qualified name on current database
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1;
+### create connection without default database
+### connect (conn2,localhost,root,,*NO-ONE*);
+### assertion: works without stating the default database
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1;
+### disconnect and switch back to master connection
+use b48297_db1;
+Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1
+DROP DATABASE b48297_db1;
+DROP DATABASE b42897_db2;
diff --git a/mysql-test/suite/rpl/r/rpl_udf.result b/mysql-test/suite/rpl/r/rpl_udf.result
index ccf16271d01..a6d23b04780 100644
--- a/mysql-test/suite/rpl/r/rpl_udf.result
+++ b/mysql-test/suite/rpl/r/rpl_udf.result
@@ -181,21 +181,21 @@ affected rows: 2
CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM;
affected rows: 0
INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00));
+affected rows: 1
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-affected rows: 1
INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00));
+affected rows: 1
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-affected rows: 1
INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00));
+affected rows: 1
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-affected rows: 1
INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00));
+affected rows: 1
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-affected rows: 1
SELECT * FROM t1 ORDER BY sum;
sum price
1 48.5
diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test
index b9ab66165cc..e77cd308f39 100644
--- a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test
+++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test
@@ -50,7 +50,7 @@ kill @id;
drop table t2,t3;
insert into t4 values (3),(4);
connection master;
---error 0,1053,2013
+--error 0,1317,2013
reap;
connection master1;
save_master_pos;
diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt
new file mode 100644
index 00000000000..f9aa8c0367e
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt
@@ -0,0 +1 @@
+--master-retry-count=60
diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
index c7c66bfde71..a290e539e32 100644
--- a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
+++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
@@ -19,6 +19,9 @@ source include/have_debug.inc;
call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'");
call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again");
+call mtr.add_suppression("Get master clock failed with error: ");
+call mtr.add_suppression("Get master SERVER_ID failed with error: ");
+call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*");
#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection
connection slave;
diff --git a/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test b/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test
index e6c1d5256a0..0a031f1bff9 100644
--- a/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test
+++ b/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test
@@ -145,7 +145,9 @@ create table t3 select 1 union select UUID();
create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3);
create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
# what if UUID() is first:
+--disable_warnings
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
+--enable_warnings
# inside a stored procedure
diff --git a/mysql-test/suite/sys_vars/r/auto_commit_basic.result b/mysql-test/suite/sys_vars/r/auto_commit_basic.result
index c3643aaa1db..96cfd3e7ee6 100644
--- a/mysql-test/suite/sys_vars/r/auto_commit_basic.result
+++ b/mysql-test/suite/sys_vars/r/auto_commit_basic.result
@@ -54,19 +54,19 @@ ERROR HY000: Variable 'autocommit' is a SESSION variable and can't be used with
SELECT @@global.autocommit;
ERROR HY000: Variable 'autocommit' is a SESSION variable
'#----------------------FN_DYNVARS_003_06------------------------#'
-SELECT @@session.autocommit = VARIABLE_VALUE
+SELECT IF(@@session.autocommit, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='autocommit';
-@@session.autocommit = VARIABLE_VALUE
-0
+IF(@@session.autocommit, "ON", "OFF") = VARIABLE_VALUE
+1
Bug # 34839: Values in variable and information_schema do not match for autocommit
'#----------------------FN_DYNVARS_003_07------------------------#'
SET @@autocommit = 1;
-SELECT @@autocommit = VARIABLE_VALUE
+SELECT IF(@@autocommit, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='autocommit';
-@@autocommit = VARIABLE_VALUE
-0
+IF(@@autocommit, "ON", "OFF") = VARIABLE_VALUE
+1
'#---------------------FN_DYNVARS_003_08-------------------------#'
SET @@autocommit = OFF;
SELECT @@autocommit;
diff --git a/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result b/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result
index b9cf9b5ee80..26e33a384b9 100644
--- a/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result
+++ b/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result
@@ -53,11 +53,11 @@ ERROR HY000: Variable 'automatic_sp_privileges' is a GLOBAL variable and should
SELECT @@session.automatic_sp_privileges;
ERROR HY000: Variable 'automatic_sp_privileges' is a GLOBAL variable
'#----------------------FN_DYNVARS_004_06------------------------#'
-SELECT @@global.automatic_sp_privileges = VARIABLE_VALUE
+SELECT IF(@@global.automatic_sp_privileges, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='automatic_sp_privileges';
-@@global.automatic_sp_privileges = VARIABLE_VALUE
-0
+IF(@@global.automatic_sp_privileges, "ON", "OFF") = VARIABLE_VALUE
+1
'Bug# 34839: Values in variable and information_schema donot match'
'#---------------------FN_DYNVARS_004_07----------------------#'
SET @@global.automatic_sp_privileges = OFF;
diff --git a/mysql-test/suite/sys_vars/r/big_tables_basic.result b/mysql-test/suite/sys_vars/r/big_tables_basic.result
index 937576a76d3..e88caae47cf 100644
--- a/mysql-test/suite/sys_vars/r/big_tables_basic.result
+++ b/mysql-test/suite/sys_vars/r/big_tables_basic.result
@@ -49,11 +49,11 @@ ERROR HY000: Variable 'big_tables' is a SESSION variable and can't be used with
SELECT @@global.big_tables;
ERROR HY000: Variable 'big_tables' is a SESSION variable
'#----------------------FN_DYNVARS_005_05------------------------#'
-SELECT @@big_tables = VARIABLE_VALUE
+SELECT IF(@@big_tables, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='big_tables';
-@@big_tables = VARIABLE_VALUE
-0
+IF(@@big_tables, "ON", "OFF") = VARIABLE_VALUE
+1
Bug # 34839: Values in variable and information_schema do not match for autocommit
'#---------------------FN_DYNVARS_005_06----------------------#'
SET @@big_tables = OFF;
diff --git a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
index 7073066c2f1..93e3cd56c77 100644
--- a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
+++ b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
@@ -103,10 +103,10 @@ SELECT @@session.engine_condition_pushdown AS res_is_1;
res_is_1
1
'#----------------------FN_DYNVARS_028_06------------------------#'
-SELECT @@global.engine_condition_pushdown = VARIABLE_VALUE
+SELECT IF(@@global.engine_condition_pushdown, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='engine_condition_pushdown';
-@@global.engine_condition_pushdown = VARIABLE_VALUE
+IF(@@global.engine_condition_pushdown, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@global.engine_condition_pushdown;
@@global.engine_condition_pushdown
@@ -117,11 +117,11 @@ WHERE VARIABLE_NAME='engine_condition_pushdown';
VARIABLE_VALUE
OFF
'#----------------------FN_DYNVARS_028_07------------------------#'
-SELECT @@session.engine_condition_pushdown = VARIABLE_VALUE
+SELECT IF(@@session.engine_condition_pushdown, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='engine_condition_pushdown';
-@@session.engine_condition_pushdown = VARIABLE_VALUE
-0
+IF(@@session.engine_condition_pushdown, "ON", "OFF") = VARIABLE_VALUE
+1
SELECT @@session.engine_condition_pushdown;
@@session.engine_condition_pushdown
1
diff --git a/mysql-test/suite/sys_vars/r/flush_basic.result b/mysql-test/suite/sys_vars/r/flush_basic.result
index 259f8f929a1..e0584d46351 100644
--- a/mysql-test/suite/sys_vars/r/flush_basic.result
+++ b/mysql-test/suite/sys_vars/r/flush_basic.result
@@ -63,11 +63,11 @@ ERROR HY000: Variable 'flush' is a GLOBAL variable and should be set with SET GL
SELECT @@session.flush;
ERROR HY000: Variable 'flush' is a GLOBAL variable
'#----------------------FN_DYNVARS_030_06------------------------#'
-SELECT @@global.flush = VARIABLE_VALUE
+SELECT IF(@@global.flush, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='flush';
-@@global.flush = VARIABLE_VALUE
-0
+IF(@@global.flush, "ON", "OFF") = VARIABLE_VALUE
+1
'#---------------------FN_DYNVARS_030_07----------------------#'
SET @@global.flush = TRUE;
SELECT @@global.flush;
diff --git a/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result b/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result
index e09e680fe99..8540467b9b2 100644
--- a/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result
+++ b/mysql-test/suite/sys_vars/r/foreign_key_checks_basic.result
@@ -65,10 +65,10 @@ SELECT count(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARI
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_032_07------------------------#'
-SELECT @@session.foreign_key_checks = VARIABLE_VALUE
+SELECT IF(@@session.foreign_key_checks, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='foreign_key_checks';
-@@session.foreign_key_checks = VARIABLE_VALUE
+IF(@@session.foreign_key_checks, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.foreign_key_checks;
@@session.foreign_key_checks
diff --git a/mysql-test/suite/sys_vars/r/general_log_basic.result b/mysql-test/suite/sys_vars/r/general_log_basic.result
index 18a5fde45c0..df6ec9fb384 100644
--- a/mysql-test/suite/sys_vars/r/general_log_basic.result
+++ b/mysql-test/suite/sys_vars/r/general_log_basic.result
@@ -47,10 +47,10 @@ ERROR HY000: Variable 'general_log' is a GLOBAL variable and should be set with
SELECT @@session.general_log;
ERROR HY000: Variable 'general_log' is a GLOBAL variable
'#----------------------FN_DYNVARS_004_05------------------------#'
-SELECT @@global.general_log = VARIABLE_VALUE
+SELECT IF(@@global.general_log, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='general_log';
-@@global.general_log = VARIABLE_VALUE
+IF(@@global.general_log, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_004_06----------------------#'
SET @@global.general_log = 0;
diff --git a/mysql-test/suite/sys_vars/r/innodb_checksums_basic.result b/mysql-test/suite/sys_vars/r/innodb_checksums_basic.result
index ac4bed60eb5..bb3cbac1863 100644
--- a/mysql-test/suite/sys_vars/r/innodb_checksums_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_checksums_basic.result
@@ -12,11 +12,11 @@ COUNT(@@GLOBAL.innodb_checksums)
1
1 Expected
'#---------------------BS_STVARS_023_03----------------------#'
-SELECT @@GLOBAL.innodb_checksums = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_checksums, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_checksums';
-@@GLOBAL.innodb_checksums = VARIABLE_VALUE
-0
+IF(@@GLOBAL.innodb_checksums, "ON", "OFF") = VARIABLE_VALUE
+1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_checksums);
COUNT(@@GLOBAL.innodb_checksums)
diff --git a/mysql-test/suite/sys_vars/r/innodb_doublewrite_basic.result b/mysql-test/suite/sys_vars/r/innodb_doublewrite_basic.result
index 6062399e8b8..4a5baf0aeda 100644
--- a/mysql-test/suite/sys_vars/r/innodb_doublewrite_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_doublewrite_basic.result
@@ -12,11 +12,11 @@ COUNT(@@GLOBAL.innodb_doublewrite)
1
1 Expected
'#---------------------BS_STVARS_026_03----------------------#'
-SELECT @@GLOBAL.innodb_doublewrite = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_doublewrite, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_doublewrite';
-@@GLOBAL.innodb_doublewrite = VARIABLE_VALUE
-0
+IF(@@GLOBAL.innodb_doublewrite, "ON", "OFF") = VARIABLE_VALUE
+1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_doublewrite);
COUNT(@@GLOBAL.innodb_doublewrite)
diff --git a/mysql-test/suite/sys_vars/r/innodb_locks_unsafe_for_binlog_basic.result b/mysql-test/suite/sys_vars/r/innodb_locks_unsafe_for_binlog_basic.result
index a5967d28913..c2229d54d02 100644
--- a/mysql-test/suite/sys_vars/r/innodb_locks_unsafe_for_binlog_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_locks_unsafe_for_binlog_basic.result
@@ -12,10 +12,10 @@ COUNT(@@GLOBAL.innodb_locks_unsafe_for_binlog)
1
1 Expected
'#---------------------BS_STVARS_031_03----------------------#'
-SELECT @@GLOBAL.innodb_locks_unsafe_for_binlog = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_locks_unsafe_for_binlog, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_locks_unsafe_for_binlog';
-@@GLOBAL.innodb_locks_unsafe_for_binlog = VARIABLE_VALUE
+IF(@@GLOBAL.innodb_locks_unsafe_for_binlog, "ON", "OFF") = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_locks_unsafe_for_binlog);
diff --git a/mysql-test/suite/sys_vars/r/innodb_rollback_on_timeout_basic.result b/mysql-test/suite/sys_vars/r/innodb_rollback_on_timeout_basic.result
index 6887166fae6..0b7c71ce488 100644
--- a/mysql-test/suite/sys_vars/r/innodb_rollback_on_timeout_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_rollback_on_timeout_basic.result
@@ -12,10 +12,10 @@ COUNT(@@GLOBAL.innodb_rollback_on_timeout)
1
1 Expected
'#---------------------BS_STVARS_039_03----------------------#'
-SELECT @@GLOBAL.innodb_rollback_on_timeout = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_rollback_on_timeout, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_rollback_on_timeout';
-@@GLOBAL.innodb_rollback_on_timeout = VARIABLE_VALUE
+IF(@@GLOBAL.innodb_rollback_on_timeout, "ON", "OFF") = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_rollback_on_timeout);
diff --git a/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result b/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result
index dcd6f498d56..96a48d7789f 100644
--- a/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result
@@ -105,10 +105,10 @@ SELECT @@session.innodb_support_xa AS res_is_1;
res_is_1
1
'#----------------------FN_DYNVARS_046_06------------------------#'
-SELECT @@global.innodb_support_xa =
+SELECT IF(@@global.innodb_support_xa, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_support_xa';
-@@global.innodb_support_xa =
+IF(@@global.innodb_support_xa, "ON", "OFF") =
VARIABLE_VALUE
1
SELECT @@global.innodb_support_xa;
@@ -119,12 +119,12 @@ WHERE VARIABLE_NAME='innodb_support_xa';
VARIABLE_VALUE
OFF
'#----------------------FN_DYNVARS_046_07------------------------#'
-SELECT @@session.innodb_support_xa =
+SELECT IF(@@session.innodb_support_xa, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='innodb_support_xa';
-@@session.innodb_support_xa =
+IF(@@session.innodb_support_xa, "ON", "OFF") =
VARIABLE_VALUE
-0
+1
SELECT @@session.innodb_support_xa;
@@session.innodb_support_xa
1
diff --git a/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result b/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result
index 14aa995273b..f2424a3ea27 100644
--- a/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result
@@ -99,10 +99,10 @@ SELECT @@session.innodb_table_locks AS res_is_1;
res_is_1
1
'#----------------------FN_DYNVARS_046_06------------------------#'
-SELECT @@global.innodb_table_locks =
+SELECT IF(@@global.innodb_table_locks, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_table_locks';
-@@global.innodb_table_locks =
+IF(@@global.innodb_table_locks, "ON", "OFF") =
VARIABLE_VALUE
1
SELECT @@global.innodb_table_locks;
@@ -113,12 +113,12 @@ WHERE VARIABLE_NAME='innodb_table_locks';
VARIABLE_VALUE
OFF
'#----------------------FN_DYNVARS_046_07------------------------#'
-SELECT @@session.innodb_table_locks =
+SELECT IF(@@session.innodb_table_locks, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='innodb_table_locks';
-@@session.innodb_table_locks =
+IF(@@session.innodb_table_locks, "ON", "OFF") =
VARIABLE_VALUE
-0
+1
SELECT @@session.innodb_table_locks;
@@session.innodb_table_locks
1
diff --git a/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result b/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result
index f782ee3b078..696ac5cc279 100644
--- a/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result
+++ b/mysql-test/suite/sys_vars/r/keep_files_on_create_basic.result
@@ -120,16 +120,16 @@ SELECT @@session.keep_files_on_create;
@@session.keep_files_on_create
0
'#------------------FN_DYNVARS_054_06-----------------------#'
-SELECT @@global.keep_files_on_create = VARIABLE_VALUE
+SELECT IF(@@global.keep_files_on_create, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='keep_files_on_create';
-@@global.keep_files_on_create = VARIABLE_VALUE
+IF(@@global.keep_files_on_create, "ON", "OFF") = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_054_07-----------------------#'
-SELECT @@session.keep_files_on_create = VARIABLE_VALUE
+SELECT IF(@@session.keep_files_on_create, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='keep_files_on_create';
-@@session.keep_files_on_create = VARIABLE_VALUE
+IF(@@session.keep_files_on_create, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_001_08----------------------#'
SET @@keep_files_on_create = OFF;
diff --git a/mysql-test/suite/sys_vars/r/local_infile_basic.result b/mysql-test/suite/sys_vars/r/local_infile_basic.result
index 5f4c215719a..7afb367fde9 100644
--- a/mysql-test/suite/sys_vars/r/local_infile_basic.result
+++ b/mysql-test/suite/sys_vars/r/local_infile_basic.result
@@ -53,11 +53,11 @@ ERROR HY000: Variable 'local_infile' is a GLOBAL variable and should be set with
SELECT @@session.local_infile = 1;
ERROR HY000: Variable 'local_infile' is a GLOBAL variable
'#----------------------FN_DYNVARS_018_06------------------------#'
-SELECT @@global.local_infile = VARIABLE_VALUE
+SELECT IF(@@global.local_infile, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='local_infile';
-@@global.local_infile = VARIABLE_VALUE
-0
+IF(@@global.local_infile, "ON", "OFF") = VARIABLE_VALUE
+1
'#---------------------FN_DYNVARS_018_07----------------------#'
SET @@global.local_infile = OFF;
SELECT @@global.local_infile;
diff --git a/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result b/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result
index 40dc0e217c4..72daac1edc1 100644
--- a/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result
+++ b/mysql-test/suite/sys_vars/r/log_bin_trust_function_creators_basic.result
@@ -69,12 +69,12 @@ ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the valu
SET @@global.log_bin_trust_function_creators = test;
ERROR 42000: Variable 'log_bin_trust_function_creators' can't be set to the value of 'test'
'#------------------FN_DYNVARS_063_06-----------------------#'
-SELECT @@global.log_bin_trust_function_creators = VARIABLE_VALUE
+SELECT IF(@@global.log_bin_trust_function_creators, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='log_bin_trust_function_creators';
-@@global.log_bin_trust_function_creators = VARIABLE_VALUE
+IF(@@global.log_bin_trust_function_creators, "ON", "OFF") = VARIABLE_VALUE
1
-SELECT @@session.log_bin_trust_function_creators = VARIABLE_VALUE
+SELECT IF(@@session.log_bin_trust_function_creators, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='log_bin_trust_function_creators';
ERROR HY000: Variable 'log_bin_trust_function_creators' is a GLOBAL variable
diff --git a/mysql-test/suite/sys_vars/r/log_queries_not_using_indexes_basic.result b/mysql-test/suite/sys_vars/r/log_queries_not_using_indexes_basic.result
index b19b11a4209..7c69655f109 100644
--- a/mysql-test/suite/sys_vars/r/log_queries_not_using_indexes_basic.result
+++ b/mysql-test/suite/sys_vars/r/log_queries_not_using_indexes_basic.result
@@ -102,3 +102,6 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SET @@SESSION log_queries_not_using_indexes= TRUE;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'log_queries_not_using_indexes= TRUE' at line 1
SET @@global.log_queries_not_using_indexes= @start_value;
+SELECT IF(@@GLOBAL.log_queries_not_using_indexes, "ON", "OFF") = VARIABLE_VALUE
+IF(@@GLOBAL.log_queries_not_using_indexes, "ON", "OFF") = VARIABLE_VALUE
+1
diff --git a/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result b/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result
index 87b30814837..d41e4cfc56f 100644
--- a/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result
+++ b/mysql-test/suite/sys_vars/r/low_priority_updates_basic.result
@@ -118,16 +118,16 @@ ERROR 42000: Variable 'low_priority_updates' can't be set to the value of '65550
SET @@session.low_priority_updates = test;
ERROR 42000: Variable 'low_priority_updates' can't be set to the value of 'test'
'#------------------FN_DYNVARS_069_06-----------------------#'
-SELECT @@global.low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@global.low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='low_priority_updates';
-@@global.low_priority_updates = VARIABLE_VALUE
+IF(@@global.low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_069_07-----------------------#'
-SELECT @@session.low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@session.low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='low_priority_updates';
-@@session.low_priority_updates = VARIABLE_VALUE
+IF(@@session.low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_069_08----------------------#'
SET @@low_priority_updates = FALSE;
diff --git a/mysql-test/suite/sys_vars/r/myisam_use_mmap_basic.result b/mysql-test/suite/sys_vars/r/myisam_use_mmap_basic.result
index c0f92acb983..4b0e4afa38e 100644
--- a/mysql-test/suite/sys_vars/r/myisam_use_mmap_basic.result
+++ b/mysql-test/suite/sys_vars/r/myisam_use_mmap_basic.result
@@ -11,10 +11,10 @@ COUNT(@@GLOBAL.myisam_use_mmap)
1
1 Expected
'#---------------------BS_STVARS_042_03----------------------#'
-SELECT @@GLOBAL.myisam_use_mmap = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.myisam_use_mmap, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='myisam_use_mmap';
-@@GLOBAL.myisam_use_mmap = VARIABLE_VALUE
+IF(@@GLOBAL.myisam_use_mmap, "ON", "OFF") = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.myisam_use_mmap);
diff --git a/mysql-test/suite/sys_vars/r/new_basic.result b/mysql-test/suite/sys_vars/r/new_basic.result
index b36e540ddd9..5854649e6b1 100644
--- a/mysql-test/suite/sys_vars/r/new_basic.result
+++ b/mysql-test/suite/sys_vars/r/new_basic.result
@@ -117,16 +117,16 @@ ERROR 42000: Variable 'new' can't be set to the value of '65550'
SET @@session.new = test;
ERROR 42000: Variable 'new' can't be set to the value of 'test'
'#------------------FN_DYNVARS_113_06-----------------------#'
-SELECT @@global.new = VARIABLE_VALUE
+SELECT IF(@@global.new, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='new';
-@@global.new = VARIABLE_VALUE
+IF(@@global.new, "ON", "OFF") = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_113_07-----------------------#'
-SELECT @@session.new = VARIABLE_VALUE
+SELECT IF(@@session.new, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='new';
-@@session.new = VARIABLE_VALUE
+IF(@@session.new, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_113_08----------------------#'
SET @@new = OFF;
diff --git a/mysql-test/suite/sys_vars/r/old_passwords_basic.result b/mysql-test/suite/sys_vars/r/old_passwords_basic.result
index ecf23ab302b..f8600167801 100644
--- a/mysql-test/suite/sys_vars/r/old_passwords_basic.result
+++ b/mysql-test/suite/sys_vars/r/old_passwords_basic.result
@@ -113,16 +113,16 @@ ERROR 42000: Variable 'old_passwords' can't be set to the value of '65550'
SET @@session.old_passwords = test;
ERROR 42000: Variable 'old_passwords' can't be set to the value of 'test'
'#------------------FN_DYNVARS_114_06-----------------------#'
-SELECT @@global.old_passwords = VARIABLE_VALUE
+SELECT IF(@@global.old_passwords, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='old_passwords';
-@@global.old_passwords = VARIABLE_VALUE
+IF(@@global.old_passwords, "ON", "OFF") = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_114_07-----------------------#'
-SELECT @@session.old_passwords = VARIABLE_VALUE
+SELECT IF(@@session.old_passwords, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='old_passwords';
-@@session.old_passwords = VARIABLE_VALUE
+IF(@@session.old_passwords, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_114_08----------------------#'
SET @@old_passwords = OFF;
diff --git a/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result b/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result
index bff07741656..bfbebab7ed1 100644
--- a/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result
+++ b/mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_basic.result
@@ -103,10 +103,10 @@ SELECT @@session.query_cache_wlock_invalidate AS res_is_1;
res_is_1
1
'#----------------------FN_DYNVARS_135_06------------------------#'
-SELECT @@global.query_cache_wlock_invalidate = VARIABLE_VALUE
+SELECT IF(@@global.query_cache_wlock_invalidate, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='query_cache_wlock_invalidate';
-@@global.query_cache_wlock_invalidate = VARIABLE_VALUE
+IF(@@global.query_cache_wlock_invalidate, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@global.query_cache_wlock_invalidate;
@@global.query_cache_wlock_invalidate
@@ -117,11 +117,11 @@ WHERE VARIABLE_NAME='query_cache_wlock_invalidate';
VARIABLE_VALUE
OFF
'#----------------------FN_DYNVARS_135_07------------------------#'
-SELECT @@session.query_cache_wlock_invalidate = VARIABLE_VALUE
+SELECT IF(@@session.query_cache_wlock_invalidate, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='query_cache_wlock_invalidate';
-@@session.query_cache_wlock_invalidate = VARIABLE_VALUE
-0
+IF(@@session.query_cache_wlock_invalidate, "ON", "OFF") = VARIABLE_VALUE
+1
SELECT @@session.query_cache_wlock_invalidate;
@@session.query_cache_wlock_invalidate
1
diff --git a/mysql-test/suite/sys_vars/r/read_only_basic.result b/mysql-test/suite/sys_vars/r/read_only_basic.result
index ac153fa337c..4ea316a41f1 100644
--- a/mysql-test/suite/sys_vars/r/read_only_basic.result
+++ b/mysql-test/suite/sys_vars/r/read_only_basic.result
@@ -82,15 +82,15 @@ SELECT @@read_only;
@@read_only
0
'#----------------------FN_DYNVARS_139_06------------------------#'
-SELECT @@global.read_only = VARIABLE_VALUE
+SELECT IF(@@global.read_only, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='read_only';
-@@global.read_only = VARIABLE_VALUE
+IF(@@global.read_only, "ON", "OFF") = VARIABLE_VALUE
1
-SELECT @@read_only = VARIABLE_VALUE
+SELECT IF(@@read_only, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='read_only';
-@@read_only = VARIABLE_VALUE
+IF(@@read_only, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_139_07----------------------#'
SET @@global.read_only = 1;
diff --git a/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result b/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result
index 6f938c5265f..660550639cc 100644
--- a/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result
+++ b/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result
@@ -69,10 +69,10 @@ ERROR HY000: Variable 'relay_log_purge' is a GLOBAL variable and should be set w
SELECT @@session.relay_log_purge;
ERROR HY000: Variable 'relay_log_purge' is a GLOBAL variable
'#----------------------FN_DYNVARS_141_06------------------------#'
-SELECT @@global.relay_log_purge = VARIABLE_VALUE
+SELECT IF(@@global.relay_log_purge, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='relay_log_purge';
-@@global.relay_log_purge = VARIABLE_VALUE
+IF(@@global.relay_log_purge, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_141_07----------------------#'
SET @@global.relay_log_purge = 1;
diff --git a/mysql-test/suite/sys_vars/r/secure_auth_basic.result b/mysql-test/suite/sys_vars/r/secure_auth_basic.result
index b8a903ba420..9f12a1760a4 100644
--- a/mysql-test/suite/sys_vars/r/secure_auth_basic.result
+++ b/mysql-test/suite/sys_vars/r/secure_auth_basic.result
@@ -68,11 +68,11 @@ WHERE VARIABLE_NAME='secure_auth';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_143_07------------------------#'
-SELECT @@global.secure_auth = VARIABLE_VALUE
+SELECT IF(@@global.secure_auth, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='secure_auth';
-@@global.secure_auth = VARIABLE_VALUE
-0
+IF(@@global.secure_auth, "ON", "OFF") = VARIABLE_VALUE
+1
SELECT @@global.secure_auth;
@@global.secure_auth
1
diff --git a/mysql-test/suite/sys_vars/r/slave_allow_batching_basic.result b/mysql-test/suite/sys_vars/r/slave_allow_batching_basic.result
index 186cfbc8f0f..36f0978d3af 100644
--- a/mysql-test/suite/sys_vars/r/slave_allow_batching_basic.result
+++ b/mysql-test/suite/sys_vars/r/slave_allow_batching_basic.result
@@ -8,5 +8,8 @@ ERROR HY000: Unknown system variable 'slave_allow_batching'
'#-------------------FN_DYNVARS_145_05----------------------------#'
'#----------------------FN_DYNVARS_145_06------------------------#'
'#----------------------FN_DYNVARS_145_07------------------------#'
+SELECT IF(@@global.slave_allow_batching, "ON", "OFF") = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='slave_allow_batching';
+IF(@@global.slave_allow_batching, "ON", "OFF") = VARIABLE_VALUE
+1
'#---------------------FN_DYNVARS_145_08-------------------------#'
'#---------------------FN_DYNVARS_145_09----------------------#'
diff --git a/mysql-test/suite/sys_vars/r/slave_compressed_protocol_basic.result b/mysql-test/suite/sys_vars/r/slave_compressed_protocol_basic.result
index 3f2d9d2fb3f..039cce257e5 100644
--- a/mysql-test/suite/sys_vars/r/slave_compressed_protocol_basic.result
+++ b/mysql-test/suite/sys_vars/r/slave_compressed_protocol_basic.result
@@ -66,11 +66,11 @@ WHERE VARIABLE_NAME='slave_compressed_protocol';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_147_07------------------------#'
-SELECT @@global.slave_compressed_protocol = VARIABLE_VALUE
+SELECT IF(@@global.slave_compressed_protocol, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='slave_compressed_protocol';
-@@global.slave_compressed_protocol = VARIABLE_VALUE
-0
+IF(@@global.slave_compressed_protocol, "ON", "OFF") = VARIABLE_VALUE
+1
SELECT @@global.slave_compressed_protocol;
@@global.slave_compressed_protocol
1
diff --git a/mysql-test/suite/sys_vars/r/slow_query_log_basic.result b/mysql-test/suite/sys_vars/r/slow_query_log_basic.result
index 716309aeaff..aece80cdada 100644
--- a/mysql-test/suite/sys_vars/r/slow_query_log_basic.result
+++ b/mysql-test/suite/sys_vars/r/slow_query_log_basic.result
@@ -47,10 +47,10 @@ ERROR HY000: Variable 'slow_query_log' is a GLOBAL variable and should be set wi
SELECT @@session.slow_query_log;
ERROR HY000: Variable 'slow_query_log' is a GLOBAL variable
'#----------------------FN_DYNVARS_004_05------------------------#'
-SELECT @@global.slow_query_log = VARIABLE_VALUE
+SELECT IF(@@global.slow_query_log, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='slow_query_log';
-@@global.slow_query_log = VARIABLE_VALUE
+IF(@@global.slow_query_log, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_004_06----------------------#'
SET @@global.slow_query_log = 0;
diff --git a/mysql-test/suite/sys_vars/r/sql_auto_is_null_basic.result b/mysql-test/suite/sys_vars/r/sql_auto_is_null_basic.result
index b3a3eecd93a..0d8247ae1ef 100644
--- a/mysql-test/suite/sys_vars/r/sql_auto_is_null_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_auto_is_null_basic.result
@@ -12,11 +12,11 @@ COUNT(@@SESSION.sql_auto_is_null)
1
1 Expected
'#---------------------BS_STVARS_044_03----------------------#'
-SELECT @@SESSION.sql_auto_is_null = VARIABLE_VALUE
+SELECT IF(@@SESSION.sql_auto_is_null, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_auto_is_null';
-@@SESSION.sql_auto_is_null = VARIABLE_VALUE
-0
+IF(@@SESSION.sql_auto_is_null, "ON", "OFF") = VARIABLE_VALUE
+1
1 Expected
SELECT COUNT(@@SESSION.sql_auto_is_null);
COUNT(@@SESSION.sql_auto_is_null)
diff --git a/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result b/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result
index 1171382380d..cf071b5b417 100644
--- a/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_big_selects_basic.result
@@ -66,10 +66,10 @@ WHERE VARIABLE_NAME='sql_big_selects';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_153_07------------------------#'
-SELECT @@session.sql_big_selects = VARIABLE_VALUE
+SELECT IF(@@session.sql_big_selects, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_big_selects';
-@@session.sql_big_selects = VARIABLE_VALUE
+IF(@@session.sql_big_selects, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
diff --git a/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result b/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result
index bce14b2aba2..46e93f7ff23 100644
--- a/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_big_tables_basic.result
@@ -71,10 +71,10 @@ WHERE VARIABLE_NAME='sql_big_tables';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_154_07------------------------#'
-SELECT @@session.sql_big_tables = VARIABLE_VALUE
+SELECT IF(@@session.sql_big_tables, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_big_tables';
-@@session.sql_big_tables = VARIABLE_VALUE
+IF(@@session.sql_big_tables, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_big_tables;
@@session.sql_big_tables
diff --git a/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result b/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result
index d03b688dbe6..146872afc1d 100644
--- a/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_buffer_result_basic.result
@@ -79,10 +79,10 @@ WHERE VARIABLE_NAME='sql_buffer_result';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_155_07------------------------#'
-SELECT @@session.sql_buffer_result = VARIABLE_VALUE
+SELECT IF(@@session.sql_buffer_result, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_buffer_result';
-@@session.sql_buffer_result = VARIABLE_VALUE
+IF(@@session.sql_buffer_result, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_buffer_result;
@@session.sql_buffer_result
diff --git a/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result b/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result
index 4e37c2079d6..751b801047c 100644
--- a/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_log_bin_basic.result
@@ -69,10 +69,10 @@ SELECT count(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARI
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_156_07------------------------#'
-SELECT @@session.sql_log_bin = VARIABLE_VALUE
+SELECT IF(@@session.sql_log_bin, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_log_bin';
-@@session.sql_log_bin = VARIABLE_VALUE
+IF(@@session.sql_log_bin, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_log_bin;
@@session.sql_log_bin
diff --git a/mysql-test/suite/sys_vars/r/sql_log_off_basic.result b/mysql-test/suite/sys_vars/r/sql_log_off_basic.result
index 03846cb6ce8..9f610991ce2 100644
--- a/mysql-test/suite/sys_vars/r/sql_log_off_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_log_off_basic.result
@@ -71,10 +71,10 @@ WHERE VARIABLE_NAME='sql_log_off';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_157_07------------------------#'
-SELECT @@session.sql_log_off = VARIABLE_VALUE
+SELECT IF(@@session.sql_log_off, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_log_off';
-@@session.sql_log_off = VARIABLE_VALUE
+IF(@@session.sql_log_off, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_log_off;
@@session.sql_log_off
diff --git a/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result b/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result
index 6a09e6720b3..7b834d70038 100644
--- a/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_low_priority_updates_basic.result
@@ -102,10 +102,10 @@ SELECT @@session.sql_low_priority_updates AS res_is_1;
res_is_1
1
'#----------------------FN_DYNVARS_159_06------------------------#'
-SELECT @@global.sql_low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@global.sql_low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='sql_low_priority_updates';
-@@global.sql_low_priority_updates = VARIABLE_VALUE
+IF(@@global.sql_low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@global.sql_low_priority_updates;
@@global.sql_low_priority_updates
@@ -116,11 +116,11 @@ WHERE VARIABLE_NAME='sql_low_priority_updates';
VARIABLE_VALUE
OFF
'#----------------------FN_DYNVARS_159_07------------------------#'
-SELECT @@session.sql_low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@session.sql_low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_low_priority_updates';
-@@session.sql_low_priority_updates = VARIABLE_VALUE
-0
+IF(@@session.sql_low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
+1
SELECT @@session.sql_low_priority_updates;
@@session.sql_low_priority_updates
1
diff --git a/mysql-test/suite/sys_vars/r/sql_notes_basic.result b/mysql-test/suite/sys_vars/r/sql_notes_basic.result
index 5dd792d8ede..d6ec1239f45 100644
--- a/mysql-test/suite/sys_vars/r/sql_notes_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_notes_basic.result
@@ -69,10 +69,10 @@ SELECT count(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARI
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_161_07------------------------#'
-SELECT @@session.sql_notes = VARIABLE_VALUE
+SELECT IF(@@session.sql_notes, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_notes';
-@@session.sql_notes = VARIABLE_VALUE
+IF(@@session.sql_notes, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_notes;
@@session.sql_notes
diff --git a/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result b/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result
index 2550f2d1057..ed9322618f0 100644
--- a/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_quote_show_create_basic.result
@@ -71,10 +71,10 @@ WHERE VARIABLE_NAME='sql_quote_show_create';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_162_07------------------------#'
-SELECT @@session.sql_quote_show_create = VARIABLE_VALUE
+SELECT IF(@@session.sql_quote_show_create, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_quote_show_create';
-@@session.sql_quote_show_create = VARIABLE_VALUE
+IF(@@session.sql_quote_show_create, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_quote_show_create;
@@session.sql_quote_show_create
diff --git a/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result b/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result
index 539b38bb1fe..4daf78228f3 100644
--- a/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_safe_updates_basic.result
@@ -71,10 +71,10 @@ WHERE VARIABLE_NAME='sql_safe_updates';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_163_07------------------------#'
-SELECT @@session.sql_safe_updates = VARIABLE_VALUE
+SELECT IF(@@session.sql_safe_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_safe_updates';
-@@session.sql_safe_updates = VARIABLE_VALUE
+IF(@@session.sql_safe_updates, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_safe_updates;
@@session.sql_safe_updates
diff --git a/mysql-test/suite/sys_vars/r/sql_warnings_basic.result b/mysql-test/suite/sys_vars/r/sql_warnings_basic.result
index 46907c0ced8..cf39ef851d4 100644
--- a/mysql-test/suite/sys_vars/r/sql_warnings_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_warnings_basic.result
@@ -71,10 +71,10 @@ WHERE VARIABLE_NAME='sql_warnings';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_166_07------------------------#'
-SELECT @@session.sql_warnings = VARIABLE_VALUE
+SELECT IF(@@session.sql_warnings, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_warnings';
-@@session.sql_warnings = VARIABLE_VALUE
+IF(@@session.sql_warnings, "ON", "OFF") = VARIABLE_VALUE
1
SELECT @@session.sql_warnings;
@@session.sql_warnings
diff --git a/mysql-test/suite/sys_vars/r/sync_frm_basic.result b/mysql-test/suite/sys_vars/r/sync_frm_basic.result
index 9792307d17f..aa5416749a3 100644
--- a/mysql-test/suite/sys_vars/r/sync_frm_basic.result
+++ b/mysql-test/suite/sys_vars/r/sync_frm_basic.result
@@ -69,10 +69,10 @@ ERROR HY000: Variable 'sync_frm' is a GLOBAL variable and should be set with SET
SELECT @@session.sync_frm;
ERROR HY000: Variable 'sync_frm' is a GLOBAL variable
'#----------------------FN_DYNVARS_169_06------------------------#'
-SELECT @@global.sync_frm = VARIABLE_VALUE
+SELECT IF(@@global.sync_frm, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='sync_frm';
-@@global.sync_frm = VARIABLE_VALUE
+IF(@@global.sync_frm, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_169_07----------------------#'
SET @@global.sync_frm = 1;
diff --git a/mysql-test/suite/sys_vars/r/timed_mutexes_basic.result b/mysql-test/suite/sys_vars/r/timed_mutexes_basic.result
index d8bd2cd975f..50a5285b0d7 100644
--- a/mysql-test/suite/sys_vars/r/timed_mutexes_basic.result
+++ b/mysql-test/suite/sys_vars/r/timed_mutexes_basic.result
@@ -67,11 +67,11 @@ WHERE VARIABLE_NAME='timed_mutexes';
count(VARIABLE_VALUE)
1
'#----------------------FN_DYNVARS_177_07------------------------#'
-SELECT @@global.timed_mutexes = VARIABLE_VALUE
+SELECT IF(@@global.timed_mutexes, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='timed_mutexes';
-@@global.timed_mutexes = VARIABLE_VALUE
-0
+IF(@@global.timed_mutexes, "ON", "OFF") = VARIABLE_VALUE
+1
SELECT @@global.timed_mutexes;
@@global.timed_mutexes
1
diff --git a/mysql-test/suite/sys_vars/r/unique_checks_basic.result b/mysql-test/suite/sys_vars/r/unique_checks_basic.result
index cc22c1c7f98..50ca7317490 100644
--- a/mysql-test/suite/sys_vars/r/unique_checks_basic.result
+++ b/mysql-test/suite/sys_vars/r/unique_checks_basic.result
@@ -58,10 +58,10 @@ ERROR 42000: Variable 'unique_checks' can't be set to the value of 'test'
SET @@session.unique_checks = 123456789031;
ERROR 42000: Variable 'unique_checks' can't be set to the value of '123456789031'
'#------------------FN_DYNVARS_005_07-----------------------#'
-SELECT @@session.unique_checks = VARIABLE_VALUE
+SELECT IF(@@session.unique_checks, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='unique_checks';
-@@session.unique_checks = VARIABLE_VALUE
+IF(@@session.unique_checks, "ON", "OFF") = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_001_08----------------------#'
SET @@unique_checks = 1;
diff --git a/mysql-test/suite/sys_vars/t/auto_commit_basic.test b/mysql-test/suite/sys_vars/t/auto_commit_basic.test
index 0ea070ded59..b899c273093 100644
--- a/mysql-test/suite/sys_vars/t/auto_commit_basic.test
+++ b/mysql-test/suite/sys_vars/t/auto_commit_basic.test
@@ -113,7 +113,7 @@ SELECT @@global.autocommit;
# Check if the value in SESSION Table matches value in variable #
#########################################################################
-SELECT @@session.autocommit = VARIABLE_VALUE
+SELECT IF(@@session.autocommit, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='autocommit';
--echo Bug # 34839: Values in variable and information_schema do not match for autocommit
@@ -124,7 +124,7 @@ WHERE VARIABLE_NAME='autocommit';
#########################################################################
SET @@autocommit = 1;
-SELECT @@autocommit = VARIABLE_VALUE
+SELECT IF(@@autocommit, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='autocommit';
diff --git a/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test b/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test
index 74da0904454..005aec91acf 100644
--- a/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test
+++ b/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test
@@ -113,7 +113,7 @@ SELECT @@session.automatic_sp_privileges;
# Check if the value in GLOBAL Tables matches values in variable #
##############################################################################
-SELECT @@global.automatic_sp_privileges = VARIABLE_VALUE
+SELECT IF(@@global.automatic_sp_privileges, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='automatic_sp_privileges';
echo 'Bug# 34839: Values in variable and information_schema donot match';
diff --git a/mysql-test/suite/sys_vars/t/big_tables_basic.test b/mysql-test/suite/sys_vars/t/big_tables_basic.test
index 8665895bb19..67215f2625d 100644
--- a/mysql-test/suite/sys_vars/t/big_tables_basic.test
+++ b/mysql-test/suite/sys_vars/t/big_tables_basic.test
@@ -107,7 +107,7 @@ SELECT @@global.big_tables;
# Check if the value in SESSION Tables matches values in variable #
##############################################################################
-SELECT @@big_tables = VARIABLE_VALUE
+SELECT IF(@@big_tables, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='big_tables';
--echo Bug # 34839: Values in variable and information_schema do not match for autocommit
diff --git a/mysql-test/suite/sys_vars/t/engine_condition_pushdown_basic.test b/mysql-test/suite/sys_vars/t/engine_condition_pushdown_basic.test
index ee781159d6a..58ac196d1c2 100644
--- a/mysql-test/suite/sys_vars/t/engine_condition_pushdown_basic.test
+++ b/mysql-test/suite/sys_vars/t/engine_condition_pushdown_basic.test
@@ -160,7 +160,7 @@ SELECT @@session.engine_condition_pushdown AS res_is_1;
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.engine_condition_pushdown = VARIABLE_VALUE
+SELECT IF(@@global.engine_condition_pushdown, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='engine_condition_pushdown';
SELECT @@global.engine_condition_pushdown;
@@ -173,7 +173,7 @@ WHERE VARIABLE_NAME='engine_condition_pushdown';
# Check if the value in SESSION Table matches value in variable #
#########################################################################
-SELECT @@session.engine_condition_pushdown = VARIABLE_VALUE
+SELECT IF(@@session.engine_condition_pushdown, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='engine_condition_pushdown';
SELECT @@session.engine_condition_pushdown;
diff --git a/mysql-test/suite/sys_vars/t/flush_basic.test b/mysql-test/suite/sys_vars/t/flush_basic.test
index f5f6665562e..0b8fc0388ee 100644
--- a/mysql-test/suite/sys_vars/t/flush_basic.test
+++ b/mysql-test/suite/sys_vars/t/flush_basic.test
@@ -120,7 +120,7 @@ SELECT @@session.flush;
# Check if the value in GLOBAL Tables matches values in variable #
####################################################################
-SELECT @@global.flush = VARIABLE_VALUE
+SELECT IF(@@global.flush, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='flush';
diff --git a/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test b/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test
index 54d94aca971..d7a01f2bf71 100644
--- a/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test
+++ b/mysql-test/suite/sys_vars/t/foreign_key_checks_basic.test
@@ -131,7 +131,7 @@ SELECT count(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARI
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.foreign_key_checks = VARIABLE_VALUE
+SELECT IF(@@session.foreign_key_checks, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='foreign_key_checks';
SELECT @@session.foreign_key_checks;
diff --git a/mysql-test/suite/sys_vars/t/general_log_basic.test b/mysql-test/suite/sys_vars/t/general_log_basic.test
index 82f3be45bc9..6a1d00f1b6f 100644
--- a/mysql-test/suite/sys_vars/t/general_log_basic.test
+++ b/mysql-test/suite/sys_vars/t/general_log_basic.test
@@ -103,7 +103,7 @@ SELECT @@session.general_log;
# Check if the value in GLOBAL Tables matches values in variable #
##############################################################################
-SELECT @@global.general_log = VARIABLE_VALUE
+SELECT IF(@@global.general_log, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='general_log';
diff --git a/mysql-test/suite/sys_vars/t/innodb_checksums_basic.test b/mysql-test/suite/sys_vars/t/innodb_checksums_basic.test
index 89daad9ce0a..c4c39d7d380 100644
--- a/mysql-test/suite/sys_vars/t/innodb_checksums_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_checksums_basic.test
@@ -52,7 +52,7 @@ SELECT COUNT(@@GLOBAL.innodb_checksums);
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.innodb_checksums = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_checksums, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_checksums';
--echo 1 Expected
diff --git a/mysql-test/suite/sys_vars/t/innodb_doublewrite_basic.test b/mysql-test/suite/sys_vars/t/innodb_doublewrite_basic.test
index 4a0460bb4bc..72dd22cbeb8 100644
--- a/mysql-test/suite/sys_vars/t/innodb_doublewrite_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_doublewrite_basic.test
@@ -52,7 +52,7 @@ SELECT COUNT(@@GLOBAL.innodb_doublewrite);
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.innodb_doublewrite = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_doublewrite, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_doublewrite';
--echo 1 Expected
diff --git a/mysql-test/suite/sys_vars/t/innodb_locks_unsafe_for_binlog_basic.test b/mysql-test/suite/sys_vars/t/innodb_locks_unsafe_for_binlog_basic.test
index 63835113770..08792d299a1 100644
--- a/mysql-test/suite/sys_vars/t/innodb_locks_unsafe_for_binlog_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_locks_unsafe_for_binlog_basic.test
@@ -52,7 +52,7 @@ SELECT COUNT(@@GLOBAL.innodb_locks_unsafe_for_binlog);
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.innodb_locks_unsafe_for_binlog = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_locks_unsafe_for_binlog, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_locks_unsafe_for_binlog';
--echo 1 Expected
diff --git a/mysql-test/suite/sys_vars/t/innodb_rollback_on_timeout_basic.test b/mysql-test/suite/sys_vars/t/innodb_rollback_on_timeout_basic.test
index c33e0fa1b75..81025bb9d73 100644
--- a/mysql-test/suite/sys_vars/t/innodb_rollback_on_timeout_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_rollback_on_timeout_basic.test
@@ -52,7 +52,7 @@ SELECT COUNT(@@GLOBAL.innodb_rollback_on_timeout);
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.innodb_rollback_on_timeout = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.innodb_rollback_on_timeout, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_rollback_on_timeout';
--echo 1 Expected
diff --git a/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test b/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test
index 6da3e68ebdf..840fd240bde 100644
--- a/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test
@@ -169,7 +169,7 @@ SELECT @@session.innodb_support_xa AS res_is_1;
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.innodb_support_xa =
+SELECT IF(@@global.innodb_support_xa, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_support_xa';
SELECT @@global.innodb_support_xa;
@@ -182,7 +182,7 @@ SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
# Check if the value in SESSION Table matches value in variable #
#########################################################################
-SELECT @@session.innodb_support_xa =
+SELECT IF(@@session.innodb_support_xa, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='innodb_support_xa';
SELECT @@session.innodb_support_xa;
diff --git a/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test b/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test
index 35961c43a7f..f7d06d18ada 100644
--- a/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test
@@ -167,7 +167,7 @@ SELECT @@session.innodb_table_locks AS res_is_1;
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.innodb_table_locks =
+SELECT IF(@@global.innodb_table_locks, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_table_locks';
SELECT @@global.innodb_table_locks;
@@ -179,7 +179,7 @@ SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
# Check if the value in SESSION Table matches value in variable #
#########################################################################
-SELECT @@session.innodb_table_locks =
+SELECT IF(@@session.innodb_table_locks, "ON", "OFF") =
VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='innodb_table_locks';
SELECT @@session.innodb_table_locks;
diff --git a/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test b/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test
index a855f56c863..bc6ac8687f7 100644
--- a/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test
+++ b/mysql-test/suite/sys_vars/t/keep_files_on_create_basic.test
@@ -156,7 +156,7 @@ SELECT @@session.keep_files_on_create;
####################################################################
-SELECT @@global.keep_files_on_create = VARIABLE_VALUE
+SELECT IF(@@global.keep_files_on_create, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='keep_files_on_create';
@@ -165,7 +165,7 @@ WHERE VARIABLE_NAME='keep_files_on_create';
# Check if the value in SESSION Table matches value in variable #
####################################################################
-SELECT @@session.keep_files_on_create = VARIABLE_VALUE
+SELECT IF(@@session.keep_files_on_create, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='keep_files_on_create';
diff --git a/mysql-test/suite/sys_vars/t/local_infile_basic.test b/mysql-test/suite/sys_vars/t/local_infile_basic.test
index 63f6b0fdb91..731eac42541 100644
--- a/mysql-test/suite/sys_vars/t/local_infile_basic.test
+++ b/mysql-test/suite/sys_vars/t/local_infile_basic.test
@@ -112,7 +112,7 @@ SELECT @@session.local_infile = 1;
# Check if the value in GLOBAL Tables matches values in variable #
####################################################################
-SELECT @@global.local_infile = VARIABLE_VALUE
+SELECT IF(@@global.local_infile, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='local_infile';
diff --git a/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test b/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test
index 3b8b43e1354..e7bdb433971 100644
--- a/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test
+++ b/mysql-test/suite/sys_vars/t/log_bin_trust_function_creators_basic.test
@@ -122,12 +122,12 @@ SET @@global.log_bin_trust_function_creators = test;
###############################################################################
-SELECT @@global.log_bin_trust_function_creators = VARIABLE_VALUE
+SELECT IF(@@global.log_bin_trust_function_creators, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='log_bin_trust_function_creators';
--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
-SELECT @@session.log_bin_trust_function_creators = VARIABLE_VALUE
+SELECT IF(@@session.log_bin_trust_function_creators, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='log_bin_trust_function_creators';
diff --git a/mysql-test/suite/sys_vars/t/log_queries_not_using_indexes_basic.test b/mysql-test/suite/sys_vars/t/log_queries_not_using_indexes_basic.test
index f1152c07176..f7e6e8df640 100644
--- a/mysql-test/suite/sys_vars/t/log_queries_not_using_indexes_basic.test
+++ b/mysql-test/suite/sys_vars/t/log_queries_not_using_indexes_basic.test
@@ -129,4 +129,5 @@ SET @@SESSION log_queries_not_using_indexes= TRUE;
SET @@global.log_queries_not_using_indexes= @start_value;
+SELECT IF(@@GLOBAL.log_queries_not_using_indexes, "ON", "OFF") = VARIABLE_VALUE
diff --git a/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test b/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test
index 0ce4ee8f921..762fa726f1f 100644
--- a/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test
+++ b/mysql-test/suite/sys_vars/t/low_priority_updates_basic.test
@@ -156,7 +156,7 @@ SET @@session.low_priority_updates = test;
####################################################################
-SELECT @@global.low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@global.low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='low_priority_updates';
@@ -165,7 +165,7 @@ WHERE VARIABLE_NAME='low_priority_updates';
# Check if the value in SESSION Table matches value in variable #
####################################################################
-SELECT @@session.low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@session.low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='low_priority_updates';
diff --git a/mysql-test/suite/sys_vars/t/myisam_use_mmap_basic.test b/mysql-test/suite/sys_vars/t/myisam_use_mmap_basic.test
index d2cc39cfea7..dd1f8dbeee7 100644
--- a/mysql-test/suite/sys_vars/t/myisam_use_mmap_basic.test
+++ b/mysql-test/suite/sys_vars/t/myisam_use_mmap_basic.test
@@ -54,7 +54,7 @@ SELECT COUNT(@@GLOBAL.myisam_use_mmap);
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
-SELECT @@GLOBAL.myisam_use_mmap = VARIABLE_VALUE
+SELECT IF(@@GLOBAL.myisam_use_mmap, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='myisam_use_mmap';
--echo 1 Expected
diff --git a/mysql-test/suite/sys_vars/t/new_basic.test b/mysql-test/suite/sys_vars/t/new_basic.test
index b1d12c9a4de..cf0ba08dfdb 100644
--- a/mysql-test/suite/sys_vars/t/new_basic.test
+++ b/mysql-test/suite/sys_vars/t/new_basic.test
@@ -154,7 +154,7 @@ SET @@session.new = test;
####################################################################
-SELECT @@global.new = VARIABLE_VALUE
+SELECT IF(@@global.new, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='new';
@@ -163,7 +163,7 @@ WHERE VARIABLE_NAME='new';
# Check if the value in SESSION Table matches value in variable #
####################################################################
-SELECT @@session.new = VARIABLE_VALUE
+SELECT IF(@@session.new, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='new';
diff --git a/mysql-test/suite/sys_vars/t/old_passwords_basic.test b/mysql-test/suite/sys_vars/t/old_passwords_basic.test
index b78ac9ca9b8..34a9394a1e7 100644
--- a/mysql-test/suite/sys_vars/t/old_passwords_basic.test
+++ b/mysql-test/suite/sys_vars/t/old_passwords_basic.test
@@ -154,7 +154,7 @@ SET @@session.old_passwords = test;
####################################################################
-SELECT @@global.old_passwords = VARIABLE_VALUE
+SELECT IF(@@global.old_passwords, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='old_passwords';
@@ -163,7 +163,7 @@ WHERE VARIABLE_NAME='old_passwords';
# Check if the value in SESSION Table matches value in variable #
####################################################################
-SELECT @@session.old_passwords = VARIABLE_VALUE
+SELECT IF(@@session.old_passwords, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='old_passwords';
diff --git a/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test b/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test
index f253c1b4f43..5acb36961af 100644
--- a/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test
+++ b/mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_basic.test
@@ -165,7 +165,7 @@ SELECT @@session.query_cache_wlock_invalidate AS res_is_1;
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.query_cache_wlock_invalidate = VARIABLE_VALUE
+SELECT IF(@@global.query_cache_wlock_invalidate, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='query_cache_wlock_invalidate';
SELECT @@global.query_cache_wlock_invalidate;
@@ -178,7 +178,7 @@ WHERE VARIABLE_NAME='query_cache_wlock_invalidate';
# Check if the value in SESSION Table matches value in variable #
#########################################################################
-SELECT @@session.query_cache_wlock_invalidate = VARIABLE_VALUE
+SELECT IF(@@session.query_cache_wlock_invalidate, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='query_cache_wlock_invalidate';
SELECT @@session.query_cache_wlock_invalidate;
diff --git a/mysql-test/suite/sys_vars/t/read_only_basic.test b/mysql-test/suite/sys_vars/t/read_only_basic.test
index 917842256b1..9d8078b8c68 100644
--- a/mysql-test/suite/sys_vars/t/read_only_basic.test
+++ b/mysql-test/suite/sys_vars/t/read_only_basic.test
@@ -121,11 +121,11 @@ SELECT @@read_only;
# Check if the value in GLOBAL & SESSION Tables matches values in variable #
##############################################################################
-SELECT @@global.read_only = VARIABLE_VALUE
+SELECT IF(@@global.read_only, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='read_only';
-SELECT @@read_only = VARIABLE_VALUE
+SELECT IF(@@read_only, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='read_only';
diff --git a/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test b/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test
index 7e4d6a51440..081b79ebb73 100644
--- a/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test
+++ b/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test
@@ -123,7 +123,7 @@ SELECT @@session.relay_log_purge;
# Check if the value in GLOBAL Tables matches values in variable #
#####################################################################
-SELECT @@global.relay_log_purge = VARIABLE_VALUE
+SELECT IF(@@global.relay_log_purge, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='relay_log_purge';
diff --git a/mysql-test/suite/sys_vars/t/secure_auth_basic.test b/mysql-test/suite/sys_vars/t/secure_auth_basic.test
index b52f219097b..4e4566ce1ff 100644
--- a/mysql-test/suite/sys_vars/t/secure_auth_basic.test
+++ b/mysql-test/suite/sys_vars/t/secure_auth_basic.test
@@ -130,7 +130,7 @@ WHERE VARIABLE_NAME='secure_auth';
# Check if the value in GLOBAL Table matches value in variable #
########################################################################
-SELECT @@global.secure_auth = VARIABLE_VALUE
+SELECT IF(@@global.secure_auth, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='secure_auth';
SELECT @@global.secure_auth;
diff --git a/mysql-test/suite/sys_vars/t/slave_allow_batching_basic.test b/mysql-test/suite/sys_vars/t/slave_allow_batching_basic.test
index cf31917933a..020fd9c84c2 100644
--- a/mysql-test/suite/sys_vars/t/slave_allow_batching_basic.test
+++ b/mysql-test/suite/sys_vars/t/slave_allow_batching_basic.test
@@ -130,7 +130,7 @@ SET @global_start_value = @@global.slave_allow_batching;
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-#SELECT @@global.slave_allow_batching = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='slave_allow_batching';
+#SELECT IF(@@global.slave_allow_batching, "ON", "OFF") = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='slave_allow_batching';
#SELECT @@global.slave_allow_batching;
#SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='slave_allow_batching';
#--echo 'Bug: value in information schema does not match'
diff --git a/mysql-test/suite/sys_vars/t/slave_compressed_protocol_basic.test b/mysql-test/suite/sys_vars/t/slave_compressed_protocol_basic.test
index 29a3227a8f5..25ac8f35c5d 100644
--- a/mysql-test/suite/sys_vars/t/slave_compressed_protocol_basic.test
+++ b/mysql-test/suite/sys_vars/t/slave_compressed_protocol_basic.test
@@ -127,7 +127,7 @@ WHERE VARIABLE_NAME='slave_compressed_protocol';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.slave_compressed_protocol = VARIABLE_VALUE
+SELECT IF(@@global.slave_compressed_protocol, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='slave_compressed_protocol';
SELECT @@global.slave_compressed_protocol;
diff --git a/mysql-test/suite/sys_vars/t/slow_query_log_basic.test b/mysql-test/suite/sys_vars/t/slow_query_log_basic.test
index 3a1b2fbd9e7..fef37b5ff4a 100644
--- a/mysql-test/suite/sys_vars/t/slow_query_log_basic.test
+++ b/mysql-test/suite/sys_vars/t/slow_query_log_basic.test
@@ -104,7 +104,7 @@ SELECT @@session.slow_query_log;
# Check if the value in GLOBAL Tables matches values in variable #
##############################################################################
-SELECT @@global.slow_query_log = VARIABLE_VALUE
+SELECT IF(@@global.slow_query_log, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='slow_query_log';
diff --git a/mysql-test/suite/sys_vars/t/sql_auto_is_null_basic.test b/mysql-test/suite/sys_vars/t/sql_auto_is_null_basic.test
index a843b88bf85..da01a3b4459 100644
--- a/mysql-test/suite/sys_vars/t/sql_auto_is_null_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_auto_is_null_basic.test
@@ -55,7 +55,7 @@ SELECT COUNT(@@SESSION.sql_auto_is_null);
# Check if the value in SESSION Table matches value in variable #
#################################################################
-SELECT @@SESSION.sql_auto_is_null = VARIABLE_VALUE
+SELECT IF(@@SESSION.sql_auto_is_null, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_auto_is_null';
--echo 1 Expected
diff --git a/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test b/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test
index dd83a19230a..dd9b585cc84 100644
--- a/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_big_selects_basic.test
@@ -132,7 +132,7 @@ WHERE VARIABLE_NAME='sql_big_selects';
# Check if the value in GLOBAL Table matches value in variable #
########################################################################
-SELECT @@session.sql_big_selects = VARIABLE_VALUE
+SELECT IF(@@session.sql_big_selects, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_big_selects';
SELECT @@session.sql_big_selects;
diff --git a/mysql-test/suite/sys_vars/t/sql_big_tables_basic.test b/mysql-test/suite/sys_vars/t/sql_big_tables_basic.test
index 4e3dbdc9504..64ce47b044b 100644
--- a/mysql-test/suite/sys_vars/t/sql_big_tables_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_big_tables_basic.test
@@ -135,7 +135,7 @@ WHERE VARIABLE_NAME='sql_big_tables';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_big_tables = VARIABLE_VALUE
+SELECT IF(@@session.sql_big_tables, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_big_tables';
SELECT @@session.sql_big_tables;
diff --git a/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test b/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test
index f5a5e323fc4..04e65239ccb 100644
--- a/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_buffer_result_basic.test
@@ -144,7 +144,7 @@ WHERE VARIABLE_NAME='sql_buffer_result';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_buffer_result = VARIABLE_VALUE
+SELECT IF(@@session.sql_buffer_result, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_buffer_result';
SELECT @@session.sql_buffer_result;
diff --git a/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test b/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test
index 0f6d9e1e126..9ac0474f982 100644
--- a/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_log_bin_basic.test
@@ -134,7 +134,7 @@ SELECT count(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARI
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_log_bin = VARIABLE_VALUE
+SELECT IF(@@session.sql_log_bin, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_log_bin';
SELECT @@session.sql_log_bin;
diff --git a/mysql-test/suite/sys_vars/t/sql_log_off_basic.test b/mysql-test/suite/sys_vars/t/sql_log_off_basic.test
index bcf9e87c1dd..a208d30a39b 100644
--- a/mysql-test/suite/sys_vars/t/sql_log_off_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_log_off_basic.test
@@ -135,7 +135,7 @@ WHERE VARIABLE_NAME='sql_log_off';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_log_off = VARIABLE_VALUE
+SELECT IF(@@session.sql_log_off, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_log_off';
SELECT @@session.sql_log_off;
diff --git a/mysql-test/suite/sys_vars/t/sql_low_priority_updates_basic.test b/mysql-test/suite/sys_vars/t/sql_low_priority_updates_basic.test
index 499723b636d..8d75349b851 100644
--- a/mysql-test/suite/sys_vars/t/sql_low_priority_updates_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_low_priority_updates_basic.test
@@ -166,7 +166,7 @@ SELECT @@session.sql_low_priority_updates AS res_is_1;
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.sql_low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@global.sql_low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='sql_low_priority_updates';
SELECT @@global.sql_low_priority_updates;
@@ -179,7 +179,7 @@ WHERE VARIABLE_NAME='sql_low_priority_updates';
# Check if the value in SESSION Table matches value in variable #
#########################################################################
-SELECT @@session.sql_low_priority_updates = VARIABLE_VALUE
+SELECT IF(@@session.sql_low_priority_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_low_priority_updates';
SELECT @@session.sql_low_priority_updates;
diff --git a/mysql-test/suite/sys_vars/t/sql_notes_basic.test b/mysql-test/suite/sys_vars/t/sql_notes_basic.test
index 984dca34e46..461e5d35e4f 100644
--- a/mysql-test/suite/sys_vars/t/sql_notes_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_notes_basic.test
@@ -135,7 +135,7 @@ SELECT count(VARIABLE_VALUE) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARI
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_notes = VARIABLE_VALUE
+SELECT IF(@@session.sql_notes, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_notes';
SELECT @@session.sql_notes;
diff --git a/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test b/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test
index 1919b3ee642..5e0edef55e5 100644
--- a/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_quote_show_create_basic.test
@@ -136,7 +136,7 @@ WHERE VARIABLE_NAME='sql_quote_show_create';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_quote_show_create = VARIABLE_VALUE
+SELECT IF(@@session.sql_quote_show_create, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_quote_show_create';
SELECT @@session.sql_quote_show_create;
diff --git a/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test b/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test
index 489b42949a0..4f2c57bdb81 100644
--- a/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_safe_updates_basic.test
@@ -135,7 +135,7 @@ WHERE VARIABLE_NAME='sql_safe_updates';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_safe_updates = VARIABLE_VALUE
+SELECT IF(@@session.sql_safe_updates, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_safe_updates';
SELECT @@session.sql_safe_updates;
diff --git a/mysql-test/suite/sys_vars/t/sql_warnings_basic.test b/mysql-test/suite/sys_vars/t/sql_warnings_basic.test
index f740403ceda..99a9ad8dda2 100644
--- a/mysql-test/suite/sys_vars/t/sql_warnings_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_warnings_basic.test
@@ -140,7 +140,7 @@ WHERE VARIABLE_NAME='sql_warnings';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@session.sql_warnings = VARIABLE_VALUE
+SELECT IF(@@session.sql_warnings, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='sql_warnings';
SELECT @@session.sql_warnings;
diff --git a/mysql-test/suite/sys_vars/t/sync_frm_basic.test b/mysql-test/suite/sys_vars/t/sync_frm_basic.test
index 6c00182a805..33e6202167f 100644
--- a/mysql-test/suite/sys_vars/t/sync_frm_basic.test
+++ b/mysql-test/suite/sys_vars/t/sync_frm_basic.test
@@ -121,7 +121,7 @@ SELECT @@session.sync_frm;
# Check if the value in GLOBAL Tables matches values in variable #
####################################################################
-SELECT @@global.sync_frm = VARIABLE_VALUE
+SELECT IF(@@global.sync_frm, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='sync_frm';
diff --git a/mysql-test/suite/sys_vars/t/timed_mutexes_basic.test b/mysql-test/suite/sys_vars/t/timed_mutexes_basic.test
index b0eb41afb49..9422ecdabf9 100644
--- a/mysql-test/suite/sys_vars/t/timed_mutexes_basic.test
+++ b/mysql-test/suite/sys_vars/t/timed_mutexes_basic.test
@@ -128,7 +128,7 @@ WHERE VARIABLE_NAME='timed_mutexes';
# Check if the value in GLOBAL Table matches value in variable #
#########################################################################
-SELECT @@global.timed_mutexes = VARIABLE_VALUE
+SELECT IF(@@global.timed_mutexes, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='timed_mutexes';
SELECT @@global.timed_mutexes;
diff --git a/mysql-test/suite/sys_vars/t/unique_checks_basic.test b/mysql-test/suite/sys_vars/t/unique_checks_basic.test
index 55308adcc82..364dfc07cd1 100644
--- a/mysql-test/suite/sys_vars/t/unique_checks_basic.test
+++ b/mysql-test/suite/sys_vars/t/unique_checks_basic.test
@@ -121,7 +121,7 @@ SET @@session.unique_checks = 123456789031;
# Check if the value in SESSION Table matches value in variable #
####################################################################
-SELECT @@session.unique_checks = VARIABLE_VALUE
+SELECT IF(@@session.unique_checks, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='unique_checks';
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 17549745203..bf599818ad6 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -1046,4 +1046,34 @@ ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9',
--disable_info
DROP TABLE t1;
+#
+# Bug#43508: Renaming timestamp or date column triggers table copy
+#
+
+CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL,
+ f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2);
+
+--echo this should affect no rows as there is no real change
+--enable_info
+ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL;
+--disable_info
+DROP TABLE t1;
+
--echo End of 5.1 tests
+
+#
+# Bug #31031 ALTER TABLE regression in 5.0
+#
+# The ALTER TABLE operation failed with
+# ERROR 1089 (HY000): Incorrect sub part key; ...
+#
+CREATE TABLE t1(c CHAR(10),
+ i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY);
+INSERT INTO t1 VALUES('a',2),('b',4),('c',6);
+ALTER TABLE t1
+ DROP i,
+ ADD i INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ AUTO_INCREMENT = 1;
+DROP TABLE t1;
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index d8466df14bf..05f739bfd69 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -10,37 +10,14 @@ insert into t1 values (1,2,"","Y","2002-03-03"), (3,4,"","N","2002-03-04"), (5,6
select count(*) from t1 procedure analyse();
select * from t1 procedure analyse();
select * from t1 procedure analyse(2);
+--error ER_WRONG_USAGE
create table t2 select * from t1 procedure analyse();
-select * from t2;
-drop table t1,t2;
+drop table t1;
--error ER_WRONG_USAGE
EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
#
-# Test with impossible where
-#
-create table t1 (a int not null);
-create table t2 select * from t1 where 0=1 procedure analyse();
-show create table t2;
-select * from t1 where 0=1 procedure analyse();
-insert into t1 values(1);
-drop table t2;
-create table t2 select * from t1 where 0=1 procedure analyse();
-show create table t2;
-select * from t2;
-insert into t2 select * from t1 procedure analyse();
-select * from t2;
-insert into t1 values(2);
-drop table t2;
-create table t2 select * from t1 where 0=1 procedure analyse();
-show create table t2;
-select * from t2;
-insert into t2 select * from t1 procedure analyse();
-select * from t2;
-drop table t1,t2;
-
-#
# Bug#2813 - analyse does not quote string values in enums from string
#
@@ -113,3 +90,46 @@ SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE();
DROP TABLE t1;
--echo End of 4.1 tests
+
+--echo #
+--echo # Bug #48293: crash with procedure analyse, view with > 10 columns,
+--echo # having clause...
+--echo #
+
+CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT,
+ f INT, g INT, h INT, i INT, j INT,k INT);
+INSERT INTO t1 VALUES (),();
+
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+--echo #should have a derived table
+EXPLAIN SELECT * FROM v1;
+--echo #should not crash
+--error ER_WRONG_USAGE
+SELECT * FROM v1 PROCEDURE analyse();
+--echo #should not crash
+--error ER_WRONG_USAGE
+SELECT * FROM t1 a, v1, t1 b PROCEDURE analyse();
+--echo #should not crash
+--error ER_WRONG_USAGE
+SELECT * FROM (SELECT * FROM t1 having a > 1) x PROCEDURE analyse();
+--echo #should not crash
+--error ER_WRONG_USAGE
+SELECT * FROM t1 a, (SELECT * FROM t1 having a > 1) x, t1 b PROCEDURE analyse();
+--echo #should not crash
+--error ER_ORDER_WITH_PROC
+SELECT 1 FROM t1 group by a having a > 1 order by 1 PROCEDURE analyse();
+
+DROP VIEW v1;
+DROP TABLE t1;
+
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1),(2);
+
+--echo # should not crash
+--error ER_WRONG_USAGE
+CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE();
+
+DROP TABLE t1;
+
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/bug40113.test b/mysql-test/t/bug40113.test
deleted file mode 100644
index 6d35d0b73d3..00000000000
--- a/mysql-test/t/bug40113.test
+++ /dev/null
@@ -1,46 +0,0 @@
---source include/have_innodb.inc
-
---echo #
---echo # Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout
---echo # without error
---echo #
-
-CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB;
-
-INSERT INTO t1 (a,b) VALUES (1070109,99);
-
-CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB;
-
-INSERT INTO t2 (b,a) VALUES (7,1070109);
-
-SELECT * FROM t1;
-
-BEGIN;
-
-SELECT b FROM t2 WHERE b=7 FOR UPDATE;
-
-CONNECT (addconroot, localhost, root,,);
-CONNECTION addconroot;
-
-BEGIN;
-
---error ER_LOCK_WAIT_TIMEOUT
-SELECT b FROM t2 WHERE b=7 FOR UPDATE;
-
---error ER_LOCK_WAIT_TIMEOUT
-INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7));
-
---error ER_LOCK_WAIT_TIMEOUT
-UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7);
-
---error ER_LOCK_WAIT_TIMEOUT
-DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7);
-
-SELECT * FROM t1;
-
-CONNECTION default;
-DISCONNECT addconroot;
-
-DROP TABLE t2, t1;
-
---echo End of 5.0 tests
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 5ffa1b93929..9f3c3a88151 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -1582,3 +1582,56 @@ create table t3 (a int) row_format=page;
--echo
--echo End of 5.1 tests
+
+
+###########################################################################
+
+--echo
+--echo # --
+--echo # -- Bug #43054 Assertion `!table->auto_increment_field_not_null'
+--echo # -- failed when redefining trigger
+--echo
+
+#--disable_abort_on_error
+
+CREATE TABLE B (
+ pk INTEGER AUTO_INCREMENT,
+ int_key INTEGER NOT NULL,
+ PRIMARY KEY (pk),
+ KEY (int_key)
+);
+
+INSERT IGNORE INTO B VALUES ('9', '9');
+
+CREATE TABLE IF NOT EXISTS t1 (
+ `pk` INTEGER NOT NULL AUTO_INCREMENT ,
+ `int` INTEGER ,
+ PRIMARY KEY ( `pk` )
+) SELECT `pk` , `int_key` FROM B ;
+
+--delimiter |
+
+CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ INSERT INTO t1 ( `int` ) VALUES (4 ),( 8 ),( 2 ) ;
+END ; |
+
+--delimiter ;
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+CREATE TABLE IF NOT EXISTS t1 (
+ `pk` INTEGER NOT NULL AUTO_INCREMENT ,
+ `int` INTEGER ,
+ PRIMARY KEY ( `pk` )
+) SELECT `pk` , `int_key` FROM B ;
+
+--delimiter |
+--error ER_NOT_SUPPORTED_YET
+CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ UPDATE A SET `pk`=1 WHERE `pk`=0 ;
+END ;|
+
+--delimiter ;
+
+DROP TABLE t1;
+DROP TABLE B;
diff --git a/mysql-test/t/ctype_collate.test b/mysql-test/t/ctype_collate.test
index 6b6abbcfbcc..cb2113277b9 100644
--- a/mysql-test/t/ctype_collate.test
+++ b/mysql-test/t/ctype_collate.test
@@ -172,6 +172,18 @@ DROP TABLE t1;
#
# Test that optimizer doesn't use indexes with wrong collation
#
+#
+# BUG#48447, Delivering too few records with indexes using collate syntax
+#
+create table t1 (a varchar(1) character set latin1 collate latin1_general_ci);
+insert into t1 values ('A'),('a'),('B'),('b'),('C'),('c');
+select * from t1 where a > 'B' collate latin1_bin;
+select * from t1 where a <> 'B' collate latin1_bin;
+create index i on t1 (a);
+select * from t1 where a > 'B' collate latin1_bin;
+select * from t1 where a <> 'B' collate latin1_bin;
+drop table t1;
+
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
diff --git a/mysql-test/t/ctype_ldml.test b/mysql-test/t/ctype_ldml.test
index e177c4522ae..7e469321d5b 100644
--- a/mysql-test/t/ctype_ldml.test
+++ b/mysql-test/t/ctype_ldml.test
@@ -57,6 +57,14 @@ SELECT * FROM t1 WHERE col1=col2 ORDER BY col1;
DROP TABLE t1;
--echo #
+--echo # Bug#45645 Mysql server close all connection and restart using lower function
+--echo #
+CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 COLLATE utf8_test_ci;
+INSERT INTO t1 (a) VALUES ('hello!');
+SELECT * FROM t1 WHERE LOWER(a)=LOWER('N');
+DROP TABLE t1;
+
+--echo #
--echo # Bug#43827 Server closes connections and restarts
--echo #
# Crash happened with a user-defined utf8 collation,
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 0a26c472f49..3cf87c2bd22 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -2,6 +2,8 @@
# Tests with the utf8 character set
#
+--source include/have_innodb.inc
+
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
@@ -256,9 +258,7 @@ drop table t1;
# Bug 4521: unique key prefix interacts poorly with utf8
# InnoDB: keys with prefix compression, case insensitive collation.
#
---disable_warnings
create table t1 (c varchar(30) character set utf8, unique(c(10))) engine=innodb;
---enable_warnings
insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z');
insert into t1 values ('aaaaaaaaaa');
--error ER_DUP_ENTRY
@@ -306,9 +306,7 @@ drop table t1;
# Bug 4521: unique key prefix interacts poorly with utf8
# InnoDB: fixed length keys, case insensitive collation
#
---disable_warnings
create table t1 (c char(3) character set utf8, unique (c(2))) engine=innodb;
---enable_warnings
insert into t1 values ('1'),('2'),('3'),('4'),('x'),('y'),('z');
insert into t1 values ('a');
insert into t1 values ('aa');
@@ -383,12 +381,10 @@ drop table t1;
# Bug 4531: unique key prefix interacts poorly with utf8
# Check BDB, case insensitive collation
#
---disable_warnings
create table t1 (
c char(10) character set utf8,
unique key a (c(1))
) engine=innodb;
---enable_warnings
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
--error ER_DUP_ENTRY
insert into t1 values ('aa');
@@ -506,12 +502,10 @@ drop table t1;
# Bug 4531: unique key prefix interacts poorly with utf8
# Check BDB, binary collation
#
---disable_warnings
create table t1 (
c char(10) character set utf8 collate utf8_bin,
unique key a (c(1))
) engine=innodb;
---enable_warnings
insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f');
--error ER_DUP_ENTRY
insert into t1 values ('aa');
@@ -543,12 +537,10 @@ drop table t1;
# Bug#4594: column index make = failed for gbk, but like works
# Check InnoDB
#
---disable_warnings
create table t1 (
str varchar(255) character set utf8 not null,
key str (str(2))
) engine=innodb;
---enable_warnings
INSERT INTO t1 VALUES ('str');
INSERT INTO t1 VALUES ('str2');
select * from t1 where str='str';
@@ -581,12 +573,10 @@ drop table t1;
# the same for BDB
#
---disable_warnings
create table t1 (
str varchar(255) character set utf8 not null,
key str (str(2))
) engine=innodb;
---enable_warnings
INSERT INTO t1 VALUES ('str');
INSERT INTO t1 VALUES ('str2');
select * from t1 where str='str';
@@ -603,14 +593,11 @@ DROP TABLE t1;
#
# Bug #5723: length(<varchar utf8 field>) returns varying results
#
---disable_warnings
SET NAMES utf8;
---disable_warnings
CREATE TABLE t1 (
subject varchar(255) character set utf8 collate utf8_unicode_ci,
p varchar(15) character set utf8
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
---enable_warnings
INSERT INTO t1 VALUES ('è°·å·ä¿ŠäºŒã¨ç”³ã—ã¾ã™ãŒã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆäºˆç´„ã®ä¼šå“¡ç™»éŒ²ã‚’ã—ã¾ã—ãŸã¨ã“ã‚ã€ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’é–“é•ãˆã¦ã—ã¾ã„会員IDãŒå—ã‘å–ã‚‹ã“ã¨ãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚é–“é•ãˆã‚¢ãƒ‰ãƒ¬ã‚¹ã¯tani-shun@n.vodafone.ne.jpを書ãè¾¼ã¿ã¾ã—ãŸã€‚ã©ã†ã™ã‚Œã°ã‚ˆã„ã§ã™ã‹ï¼Ÿ ãã®ä»–ã€ä½æ‰€ç­‰ã¯é–“é•ãˆã‚ã‚Šã¾ã›ã‚“。連絡ãã ã•ã„。よã‚ã—ããŠé¡˜ã„ã—ã¾ã™ã€‚m(__)m','040312-000057');
INSERT INTO t1 VALUES ('aaa','bbb');
SELECT length(subject) FROM t1;
@@ -661,18 +648,14 @@ DROP TABLE t1;
# Bug #6019 SELECT tries to use too short prefix index on utf8 data
#
set names utf8;
---disable_warnings
create table t1 (
a int primary key,
b varchar(6),
index b3(b(3))
) engine=innodb character set=utf8;
---enable_warnings
insert into t1 values(1,'foo'),(2,'foobar');
select * from t1 where b like 'foob%';
---disable_warnings
alter table t1 engine=innodb;
---enable_warnings
select * from t1 where b like 'foob%';
drop table t1;
@@ -841,14 +824,12 @@ INSERT INTO t1 VALUES
(1,'blah','464','aaa','fkc1c9ilc20x0hgae7lx6j09','ERR','ERR Имри.Ðфимим.Ðеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ðд.Д имдимримрад.Ðдимримримрмдиримримримр м.Дадимфшьмримд им.Ðдимимрн имадми','ИМРИ.ÐФИМИМ.ÐЕИМИМРИМДМРИМРМРИРОР',3,'2005-06-01 17:30:43','1234567890'),
(2,'blah','464','aaa','haxpl2ilc20x00bj4tt2m5ti','11','11 g','G',3,'2005-06-02 22:43:10','1234567890');
---disable_warnings
CREATE TABLE t2 (
`msisdn` varchar(15) NOT NULL default '',
`operator_id` int(11) NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
UNIQUE KEY `PK_user` (`msisdn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
---enable_warnings
INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25');
@@ -1013,10 +994,8 @@ drop table t1;
# additional tests from duplicate bug#20744 MySQL return no result
set names utf8;
---disable_warnings
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_general_ci;
---enable_warnings
insert into t1 values ('ã‚ã„ã†ãˆãŠã‹ããã‘ã“ã•ã—ã™ã›ã');
insert into t1 values ('ã•ã—ã™ã›ãã‹ããã‘ã“ã‚ã„ã†ãˆãŠ');
select a as gci1 from t1 where a like 'ã•ã—ã™ã›ãã‹ããã‘ã“ã‚ã„ã†ãˆãŠ%';
@@ -1024,10 +1003,8 @@ select a as gci2 from t1 where a like 'ã‚ã„ã†ãˆãŠã‹ããã‘ã“ã•ã—ã™ã
drop table t1;
set names utf8;
---disable_warnings
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_unicode_ci;
---enable_warnings
insert into t1 values ('ã‚ã„ã†ãˆãŠã‹ããã‘ã“ã•ã—ã™ã›ã');
insert into t1 values ('ã•ã—ã™ã›ãã‹ããã‘ã“ã‚ã„ã†ãˆãŠ');
select a as uci1 from t1 where a like 'ã•ã—ã™ã›ãã‹ããã‘ã“ã‚ã„ã†ãˆãŠ%';
@@ -1035,10 +1012,8 @@ select a as uci2 from t1 where a like 'ã‚ã„ã†ãˆãŠã‹ããã‘ã“ã•ã—ã™ã
drop table t1;
set names utf8;
---disable_warnings
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_bin;
---enable_warnings
insert into t1 values ('ã‚ã„ã†ãˆãŠã‹ããã‘ã“ã•ã—ã™ã›ã');
insert into t1 values ('ã•ã—ã™ã›ãã‹ããã‘ã“ã‚ã„ã†ãˆãŠ');
select a as bin1 from t1 where a like 'ã•ã—ã™ã›ãã‹ããã‘ã“ã‚ã„ã†ãˆãŠ%';
@@ -1363,26 +1338,22 @@ select concat(a, if(b>10, 'x' 'x', 'y' 'y')) from t1;
select concat(a, if(b>10, 'x' 'æ', 'y' 'ß')) from t1;
drop table t1;
-
#
# Bug#19960: Inconsistent results when joining
# InnoDB tables using partial UTF8 indexes
#
---disable_warnings
+
CREATE TABLE t1 (
colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL,
PRIMARY KEY (colA)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
---enable_warnings
INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar');
---disable_warnings
CREATE TABLE t2 (
colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL,
KEY bad (colA,colB(3))
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
---enable_warnings
INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar');
SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB
WHERE t1.colA < 3;
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index 14833b8f837..ee658d70d16 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -329,3 +329,38 @@ drop table t1;
set global low_priority_updates = @old_delayed_updates;
--echo End of 5.1 tests
+
+
+
+--echo #
+--echo # Bug #47274 assert in open_table on CREATE TABLE <already existing>
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+CREATE TABLE t1 ( f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1));
+
+--echo # The following CREATE TABLEs before gave an assert.
+
+INSERT DELAYED t1 VALUES (4);
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 AS SELECT 1 AS f1;
+
+REPLACE DELAYED t1 VALUES (5);
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 AS SELECT 1 AS f1;
+
+INSERT DELAYED t1 VALUES (6);
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 (f1 INTEGER);
+
+CREATE TABLE t2 (f1 INTEGER);
+INSERT DELAYED t1 VALUES (7);
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t1 LIKE t2;
+
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 8b34bd03faa..ad7617b9403 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -10,8 +10,8 @@
#
##############################################################################
kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
-innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently"
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes
partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes
-innodb_bug46000 : Bug#47860 2009-10-16 satyab Test fails for innodb plugin 1.0.5
+innodb-autoinc : Bug#48482 2009-11-02 svoj innodb-autoinc.test fails with results difference
+rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2
diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test
index bb4dd3e11f9..6be4ea25007 100644
--- a/mysql-test/t/drop.test
+++ b/mysql-test/t/drop.test
@@ -202,3 +202,24 @@ use test;
drop database mysqltestbug26703;
--echo End of 5.1 tests
+
+###########################################################################
+
+--echo
+--echo # --
+--echo # -- Bug#37431 (DROP TABLE does not report errors correctly).
+--echo # --
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--error ER_BAD_TABLE_ERROR
+DROP TABLE t1;
+
+SHOW WARNINGS;
+
+--echo
+--echo # --
+--echo # -- End of Bug#37431.
+--echo # --
diff --git a/mysql-test/t/drop_debug.test b/mysql-test/t/drop_debug.test
new file mode 100644
index 00000000000..97ee5847d0a
--- /dev/null
+++ b/mysql-test/t/drop_debug.test
@@ -0,0 +1,35 @@
+#
+# DROP-related tests which execution requires debug server.
+#
+--source include/have_debug.inc
+
+###########################################################################
+--echo
+--echo # --
+--echo # -- Bug#43138: DROP DATABASE failure does not clean up message list.
+--echo # --
+--echo
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysql_test;
+--enable_warnings
+
+--echo
+CREATE DATABASE mysql_test;
+CREATE TABLE mysql_test.t1(a INT);
+
+--echo
+SET SESSION DEBUG = "+d,bug43138";
+
+--echo
+DROP DATABASE mysql_test;
+
+--echo
+SET SESSION DEBUG = "-d,bug43138";
+
+--echo
+--echo # --
+--echo # -- End of Bug#43138.
+--echo # --
+
+###########################################################################
diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test
index 162a310c0a6..7e2a9bdc811 100644
--- a/mysql-test/t/explain.test
+++ b/mysql-test/t/explain.test
@@ -167,6 +167,25 @@ flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
drop tables t1, t2;
+--echo #
+--echo # Bug#48295:
+--echo # explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode
+--echo #
+
+CREATE TABLE t1 (f1 INT);
+
+SELECT @@session.sql_mode INTO @old_sql_mode;
+SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
+
+# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE.
+--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
+EXPLAIN EXTENDED SELECT 1 FROM t1
+ WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
+SHOW WARNINGS;
+
+SET SESSION sql_mode=@old_sql_mode;
+
+DROP TABLE t1;
--echo #
--echo # Bug#30302: Tables that were optimized away are printed in the
@@ -179,4 +198,5 @@ insert into t2 values(1),(2);
explain extended select * from t1 where f1=1;
explain extended select * from t1 join t2 on f1=f2 where f1=1;
drop table t1,t2;
+
--echo End of 5.1 tests.
diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test
index aeb09d52460..2d359383949 100644
--- a/mysql-test/t/flush_read_lock_kill.test
+++ b/mysql-test/t/flush_read_lock_kill.test
@@ -57,7 +57,7 @@ connection con1;
# debug build running without our --debug=make_global..., will be
# error 0 (no error). The only important thing to test is that on
# debug builds with our --debug=make_global... we don't hang forever.
---error 0,1053,2013
+--error 0,1317,2013
reap;
connection con2;
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index 19bbcf19cca..c325b3bd223 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -881,4 +881,25 @@ SELECT COUNT(*) FROM t1 IGNORE INDEX (b) WHERE
DROP TABLE t1;
+
+--echo #
+--echo # Bug #48258: Assertion failed when using a spatial index
+--echo #
+CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a));
+INSERT INTO t1 VALUES
+ (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')),
+ (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'));
+EXPLAIN SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+EXPLAIN SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+EXPLAIN SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+EXPLAIN SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+EXPLAIN SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)');
+DROP TABLE t1;
+
+
--echo End of 5.0 tests.
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 4a60e777cc7..2d10c3bf1e1 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -655,6 +655,22 @@ insert into t1 values (),(),();
select min(`col002`) from t1 union select `col002` from t1;
drop table t1;
+--echo #
+--echo # Bug #47780: crash when comparing GIS items from subquery
+--echo #
+
+CREATE TABLE t1(a INT, b MULTIPOLYGON);
+INSERT INTO t1 VALUES
+ (0,
+ GEOMFROMTEXT(
+ 'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))'));
+
+--echo # must not crash
+SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
+
+DROP TABLE t1;
+
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index bcd393bd6ab..bda48fb9ecf 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -1525,5 +1525,357 @@ DROP USER 'user1'@'localhost';
DROP USER 'user2';
DROP DATABASE db1;
+
+--echo #
+--echo # Bug #25863 No database selected error, but documentation
+--echo # says * for global allowed
+--echo #
+
+connect(conn1,localhost,root,,*NO-ONE*);
+
+--error ER_NO_DB_ERROR
+GRANT ALL ON * TO mysqltest_1;
+
+GRANT ALL ON *.* TO mysqltest_1;
+SHOW GRANTS FOR mysqltest_1;
+DROP USER mysqltest_1;
+
+USE test;
+
+GRANT ALL ON * TO mysqltest_1;
+SHOW GRANTS FOR mysqltest_1;
+DROP USER mysqltest_1;
+
+GRANT ALL ON *.* TO mysqltest_1;
+SHOW GRANTS FOR mysqltest_1;
+DROP USER mysqltest_1;
+
+connection default;
+disconnect conn1;
+
+
# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
+
+--echo #########################################################################
+--echo #
+--echo # Bug#38347: ALTER ROUTINE privilege allows SHOW CREATE TABLE.
+--echo #
+--echo #########################################################################
+
+--echo
+--echo # --
+--echo # -- Prepare the environment.
+--echo # --
+
+DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%';
+FLUSH PRIVILEGES;
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db1;
+--enable_warnings
+
+CREATE DATABASE mysqltest_db1;
+
+CREATE TABLE mysqltest_db1.t1(a INT);
+
+--echo
+--echo # --
+--echo # -- Check that global privileges don't allow SHOW CREATE TABLE.
+--echo # --
+
+GRANT EVENT ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT LOCK TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT ALTER ROUTINE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT CREATE ROUTINE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+GRANT FILE ON *.* TO mysqltest_u1@localhost;
+GRANT CREATE USER ON *.* TO mysqltest_u1@localhost;
+GRANT PROCESS ON *.* TO mysqltest_u1@localhost;
+GRANT RELOAD ON *.* TO mysqltest_u1@localhost;
+GRANT REPLICATION CLIENT ON *.* TO mysqltest_u1@localhost;
+GRANT REPLICATION SLAVE ON *.* TO mysqltest_u1@localhost;
+GRANT SHOW DATABASES ON *.* TO mysqltest_u1@localhost;
+GRANT SHUTDOWN ON *.* TO mysqltest_u1@localhost;
+GRANT USAGE ON *.* TO mysqltest_u1@localhost;
+
+--echo
+SHOW GRANTS FOR mysqltest_u1@localhost;
+
+--echo
+--echo # connection: con1 (mysqltest_u1@mysqltest_db1)
+--connect (con1,localhost,mysqltest_u1,,mysqltest_db1)
+--connection con1
+
+--echo
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW CREATE TABLE t1;
+
+--echo
+--echo # connection: default
+--connection default
+
+--disconnect con1
+
+--echo
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+SHOW GRANTS FOR mysqltest_u1@localhost;
+
+--echo
+--echo # --
+--echo # -- Check that global SELECT allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT SELECT ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global INSERT allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT INSERT ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global UPDATE allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global DELETE allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT DELETE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global CREATE allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT CREATE ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global DROP allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT DROP ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global ALTER allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT ALTER ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global INDEX allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT INDEX ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global REFERENCES allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT REFERENCES ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global GRANT OPTION allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT GRANT OPTION ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global CREATE VIEW allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT CREATE VIEW ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that global SHOW VIEW allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT SHOW VIEW ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level SELECT allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT SELECT ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level INSERT allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT INSERT ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level UPDATE allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT UPDATE ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level DELETE allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT DELETE ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level CREATE allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT CREATE ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level DROP allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT DROP ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level ALTER allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT ALTER ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level INDEX allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT INDEX ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level REFERENCES allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT REFERENCES ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level GRANT OPTION allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT GRANT OPTION ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level CREATE VIEW allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT CREATE VIEW ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Check that table-level SHOW VIEW allows SHOW CREATE TABLE.
+--echo # --
+
+--echo
+GRANT SHOW VIEW ON mysqltest_db1.t1 TO mysqltest_u1@localhost;
+
+--source include/bug38347.inc
+
+--echo
+--echo # --
+--echo # -- Cleanup.
+--echo # --
+
+--echo
+DROP DATABASE mysqltest_db1;
+
+DROP USER mysqltest_u1@localhost;
+
+--echo
+--echo # End of Bug#38347.
+--echo
diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test
index 9a635048774..437fc9a278f 100644
--- a/mysql-test/t/grant3.test
+++ b/mysql-test/t/grant3.test
@@ -163,6 +163,41 @@ connection default;
DROP USER 'mysqltest1'@'%';
DROP DATABASE mysqltest_1;
+--echo #
+--echo # Bug#41597 - After rename of user, there are additional grants
+--echo # when grants are reapplied.
+--echo #
+
+CREATE DATABASE temp;
+CREATE TABLE temp.t1(a INT, b VARCHAR(10));
+INSERT INTO temp.t1 VALUES(1, 'name1');
+INSERT INTO temp.t1 VALUES(2, 'name2');
+INSERT INTO temp.t1 VALUES(3, 'name3');
+
+
+CREATE USER 'user1'@'%';
+RENAME USER 'user1'@'%' TO 'user2'@'%';
+--echo # Show privileges after rename and BEFORE grant
+SHOW GRANTS FOR 'user2'@'%';
+GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%';
+--echo # Show privileges after rename and grant
+SHOW GRANTS FOR 'user2'@'%';
+
+--echo # Connect as the renamed user
+connect (conn1, localhost, user2,,);
+connection conn1;
+SHOW GRANTS;
+SELECT a FROM temp.t1;
+--echo # Check for additional privileges by accessing a
+--echo # non privileged column. We shouldn't be able to
+--echo # access this column.
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT b FROM temp.t1;
+disconnect conn1;
+
+connection default;
+DROP USER 'user2'@'%';
+DROP DATABASE temp;
--echo End of 5.0 tests
diff --git a/mysql-test/t/grant4.test b/mysql-test/t/grant4.test
new file mode 100644
index 00000000000..f3e551cd623
--- /dev/null
+++ b/mysql-test/t/grant4.test
@@ -0,0 +1,146 @@
+--source include/not_embedded.inc
+
+# Setup database, tables and user accounts
+--disable_warnings
+drop database if exists mysqltest_db1;
+--enable_warnings
+create database mysqltest_db1;
+use mysqltest_db1;
+create table t_column_priv_only (a int, b int);
+create table t_select_priv like t_column_priv_only;
+create table t_no_priv like t_column_priv_only;
+grant all privileges on test.* to mysqltest_u1@localhost;
+grant insert (a) on mysqltest_db1.t_column_priv_only to mysqltest_u1@localhost;
+grant select on mysqltest_db1.t_select_priv to mysqltest_u1@localhost;
+
+--echo ** Connect as restricted user mysqltest_u1.
+--echo
+connect (con1,localhost,mysqltest_u1,,);
+connection con1;
+
+########################################################################
+--echo ** Test column level privileges only. No SELECT privileges on the table.
+--echo ** INSERT INTO ... VALUES ...
+--echo ** Attempting to insert values to a table with only column privileges
+--echo ** should work.
+insert into mysqltest_db1.t_column_priv_only (a) VALUES (1);
+--echo
+
+#########################################################################
+--echo ** SHOW COLUMNS
+--echo ** Should succeed because we have privileges (any) on at least one of the columns.
+select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_column_priv_only';
+show columns from mysqltest_db1.t_column_priv_only;
+#########################################################################
+--echo ** SHOW COLUMNS
+--echo ** Should fail because there are no privileges on any column combination.
+--error 1142
+show columns from mysqltest_db1.t_no_priv;
+--echo ** However, select from I_S.COLUMNS will succeed but not show anything:
+select column_name as 'Field',column_type as 'Type',is_nullable as 'Null',column_key as 'Key',column_default as 'Default',extra as 'Extra' from information_schema.columns where table_schema='mysqltest_db1' and table_name='t_no_priv';
+--echo
+#########################################################################
+--echo ** CREATE TABLE ... LIKE ... require SELECT privleges and will fail.
+--error 1142
+create table test.t_no_priv like mysqltest_db1.column_priv_only;
+--echo
+#########################################################################
+--echo ** Just to be sure... SELECT also fails.
+--error 1142
+select * from mysqltest_db1.t_column_priv_only;
+--echo
+#########################################################################
+--echo ** SHOW CREATE TABLE ... require any privileges on all columns (the entire table).
+--echo ** First we try and fail on a table with only one column privilege.
+--error 1142
+show create table mysqltest_db1.t_column_priv_only;
+--echo
+#########################################################################
+--echo ** Now we do the same on a table with SELECT privileges.
+--echo
+#########################################################################
+--echo ** SHOW COLUMNS
+--echo ** Success because we got some privileges on the table (SELECT_ACL)
+show columns from mysqltest_db1.t_select_priv;
+--echo
+#########################################################################
+--echo ** CREATE TABLE ... LIKE ... require SELECT privleges and will SUCCEED.
+--disable_warnings
+drop table if exists test.t_duplicated;
+--enable_warnings
+create table test.t_duplicated like mysqltest_db1.t_select_priv;
+drop table test.t_duplicated;
+--echo
+#########################################################################
+--echo ** SHOW CREATE TABLE will succeed because we have a privilege on all columns in the table (table-level privilege).
+show create table mysqltest_db1.t_select_priv;
+--echo
+#########################################################################
+--echo ** SHOW CREATE TABLE will fail if there is no grants at all:
+--error 1142
+show create table mysqltest_db1.t_no_priv;
+--echo
+
+connection default;
+
+#
+# SHOW INDEX
+#
+use mysqltest_db1;
+CREATE TABLE t5 (s1 INT);
+CREATE INDEX i ON t5 (s1);
+CREATE TABLE t6 (s1 INT, s2 INT);
+CREATE VIEW v5 AS SELECT * FROM t5;
+CREATE VIEW v6 AS SELECT * FROM t6;
+CREATE VIEW v2 AS SELECT * FROM t_select_priv;
+CREATE VIEW v3 AS SELECT * FROM t_select_priv;
+CREATE INDEX i ON t6 (s1);
+GRANT UPDATE (s2) ON t6 to mysqltest_u1@localhost;
+GRANT UPDATE (s2) ON v6 to mysqltest_u1@localhost;
+GRANT SHOW VIEW ON v2 to mysqltest_u1@localhost;
+GRANT SHOW VIEW, SELECT ON v3 to mysqltest_u1@localhost;
+
+connection con1;
+use mysqltest_db1;
+--echo ** Connect as restricted user mysqltest_u1.
+--echo ** SELECT FROM INFORMATION_SCHEMA.STATISTICS will succeed because any privileges will do (authentication is enough).
+#
+# this result is wrong. reported as bug#34104
+#
+SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name='t5';
+#
+# Bug27145 EXTRA_ACL trouble
+#
+--echo ** SHOW INDEX FROM t5 will fail because we don't have any privileges on any column combination.
+--error 1142
+SHOW INDEX FROM t5;
+--echo ** SHOW INDEX FROM t6 will succeed because there exist a privilege on a column combination on t6.
+SHOW INDEX FROM t6;
+
+# CHECK TABLE
+--echo ** CHECK TABLE requires any privilege on any column combination and should succeed for t6:
+CHECK TABLE t6;
+--echo ** With no privileges access is naturally denied:
+--error 1142
+CHECK TABLE t5;
+
+# CHECKSUM
+--echo ** CHECKSUM TABLE requires SELECT privileges on the table. The following should fail:
+--error 1142
+CHECKSUM TABLE t6;
+--echo ** And this should work:
+CHECKSUM TABLE t_select_priv;
+
+# SHOW CREATE VIEW
+--error 1142
+SHOW CREATE VIEW v5;
+--error 1142
+SHOW CREATE VIEW v6;
+--error 1142
+SHOW CREATE VIEW v2;
+SHOW CREATE VIEW v3;
+
+connection default;
+disconnect con1;
+drop database mysqltest_db1;
+drop user mysqltest_u1@localhost;
diff --git a/mysql-test/t/grant_lowercase_fs.test b/mysql-test/t/grant_lowercase_fs.test
new file mode 100644
index 00000000000..f57f950ec8c
--- /dev/null
+++ b/mysql-test/t/grant_lowercase_fs.test
@@ -0,0 +1,30 @@
+-- source include/have_case_insensitive_fs.inc
+-- source include/not_embedded.inc
+
+
+#
+# Bug#41049 does syntax "grant" case insensitive?
+#
+create database db1;
+GRANT CREATE ON db1.* to user_1@localhost;
+GRANT SELECT ON db1.* to USER_1@localhost;
+
+connect (con1,localhost,user_1,,db1);
+CREATE TABLE t1(f1 int);
+--error 1142
+SELECT * FROM t1;
+connect (con2,localhost,USER_1,,db1);
+SELECT * FROM t1;
+--error 1142
+CREATE TABLE t2(f1 int);
+
+connection default;
+disconnect con1;
+disconnect con2;
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost;
+DROP USER user_1@localhost;
+DROP USER USER_1@localhost;
+DROP DATABASE db1;
+use test;
diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test
index ef66f71d2ad..7326f33b113 100644
--- a/mysql-test/t/information_schema_db.test
+++ b/mysql-test/t/information_schema_db.test
@@ -1,5 +1,5 @@
# this test mostly test privilege control (what doesn't work
-# in the embedded server by default). So disabled in embedded-server mode
+# in the embedded server by default). So skip the test in embedded-server mode.
-- source include/not_embedded.inc
-- source include/testdb_only.inc
@@ -13,7 +13,7 @@ drop function if exists f2;
use INFORMATION_SCHEMA;
--replace_result Tables_in_INFORMATION_SCHEMA Tables_in_information_schema
-show tables where Tables_in_information_schema not like "Innodb%";
+show tables where Tables_in_INFORMATION_SCHEMA NOT LIKE 'Innodb%';
--replace_result 'Tables_in_INFORMATION_SCHEMA (T%)' 'Tables_in_information_schema (T%)'
show tables from INFORMATION_SCHEMA like 'T%';
create database `inf%`;
@@ -123,7 +123,7 @@ create view v1 as select f1 from t1;
grant insert on v1 to testdb_2@localhost;
create view v5 as select f1 from t1;
-grant show view on v5 to testdb_2@localhost;
+grant select, show view on v5 to testdb_2@localhost;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
@@ -131,7 +131,7 @@ create definer=`no_such_user`@`no_such_host` view v6 as select f1 from t1;
connection default;
use testdb_1;
create view v6 as select f1 from t1;
-grant show view on v6 to testdb_2@localhost;
+grant select, show view on v6 to testdb_2@localhost;
create table t2 (f1 char(4));
create definer=`no_such_user`@`no_such_host` view v7 as select * from t2;
@@ -163,10 +163,10 @@ show fields from testdb_1.v7;
show create view testdb_1.v7;
revoke insert(f1) on v3 from testdb_2@localhost;
-revoke show view on v5 from testdb_2@localhost;
+revoke select,show view on v5 from testdb_2@localhost;
connection default;
use testdb_1;
-revoke show view on v6 from testdb_2@localhost;
+revoke select,show view on v6 from testdb_2@localhost;
connection testdb_2;
--error ER_TABLEACCESS_DENIED_ERROR
diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test
index 0f4113ae3f2..558de6a1060 100644
--- a/mysql-test/t/innodb-autoinc.test
+++ b/mysql-test/t/innodb-autoinc.test
@@ -479,9 +479,10 @@ INSERT INTO t2 SELECT NULL FROM t1;
DROP TABLE t1;
DROP TABLE t2;
#
-# BUG#44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from
+# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from
# the index (PRIMARY)
# This test requires a restart of the server
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (null);
INSERT INTO t1 VALUES (null);
@@ -495,6 +496,123 @@ SELECT * FROM t1;
-- error ER_AUTOINC_READ_FAILED,1467
INSERT INTO t1 VALUES(null);
ALTER TABLE t1 AUTO_INCREMENT = 3;
+SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
DROP TABLE t1;
+
+# If the user has specified negative values for an AUTOINC column then
+# InnoDB should ignore those values when setting the table's max value.
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+# TINYINT
+CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-127, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-127, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# SMALLINT
+#
+CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-32767, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-32757, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# MEDIUMINT
+#
+CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-8388607, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-8388607, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# INT
+#
+CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-2147483647, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-2147483647, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# BIGINT
+#
+CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-9223372036854775807, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (-1, 'innodb');
+INSERT INTO t1 VALUES (-9223372036854775807, 'innodb');
+INSERT INTO t1 VALUES (NULL, NULL);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# End negative number check
+
+##
+# 47125: auto_increment start value is ignored if an index is created
+# and engine=innodb
+#
+CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB;
+CREATE INDEX i1 on T1(c2);
+SHOW CREATE TABLE T1;
+INSERT INTO T1 (c2) values (0);
+SELECT * FROM T1;
+DROP TABLE T1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 4f45c30f318..2879a4c0b9f 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1317,7 +1317,6 @@ drop table t1;
# Test for testable InnoDB status variables. This test
# uses previous ones(pages_created, rows_deleted, ...).
-# We get one of 511 or 512 randomly
--replace_result 511 512
SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_pages_total';
SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size';
diff --git a/mysql-test/t/innodb_bug39438.test b/mysql-test/t/innodb_bug39438.test
index 4dc3d957c39..2a51e5fcbb8 100644
--- a/mysql-test/t/innodb_bug39438.test
+++ b/mysql-test/t/innodb_bug39438.test
@@ -9,6 +9,10 @@
-- source include/have_innodb.inc
+--disable_query_log
+call mtr.add_suppression("InnoDB: Error: table 'test/bug39438'");
+--enable_query_log
+
SET storage_engine=InnoDB;
# we care only that the following SQL commands do not crash the server
diff --git a/mysql-test/t/innodb_bug44369.test b/mysql-test/t/innodb_bug44369.test
index 4943627fa90..238dc3d8fb1 100644
--- a/mysql-test/t/innodb_bug44369.test
+++ b/mysql-test/t/innodb_bug44369.test
@@ -13,15 +13,9 @@ create table bug44369 (DB_ROW_ID int) engine=innodb;
--error ER_CANT_CREATE_TABLE
create table bug44369 (db_row_id int) engine=innodb;
-# TODO: after Bug#47233 is fixed, 'show warning' should be replaced by 'show
-# errors' again.
-# show errors;
show warnings;
--error ER_CANT_CREATE_TABLE
create table bug44369 (db_TRX_Id int) engine=innodb;
-# TODO: after Bug#47233 is fixed, 'show warning' should be replaced by 'show
-# errors' again.
-# show errors;
show warnings;
diff --git a/mysql-test/t/innodb_bug46000.test b/mysql-test/t/innodb_bug46000.test
index 80c18c58ef0..5a3c666326e 100644
--- a/mysql-test/t/innodb_bug46000.test
+++ b/mysql-test/t/innodb_bug46000.test
@@ -7,24 +7,22 @@
# This 'create table' operation should fail because of
# using the reserve name as its index name.
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_NAME_FOR_INDEX
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
# Mixed upper/lower case of the reserved key words
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_NAME_FOR_INDEX
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
-show errors;
+show warnings;
create table bug46000(id int) engine=innodb;
# This 'create index' operation should fail.
---replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_WRONG_NAME_FOR_INDEX
create index GEN_CLUST_INDEX on bug46000(id);
---replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
-show errors;
+show warnings;
# This 'create index' operation should succeed, no
# temp table left from last failed create index
diff --git a/mysql-test/t/innodb_bug47777.test b/mysql-test/t/innodb_bug47777.test
new file mode 100644
index 00000000000..8f2985b2cf0
--- /dev/null
+++ b/mysql-test/t/innodb_bug47777.test
@@ -0,0 +1,24 @@
+# This is the test for bug 47777. GEOMETRY
+# data is treated as BLOB data in innodb.
+# Consequently, its key value generation/storing
+# should follow the process for the BLOB
+# datatype as well.
+
+--source include/have_innodb.inc
+
+create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb;
+
+insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'));
+
+# Verify correct row get inserted.
+select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)');
+
+# Update table bug47777 should be successful.
+update bug47777 set c2=GeomFromText('POINT(1 1)');
+
+# Verify the row get updated successfully. The original
+# c2 value should be changed to GeomFromText('POINT(1 1)').
+select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)');
+select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)');
+
+drop table bug47777;
diff --git a/mysql-test/t/bug40113-master.opt b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt
index 462f8fbe828..462f8fbe828 100644
--- a/mysql-test/t/bug40113-master.opt
+++ b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt
diff --git a/mysql-test/t/innodb_lock_wait_timeout_1.test b/mysql-test/t/innodb_lock_wait_timeout_1.test
new file mode 100644
index 00000000000..e42e9f3e37c
--- /dev/null
+++ b/mysql-test/t/innodb_lock_wait_timeout_1.test
@@ -0,0 +1,230 @@
+--source include/have_innodb.inc
+
+--echo #
+--echo # Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout
+--echo # without error
+--echo #
+
+CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB;
+
+INSERT INTO t1 (a,b) VALUES (1070109,99);
+
+CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB;
+
+INSERT INTO t2 (b,a) VALUES (7,1070109);
+
+SELECT * FROM t1;
+
+BEGIN;
+
+SELECT b FROM t2 WHERE b=7 FOR UPDATE;
+
+CONNECT (addconroot, localhost, root,,);
+CONNECTION addconroot;
+
+BEGIN;
+
+--error ER_LOCK_WAIT_TIMEOUT
+SELECT b FROM t2 WHERE b=7 FOR UPDATE;
+
+--error ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7));
+
+--error ER_LOCK_WAIT_TIMEOUT
+UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7);
+
+--error ER_LOCK_WAIT_TIMEOUT
+DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7);
+
+SELECT * FROM t1;
+
+CONNECTION default;
+DISCONNECT addconroot;
+
+DROP TABLE t2, t1;
+
+--echo # End of 5.0 tests
+
+--echo #
+--echo # Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT
+--echo # FOR UPDATE
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int primary key auto_increment,
+ b int, index(b)) engine=innodb;
+insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+set autocommit=0;
+begin;
+select * from t1 where b=5 for update;
+connect (con1, localhost, root,,);
+connection con1;
+--error ER_LOCK_WAIT_TIMEOUT
+insert ignore into t1 (b) select a as b from t1;
+connection default;
+--echo # Cleanup
+--echo #
+disconnect con1;
+commit;
+set autocommit=default;
+drop table t1;
+
+--echo #
+--echo # Bug#41756 Strange error messages about locks from InnoDB
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+--echo # In the default transaction isolation mode, and/or with
+--echo # innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row()
+--echo # in InnoDB does nothing.
+--echo # Thus in order to reproduce the condition that led to the
+--echo # warning, one needs to relax isolation by either
+--echo # setting a weaker tx_isolation value, or by turning on
+--echo # the unsafe replication switch.
+--echo # For testing purposes, choose to tweak the isolation level,
+--echo # since it's settable at runtime, unlike
+--echo # innodb_locks_unsafe_for_binlog, which is
+--echo # only a command-line switch.
+--echo #
+set @@session.tx_isolation="read-committed";
+
+--echo # Prepare data. We need a table with a unique index,
+--echo # for join_read_key to be used. The other column
+--echo # allows to control what passes WHERE clause filter.
+create table t1 (a int primary key, b int) engine=innodb;
+--echo # Let's make sure t1 has sufficient amount of rows
+--echo # to exclude JT_ALL access method when reading it,
+--echo # i.e. make sure that JT_EQ_REF(a) is always preferred.
+insert into t1 values (1,1), (2,null), (3,1), (4,1),
+ (5,1), (6,1), (7,1), (8,1), (9,1), (10,1),
+ (11,1), (12,1), (13,1), (14,1), (15,1),
+ (16,1), (17,1), (18,1), (19,1), (20,1);
+--echo #
+--echo # Demonstrate that for the SELECT statement
+--echo # used later in the test JT_EQ_REF access method is used.
+--echo #
+--vertical_results
+explain
+select 1 from t1 natural join (select 2 as a, 1 as b union all
+ select 2 as a, 2 as b) as t2 for update;
+--horizontal_results
+--echo #
+--echo # Demonstrate that the reported SELECT statement
+--echo # no longer produces warnings.
+--echo #
+select 1 from t1 natural join (select 2 as a, 1 as b union all
+ select 2 as a, 2 as b) as t2 for update;
+commit;
+--echo #
+--echo # Demonstrate that due to lack of inter-sweep "reset" function,
+--echo # we keep some non-matching records locked, even though we know
+--echo # we could unlock them.
+--echo # To do that, show that if there is only one distinct value
+--echo # for a in t2 (a=2), we will keep record (2,null) in t1 locked.
+--echo # But if we add another value for "a" to t2, say 6,
+--echo # join_read_key cache will be pruned at least once,
+--echo # and thus record (2, null) in t1 will get unlocked.
+--echo #
+begin;
+select 1 from t1 natural join (select 2 as a, 1 as b union all
+ select 2 as a, 2 as b) as t2 for update;
+connect (con1,localhost,root,,);
+--echo #
+--echo # Switching to connection con1
+connection con1;
+--echo # We should be able to delete all records from t1 except (2, null),
+--echo # since they were not locked.
+begin;
+--echo # Delete in series of 3 records so that full scan
+--echo # is not used and we're not blocked on record (2,null)
+delete from t1 where a in (1,3,4);
+delete from t1 where a in (5,6,7);
+delete from t1 where a in (8,9,10);
+delete from t1 where a in (11,12,13);
+delete from t1 where a in (14,15,16);
+delete from t1 where a in (17,18);
+delete from t1 where a in (19,20);
+--echo #
+--echo # Record (2, null) is locked. This is actually unnecessary,
+--echo # because the previous select returned no rows.
+--echo # Just demonstrate the effect.
+--echo #
+--error ER_LOCK_WAIT_TIMEOUT
+delete from t1;
+rollback;
+--echo #
+--echo # Switching to connection default
+connection default;
+--echo #
+--echo # Show that the original contents of t1 is intact:
+select * from t1;
+commit;
+--echo #
+--echo # Have a one more record in t2 to show that
+--echo # if join_read_key cache is purned, the current
+--echo # row under the cursor is unlocked (provided, this row didn't
+--echo # match the partial WHERE clause, of course).
+--echo # Sic: the result of this test dependent on the order of retrieval
+--echo # of records --echo # from the derived table, if !
+--echo # We use DELETE to disable the JOIN CACHE. This DELETE modifies no
+--echo # records. It also should leave no InnoDB row locks.
+--echo #
+begin;
+delete t1.* from t1 natural join (select 2 as a, 2 as b union all
+ select 0 as a, 0 as b) as t2;
+--echo # Demonstrate that nothing was deleted form t1
+select * from t1;
+--echo #
+--echo # Switching to connection con1
+connection con1;
+begin;
+--echo # Since there is another distinct record in the derived table
+--echo # the previous matching record in t1 -- (2,null) -- was unlocked.
+delete from t1;
+--echo # We will need the contents of the table again.
+rollback;
+select * from t1;
+commit;
+--echo #
+--echo # Switching to connection default
+connection default;
+rollback;
+begin;
+--echo #
+--echo # Before this patch, we could wrongly unlock a record
+--echo # that was cached and later used in a join. Demonstrate that
+--echo # this is no longer the case.
+--echo # Sic: this test is also order-dependent (i.e. the
+--echo # the bug would show up only if the first record in the union
+--echo # is retreived and processed first.
+--echo #
+--echo # Verify that JT_EQ_REF is used.
+--vertical_results
+explain
+select 1 from t1 natural join (select 3 as a, 2 as b union all
+ select 3 as a, 1 as b) as t2 for update;
+--horizontal_results
+--echo # Lock the record.
+select 1 from t1 natural join (select 3 as a, 2 as b union all
+ select 3 as a, 1 as b) as t2 for update;
+--echo # Switching to connection con1
+connection con1;
+--echo #
+--echo # We should not be able to delete record (3,1) from t1,
+--echo # (previously it was possible).
+--echo #
+--error ER_LOCK_WAIT_TIMEOUT
+delete from t1 where a=3;
+--echo # Switching to connection default
+connection default;
+commit;
+
+disconnect con1;
+set @@session.tx_isolation=default;
+drop table t1;
+
+--echo #
+--echo # End of 5.1 tests
+--echo #
diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test
index c643465b2f3..9d0f76c4f7e 100644
--- a/mysql-test/t/innodb_mysql.test
+++ b/mysql-test/t/innodb_mysql.test
@@ -461,4 +461,51 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a;
DROP TABLE t1;
+--echo #
+--echo # Bug #47963: Wrong results when index is used
+--echo #
+CREATE TABLE t1(
+ a VARCHAR(5) NOT NULL,
+ b VARCHAR(5) NOT NULL,
+ c DATETIME NOT NULL,
+ KEY (c)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00');
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00';
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0';
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00';
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0';
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000';
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001';
+SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00';
+EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND
+ c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00';
+DROP TABLE t1;
+
+
--echo End of 5.1 tests
+
+
+--echo #
+--echo # Test for bug #39932 "create table fails if column for FK is in different
+--echo # case than in corr index".
+--echo #
+--disable_warnings
+drop tables if exists t1, t2;
+--enable_warnings
+create table t1 (pk int primary key) engine=InnoDB;
+--echo # Even although the below statement uses uppercased field names in
+--echo # foreign key definition it still should be able to find explicitly
+--echo # created supporting index. So it should succeed and should not
+--echo # create any additional supporting indexes.
+create table t2 (fk int, key x (fk),
+ constraint x foreign key (FK) references t1 (PK)) engine=InnoDB;
+show create table t2;
+drop table t2, t1;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 155ae6937ef..40d1464b86a 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -501,3 +501,33 @@ DROP TABLE t1, t2;
--echo End of 5.0 tests.
+--echo #
+--echo # Bug#34898 "mysql_info() reports 0 warnings while
+--echo # mysql_warning_count() reports 1"
+--echo # Check that the number of warnings reported by
+--echo # mysql_info() is correct.
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (data varchar(4) not null);
+
+set sql_mode='error_for_division_by_zero';
+--echo #
+--echo # Demonstrate that the number of warnings matches
+--echo # the information in mysql_info().
+--echo #
+--enable_info
+insert t1 (data) values ('letter'), (1/0);
+update t1 set data='envelope' where 1/0 or 1;
+insert t1 (data) values (default), (1/0), ('dead beef');
+--disable_info
+
+set sql_mode=default;
+drop table t1;
+
+--echo #
+--echo # End of 5.4 tests
+--echo #
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 1cd05c8cb65..dbf36dedec8 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -730,6 +730,60 @@ SELECT * FROM t1 JOIN t2 ON a=c ORDER BY a;
DROP TABLE IF EXISTS t1,t2;
+
+--echo #
+--echo # Bug #42116: Mysql crash on specific query
+--echo #
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+CREATE TABLE t3 (a INT, INDEX (a));
+CREATE TABLE t4 (a INT);
+CREATE TABLE t5 (a INT);
+CREATE TABLE t6 (a INT);
+
+INSERT INTO t1 VALUES (1), (1), (1);
+
+INSERT INTO t2 VALUES
+(2), (2), (2), (2), (2), (2), (2), (2), (2), (2);
+
+INSERT INTO t3 VALUES
+(3), (3), (3), (3), (3), (3), (3), (3), (3), (3);
+
+EXPLAIN
+SELECT *
+FROM
+ t1 JOIN t2 ON t1.a = t2.a
+ LEFT JOIN
+ (
+ (
+ t3 LEFT JOIN t4 ON t3.a = t4.a
+ )
+ LEFT JOIN
+ (
+ t5 LEFT JOIN t6 ON t5.a = t6.a
+ )
+ ON t4.a = t5.a
+ )
+ ON t1.a = t3.a;
+
+SELECT *
+FROM
+ t1 JOIN t2 ON t1.a = t2.a
+ LEFT JOIN
+ (
+ (
+ t3 LEFT JOIN t4 ON t3.a = t4.a
+ )
+ LEFT JOIN
+ (
+ t5 LEFT JOIN t6 ON t5.a = t6.a
+ )
+ ON t4.a = t5.a
+ )
+ ON t1.a = t3.a;
+
+DROP TABLE t1,t2,t3,t4,t5,t6;
+
--echo End of 5.0 tests.
diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test
index 8ef668f542b..02b033df2e5 100644
--- a/mysql-test/t/kill.test
+++ b/mysql-test/t/kill.test
@@ -97,7 +97,7 @@ select ((@id := kill_id) - kill_id) from t3;
kill @id;
connection conn1;
--- error 1053,2013
+-- error 1317,2013
reap;
connection default;
diff --git a/mysql-test/t/loadxml.test b/mysql-test/t/loadxml.test
index accd08c8bfe..8b9c1bd1b0d 100644
--- a/mysql-test/t/loadxml.test
+++ b/mysql-test/t/loadxml.test
@@ -70,17 +70,18 @@ connection addconroot;
create table t2(fl text);
--let $PSEUDO_THREAD_ID=`select @@pseudo_thread_id `
---send LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<person>';
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--send_eval LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<person>';
sleep 3;
connection default;
---replace_column 1 # 3 localhost 6 #
-show processlist;
+sleep 1;
--disable_query_log
--eval kill $PSEUDO_THREAD_ID
+sleep 2;
--enable_query_log
disconnect addconroot;
diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test
index 4b669cc3de8..04ac95cea06 100644
--- a/mysql-test/t/locale.test
+++ b/mysql-test/t/locale.test
@@ -34,10 +34,23 @@ DROP TABLE t1;
--echo #
--echo # Bug#46633 Obsolete Serbian locale name
--echo #
---error ER_UNKNOWN_LOCALE
-set lc_messages=sr_YU;
-set lc_messages=sr_RS;
-set lc_time_names=sr_RS;
-select format(123456.789, 3, 'sr_RS');
+SET lc_messages=sr_YU;
+SHOW VARIABLES LIKE 'lc_messages';
+SET lc_messages=sr_RS;
+SHOW VARIABLES LIKE 'lc_messages';
+SET lc_time_names=sr_RS;
+SELECT format(123456.789, 3, 'sr_RS');
+--echo #
+--echo # Bug#43207 wrong LC_TIME names for romanian locale
+--echo #
+SET NAMES utf8;
+SET lc_time_names=ro_RO;
+SELECT DATE_FORMAT('2001-01-01', '%w %a %W');
+SELECT DATE_FORMAT('2001-01-02', '%w %a %W');
+SELECT DATE_FORMAT('2001-01-03', '%w %a %W');
+SELECT DATE_FORMAT('2001-01-04', '%w %a %W');
+SELECT DATE_FORMAT('2001-01-05', '%w %a %W');
+SELECT DATE_FORMAT('2001-01-06', '%w %a %W');
+SELECT DATE_FORMAT('2001-01-07', '%w %a %W');
--echo End of 5.4 tests
diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test
index e40dd1e3491..4d8c8fc6e74 100644
--- a/mysql-test/t/log_state.test
+++ b/mysql-test/t/log_state.test
@@ -1,16 +1,5 @@
### t/log_state.test ###
#
-# This test suffers from server
-# Bug#38124 "general_log_file" variable silently unset when using expression
-# In short:
-# SET GLOBAL general_log_file = @<whatever>
-# SET GLOBAL slow_query_log = @<whatever>
-# cause that the value of these server system variables is set to default
-# instead of the assigned values. There comes no error message or warning.
-# If this bug is fixed please
-# 1. try this test with "let $fixed_bug38124 = 0;"
-# 2. remove all workarounds if 1. was successful.
-let $fixed_bug38124 = 0;
--source include/not_embedded.inc
--source include/have_csv.inc
@@ -166,16 +155,6 @@ SET @@global.general_log = @old_general_log;
SET @@global.general_log_file = @old_general_log_file;
SET @@global.slow_query_log = @old_slow_query_log;
SET @@global.slow_query_log_file = @old_slow_query_log_file;
-if(!$fixed_bug38124)
-{
- --disable_query_log
- let $my_var = `SELECT @old_general_log_file`;
- eval SET @@global.general_log_file = '$my_var';
- let $my_var = `SELECT @old_slow_query_log_file`;
- eval SET @@global.slow_query_log_file = '$my_var';
- --enable_query_log
-}
-
###########################################################################
@@ -278,15 +257,6 @@ SET GLOBAL slow_query_log_file= NULL;
# Reset to initial values in case a setting above was successful.
SET GLOBAL general_log_file= @old_general_log_file;
SET GLOBAL slow_query_log_file= @old_slow_query_log_file;
-if(!$fixed_bug38124)
-{
- --disable_query_log
- let $my_var = `SELECT @old_general_log_file`;
- eval SET @@global.general_log_file = '$my_var';
- let $my_var = `SELECT @old_slow_query_log_file`;
- eval SET @@global.slow_query_log_file = '$my_var';
- --enable_query_log
-}
###########################################################################
@@ -307,15 +277,6 @@ SHOW VARIABLES LIKE '%log_file';
--echo
SET GLOBAL general_log_file = @old_general_log_file;
SET GLOBAL slow_query_log_file = @old_slow_query_log_file;
-if(!$fixed_bug38124)
-{
- --disable_query_log
- let $my_var = `SELECT @old_general_log_file`;
- eval SET @@global.general_log_file = '$my_var';
- let $my_var = `SELECT @old_slow_query_log_file`;
- eval SET @@global.slow_query_log_file = '$my_var';
- --enable_query_log
-}
--echo
--echo # -- End of Bug#32748.
@@ -351,19 +312,43 @@ SET @@global.general_log = @old_general_log;
SET @@global.general_log_file = @old_general_log_file;
SET @@global.slow_query_log = @old_slow_query_log;
SET @@global.slow_query_log_file = @old_slow_query_log_file;
-if(!$fixed_bug38124)
-{
- --disable_query_log
- let $my_var = `SELECT @old_general_log_file`;
- eval SET @@global.general_log_file = '$my_var';
- let $my_var = `SELECT @old_slow_query_log_file`;
- eval SET @@global.slow_query_log_file = '$my_var';
- --enable_query_log
-}
-
--echo End of 5.1 tests
+
+###########################################################################
+
+--echo
+--echo # --
+--echo # -- Bug#38124: "general_log_file" variable silently unset when
+--echo # -- using expression
+--echo # --
+
+# Store away the special DEFAULT value so we
+# can compare it later, then try to set the
+# general_log_file using different functions
+# and expressions.
+
+SET GLOBAL general_log_file = DEFAULT;
+SELECT @@general_log_file INTO @my_glf;
+
+SET GLOBAL general_log_file = 'BUG38124.LOG';
+SELECT @@general_log_file;
+
+SET GLOBAL general_log_file = concat('BUG38124-2.LOG');
+SELECT @@general_log_file;
+
+SET GLOBAL general_log_file = substr('BUG38124-2.LOG',3,6);
+SELECT @@general_log_file;
+
+SET GLOBAL general_log_file = DEFAULT;
+SELECT @@general_log_file = @my_glf;
+
+
+## Reset to initial values
+SET GLOBAL general_log_file = @old_general_log_file;
+
+
--enable_ps_protocol
#
@@ -380,17 +365,7 @@ SET global general_log = @old_general_log;
SET global general_log_file = @old_general_log_file;
SET global slow_query_log = @old_slow_query_log;
SET global slow_query_log_file = @old_slow_query_log_file;
-if(!$fixed_bug38124)
-{
- --disable_query_log
- let $my_var = `SELECT @old_general_log_file`;
- eval SET @@global.general_log_file = '$my_var';
- let $my_var = `SELECT @old_slow_query_log_file`;
- eval SET @@global.slow_query_log_file = '$my_var';
- --enable_query_log
-}
-
-# Remove the log files that was created in the "default location"
+
+# Remove the log file that was created in the "default location"
# i.e var/run
---remove_file $MYSQLTEST_VARDIR/run/mysqld.log
--remove_file $MYSQLTEST_VARDIR/tmp/log.master
diff --git a/mysql-test/t/log_state_bug33693-master.opt b/mysql-test/t/log_state_bug33693-master.opt
new file mode 100644
index 00000000000..9f4ae1a0c8f
--- /dev/null
+++ b/mysql-test/t/log_state_bug33693-master.opt
@@ -0,0 +1 @@
+--pid-file=$MYSQLTEST_VARDIR/run/mysqld.1.pid --log=
diff --git a/mysql-test/t/log_state_bug33693.test b/mysql-test/t/log_state_bug33693.test
new file mode 100644
index 00000000000..d67b28fc3e9
--- /dev/null
+++ b/mysql-test/t/log_state_bug33693.test
@@ -0,0 +1,18 @@
+### t/log_state_bug33693.test
+#
+# Regression test for bug #33693
+# "general log name and location depend on PID
+# file, not on predefined values"
+#
+# The server is started with a hard-coded
+# PID file in the $MYSQLTEST_VARDIR/run
+# directory, and an unspecified general log
+# file name.
+#
+# The correct result should show the log file to
+# rest in the database directory. Unfixed, the
+# log file will be in the same directory as the
+# PID.
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval SELECT INSTR(@@general_log_file, '$MYSQLTEST_VARDIR/run');
diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test
index 878564c32ab..86d1e084c29 100644
--- a/mysql-test/t/lowercase_fs_off.test
+++ b/mysql-test/t/lowercase_fs_off.test
@@ -29,3 +29,65 @@ disconnect master;
connection default;
# End of 4.1 tests
+
+#
+# Bug#41049 does syntax "grant" case insensitive?
+#
+CREATE DATABASE d1;
+USE d1;
+CREATE TABLE T1(f1 INT);
+CREATE TABLE t1(f1 INT);
+GRANT SELECT ON T1 to user_1@localhost;
+
+connect (con1,localhost,user_1,,d1);
+--error ER_TABLEACCESS_DENIED_ERROR
+select * from t1;
+select * from T1;
+connection default;
+GRANT SELECT ON t1 to user_1@localhost;
+connection con1;
+select * from information_schema.table_privileges;
+connection default;
+disconnect con1;
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
+DROP USER user_1@localhost;
+DROP DATABASE d1;
+USE test;
+
+CREATE DATABASE db1;
+USE db1;
+CREATE PROCEDURE p1() BEGIN END;
+CREATE FUNCTION f1(i INT) RETURNS INT RETURN i+1;
+
+GRANT USAGE ON db1.* to user_1@localhost;
+GRANT EXECUTE ON PROCEDURE db1.P1 to user_1@localhost;
+GRANT EXECUTE ON FUNCTION db1.f1 to user_1@localhost;
+GRANT UPDATE ON db1.* to USER_1@localhost;
+
+connect (con1,localhost,user_1,,db1);
+call p1();
+call P1();
+select f1(1);
+connect (con2,localhost,USER_1,,db1);
+--error ER_PROCACCESS_DENIED_ERROR
+call p1();
+--error ER_PROCACCESS_DENIED_ERROR
+call P1();
+--error ER_PROCACCESS_DENIED_ERROR
+select f1(1);
+
+connection default;
+disconnect con1;
+disconnect con2;
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost;
+DROP FUNCTION f1;
+DROP PROCEDURE p1;
+DROP USER user_1@localhost;
+DROP USER USER_1@localhost;
+DROP DATABASE db1;
+use test;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test
index 521df01cc9b..92add60616a 100644
--- a/mysql-test/t/lowercase_table2.test
+++ b/mysql-test/t/lowercase_table2.test
@@ -150,3 +150,75 @@ select TABLE_SCHEMA,TABLE_NAME FROM information_schema.TABLES
where TABLE_SCHEMA ='mysqltest_LC2';
use test;
drop database mysqltest_LC2;
+
+--echo # End of 5.1 tests
+
+
+--echo #
+--echo # Test for bug #44738 "fill_schema_table_from_frm() opens tables without
+--echo # lowercasing table name". Due to not properly normalizing table names
+--echo # in lower_case_table_names modes in this function queries to I_S which
+--echo # were executed through it left entries with incorrect key in table
+--echo # definition cache. As result further queries to I_S that used this
+--echo # function produced stale results in cases when table definition was
+--echo # changed by a DDL statement. Also combination of this issue and a
+--echo # similar problem in CREATE TABLE (it also has peeked into table
+--echo # definition cache using non-normalized key) led to spurious
+--echo # ER_TABLE_EXISTS_ERROR errors when one tried to create table with the
+--echo # same name as a previously existing but dropped table.
+--echo #
+--disable_warnings
+drop database if exists mysqltest_UPPERCASE;
+drop table if exists t_bug44738_UPPERCASE;
+--enable_warnings
+create database mysqltest_UPPERCASE;
+use mysqltest_UPPERCASE;
+create table t_bug44738_UPPERCASE (i int) comment='Old comment';
+create table t_bug44738_lowercase (i int) comment='Old comment';
+select table_schema, table_name, table_comment from information_schema.tables
+ where table_schema like 'mysqltest_%' and table_name like 't_bug44738_%'
+ order by table_name;
+alter table t_bug44738_UPPERCASE comment='New comment';
+alter table t_bug44738_lowercase comment='New comment';
+--echo # There should be no stale entries in TDC for our tables after the
+--echo # above ALTER TABLE statements so new version of comments should be
+--echo # returned by the below query to I_S.
+select table_schema, table_name, table_comment from information_schema.tables
+ where table_schema like 'mysqltest_%' and table_name like 't_bug44738_%'
+ order by table_name;
+drop database mysqltest_UPPERCASE;
+use test;
+
+--echo # Let us check that the original test case which led to discovery
+--echo # of this problem also works.
+create table t_bug44738_UPPERCASE (i int);
+select table_schema, table_name, table_comment from information_schema.tables
+ where table_schema = 'test' and table_name like 't_bug44738_%';
+drop table t_bug44738_UPPERCASE;
+--echo # After the above DROP TABLE there are no entries in TDC which correspond
+--echo # to our table and therefore the below statement should succeed.
+create table t_bug44738_UPPERCASE (i int);
+drop table t_bug44738_UPPERCASE;
+
+--echo # Finally, let us check that another issue which was exposed by
+--echo # the original test case is solved. I.e. that fuse in CREATE TABLE
+--echo # which ensures that table is not created if there is an entry for
+--echo # it in TDC even though it was removed from disk uses normalized
+--echo # version of the table name.
+create table t_bug44738_UPPERCASE (i int) engine = myisam;
+--echo # Load table definition in TDC.
+select table_schema, table_name, table_comment from information_schema.tables
+ where table_schema = 'test' and table_name like 't_bug44738_%';
+--echo # Simulate manual removal of the table.
+let $MYSQLD_DATADIR= `select @@datadir`;
+--remove_file $MYSQLD_DATADIR/test/t_bug44738_UPPERCASE.frm
+--remove_file $MYSQLD_DATADIR/test/t_bug44738_UPPERCASE.MYD
+--remove_file $MYSQLD_DATADIR/test/t_bug44738_UPPERCASE.MYI
+--echo # After manual removal of table still there should be an entry for table
+--echo # in TDC so attempt to create table with the same name should fail.
+--error ER_TABLE_EXISTS_ERROR
+create table t_bug44738_UPPERCASE (i int);
+--echo # And should succeed after FLUSH TABLES.
+flush tables;
+create table t_bug44738_UPPERCASE (i int);
+drop table t_bug44738_UPPERCASE;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 015ae28c155..63ad5a1e97c 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -1634,3 +1634,63 @@ DROP TRIGGER tr1;
DROP TABLE t1, t2, t3;
--echo End of 5.1 tests
+
+--echo #
+--echo # An additional test case for Bug#27430 Crash in subquery code
+--echo # when in PS and table DDL changed after PREPARE
+--echo #
+--echo # Test merge table with too many merge children.
+--echo #
+--disable_warnings
+drop table if exists t_parent;
+--enable_warnings
+set @save_table_definition_cache=@@global.table_definition_cache;
+--echo #
+--echo # Set @@global.table_definition_cache to minimum
+--echo #
+set @@global.table_definition_cache=400;
+set @a=null;
+let $1 = 400;
+--echo #
+--echo # Create 400 merge children
+--echo #
+--disable_query_log
+while ($1)
+{
+--disable_warnings
+ eval drop table if exists t$1;
+--enable_warnings
+ eval create table t$1 (a int) engine=myisam;
+ eval set @a=ifnull(concat(@a, ", ", "t$1"), "t$1");
+ dec $1;
+}
+--enable_query_log
+set @a=concat("create table t_parent (a int) union(", @a,
+ ") insert_method=first engine=mrg_myisam");
+prepare stmt from @a;
+execute stmt;
+prepare stmt from "select * from t_parent";
+--error ER_NEED_REPREPARE
+execute stmt;
+--error ER_NEED_REPREPARE
+execute stmt;
+--error ER_NEED_REPREPARE
+execute stmt;
+deallocate prepare stmt;
+--echo #
+--echo # Create merge parent
+--echo #
+
+--echo #
+--echo # Cleanup
+--echo #
+let $1 = 400;
+--disable_query_log
+while ($1)
+{
+ eval drop table t$1;
+ dec $1;
+}
+--enable_query_log
+drop table t_parent;
+set @@global.table_definition_cache=@save_table_definition_cache;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index e4ea939f348..56fe103adc9 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -1539,14 +1539,14 @@ INSERT INTO t1 SELECT a+5120,b FROM t1;
SET myisam_sort_buffer_size=4;
REPAIR TABLE t1;
-# !!! Disabled until additional fix for BUG#47073 is pushed.
-#SET myisam_repair_threads=2;
+SET myisam_repair_threads=2;
# May report different values depending on threads activity.
-#--replace_regex /changed from [0-9]+/changed from #/
-#REPAIR TABLE t1;
-#SET myisam_repair_threads=@@global.myisam_repair_threads;
-
+--disable_result_log
+REPAIR TABLE t1;
+--enable_result_log
+SET myisam_repair_threads=@@global.myisam_repair_threads;
SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size;
+CHECK TABLE t1;
DROP TABLE t1;
--echo End of 5.1 tests
diff --git a/mysql-test/t/myisam_crash_before_flush_keys.test b/mysql-test/t/myisam_crash_before_flush_keys.test
index d6559f7760d..1860ddd27e3 100644
--- a/mysql-test/t/myisam_crash_before_flush_keys.test
+++ b/mysql-test/t/myisam_crash_before_flush_keys.test
@@ -26,12 +26,6 @@ SET SESSION debug="d,crash_before_flush_keys";
--error 2013
FLUSH TABLE t1;
---echo # Run MYISAMCHK tool to check the table t1 and repair
---replace_result $MYISAMCHK MYISAMCHK $MYSQLD_DATADIR MYSQLD_DATADIR
---error 255
---exec $MYISAMCHK -cs $MYSQLD_DATADIR/test/t1 2>&1
---exec $MYISAMCHK -rs $MYSQLD_DATADIR/test/t1
-
--echo # Write file to make mysql-test-run.pl start the server
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
@@ -42,8 +36,6 @@ FLUSH TABLE t1;
--echo # it to be back online again
--source include/wait_until_connected_again.inc
-SHOW CREATE TABLE t1;
-
-SELECT * FROM t1 FORCE INDEX (PRIMARY);
-
+# Must report that the table wasn't closed properly
+CHECK TABLE t1;
DROP TABLE t1;
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index d1e40024733..8f672af40a3 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -375,4 +375,19 @@ INSERT INTO t1 VALUES(0);
SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP;
DROP TABLE t1;
+--echo #
+--echo # Bug #48131: crash group by with rollup, distinct,
+--echo # filesort, with temporary tables
+--echo #
+
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY);
+INSERT INTO t1 VALUES (1), (2);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (100);
+
+SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
+SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
+
+DROP TABLE t1, t2;
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test
index 45b13f141f7..9f2fc22da99 100644
--- a/mysql-test/t/outfile.test
+++ b/mysql-test/t/outfile.test
@@ -109,7 +109,7 @@ create user user_1@localhost;
grant all on mysqltest.* to user_1@localhost;
connect (con28181_1,localhost,user_1,,mysqltest);
---error ER_DBACCESS_DENIED_ERROR
+--error ER_ACCESS_DENIED_ERROR
eval select schema_name
into outfile "../../tmp/outfile-test.4"
fields terminated by ',' optionally enclosed by '"'
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index 1dfc53c6232..459acc9f1f5 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -352,12 +352,12 @@ drop table t1;
#
# BUG 16002: Handle unsigned integer functions properly
#
---error ER_PARSE_ERROR
+--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
create table t1 (a bigint)
partition by range (a)
(partition p0 values less than (0xFFFFFFFFFFFFFFFF),
partition p1 values less than (10));
---error ER_PARSE_ERROR
+--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
create table t1 (a bigint)
partition by list (a)
(partition p0 values in (0xFFFFFFFFFFFFFFFF),
@@ -1390,7 +1390,7 @@ PARTITION BY LIST (a)
SHOW CREATE TABLE t1;
DROP TABLE t1;
---error ER_PARSE_ERROR
+--error ER_NULL_IN_VALUES_LESS_THAN
CREATE TABLE t1 (a int)
PARTITION BY RANGE(a)
(PARTITION p0 VALUES LESS THAN (NULL));
diff --git a/mysql-test/t/partition_column.test b/mysql-test/t/partition_column.test
new file mode 100644
index 00000000000..7577325234f
--- /dev/null
+++ b/mysql-test/t/partition_column.test
@@ -0,0 +1,411 @@
+#
+# Tests for the new column list partitioning introduced in second
+# version for partitioning.
+#
+--source include/have_partition.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# BUG#48161, Delivering too few records using collate syntax with partitions
+#
+# Test case from BUG#48447 with some extension
+create table t1 (a varchar(1) character set latin1 collate latin1_general_ci)
+partition by range columns(a)
+( partition p0 values less than ('a'),
+ partition p1 values less than ('b'),
+ partition p2 values less than ('c'),
+ partition p3 values less than ('d'));
+insert into t1 values ('A'),('a'),('B'),('b'),('C'),('c');
+select * from t1 where a > 'B' collate latin1_bin;
+select * from t1 where a <> 'B' collate latin1_bin;
+alter table t1 remove partitioning;
+select * from t1 where a > 'B' collate latin1_bin;
+select * from t1 where a <> 'B' collate latin1_bin;
+drop table t1;
+
+# Test case from BUG#48161
+create table t1 (a varchar(2) character set latin1,
+ b varchar(2) character set latin1)
+partition by list columns(a,b)
+(partition p0 values in (('a','a')));
+insert into t1 values ('A','A');
+select * from t1 where b <> 'a' collate latin1_bin AND
+ a = 'A' collate latin1_bin;
+alter table t1 remove partitioning;
+select * from t1 where b <> 'a' collate latin1_bin AND
+ a = 'A' collate latin1_bin;
+drop table t1;
+
+create table t1 (a varchar(5))
+partition by list columns(a)
+( partition p0 values in ('\''),
+ partition p1 values in ('\\'),
+ partition p2 values in ('\0'));
+show create table t1;
+drop table t1;
+
+#
+# BUG#48165, sql_mode gives error
+#
+set @@sql_mode=allow_invalid_dates;
+--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+create table t1 (a char, b char, c date)
+partition by range columns (a,b,c)
+( partition p0 values less than (0,0,to_days('3000-11-31')));
+
+--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+create table t1 (a char, b char, c date)
+partition by range columns (a,b,c)
+( partition p0 values less than (0,0,'3000-11-31'));
+set @@sql_mode='';
+
+--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+create table t1 (a int, b char(10), c varchar(25), d datetime)
+partition by range columns(a,b,c,d)
+subpartition by hash (to_seconds(d))
+subpartitions 4
+( partition p0 values less than (1, 0, MAXVALUE, '1900-01-01'),
+ partition p1 values less than (1, 'a', MAXVALUE, '1999-01-01'),
+ partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+ partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
+
+create table t1 (a int, b char(10), c varchar(25), d datetime)
+partition by range columns(a,b,c,d)
+subpartition by hash (to_seconds(d))
+subpartitions 4
+( partition p0 values less than (1, '0', MAXVALUE, '1900-01-01'),
+ partition p1 values less than (1, 'a', MAXVALUE, '1999-01-01'),
+ partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
+ partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+show create table t1;
+drop table t1;
+
+--error ER_NULL_IN_VALUES_LESS_THAN
+create table t1 (a int, b int)
+partition by range columns (a,b)
+(partition p0 values less than (NULL, maxvalue));
+
+--error ER_MAXVALUE_IN_VALUES_IN, ER_PARSE_ERROR
+create table t1 (a int, b int)
+partition by list columns(a,b)
+( partition p0 values in ((maxvalue, 0)));
+
+create table t1 (a int, b int)
+partition by list columns (a,b)
+( partition p0 values in ((0,0)));
+--error ER_MAXVALUE_IN_VALUES_IN, ER_PARSE_ERROR
+alter table t1 add partition
+(partition p1 values in (maxvalue, maxvalue));
+drop table t1;
+#
+# BUG#47837, Crash when two same fields in column list processing
+#
+--error ER_SAME_NAME_PARTITION_FIELD
+create table t1 (a int, b int)
+partition by key (a,a);
+--error ER_SAME_NAME_PARTITION_FIELD
+create table t1 (a int, b int)
+partition by list columns(a,a)
+( partition p values in ((1,1)));
+
+#
+# BUG#47838, List partitioning have problems with <= and >=
+#
+create table t1 (a int signed)
+partition by list (a)
+( partition p0 values in (1, 3, 5, 7, 9, NULL),
+ partition p1 values in (2, 4, 6, 8, 0));
+insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
+select * from t1 where NULL <= a;
+select * from t1 where a is null;
+explain partitions select * from t1 where a is null;
+select * from t1 where a <= 1;
+drop table t1;
+
+create table t1 (a int signed)
+partition by list columns(a)
+( partition p0 values in (1, 3, 5, 7, 9, NULL),
+ partition p1 values in (2, 4, 6, 8, 0));
+insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
+select * from t1 where a <= NULL;
+select * from t1 where a is null;
+explain partitions select * from t1 where a is null;
+select * from t1 where a <= 1;
+drop table t1;
+
+create table t1 (a int, b int)
+partition by list columns(a,b)
+( partition p0 values in ((1, NULL), (2, NULL), (NULL, NULL)),
+ partition p1 values in ((1,1), (2,2)),
+ partition p2 values in ((3, NULL), (NULL, 1)));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+show create table t1;
+#
+# BUG#47754 Crash when selecting using NOT BETWEEN for column list partitioning
+#
+insert into t1 values (3, NULL);
+insert into t1 values (NULL, 1);
+insert into t1 values (NULL, NULL);
+insert into t1 values (1, NULL);
+insert into t1 values (2, NULL);
+insert into t1 values (1,1);
+insert into t1 values (2,2);
+select * from t1 where a = 1;
+select * from t1 where a = 2;
+select * from t1 where a > 8;
+select * from t1 where a not between 8 and 8;
+show create table t1;
+drop table t1;
+
+--error ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR
+create table t1 (a int)
+partition by list (a)
+( partition p0 values in (1),
+ partition p1 values in (1));
+
+create table t1 (a int)
+partition by list (a)
+( partition p0 values in (2, 1),
+ partition p1 values in (4, NULL, 3));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+show create table t1;
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+insert into t1 values (4);
+insert into t1 values (NULL);
+--error ER_NO_PARTITION_FOR_GIVEN_VALUE
+insert into t1 values (5);
+drop table t1;
+
+--error ER_PARSE_ERROR
+create table t1 (a int)
+partition by list columns(a)
+( partition p0 values in (2, 1),
+ partition p1 values in ((4), (NULL), (3)));
+
+create table t1 (a int)
+partition by list columns(a)
+( partition p0 values in (2, 1),
+ partition p1 values in (4, NULL, 3));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+show create table t1;
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t1 values (3);
+insert into t1 values (4);
+insert into t1 values (NULL);
+--error ER_NO_PARTITION_FOR_GIVEN_VALUE
+insert into t1 values (5);
+show create table t1;
+drop table t1;
+
+create table t1 (a int, b char(10), c varchar(5), d int)
+partition by range columns(a,b,c)
+subpartition by key (c,d)
+subpartitions 3
+( partition p0 values less than (1,'abc','abc'),
+ partition p1 values less than (2,'abc','abc'),
+ partition p2 values less than (3,'abc','abc'),
+ partition p3 values less than (4,'abc','abc'));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+show create table t1;
+
+insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
+insert into t1 values (1,'b','c',1),(2,'b','c',2),(3,'b','c',3);
+insert into t1 values (1,'c','d',1),(2,'c','d',2),(3,'c','d',3);
+insert into t1 values (1,'d','e',1),(2,'d','e',2),(3,'d','e',3);
+select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR
+ (a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2))));
+drop table t1;
+
+create table t1 (a int, b varchar(2), c int)
+partition by range columns (a, b, c)
+(partition p0 values less than (1, 'A', 1),
+ partition p1 values less than (1, 'B', 1));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+show create table t1;
+insert into t1 values (1, 'A', 1);
+explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 1;
+select * from t1 where a = 1 AND b <= 'A' and c = 1;
+drop table t1;
+
+create table t1 (a char, b char, c char)
+partition by list columns(a)
+( partition p0 values in ('a'));
+insert into t1 (a) values ('a');
+select * from t1 where a = 'a';
+drop table t1;
+
+--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+create table t1 (d time)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+ partition p1 values less than ('2040-01-01'));
+
+--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
+create table t1 (d timestamp)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+ partition p1 values less than ('2040-01-01'));
+
+--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
+create table t1 (d bit(1))
+partition by range columns(d)
+( partition p0 values less than (0),
+ partition p1 values less than (1));
+
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (maxvalue, 10));
+drop table t1;
+
+create table t1 (d date)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+ partition p1 values less than ('2009-01-01'));
+drop table t1;
+
+create table t1 (d date)
+partition by range columns(d)
+( partition p0 values less than ('1999-01-01'),
+ partition p1 values less than ('2000-01-01'));
+drop table t1;
+
+create table t1 (d date)
+partition by range columns(d)
+( partition p0 values less than ('2000-01-01'),
+ partition p1 values less than ('3000-01-01'));
+drop table t1;
+
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p2 values less than (99,99),
+ partition p1 values less than (99,999));
+
+insert into t1 values (99,998);
+select * from t1 where b = 998;
+drop table t1;
+
+create table t1 as select to_seconds(null) as to_seconds;
+select data_type from information_schema.columns
+where column_name='to_seconds';
+drop table t1;
+
+--error ER_PARSE_ERROR
+create table t1 (a int, b int)
+partition by list columns(a,b)
+(partition p0 values in ((maxvalue,maxvalue)));
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (maxvalue,maxvalue));
+drop table t1;
+
+create table t1 (a int)
+partition by list columns(a)
+(partition p0 values in (0));
+select partition_method from information_schema.partitions where table_name='t1';
+drop table t1;
+
+create table t1 (a char(6))
+partition by range columns(a)
+(partition p0 values less than ('H23456'),
+ partition p1 values less than ('M23456'));
+insert into t1 values ('F23456');
+select * from t1;
+drop table t1;
+
+-- error 1054
+create table t1 (a char(6))
+partition by range columns(a)
+(partition p0 values less than (H23456),
+ partition p1 values less than (M23456));
+
+-- error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+create table t1 (a char(6))
+partition by range columns(a)
+(partition p0 values less than (23456),
+ partition p1 values less than (23456));
+
+-- error 1064
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (10));
+
+-- error ER_PARTITION_COLUMN_LIST_ERROR
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (1,1,1);
+
+create table t1 (a int, b int)
+partition by range columns(a,b)
+(partition p0 values less than (1, 0),
+ partition p1 values less than (2, maxvalue),
+ partition p2 values less than (3, 3),
+ partition p3 values less than (10, maxvalue));
+
+-- error ER_NO_PARTITION_FOR_GIVEN_VALUE
+insert into t1 values (11,0);
+insert into t1 values (0,1),(1,1),(2,1),(3,1),(3,4),(4,9),(9,1);
+select * from t1;
+
+alter table t1
+partition by range columns(b,a)
+(partition p0 values less than (1,2),
+ partition p1 values less than (3,3),
+ partition p2 values less than (9,5));
+explain partitions select * from t1 where b < 2;
+select * from t1 where b < 2;
+explain partitions select * from t1 where b < 4;
+select * from t1 where b < 4;
+
+alter table t1 reorganize partition p1 into
+(partition p11 values less than (2,2),
+ partition p12 values less than (3,3));
+
+-- error ER_REORG_OUTSIDE_RANGE
+alter table t1 reorganize partition p0 into
+(partition p01 values less than (0,3),
+ partition p02 values less than (1,1));
+
+-- error ER_PARTITION_COLUMN_LIST_ERROR
+alter table t1 reorganize partition p2 into
+(partition p2 values less than(9,6,1));
+
+-- error ER_PARTITION_COLUMN_LIST_ERROR
+alter table t1 reorganize partition p2 into
+(partition p2 values less than (10));
+
+alter table t1 reorganize partition p2 into
+(partition p21 values less than (4,7),
+ partition p22 values less than (9,5));
+explain partitions select * from t1 where b < 4;
+select * from t1 where b < 4;
+drop table t1;
+
+create table t1 (a int, b int)
+partition by list columns(a,b)
+subpartition by hash (b)
+subpartitions 2
+(partition p0 values in ((0,0), (1,1)),
+ partition p1 values in ((1000,1000)));
+insert into t1 values (1000,1000);
+#select * from t1 where a = 0 and b = 0;
+drop table t1;
+
+create table t1 (a char, b char, c char)
+partition by range columns(a,b,c)
+( partition p0 values less than ('a','b','c'));
+alter table t1 add partition
+(partition p1 values less than ('b','c','d'));
+drop table t1;
diff --git a/mysql-test/t/partition_column_prune.test b/mysql-test/t/partition_column_prune.test
new file mode 100644
index 00000000000..848825ba71b
--- /dev/null
+++ b/mysql-test/t/partition_column_prune.test
@@ -0,0 +1,71 @@
+#
+# Partition pruning tests for new COLUMN LIST feature
+#
+-- source include/have_partition.inc
+
+--disable_warnings
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+--enable_warnings
+
+create table t1 (a char, b char, c char)
+partition by range columns(a,b,c)
+( partition p0 values less than ('a','b','c'));
+insert into t1 values ('a', NULL, 'd');
+explain partitions select * from t1 where a = 'a' AND c = 'd';
+select * from t1 where a = 'a' AND c = 'd';
+drop table t1;
+
+## COLUMN_LIST partition pruning tests
+create table t1 (a int not null) partition by range columns(a) (
+ partition p0 values less than (10),
+ partition p1 values less than (20),
+ partition p2 values less than (30),
+ partition p3 values less than (40),
+ partition p4 values less than (50),
+ partition p5 values less than (60),
+ partition p6 values less than (70)
+);
+insert into t1 values (5),(15),(25),(35),(45),(55),(65);
+insert into t1 values (5),(15),(25),(35),(45),(55),(65);
+
+create table t2 (a int not null) partition by range(a) (
+ partition p0 values less than (10),
+ partition p1 values less than (20),
+ partition p2 values less than (30),
+ partition p3 values less than (40),
+ partition p4 values less than (50),
+ partition p5 values less than (60),
+ partition p6 values less than (70)
+);
+insert into t2 values (5),(15),(25),(35),(45),(55),(65);
+insert into t2 values (5),(15),(25),(35),(45),(55),(65);
+
+explain partitions select * from t1 where a > 35 and a < 45;
+explain partitions select * from t2 where a > 35 and a < 45;
+
+drop table t1, t2;
+
+create table t1 (a int not null, b int not null )
+partition by range columns(a,b) (
+ partition p01 values less than (2,10),
+ partition p02 values less than (2,20),
+ partition p03 values less than (2,30),
+
+ partition p11 values less than (4,10),
+ partition p12 values less than (4,20),
+ partition p13 values less than (4,30),
+
+ partition p21 values less than (6,10),
+ partition p22 values less than (6,20),
+ partition p23 values less than (6,30)
+);
+
+insert into t1 values (2,5), (2,15), (2,25),
+ (4,5), (4,15), (4,25), (6,5), (6,15), (6,25);
+insert into t1 select * from t1;
+
+explain partitions select * from t1 where a=2;
+explain partitions select * from t1 where a=4;
+explain partitions select * from t1 where a=2 and b < 22;
+
+drop table t1;
diff --git a/mysql-test/t/partition_datatype.test b/mysql-test/t/partition_datatype.test
index 7440a9bf3a3..0a9fae15354 100644
--- a/mysql-test/t/partition_datatype.test
+++ b/mysql-test/t/partition_datatype.test
@@ -4,6 +4,7 @@
# as partition by key
# Created to verify the fix for Bug#31705
# Partitions: crash if varchar length > 65530
+# BUG#48164 limited size to 3072 bytes
#
-- source include/have_partition.inc
@@ -192,27 +193,29 @@ create table t1 (a set('y','n')) partition by key (a);
insert into t1 values ('y');
select * from t1 where a = 'y';
drop table t1;
-create table t1 (a varchar(65531)) partition by key (a);
+create table t1 (a varchar(3068)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
select * from t1 where a like 'aaa%';
select * from t1 where a = 'bbbb';
drop table t1;
-create table t1 (a varchar(65532)) partition by key (a);
+create table t1 (a varchar(3069)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
select * from t1 where a like 'aaa%';
select * from t1 where a = 'bbbb';
drop table t1;
-create table t1 (a varchar(65533) not null) partition by key (a);
+create table t1 (a varchar(3070) not null) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
select * from t1 where a like 'aaa%';
select * from t1 where a = 'bbbb';
drop table t1;
+-- error ER_PARTITION_FIELDS_TOO_LONG
+create table t1 (a varchar(3070)) partition by key (a);
-- error ER_TOO_BIG_ROWSIZE
create table t1 (a varchar(65533)) partition by key (a);
-- error ER_TOO_BIG_ROWSIZE
diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test
index 49632f95dfb..eb7a4942f5b 100644
--- a/mysql-test/t/partition_error.test
+++ b/mysql-test/t/partition_error.test
@@ -180,7 +180,7 @@ partitions 3
(partition x1, partition x2);
#
-# Partition by key specified 3 partitions but only defined 2 => error
+# Partition by hash, random function
#
--error 1064
CREATE TABLE t1 (
@@ -193,7 +193,7 @@ partitions 2
(partition x1, partition x2);
#
-# Partition by key specified 3 partitions but only defined 2 => error
+# Partition by range, random function
#
--error 1064
CREATE TABLE t1 (
@@ -206,7 +206,7 @@ partitions 2
(partition x1 values less than (0), partition x2 values less than (2));
#
-# Partition by key specified 3 partitions but only defined 2 => error
+# Partition by list, random function
#
--error 1064
CREATE TABLE t1 (
@@ -452,7 +452,7 @@ partitions 2
#
# Partition by range, inconsistent partition function and constants
#
---error 1064
+--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -522,7 +522,7 @@ partitions 2
#
# Partition by range, missing parenthesis
#
---error 1064
+--error ER_PARTITION_WRONG_VALUES_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -536,7 +536,7 @@ partitions 2
#
# Partition by range, maxvalue in wrong place
#
---error 1064
+--error ER_PARTITION_MAXVALUE_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -550,7 +550,7 @@ partitions 2
#
# Partition by range, maxvalue in several places
#
---error 1064
+--error ER_PARTITION_MAXVALUE_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -765,7 +765,7 @@ partitions 2
#
# Partition by list, wrong constant result type (not INT)
#
---error 1064
+--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test
index 36e3edf05aa..2e08834cfc7 100644
--- a/mysql-test/t/partition_innodb.test
+++ b/mysql-test/t/partition_innodb.test
@@ -6,6 +6,51 @@ drop table if exists t1;
--enable_warnings
#
+# BUG#47774, Assertion failure in InnoDB using column list partitioning
+#
+create table t1 (a varchar(5), b int signed, c varchar(10), d datetime)
+partition by range columns(b,c)
+subpartition by hash(to_seconds(d))
+( partition p0 values less than (2, 'b'),
+ partition p1 values less than (4, 'd'),
+ partition p2 values less than (10, 'za'));
+insert into t1 values ('a', 3, 'w', '2001-10-27 04:34:00');
+insert into t1 values ('r', 7, 'w', '2001-10-27 05:34:00');
+insert into t1 values ('g', 10, 'w', '2001-10-27 06:34:00');
+update t1 set a = 'c' where a > 'f';
+drop table t1;
+
+#
+# BUG#47776, Failed to update for MEMORY engine, crash for InnoDB and success for MyISAM
+#
+create table t1 (a varchar(5))
+engine=memory
+partition by range columns(a)
+( partition p0 values less than ('m'),
+ partition p1 values less than ('za'));
+insert into t1 values ('j');
+update t1 set a = 'z' where (a >= 'j');
+drop table t1;
+
+create table t1 (a varchar(5))
+engine=myisam
+partition by range columns(a)
+( partition p0 values less than ('m'),
+ partition p1 values less than ('za'));
+insert into t1 values ('j');
+update t1 set a = 'z' where (a >= 'j');
+drop table t1;
+
+create table t1 (a varchar(5))
+engine=innodb
+partition by range columns(a)
+( partition p0 values less than ('m'),
+ partition p1 values less than ('za'));
+insert into t1 values ('j');
+update t1 set a = 'z' where (a >= 'j');
+drop table t1;
+
+#
# Bug#47029: Crash when reorganize partition with subpartition
#
create table t1 (a int not null,
diff --git a/mysql-test/t/partition_list.test b/mysql-test/t/partition_list.test
index 1c76de9d55a..8d2ec88e0f4 100644
--- a/mysql-test/t/partition_list.test
+++ b/mysql-test/t/partition_list.test
@@ -40,6 +40,8 @@ subpartitions 2
partition p1 values in (1),
partition pnull values in (null, 2),
partition p3 values in (3));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
insert into t1 values (0,0),(0,1),(1,0),(1,1),(null,0),(null,1);
insert into t1 values (2,0),(2,1),(3,0),(3,1);
diff --git a/mysql-test/t/partition_mgm_err.test b/mysql-test/t/partition_mgm_err.test
index 0f8b8d3cd90..f921fa8ebca 100644
--- a/mysql-test/t/partition_mgm_err.test
+++ b/mysql-test/t/partition_mgm_err.test
@@ -61,7 +61,7 @@ ALTER TABLE t1 REORGANIZE PARTITION x0, x1, x1 INTO
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (5));
---error ER_REORG_OUTSIDE_RANGE
+--error ER_RANGE_NOT_INCREASING_ERROR
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (4),
PARTITION x11 VALUES LESS THAN (2));
diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test
index ea72cef5b62..fd3f7f2c322 100644
--- a/mysql-test/t/partition_pruning.test
+++ b/mysql-test/t/partition_pruning.test
@@ -51,6 +51,26 @@ INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
ALTER TABLE t1 DROP KEY a;
--source include/partition_date_range.inc
DROP TABLE t1;
+--echo # TO_SECONDS, test of LIST and index
+CREATE TABLE t1 (a DATE, KEY(a))
+PARTITION BY LIST (TO_SECONDS(a))
+(PARTITION `p0001-01-01` VALUES IN (TO_SECONDS('0001-01-01')),
+ PARTITION `p2001-01-01` VALUES IN (TO_SECONDS('2001-01-01')),
+ PARTITION `pNULL` VALUES IN (NULL),
+ PARTITION `p0000-01-02` VALUES IN (TO_SECONDS('0000-01-02')),
+ PARTITION `p1001-01-01` VALUES IN (TO_SECONDS('1001-01-01')));
+if ($verify_without_partitions)
+{
+ALTER TABLE t1 REMOVE PARTITIONING;
+}
+INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
+ ('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
+--source include/partition_date_range.inc
+--echo # test without index
+ALTER TABLE t1 DROP KEY a;
+--source include/partition_date_range.inc
+DROP TABLE t1;
+
#
# Bug#46362: Endpoint should be set to false for TO_DAYS(DATE)
diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test
index c02d9049f2e..07c345faed5 100644
--- a/mysql-test/t/partition_range.test
+++ b/mysql-test/t/partition_range.test
@@ -9,6 +9,78 @@
drop table if exists t1, t2;
--enable_warnings
+--error ER_NULL_IN_VALUES_LESS_THAN
+create table t1 (a int)
+partition by range (a)
+( partition p0 values less than (NULL),
+ partition p1 values less than (MAXVALUE));
+#
+# Merge fix of bug#27927 for TO_SECONDS function
+#
+create table t1 (a datetime not null)
+partition by range (TO_SECONDS(a))
+( partition p0 VALUES LESS THAN (TO_SECONDS('2007-03-08 00:00:00')),
+ partition p1 VALUES LESS THAN (TO_SECONDS('2007-04-01 00:00:00')));
+select partition_method, partition_expression, partition_description
+ from information_schema.partitions where table_name = "t1";
+INSERT INTO t1 VALUES ('2007-03-01 12:00:00'), ('2007-03-07 12:00:00');
+INSERT INTO t1 VALUES ('2007-03-08 12:00:00'), ('2007-03-15 12:00:00');
+explain partitions select * from t1 where a < '2007-03-08 00:00:00';
+explain partitions select * from t1 where a < '2007-03-08 00:00:01';
+explain partitions select * from t1 where a <= '2007-03-08 00:00:00';
+explain partitions select * from t1 where a <= '2007-03-07 23:59:59';
+explain partitions select * from t1 where a < '2007-03-07 23:59:59';
+drop table t1;
+#
+# New test cases for new function to_seconds
+#
+create table t1 (a date)
+partition by range(to_seconds(a))
+(partition p0 values less than (to_seconds('2004-01-01')),
+ partition p1 values less than (to_seconds('2005-01-01')));
+insert into t1 values ('2003-12-30'),('2004-12-31');
+select * from t1;
+explain partitions select * from t1 where a <= '2003-12-31';
+select * from t1 where a <= '2003-12-31';
+explain partitions select * from t1 where a <= '2005-01-01';
+select * from t1 where a <= '2005-01-01';
+drop table t1;
+
+create table t1 (a datetime)
+partition by range(to_seconds(a))
+(partition p0 values less than (to_seconds('2004-01-01 12:00:00')),
+ partition p1 values less than (to_seconds('2005-01-01 12:00:00')));
+insert into t1 values ('2004-01-01 11:59:29'),('2005-01-01 11:59:59');
+select * from t1;
+explain partitions select * from t1 where a <= '2004-01-01 11:59.59';
+select * from t1 where a <= '2004-01-01 11:59:59';
+explain partitions select * from t1 where a <= '2005-01-01';
+select * from t1 where a <= '2005-01-01';
+drop table t1;
+
+#
+# Adding new test cases for column list variant for partitioning
+#
+--error 1064
+create table t1 (a int, b char(20))
+partition by range columns(a,b)
+(partition p0 values less than (1));
+
+--error ER_TOO_MANY_VALUES_ERROR
+create table t1 (a int, b char(20))
+partition by range(a)
+(partition p0 values less than (1,"b"));
+
+--error ER_TOO_MANY_VALUES_ERROR
+create table t1 (a int, b char(20))
+partition by range(a)
+(partition p0 values less than (1,"b"));
+
+create table t1 (a int, b char(20))
+partition by range columns(b)
+(partition p0 values less than ("b"));
+drop table t1;
+
#
# BUG 33429: Succeeds in adding partition when maxvalue on last partition
#
diff --git a/mysql-test/t/partition_utf8.test b/mysql-test/t/partition_utf8.test
new file mode 100644
index 00000000000..d3ad7ba671e
--- /dev/null
+++ b/mysql-test/t/partition_utf8.test
@@ -0,0 +1,42 @@
+# Tests for Column list which requires utf8 output
+--source include/have_partition.inc
+set names utf8;
+create table t1 (a varchar(2) character set cp1250)
+partition by list columns (a)
+( partition p0 values in (0x81));
+show create table t1;
+drop table t1;
+create table t1 (a varchar(2) character set cp1250)
+partition by list columns (a)
+( partition p0 values in (0x80));
+show create table t1;
+drop table t1;
+
+#
+# BUG#48164, too long partition fields causes crash
+#
+--error ER_PARTITION_FIELDS_TOO_LONG
+create table t1 (a varchar(1500), b varchar(1570))
+partition by list columns(a,b)
+( partition p0 values in (('a','b')));
+
+create table t1 (a varchar(1023) character set utf8 collate utf8_spanish2_ci)
+partition by range columns(a)
+( partition p0 values less than ('CZ'),
+ partition p1 values less than ('CH'),
+ partition p2 values less than ('D'));
+insert into t1 values ('czz'),('chi'),('ci'),('cg');
+select * from t1 where a between 'cg' AND 'ci';
+drop table t1;
+
+#
+# BUG#48163, Dagger in UCS2 not working as partition value
+#
+create table t1 (a varchar(2) character set ucs2)
+partition by list columns (a)
+(partition p0 values in (0x2020),
+ partition p1 values in (''));
+show create table t1;
+insert into t1 values ('');
+insert into t1 values (_ucs2 0x2020);
+drop table t1;
diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test
index 788a7b336ef..0bf86b47dd7 100644
--- a/mysql-test/t/plugin.test
+++ b/mysql-test/t/plugin.test
@@ -22,6 +22,12 @@ SELECT * FROM t1;
DROP TABLE t1;
+# a couple of tests for variables
+set global example_ulong_var=500;
+set global example_enum_var= e1;
+show status like 'example%';
+show variables like 'example%';
+
UNINSTALL PLUGIN example;
--error 1305
UNINSTALL PLUGIN EXAMPLE;
diff --git a/mysql-test/t/profiling.test b/mysql-test/t/profiling.test
index 275c2d77c4a..afbce04b966 100644
--- a/mysql-test/t/profiling.test
+++ b/mysql-test/t/profiling.test
@@ -1,4 +1,4 @@
---source include/have_community_features.inc
+--source include/have_profiling.inc
# Verify that the protocol isn't violated if we ask for profiling info
# before profiling has recorded anything.
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index db5994d434b..844be582290 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -3009,5 +3009,209 @@ execute stmt;
drop table t1;
deallocate prepare stmt;
+###########################################################################
+--echo
--echo End of 5.1 tests.
+
+###########################################################################
+
+--echo
+--echo #
+--echo # WL#4435: Support OUT-parameters in prepared statements.
+--echo #
+--echo
+
+# The idea of this test case is to check that
+# - OUT-parameters of four allowed types (string, double, int, decimal) work
+# properly;
+# - INOUT and OUT parameters work properly;
+# - A mix of IN and OUT parameters work properly;
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p_string;
+DROP PROCEDURE IF EXISTS p_double;
+DROP PROCEDURE IF EXISTS p_int;
+DROP PROCEDURE IF EXISTS p_decimal;
+--enable_warnings
+
+delimiter |;
+
+--echo
+CREATE PROCEDURE p_string(
+ IN v0 INT,
+ OUT v1 CHAR(32),
+ IN v2 CHAR(32),
+ INOUT v3 CHAR(32))
+BEGIN
+ SET v0 = -1;
+ SET v1 = 'test_v1';
+ SET v2 = 'n/a';
+ SET v3 = 'test_v3';
+END|
+
+--echo
+CREATE PROCEDURE p_double(
+ IN v0 INT,
+ OUT v1 DOUBLE(4, 2),
+ IN v2 DOUBLE(4, 2),
+ INOUT v3 DOUBLE(4, 2))
+BEGIN
+ SET v0 = -1;
+ SET v1 = 12.34;
+ SET v2 = 98.67;
+ SET v3 = 56.78;
+END|
+
+--echo
+CREATE PROCEDURE p_int(
+ IN v0 CHAR(10),
+ OUT v1 INT,
+ IN v2 INT,
+ INOUT v3 INT)
+BEGIN
+ SET v0 = 'n/a';
+ SET v1 = 1234;
+ SET v2 = 9876;
+ SET v3 = 5678;
+END|
+
+--echo
+CREATE PROCEDURE p_decimal(
+ IN v0 INT,
+ OUT v1 DECIMAL(4, 2),
+ IN v2 DECIMAL(4, 2),
+ INOUT v3 DECIMAL(4, 2))
+BEGIN
+ SET v0 = -1;
+ SET v1 = 12.34;
+ SET v2 = 98.67;
+ SET v3 = 56.78;
+END|
+
+delimiter ;|
+
+--echo
+PREPARE stmt_str FROM 'CALL p_string(?, ?, ?, ?)';
+PREPARE stmt_dbl FROM 'CALL p_double(?, ?, ?, ?)';
+PREPARE stmt_int FROM 'CALL p_int(?, ?, ?, ?)';
+PREPARE stmt_dec FROM 'CALL p_decimal(?, ?, ?, ?)';
+
+--echo
+SET @x_str_1 = NULL;
+SET @x_str_2 = NULL;
+SET @x_str_3 = NULL;
+SET @x_dbl_1 = NULL;
+SET @x_dbl_2 = NULL;
+SET @x_dbl_3 = NULL;
+SET @x_int_1 = NULL;
+SET @x_int_2 = NULL;
+SET @x_int_3 = NULL;
+SET @x_dec_1 = NULL;
+SET @x_dec_2 = NULL;
+SET @x_dec_3 = NULL;
+
+--echo
+--echo -- Testing strings...
+
+--echo
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+
+--echo
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+
+--echo
+--echo -- Testing doubles...
+
+--echo
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+
+--echo
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+
+--echo
+--echo -- Testing ints...
+
+--echo
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+
+--echo
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+
+--echo
+--echo -- Testing decs...
+
+--echo
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+
+--echo
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+
+--echo
+DEALLOCATE PREPARE stmt_str;
+DEALLOCATE PREPARE stmt_dbl;
+DEALLOCATE PREPARE stmt_int;
+DEALLOCATE PREPARE stmt_dec;
+
+--echo
+DROP PROCEDURE p_string;
+DROP PROCEDURE p_double;
+DROP PROCEDURE p_int;
+DROP PROCEDURE p_decimal;
+
+#
+# Another test case for WL#4435: check out parameters in Dynamic SQL.
+#
+
+--echo
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+--enable_warnings
+
+--echo
+
+CREATE PROCEDURE p1(OUT v1 CHAR(10))
+ SET v1 = 'test1';
+
+--echo
+
+delimiter |;
+CREATE PROCEDURE p2(OUT v2 CHAR(10))
+BEGIN
+ SET @query = 'CALL p1(?)';
+ PREPARE stmt1 FROM @query;
+ EXECUTE stmt1 USING @u1;
+ DEALLOCATE PREPARE stmt1;
+
+ SET v2 = @u1;
+END|
+delimiter ;|
+
+--echo
+
+CALL p2(@a);
+SELECT @a;
+
+--echo
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+--echo
+--echo # End of WL#4435.
+
+###########################################################################
+
+--echo
+--echo End of 6.0 tests.
+
+###########################################################################
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 7841e7274dd..0edc9cca385 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -1294,7 +1294,7 @@ SET GLOBAL query_cache_size= default;
# Bug #31157: Crash when select+order by the avg of some field within the
# group by
#
-
+SET GLOBAL query_cache_size=1024*1024*512;
CREATE TABLE t1 (a ENUM('rainbow'));
INSERT INTO t1 VALUES (),(),(),(),();
SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID()));
@@ -1305,6 +1305,7 @@ INSERT INTO t1 SET a = 'aaaa';
SELECT 1 FROM t1 GROUP BY
(SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1);
DROP TABLE t1;
+SET GLOBAL query_cache_size= default;
--echo End of 5.1 tests
diff --git a/mysql-test/t/query_cache_disabled-master.opt b/mysql-test/t/query_cache_disabled-master.opt
new file mode 100644
index 00000000000..d7d47164883
--- /dev/null
+++ b/mysql-test/t/query_cache_disabled-master.opt
@@ -0,0 +1 @@
+--query_cache_type=0
diff --git a/mysql-test/t/query_cache_disabled.test b/mysql-test/t/query_cache_disabled.test
new file mode 100644
index 00000000000..cbc98bd94d6
--- /dev/null
+++ b/mysql-test/t/query_cache_disabled.test
@@ -0,0 +1,15 @@
+-- source include/have_query_cache.inc
+#
+# Bug#38551 query cache can still consume [very little] cpu time even when it is off.
+#
+SHOW GLOBAL VARIABLES LIKE 'query_cache_type';
+--error ER_QUERY_CACHE_DISABLED
+SET GLOBAL query_cache_type=ON;
+--error ER_QUERY_CACHE_DISABLED
+SET GLOBAL query_cache_type=DEMAND;
+--error ER_QUERY_CACHE_DISABLED
+SET GLOBAL query_cache_type=OFF;
+SET GLOBAL query_cache_size=1024*1024;
+SHOW GLOBAL VARIABLES LIKE 'query_cache_size';
+SET GLOBAL query_cache_size=0;
+
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index dc119b6a77e..3a845471cd0 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -1171,3 +1171,93 @@ a < 5 OR
a < 10;
DROP TABLE t1, t2, t3;
+
+--echo #
+--echo # Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN
+--echo #
+
+CREATE TABLE t1(a INT, KEY(a));
+INSERT INTO t1 VALUES (1), (NULL);
+SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL);
+DROP TABLE t1;
+
+--echo #
+--echo # Bug#47925: regression of range optimizer and date comparison in 5.1.39!
+--echo #
+CREATE TABLE t1 ( a DATE, KEY ( a ) );
+CREATE TABLE t2 ( a DATETIME, KEY ( a ) );
+
+--echo # Make optimizer choose range scan
+INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22');
+INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23');
+
+INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'),
+ ('2009-09-22 12:00:00');
+INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'),
+ ('2009-09-23 12:00:00');
+
+--echo # DATE vs DATE
+--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
+EXPLAIN
+SELECT * FROM t1 WHERE a >= '2009/09/23';
+SELECT * FROM t1 WHERE a >= '2009/09/23';
+SELECT * FROM t1 WHERE a >= '20090923';
+SELECT * FROM t1 WHERE a >= 20090923;
+SELECT * FROM t1 WHERE a >= '2009-9-23';
+SELECT * FROM t1 WHERE a >= '2009.09.23';
+SELECT * FROM t1 WHERE a >= '2009:09:23';
+
+--echo # DATE vs DATETIME
+--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
+EXPLAIN
+SELECT * FROM t2 WHERE a >= '2009/09/23';
+SELECT * FROM t2 WHERE a >= '2009/09/23';
+SELECT * FROM t2 WHERE a >= '2009/09/23';
+SELECT * FROM t2 WHERE a >= '20090923';
+SELECT * FROM t2 WHERE a >= 20090923;
+SELECT * FROM t2 WHERE a >= '2009-9-23';
+SELECT * FROM t2 WHERE a >= '2009.09.23';
+SELECT * FROM t2 WHERE a >= '2009:09:23';
+
+--echo # DATETIME vs DATETIME
+--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
+EXPLAIN
+SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
+SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00';
+SELECT * FROM t2 WHERE a >= '20090923120000';
+SELECT * FROM t2 WHERE a >= 20090923120000;
+SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00';
+SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00';
+SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00';
+
+--echo # DATETIME vs DATE
+--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X
+EXPLAIN
+SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
+SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
+SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00';
+SELECT * FROM t1 WHERE a >= '20090923000000';
+SELECT * FROM t1 WHERE a >= 20090923000000;
+SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00';
+SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00';
+SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00';
+
+--echo # Test of the new get_date_from_str implementation
+--echo # Behavior differs slightly between the trunk and mysql-pe.
+--echo # The former may give errors for the truncated values, while the latter
+--echo # gives warnings. The purpose of this test is not to interfere, and only
+--echo # preserve existing behavior.
+SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND
+ str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20';
+
+SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND
+ str_to_date('2007-20-00', '%Y-%m-%d') <= '';
+
+SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
+SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '';
+
+SELECT str_to_date('', '%Y-%m-%d');
+
+DROP TABLE t1, t2;
+
+--echo End of 5.1 tests
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 7d3785ecccc..51f0cd73374 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -3739,7 +3739,40 @@ EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2;
EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2;
DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when
+--echo # forcing a spatial index
+--echo #
+CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a));
+INSERT INTO t1 VALUES
+ (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')),
+ (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'));
+EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
+SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2;
+EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
+SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a);
+DROP TABLE t1;
+
+
+--echo #
+--echo # Bug #48291 : crash with row() operator,select into @var, and
+--echo # subquery returning multiple rows
+--echo #
+
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (2),(3);
+
+--echo # Should not crash
+--error ER_SUBQUERY_NO_1_ROW
+SELECT 1 FROM t1 WHERE a <> 1 AND NOT
+ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1))
+INTO @var0;
+
+DROP TABLE t1;
+
--echo End of 5.0 tests
#
diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test
new file mode 100644
index 00000000000..7b94e65a5e9
--- /dev/null
+++ b/mysql-test/t/sp-bugs.test
@@ -0,0 +1,61 @@
+# Test file for stored procedure bugfixes
+
+--echo #
+--echo # Bug #47412: Valgrind warnings / user can read uninitalized memory
+--echo # using SP variables
+--echo #
+
+CREATE SCHEMA testdb;
+USE testdb;
+DELIMITER |;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+ RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg1 VARCHAR(32) )
+BEGIN
+ CALL p_not_exists ( );
+END|
+DELIMITER ;|
+--echo # should not return valgrind warnings
+--error ER_SP_DOES_NOT_EXIST
+CALL p3 ( f2 () );
+
+DROP SCHEMA testdb;
+
+CREATE SCHEMA testdb;
+USE testdb;
+DELIMITER |;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+ RETURN f_not_exists () ;
+END|
+CREATE PROCEDURE p3 ( arg2 INTEGER )
+BEGIN
+ CALL p_not_exists ( );
+END|
+DELIMITER ;|
+--echo # should not return valgrind warnings
+--error ER_SP_DOES_NOT_EXIST
+CALL p3 ( f2 () );
+
+DROP SCHEMA testdb;
+
+CREATE SCHEMA testdb;
+USE testdb;
+DELIMITER |;
+CREATE FUNCTION f2 () RETURNS INTEGER
+BEGIN
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1;
+ RETURN f_not_exists () ;
+END|
+DELIMITER ;|
+--echo # should not return valgrind warnings
+SELECT f2 ();
+
+DROP SCHEMA testdb;
+
+
+--echo End of 5.1 tests
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 66b960c938f..18a4a117939 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -2448,3 +2448,27 @@ SELECT AVG (a) FROM t1 WHERE b = 999999;
--error ER_SP_DOES_NOT_EXIST
SELECT non_existent (a) FROM t1 WHERE b = 999999;
DROP TABLE t1;
+
+--echo #
+--echo # Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW +
+--echo # SP + MERGE + ALTER
+--echo #
+
+CREATE TABLE t1 (pk INT, b INT, KEY (b));
+CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+
+CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a;
+
+--error ER_NON_UPDATABLE_TABLE
+CALL p1(5);
+
+ALTER TABLE t1 CHANGE COLUMN b b2 INT;
+
+--error ER_VIEW_INVALID
+CALL p1(7);
+
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo End of 5.1 tests
diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test
index fe063889f81..2e7257cbcea 100644
--- a/mysql-test/t/sp-vars.test
+++ b/mysql-test/t/sp-vars.test
@@ -1448,3 +1448,42 @@ drop function f1;
drop table t1;
# End of 5.1 tests.
+
+###########################################################################
+#
+# Test case for BUG#28299: To-number conversion warnings work
+# differenly with CHAR and VARCHAR sp variables
+#
+###########################################################################
+
+--echo
+--echo ---------------------------------------------------------------
+--echo BUG#28299
+--echo ---------------------------------------------------------------
+--echo
+
+DELIMITER |;
+CREATE PROCEDURE ctest()
+BEGIN
+ DECLARE i CHAR(16);
+ DECLARE j INT;
+ SET i= 'string';
+ SET j= 1 + i;
+END|
+DELIMITER ;|
+
+CALL ctest();
+DROP PROCEDURE ctest;
+
+DELIMITER |;
+CREATE PROCEDURE vctest()
+BEGIN
+ DECLARE i VARCHAR(16);
+ DECLARE j INT;
+ SET i= 'string';
+ SET j= 1 + i;
+END|
+DELIMITER ;|
+
+CALL vctest();
+DROP PROCEDURE vctest;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 168b6020670..eef843ded59 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -8266,3 +8266,53 @@ DROP TABLE t1, t2;
--echo # ------------------------------------------------------------------
--echo # -- End of 5.1 tests
--echo # ------------------------------------------------------------------
+
+#
+# Bug#39255: Stored procedures: crash if function references nonexistent table
+#
+
+--disable_warnings
+DROP FUNCTION IF EXISTS f1;
+DROP TABLE IF EXISTS t_non_existing;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+delimiter |;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ DECLARE v INT;
+ SELECT a INTO v FROM t_non_existing;
+ RETURN 1;
+END|
+delimiter ;|
+
+CREATE TABLE t1 (a INT) ENGINE = myisam;
+INSERT INTO t1 VALUES (1);
+
+--error ER_NO_SUCH_TABLE
+SELECT * FROM t1 WHERE a = f1();
+
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug#34197: CREATE PROCEDURE fails when COMMENT truncated in non
+--echo # strict SQL mode
+--echo #
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+CREATE PROCEDURE p1 ()
+COMMENT
+'12345678901234567890123456789012345678901234567890123456789012345678901234567890'
+BEGIN
+END;
+
+SELECT comment FROM mysql.proc WHERE name = "p1";
+
+SELECT routine_comment FROM information_schema.routines WHERE routine_name = "p1";
+
+DROP PROCEDURE p1;
+
diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test
index 0b04b9d7668..ce18b2b578e 100644
--- a/mysql-test/t/sp_trans.test
+++ b/mysql-test/t/sp_trans.test
@@ -592,6 +592,44 @@ select distinct f1, bug13575(f1) from t3 order by f1|
drop function bug13575|
drop table t3|
+--echo #
+--echo # End of 5.1 tests
+--echo #
+
+--echo #
+--echo # Bug #35877 Update .. WHERE with function, constraint violation, crash
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1_aux|
+DROP TABLE IF EXISTS t1_not_null|
+DROP FUNCTION IF EXISTS f1_two_inserts|
+--enable_warnings
+
+-- echo # MyISAM test
+CREATE TABLE t1_not_null (f1 BIGINT, f2 BIGINT NOT NULL)|
+CREATE TABLE t1_aux (f1 BIGINT, f2 BIGINT)|
+INSERT INTO t1_aux VALUES (1,1)|
+
+CREATE FUNCTION f1_two_inserts() returns INTEGER
+BEGIN
+ INSERT INTO t1_not_null SET f1 = 10, f2 = NULL;
+ RETURN 1;
+END|
+
+-- error ER_BAD_NULL_ERROR
+UPDATE t1_aux SET f2 = 2 WHERE f1 = f1_two_inserts()|
+
+-- echo # InnoDB test
+ALTER TABLE t1_not_null ENGINE = InnoDB|
+ALTER TABLE t1_aux ENGINE = InnoDB|
+
+-- error ER_BAD_NULL_ERROR
+UPDATE t1_aux SET f2 = 2 WHERE f1 = f1_two_inserts()|
+
+DROP TABLE t1_aux, t1_not_null|
+DROP FUNCTION f1_two_inserts|
+
#
# BUG#NNNN: New bug synopsis
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index 4a9f34443cb..27956bc8877 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -309,6 +309,21 @@ flush privileges;
--connection default
drop user mysqltest_32753@localhost;
+
+#
+# Bug#21099 MySQL 5.0.22 silently creates MyISAM tables even though
+# InnoDB specified.
+#
+
+SET @org_mode=@@sql_mode;
+SET @@sql_mode='traditional';
+
+# Agreed change was to add NO_ENGINE_SUBSTITUTION to TRADITIONAL sql mode.
+SELECT @@sql_mode LIKE '%NO_ENGINE_SUBSTITUTION%';
+
+SET sql_mode=@org_mode;
+
+
#
# Bug#45100: Incomplete DROP USER in case of SQL_MODE = 'PAD_CHAR_TO_FULL_LENGTH'
#
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index d25aab68b5e..98c4a75c426 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1);
SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
-- error ER_WRONG_USAGE
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
--- error ER_WRONG_USAGE
+-- error ER_WRONG_PARAMETERS_TO_PROCEDURE
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-- error ER_BAD_FIELD_ERROR
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
@@ -3764,5 +3764,19 @@ SELECT * FROM t1 WHERE EXISTS ( SELECT 1 INTO @v );
SELECT * FROM t1 WHERE a IN ( SELECT 1 INTO @v );
DROP TABLE t1, t2;
+#
+# Bug #31157: Crash when select+order by the avg of some field within the
+# group by
+#
+CREATE TABLE t1 (a ENUM('rainbow'));
+INSERT INTO t1 VALUES (),(),(),(),();
+SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID()));
+DROP TABLE t1;
+CREATE TABLE t1 (a LONGBLOB);
+INSERT INTO t1 SET a = 'aaaa';
+INSERT INTO t1 SET a = 'aaaa';
+SELECT 1 FROM t1 GROUP BY
+ (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1);
+DROP TABLE t1;
--echo End of 5.1 tests.
diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test
index 7a2a9f328ef..fab0a462157 100644
--- a/mysql-test/t/subselect3.test
+++ b/mysql-test/t/subselect3.test
@@ -728,3 +728,69 @@ where
from t4, t5 limit 2));
drop table t0, t1, t2, t3, t4, t5;
+
+--echo #
+--echo # BUG#48177 - SELECTs with NOT IN subqueries containing NULL
+--echo # values return too many records
+--echo #
+
+CREATE TABLE t1 (
+ i1 int DEFAULT NULL,
+ i2 int DEFAULT NULL
+) ;
+
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t1 VALUES (2, 3);
+INSERT INTO t1 VALUES (4, NULL);
+INSERT INTO t1 VALUES (4, 0);
+INSERT INTO t1 VALUES (NULL, NULL);
+
+CREATE TABLE t2 (
+ i1 int DEFAULT NULL,
+ i2 int DEFAULT NULL
+) ;
+
+INSERT INTO t2 VALUES (4, NULL);
+INSERT INTO t2 VALUES (5, 0);
+
+--echo
+--echo Data in t1
+SELECT i1, i2 FROM t1;
+
+--echo
+--echo Data in subquery (should be filtered out)
+SELECT i1, i2 FROM t2 ORDER BY i1;
+
+FLUSH STATUS;
+
+--echo
+SELECT i1, i2
+FROM t1
+WHERE (i1, i2)
+ NOT IN (SELECT i1, i2 FROM t2);
+
+--echo
+--echo # Check that the subquery only has to be evaluated once
+--echo # for all-NULL values even though there are two (NULL,NULL) records
+--echo # Baseline:
+SHOW STATUS LIKE '%Handler_read_rnd_next';
+
+--echo
+INSERT INTO t1 VALUES (NULL, NULL);
+FLUSH STATUS;
+
+--echo
+SELECT i1, i2
+FROM t1
+WHERE (i1, i2)
+ NOT IN (SELECT i1, i2 FROM t2);
+
+--echo
+--echo # Handler_read_rnd_next should be one more than baseline
+--echo # (read record from t1, but do not read from t2)
+SHOW STATUS LIKE '%Handler_read_rnd_next';
+
+
+DROP TABLE t1,t2;
+
+--echo End of 5.1 tests
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 1e55f9d5993..3ab724a835a 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2397,3 +2397,31 @@ SELECT * FROM t2;
DROP TABLE t1, t2;
--echo End of 5.1 tests.
+
+
+--echo #
+--echo # Bug#34453 Can't change size of file (Errcode: 1224)
+--echo #
+
+--disable_warnings
+DROP TRIGGER IF EXISTS t1_bi;
+DROP TRIGGER IF EXISTS t1_bd;
+DROP TABLE IF EXISTS t1;
+DROP TEMPORARY TABLE IF EXISTS t2;
+--enable_warnings
+
+CREATE TABLE t1 (s1 INT);
+CREATE TEMPORARY TABLE t2 (s1 INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (0);
+CREATE TRIGGER t1_bd BEFORE DELETE ON t1 FOR EACH ROW DELETE FROM t2;
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 VALUES (0);
+SELECT * FROM t1;
+SELECT * FROM t2;
+-- echo # Reported to give ERROR 14 (HY000):
+-- echo # Can't change size of file (Errcode: 1224)
+-- echo # on Windows
+DELETE FROM t1;
+
+DROP TABLE t1;
+DROP TEMPORARY TABLE t2;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 8a81908296f..dfe36ed0905 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -8,13 +8,13 @@ SET SQL_WARNINGS=1;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
datatype_id int(11) DEFAULT '0' NOT NULL,
- minvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
- maxvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
+ min_value decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
+ max_value decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
valuename varchar(20),
forecolor int(11),
backcolor int(11),
PRIMARY KEY (id),
- UNIQUE datatype_id (datatype_id, minvalue, maxvalue)
+ UNIQUE datatype_id (datatype_id, min_value, max_value)
);
INSERT INTO t1 VALUES ( '1', '4', '0.0000000000', '0.0000000000', 'Ei saja', '0', '16776960');
INSERT INTO t1 VALUES ( '2', '4', '1.0000000000', '1.0000000000', 'Sajab', '16777215', '255');
@@ -148,8 +148,8 @@ INSERT INTO t1 VALUES ( '139', '21', '326.0000000000', '326.0000000000', 'Lumine
INSERT INTO t1 VALUES ( '143', '16', '-4.9000000000', '-0.1000000000', '', NULL, '15774720');
INSERT INTO t1 VALUES ( '145', '15', '0.0000000000', '1.9000000000', '', '0', '16769024');
INSERT INTO t1 VALUES ( '146', '16', '0.0000000000', '1.9000000000', '', '0', '16769024');
-select * from t1 where minvalue<=1 and maxvalue>=-1 and datatype_id=16;
-select * from t1 where minvalue<=-1 and maxvalue>=-1 and datatype_id=16;
+select * from t1 where min_value<=1 and max_value>=-1 and datatype_id=16;
+select * from t1 where min_value<=-1 and max_value>=-1 and datatype_id=16;
drop table t1;
#
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index 65bafaae77e..cd3c3f81510 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -1286,137 +1286,3 @@ CREATE TABLE t1 SELECT 1 % .1234567891234567891234567891234567891234567891234567
DESCRIBE t1;
SELECT my_col FROM t1;
DROP TABLE t1;
-
---echo #
---echo # Bug#45261: Crash, stored procedure + decimal
---echo #
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
-CREATE TABLE t1 SELECT
- /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT
- .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */
- AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
-CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
-
---echo #
---echo # Test that the integer and decimal parts are properly calculated.
---echo #
-
-CREATE TABLE t1 (a DECIMAL(30,30));
-INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
-CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
-DESC t2;
-DROP TABLE t1,t2;
-
-CREATE TABLE t1 (a DECIMAL(30,30));
-INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
-CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1;
-DESC t2;
-DROP TABLE t1,t2;
-
-CREATE TABLE t1 (a DECIMAL(30,30));
-INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
-CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1;
-DESC t2;
-DROP TABLE t1,t2;
-
---echo #
---echo # Test that variables get maximum precision.
---echo #
-
-SET @decimal= 1.1;
-CREATE TABLE t1 SELECT @decimal AS c1;
-DESC t1;
-SELECT * FROM t1;
-DROP TABLE t1;
diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test
index 9098881e379..33b84266118 100644
--- a/mysql-test/t/type_varchar.test
+++ b/mysql-test/t/type_varchar.test
@@ -199,3 +199,21 @@ SELECT a,(a + 0) FROM t1 ORDER BY a;
SELECT a,(a DIV 2) FROM t1 ORDER BY a;
SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a;
DROP TABLE t1;
+
+#
+# Bug #28299: To-number conversion warnings work differenly with CHAR
+# and VARCHAR sp variables
+#
+# * Verify that 'Truncated incorrect DOUBLE value' is shown for 's'
+# when using both CHAR and VARCHAR.
+#
+
+CREATE TABLE t1 (a VARCHAR(16));
+INSERT INTO t1 VALUES ('5'), ('s'), ('');
+SELECT 5 = a FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a CHAR(16));
+INSERT INTO t1 VALUES ('5'), ('s'), ('');
+SELECT 5 = a FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 7d56df259ba..02e8763a630 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -452,3 +452,18 @@ DROP TABLE t1;
DROP FUNCTION f1;
--echo End of 5.0 tests
+
+--echo #
+--echo # Bug #47919 assert in open_table during ALTER temporary table
+--echo #
+
+CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1));
+CREATE TEMPORARY TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+
+ALTER TABLE t2 COMMENT = 'ABC';
+UPDATE t2, t1 SET t2.f1 = 2, t1.f1 = 9;
+ALTER TABLE t2 COMMENT = 'DEF';
+
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/variables+c.test b/mysql-test/t/variables+c.test
index 0092d34133d..aa4bc6c631c 100644
--- a/mysql-test/t/variables+c.test
+++ b/mysql-test/t/variables+c.test
@@ -1,4 +1,4 @@
---source include/have_community_features.inc
+--source include/have_profiling.inc
#
# Bug#24822: Patch: uptime_since_flush_status
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
index 2ad488b7529..f01edb1e499 100644
--- a/mysql-test/t/view_grant.test
+++ b/mysql-test/t/view_grant.test
@@ -1072,12 +1072,12 @@ CREATE USER u29908_1@localhost;
CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1;
CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS
SELECT f1 FROM t1;
-GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
-GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
+GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost;
+GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost;
CREATE USER u29908_2@localhost;
-GRANT DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
-GRANT DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
+GRANT SELECT, DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost;
+GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost;
GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost;
connect (u2,localhost,u29908_2,,mysqltest_29908);
@@ -1506,3 +1506,29 @@ DROP VIEW v1;
# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
+--echo #
+--echo # Bug #46019: ERROR 1356 When selecting from within another
+--echo # view that has Group By
+--echo #
+CREATE DATABASE mysqltest1;
+USE mysqltest1;
+
+CREATE TABLE t1 (a INT);
+
+CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT a FROM t1 GROUP BY a;
+CREATE SQL SECURITY INVOKER VIEW v2 AS SELECT a FROM v1;
+
+CREATE USER mysqluser1;
+
+GRANT SELECT ON TABLE t1 TO mysqluser1;
+GRANT SELECT, SHOW VIEW ON TABLE v1 TO mysqluser1;
+GRANT SELECT, SHOW VIEW ON TABLE v2 TO mysqluser1;
+
+--connect (mysqluser1, localhost, mysqluser1,,mysqltest1)
+SELECT a FROM v1;
+SELECT a FROM v2;
+
+--connection default
+--disconnect mysqluser1
+DROP USER mysqluser1;
+DROP DATABASE mysqltest1;
diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test
index 7b1c6a268d5..f84d822170f 100644
--- a/mysql-test/t/xa.test
+++ b/mysql-test/t/xa.test
@@ -149,6 +149,68 @@ xa end 'a';
xa prepare 'a';
xa commit 'a';
+#
+# BUG#43171 - Assertion failed: thd->transaction.xid_state.xid.is_null()
+#
+CREATE TABLE t1(a INT, KEY(a)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1),(2);
+connect(con1,localhost,root,,);
+
+# Part 1: Prepare to test XA START after regular transaction deadlock
+BEGIN;
+UPDATE t1 SET a=3 WHERE a=1;
+
+connection default;
+BEGIN;
+UPDATE t1 SET a=4 WHERE a=2;
+
+connection con1;
+let $conn_id= `SELECT CONNECTION_ID()`;
+SEND UPDATE t1 SET a=5 WHERE a=2;
+
+connection default;
+let $wait_timeout= 2;
+let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE ID=$conn_id AND STATE='Searching rows for update';
+--source include/wait_condition.inc
+
+--error ER_LOCK_DEADLOCK
+UPDATE t1 SET a=5 WHERE a=1;
+ROLLBACK;
+
+# Part 2: Prepare to test XA START after XA transaction deadlock
+connection con1;
+REAP;
+ROLLBACK;
+BEGIN;
+UPDATE t1 SET a=3 WHERE a=1;
+
+connection default;
+XA START 'xid1';
+UPDATE t1 SET a=4 WHERE a=2;
+
+connection con1;
+SEND UPDATE t1 SET a=5 WHERE a=2;
+
+connection default;
+let $wait_timeout= 2;
+let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE ID=$conn_id AND STATE='Searching rows for update';
+--source include/wait_condition.inc
+
+--error ER_LOCK_DEADLOCK
+UPDATE t1 SET a=5 WHERE a=1;
+--error ER_XA_RBDEADLOCK
+XA END 'xid1';
+XA ROLLBACK 'xid1';
+
+XA START 'xid1';
+XA END 'xid1';
+XA ROLLBACK 'xid1';
+
+disconnect con1;
+DROP TABLE t1;
+
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
diff --git a/mysys/default.c b/mysys/default.c
index 6468cf2b35d..f7c18ed83eb 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -503,9 +503,13 @@ int my_load_defaults(const char *conf_file, const char **groups,
ctx.args= &args;
ctx.group= &group;
- error= my_search_option_files(conf_file, argc, argv, &args_used,
- handle_default_option, (void *) &ctx,
- dirs);
+ if ((error= my_search_option_files(conf_file, argc, argv, &args_used,
+ handle_default_option, (void *) &ctx,
+ dirs)))
+ {
+ free_root(&alloc,MYF(0));
+ DBUG_RETURN(error);
+ }
/*
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file
@@ -557,10 +561,10 @@ int my_load_defaults(const char *conf_file, const char **groups,
exit(0);
}
- if (error == 0 && default_directories)
+ if (default_directories)
*default_directories= dirs;
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
err:
fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c
index 6227a05ce06..999e8cc7975 100644
--- a/mysys/mf_keycaches.c
+++ b/mysys/mf_keycaches.c
@@ -108,9 +108,9 @@ static my_bool safe_hash_init(SAFE_HASH *hash, uint elements,
uchar *default_value)
{
DBUG_ENTER("safe_hash");
- if (hash_init(&hash->hash, &my_charset_bin, elements,
- 0, 0, (hash_get_key) safe_hash_entry_get,
- (void (*)(void*)) safe_hash_entry_free, 0))
+ if (my_hash_init(&hash->hash, &my_charset_bin, elements,
+ 0, 0, (my_hash_get_key) safe_hash_entry_get,
+ (void (*)(void*)) safe_hash_entry_free, 0))
{
hash->default_value= 0;
DBUG_RETURN(1);
@@ -137,7 +137,7 @@ static void safe_hash_free(SAFE_HASH *hash)
*/
if (hash->default_value)
{
- hash_free(&hash->hash);
+ my_hash_free(&hash->hash);
rwlock_destroy(&hash->mutex);
hash->default_value=0;
}
@@ -152,7 +152,7 @@ static uchar *safe_hash_search(SAFE_HASH *hash, const uchar *key, uint length)
uchar *result;
DBUG_ENTER("safe_hash_search");
rw_rdlock(&hash->mutex);
- result= hash_search(&hash->hash, key, length);
+ result= my_hash_search(&hash->hash, key, length);
rw_unlock(&hash->mutex);
if (!result)
result= hash->default_value;
@@ -192,7 +192,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length,
DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data));
rw_wrlock(&hash->mutex);
- entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length);
+ entry= (SAFE_HASH_ENTRY*) my_hash_search(&hash->hash, key, length);
if (data == hash->default_value)
{
@@ -206,7 +206,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length,
/* unlink entry from list */
if ((*entry->prev= entry->next))
entry->next->prev= entry->prev;
- hash_delete(&hash->hash, (uchar*) entry);
+ my_hash_delete(&hash->hash, (uchar*) entry);
goto end;
}
if (entry)
@@ -277,7 +277,7 @@ static void safe_hash_change(SAFE_HASH *hash, uchar *old_data, uchar *new_data)
{
if ((*entry->prev= entry->next))
entry->next->prev= entry->prev;
- hash_delete(&hash->hash, (uchar*) entry);
+ my_hash_delete(&hash->hash, (uchar*) entry);
}
else
entry->data= new_data;
diff --git a/mysys/my_error.c b/mysys/my_error.c
index ff9156faf82..e2523a39d0b 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -126,6 +126,29 @@ void my_printf_error(uint error, const char *format, myf MyFlags, ...)
}
/*
+ Error with va_list
+
+ SYNOPSIS
+ my_printv_error()
+ error Errno
+ format Format string
+ MyFlags Flags
+ ... variable list
+*/
+
+void my_printv_error(uint error, const char *format, myf MyFlags, va_list ap)
+{
+ char ebuff[ERRMSGSIZE];
+ DBUG_ENTER("my_printv_error");
+ DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s",
+ error, MyFlags, errno, format));
+
+ (void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap);
+ (*error_handler_hook)(error, ebuff, MyFlags);
+ DBUG_VOID_RETURN;
+}
+
+/*
Give message using error_handler_hook
SYNOPSIS
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 22b1216f99c..f444e0f0c94 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -1041,9 +1041,11 @@ static void init_one_value(const struct my_option *option, uchar* *variable,
*((longlong*) variable)= (longlong) getopt_ll_limit_value((longlong) value, option, NULL);
break;
case GET_ULL:
- case GET_SET:
*((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL);
break;
+ case GET_SET:
+ *((ulonglong*) variable)= (ulonglong) value;
+ break;
case GET_DOUBLE:
*((double*) variable)= (double) value;
break;
diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c
index b50a606c8d8..d96e1048fd0 100644
--- a/mysys/my_largepage.c
+++ b/mysys/my_largepage.c
@@ -128,7 +128,7 @@ uchar* my_large_malloc_int(size_t size, myf my_flags)
{
if (my_flags & MY_WME)
fprintf(stderr,
- "Warning: Failed to allocate %lu bytesx from HugeTLB memory."
+ "Warning: Failed to allocate %lu bytes from HugeTLB memory."
" errno %d\n", (ulong) size, errno);
DBUG_RETURN(NULL);
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index f37ba111993..b2972faf0f8 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -387,6 +387,15 @@ const char *my_thread_name(void)
}
return tmp->name;
}
+
+/* Return pointer to DBUG for holding current state */
+
+extern void **my_thread_var_dbug()
+{
+ struct st_my_thread_var *tmp=
+ my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
+ return tmp && tmp->init ? &tmp->dbug : 0;
+}
#endif /* DBUG_OFF */
diff --git a/mysys/typelib.c b/mysys/typelib.c
index 92ffe9316ff..a0fe8a96a89 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -182,7 +182,10 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err)
{
(*err)++;
i= x;
- while (*x && *x != field_separator) x++;
+ while (*x && *x != field_separator)
+ x++;
+ if (x[0] && x[1]) // skip separator if found
+ x++;
if ((find= find_type(i, lib, 2 | 8) - 1) < 0)
DBUG_RETURN(0);
result|= (ULL(1) << find);
diff --git a/plugin/daemon_example/Makefile.am b/plugin/daemon_example/Makefile.am
index c5414cd46c7..fce67285a5f 100644
--- a/plugin/daemon_example/Makefile.am
+++ b/plugin/daemon_example/Makefile.am
@@ -26,7 +26,8 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
EXTRA_LTLIBRARIES = libdaemon_example.la
pkgplugin_LTLIBRARIES = @plugin_daemon_example_shared_target@
-libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir)
+libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
+
libdaemon_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
libdaemon_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
libdaemon_example_la_SOURCES = daemon_example.cc
diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
index 3dd4b7a7a8c..48bca8ee2a9 100644
--- a/scripts/mysql_system_tables.sql
+++ b/scripts/mysql_system_tables.sql
@@ -13,7 +13,7 @@ set @had_db_table= @@warning_count != 0;
CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
-CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
+CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
-- Remember for later if user table already existed
set @had_user_table= @@warning_count != 0;
@@ -60,9 +60,9 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
-CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
+CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
-CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
+CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
-- Create general_log if CSV is enabled.
diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql
index 9a3a3f7bb84..03136fe9361 100644
--- a/scripts/mysql_system_tables_data.sql
+++ b/scripts/mysql_system_tables_data.sql
@@ -21,9 +21,9 @@ DROP TABLE tmp_db;
-- from local machine if "users" table didn't exist before
CREATE TEMPORARY TABLE tmp_user LIKE user;
set @current_hostname= @@hostname;
-INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
-REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost';
-REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost';
+REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
INSERT INTO tmp_user (host,user) VALUES ('localhost','');
INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost';
INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;
diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql
index 71d18de8898..8dc1ae94de0 100644
--- a/scripts/mysql_system_tables_fix.sql
+++ b/scripts/mysql_system_tables_fix.sql
@@ -342,6 +342,10 @@ ALTER TABLE procs_priv
MODIFY Proc_priv set('Execute','Alter Routine','Grant')
COLLATE utf8_general_ci DEFAULT '' NOT NULL;
+ALTER IGNORE TABLE procs_priv
+ MODIFY Routine_name char(64)
+ COLLATE utf8_general_ci DEFAULT '' NOT NULL;
+
ALTER TABLE procs_priv
ADD Routine_type enum('FUNCTION','PROCEDURE')
COLLATE utf8_general_ci NOT NULL AFTER Routine_name;
@@ -432,6 +436,9 @@ ALTER TABLE proc ADD body_utf8 longblob DEFAULT NULL
AFTER db_collation;
ALTER TABLE proc MODIFY body_utf8 longblob DEFAULT NULL;
+# Change comment from char(64) to text
+ALTER TABLE proc MODIFY comment
+ text collate utf8_bin NOT NULL;
#
# EVENT privilege
@@ -542,6 +549,18 @@ ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete
UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0;
+#
+# user.Create_tablespace_priv
+#
+
+SET @hadCreateTablespacePriv := 0;
+SELECT @hadCreateTablespacePriv :=1 FROM user WHERE Create_tablespace_priv LIKE '%';
+
+ALTER TABLE user ADD Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Trigger_priv;
+ALTER TABLE user MODIFY Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Trigger_priv;
+
+UPDATE user SET Create_tablespace_priv = Super_priv WHERE @hadCreateTablespacePriv = 0;
+
# Activate the new, possible modified privilege tables
# This should not be needed, but gives us some extra testing that the above
# changes was correct
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 95c4419273f..70b9b9f630e 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -160,7 +160,13 @@ parse_arguments() {
fi
for arg do
- val=`echo "$arg" | sed -e "s;--[^=]*=;;"`
+ # the parameter after "=", or the whole $arg if no match
+ val=`echo "$arg" | sed -e 's;^--[^=]*=;;'`
+ # what's before "=", or the whole $arg if no match
+ optname=`echo "$arg" | sed -e 's/^\(--[^=]*\)=.*$/\1/'`
+ # replace "_" by "-" ; mysqld_safe must accept "_" like mysqld does.
+ optname_subst=`echo "$optname" | sed 's/_/-/g'`
+ arg=`echo $arg | sed "s/^$optname/$optname_subst/"`
case "$arg" in
# these get passed explicitly to mysqld
--basedir=*) MY_BASEDIR_VERSION="$val" ;;
diff --git a/sql-common/client.c b/sql-common/client.c
index 843db3b47f6..5114b645818 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -710,10 +710,14 @@ err:
}
#endif
-/*****************************************************************************
+/**
Read a packet from server. Give error message if socket was down
or packet is an error message
-*****************************************************************************/
+
+ @retval packet_error An error occurred during reading.
+ Error message is set.
+ @retval
+*/
ulong
cli_safe_read(MYSQL *mysql)
@@ -879,31 +883,132 @@ void free_old_query(MYSQL *mysql)
DBUG_VOID_RETURN;
}
+
+/**
+ Finish reading of a partial result set from the server.
+ Get the EOF packet, and update mysql->status
+ and mysql->warning_count.
+
+ @return TRUE if a communication or protocol error, an error
+ is set in this case, FALSE otherwise.
+*/
+
+my_bool flush_one_result(MYSQL *mysql)
+{
+ ulong packet_length;
+
+ DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY);
+
+ do
+ {
+ packet_length= cli_safe_read(mysql);
+ /*
+ There is an error reading from the connection,
+ or (sic!) there were no error and no
+ data in the stream, i.e. no more data from the server.
+ Since we know our position in the stream (somewhere in
+ the middle of a result set), this latter case is an error too
+ -- each result set must end with a EOF packet.
+ cli_safe_read() has set an error for us, just return.
+ */
+ if (packet_length == packet_error)
+ return TRUE;
+ }
+ while (packet_length > 8 || mysql->net.read_pos[0] != 254);
+
+ /* Analyze EOF packet of the result set. */
+
+ if (protocol_41(mysql))
+ {
+ char *pos= (char*) mysql->net.read_pos + 1;
+ mysql->warning_count=uint2korr(pos);
+ pos+=2;
+ mysql->server_status=uint2korr(pos);
+ pos+=2;
+ }
+ return FALSE;
+}
+
+
+/**
+ Read a packet from network. If it's an OK packet, flush it.
+
+ @return TRUE if error, FALSE otherwise. In case of
+ success, is_ok_packet is set to TRUE or FALSE,
+ based on what we got from network.
+*/
+
+my_bool opt_flush_ok_packet(MYSQL *mysql, my_bool *is_ok_packet)
+{
+ ulong packet_length= cli_safe_read(mysql);
+
+ if (packet_length == packet_error)
+ return TRUE;
+
+ /* cli_safe_read always reads a non-empty packet. */
+ DBUG_ASSERT(packet_length);
+
+ *is_ok_packet= mysql->net.read_pos[0] == 0;
+ if (*is_ok_packet)
+ {
+ uchar *pos= mysql->net.read_pos + 1;
+
+ net_field_length_ll(&pos); /* affected rows */
+ net_field_length_ll(&pos); /* insert id */
+
+ mysql->server_status=uint2korr(pos);
+ pos+=2;
+
+ if (protocol_41(mysql))
+ {
+ mysql->warning_count=uint2korr(pos);
+ pos+=2;
+ }
+ }
+ return FALSE;
+}
+
+
/*
Flush result set sent from server
*/
-static void cli_flush_use_result(MYSQL *mysql)
+static void cli_flush_use_result(MYSQL *mysql, my_bool flush_all_results)
{
/* Clear the current execution status */
DBUG_ENTER("cli_flush_use_result");
DBUG_PRINT("warning",("Not all packets read, clearing them"));
- for (;;)
+
+ if (flush_one_result(mysql))
+ DBUG_VOID_RETURN; /* An error occurred */
+
+ if (! flush_all_results)
+ DBUG_VOID_RETURN;
+
+ while (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
{
- ulong pkt_len;
- if ((pkt_len=cli_safe_read(mysql)) == packet_error)
- break;
- if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
+ my_bool is_ok_packet;
+ if (opt_flush_ok_packet(mysql, &is_ok_packet))
+ DBUG_VOID_RETURN; /* An error occurred. */
+ if (is_ok_packet)
{
- if (protocol_41(mysql))
- {
- char *pos= (char*) mysql->net.read_pos + 1;
- mysql->warning_count=uint2korr(pos); pos+=2;
- mysql->server_status=uint2korr(pos); pos+=2;
- }
- break; /* End of data */
+ /*
+ Indeed what we got from network was an OK packet, and we
+ know that OK is the last one in a multi-result-set, so
+ just return.
+ */
+ DBUG_VOID_RETURN;
}
+ /*
+ It's a result set, not an OK packet. A result set contains
+ of two result set subsequences: field metadata, terminated
+ with EOF packet, and result set data, again terminated with
+ EOF packet. Read and flush them.
+ */
+ if (flush_one_result(mysql) || flush_one_result(mysql))
+ DBUG_VOID_RETURN; /* An error occurred. */
}
+
DBUG_VOID_RETURN;
}
@@ -1009,7 +1114,7 @@ mysql_free_result(MYSQL_RES *result)
mysql->unbuffered_fetch_owner= 0;
if (mysql->status == MYSQL_STATUS_USE_RESULT)
{
- (*mysql->methods->flush_use_result)(mysql);
+ (*mysql->methods->flush_use_result)(mysql, FALSE);
mysql->status=MYSQL_STATUS_READY;
if (mysql->unbuffered_fetch_owner)
*mysql->unbuffered_fetch_owner= TRUE;
@@ -1036,7 +1141,6 @@ static const char *default_options[]=
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
"character-sets-dir", "default-character-set", "interactive-timeout",
"connect-timeout", "local-infile", "disable-local-infile",
- "replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
"report-data-truncation",
@@ -1184,7 +1288,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 26: /* ssl_cipher */
+ case 23: /* ssl_cipher */
my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
break;
@@ -1193,7 +1297,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
case 14:
case 15:
case 16:
- case 26:
+ case 23:
break;
#endif /* HAVE_OPENSSL */
case 17: /* charset-lib */
@@ -1216,24 +1320,11 @@ void mysql_read_default_options(struct st_mysql_options *options,
case 22:
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 23: /* replication probe */
-#ifndef TO_BE_DELETED
- options->rpl_probe= 1;
-#endif
- break;
- case 24: /* enable-reads-from-master */
- options->no_master_reads= 0;
- break;
- case 25: /* repl-parse-query */
-#ifndef TO_BE_DELETED
- options->rpl_parse= 1;
-#endif
- break;
- case 27:
+ case 24: /* max-allowed-packet */
if (opt_arg)
options->max_allowed_packet= atoi(opt_arg);
break;
- case 28: /* protocol */
+ case 25: /* protocol */
if ((options->protocol= find_type(opt_arg,
&sql_protocol_typelib,0)) <= 0)
{
@@ -1241,24 +1332,24 @@ void mysql_read_default_options(struct st_mysql_options *options,
exit(1);
}
break;
- case 29: /* shared_memory_base_name */
+ case 26: /* shared_memory_base_name */
#ifdef HAVE_SMEM
if (options->shared_memory_base_name != def_shared_memory_base_name)
my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
#endif
break;
- case 30:
+ case 27: /* multi-results */
options->client_flag|= CLIENT_MULTI_RESULTS;
break;
- case 31:
- case 32:
+ case 28: /* multi-statements */
+ case 29: /* multi-queries */
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break;
- case 33: /* secure-auth */
+ case 30: /* secure-auth */
options->secure_auth= TRUE;
break;
- case 34: /* report-data-truncation */
+ case 31: /* report-data-truncation */
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
break;
default:
@@ -1585,16 +1676,8 @@ mysql_init(MYSQL *mysql)
else
bzero((char*) (mysql), sizeof(*(mysql)));
mysql->options.connect_timeout= CONNECT_TIMEOUT;
- mysql->last_used_con= mysql->next_slave= mysql->master = mysql;
mysql->charset=default_client_charset_info;
strmov(mysql->net.sqlstate, not_error_sqlstate);
- /*
- By default, we are a replication pivot. The caller must reset it
- after we return if this is not the case.
- */
-#ifndef TO_BE_DELETED
- mysql->rpl_pivot = 1;
-#endif
/*
Only enable LOAD DATA INFILE by default if configured with
@@ -2167,6 +2250,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
db ? db : "(Null)",
user ? user : "(Null)"));
+ /* Test whether we're already connected */
+ if (net->vio)
+ {
+ set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
+ DBUG_RETURN(0);
+ }
+
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
mysql->methods= &client_methods;
@@ -2389,7 +2479,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
for (i= 0; status && hp->h_addr_list[i]; i++)
{
- IF_DBUG(char ipaddr[18];)
+ char ipaddr[18] __attribute__((unused));
memcpy(&sock_addr.sin_addr, hp->h_addr_list[i],
min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length));
DBUG_PRINT("info",("Trying %s...",
@@ -2774,11 +2864,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->reconnect=reconnect;
}
-#ifndef TO_BE_DELETED
- if (mysql->options.rpl_probe && mysql_rpl_probe(mysql))
- goto error;
-#endif
-
DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql));
reset_sigpipe(mysql);
DBUG_RETURN(mysql);
@@ -2800,28 +2885,6 @@ error:
}
-/* needed when we move MYSQL structure to a different address */
-
-#ifndef TO_BE_DELETED
-static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql)
-{
- MYSQL *tmp, *tmp_prev;
- if (mysql->master == old_mysql)
- mysql->master= mysql;
- if (mysql->last_used_con == old_mysql)
- mysql->last_used_con= mysql;
- if (mysql->last_used_slave == old_mysql)
- mysql->last_used_slave= mysql;
- for (tmp_prev = mysql, tmp = mysql->next_slave;
- tmp != old_mysql;tmp = tmp->next_slave)
- {
- tmp_prev= tmp;
- }
- tmp_prev->next_slave= mysql;
-}
-#endif
-
-
my_bool mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
@@ -2840,8 +2903,7 @@ my_bool mysql_reconnect(MYSQL *mysql)
mysql_init(&tmp_mysql);
tmp_mysql.options= mysql->options;
tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0;
- tmp_mysql.rpl_pivot= mysql->rpl_pivot;
-
+
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket,
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
@@ -2875,7 +2937,6 @@ my_bool mysql_reconnect(MYSQL *mysql)
mysql->free_me=0;
mysql_close(mysql);
*mysql=tmp_mysql;
- mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */
net_clear(&mysql->net, 1);
mysql->affected_rows= ~(my_ulonglong) 0;
DBUG_RETURN(0);
@@ -3053,23 +3114,6 @@ void STDCALL mysql_close(MYSQL *mysql)
mysql_close_free_options(mysql);
mysql_close_free(mysql);
mysql_detach_stmt_list(&mysql->stmts, "mysql_close");
-#ifndef TO_BE_DELETED
- /* free/close slave list */
- if (mysql->rpl_pivot)
- {
- MYSQL* tmp;
- for (tmp = mysql->next_slave; tmp != mysql; )
- {
- /* trick to avoid following freed pointer */
- MYSQL* tmp1 = tmp->next_slave;
- mysql_close(tmp);
- tmp = tmp1;
- }
- mysql->rpl_pivot=0;
- }
-#endif
- if (mysql != mysql->master)
- mysql_close(mysql->master);
#ifndef MYSQL_SERVER
if (mysql->thd)
(*mysql->methods->free_embedded_thd)(mysql);
@@ -3089,12 +3133,6 @@ static my_bool cli_read_query_result(MYSQL *mysql)
ulong length;
DBUG_ENTER("cli_read_query_result");
- /*
- Read from the connection which we actually used, which
- could differ from the original connection if we have slaves
- */
- mysql = mysql->last_used_con;
-
if ((length = cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
@@ -3169,23 +3207,6 @@ int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
{
DBUG_ENTER("mysql_send_query");
- DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d",
- mysql->options.rpl_parse, mysql->rpl_pivot));
-#ifndef TO_BE_DELETED
- if (mysql->options.rpl_parse && mysql->rpl_pivot)
- {
- switch (mysql_rpl_query_type(query, length)) {
- case MYSQL_RPL_MASTER:
- DBUG_RETURN(mysql_master_send_query(mysql, query, length));
- case MYSQL_RPL_SLAVE:
- DBUG_RETURN(mysql_slave_send_query(mysql, query, length));
- case MYSQL_RPL_ADMIN:
- break; /* fall through */
- }
- }
- mysql->last_used_con = mysql;
-#endif
-
DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
}
@@ -3212,8 +3233,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
{
MYSQL_RES *result;
DBUG_ENTER("mysql_store_result");
- /* read from the actually used connection */
- mysql = mysql->last_used_con;
+
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
@@ -3268,8 +3288,6 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
MYSQL_RES *result;
DBUG_ENTER("cli_use_result");
- mysql = mysql->last_used_con;
-
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 3e350144f74..15c2d950ff9 100755
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -45,7 +45,7 @@ SET (SQL_SOURCE
discover.cc ../libmysql/errmsg.c field.cc field_conv.cc
filesort.cc gstream.cc
ha_partition.cc
- handler.cc hash_filo.cc hash_filo.h
+ handler.cc hash_filo.cc hash_filo.h sql_plugin_services.h
hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc
item_create.cc item_func.cc item_geofunc.cc item_row.cc
item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 569bb70965e..15ee0d588c4 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -82,7 +82,7 @@ mysqld_LDADD = libndb.la \
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
item_strfunc.h item_timefunc.h \
- item_xmlfunc.h \
+ item_xmlfunc.h sql_plugin_services.h \
item_create.h item_subselect.h item_row.h \
mysql_priv.h item_geofunc.h sql_bitmap.h \
procedure.h sql_class.h sql_lex.h sql_list.h \
@@ -111,8 +111,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_plugin.h authors.h event_parse_data.h \
event_data_objects.h event_scheduler.h \
sql_partition.h partition_info.h partition_element.h \
- contributors.h sql_servers.h sql_signal.h \
- rpl_handler.h replication.h
+ contributors.h sql_servers.h sql_signal.h records.h \
+ sql_prepare.h rpl_handler.h replication.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index 2580d526b52..81870e6b7a3 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -1701,9 +1701,11 @@ uchar *sys_var_debug_sync::value_ptr(THD *thd,
static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
{
- IF_DBUG(const char *dsp_name= action->sync_point.c_ptr());
- IF_DBUG(const char *sig_emit= action->signal.c_ptr());
- IF_DBUG(const char *sig_wait= action->wait_for.c_ptr());
+#ifndef DBUG_OFF
+ const char *dsp_name= action->sync_point.c_ptr();
+ const char *sig_emit= action->signal.c_ptr();
+ const char *sig_wait= action->wait_for.c_ptr();
+#endif
DBUG_ENTER("debug_sync_execute");
DBUG_ASSERT(thd);
DBUG_ASSERT(action);
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 271ac73bd30..23eec749a30 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -1435,7 +1435,7 @@ Event_job_data::execute(THD *thd, bool drop)
thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
{
- Parser_state parser_state(thd, thd->query, thd->query_length);
+ Parser_state parser_state(thd, thd->query(), thd->query_length());
lex_start(thd);
if (parse_sql(thd, & parser_state, creation_ctx))
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index daaa6be0520..d9ca161f260 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -128,7 +128,6 @@ post_init_event_thread(THD *thd)
thd->cleanup();
return TRUE;
}
- lex_start(thd);
pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd);
@@ -607,7 +606,12 @@ Event_scheduler::stop()
LOCK_DATA();
DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state].str));
if (state != RUNNING)
+ {
+ /* Synchronously wait until the scheduler stops. */
+ while (state != INITIALIZED)
+ COND_STATE_WAIT(thd, NULL, "Waiting for the scheduler to stop");
goto end;
+ }
/* Guarantee we don't catch spurious signals */
do {
diff --git a/sql/events.cc b/sql/events.cc
index 34da0e185b7..ac37a2bd595 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -465,7 +465,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
if (!dropped)
{
/* Binlog the create event. */
- DBUG_ASSERT(thd->query && thd->query_length);
+ DBUG_ASSERT(thd->query() && thd->query_length());
String log_query;
if (create_query_string(thd, &log_query))
{
@@ -595,8 +595,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
event_queue->update_event(thd, parse_data->dbname, parse_data->name,
new_element);
/* Binlog the alter event. */
- DBUG_ASSERT(thd->query && thd->query_length);
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ DBUG_ASSERT(thd->query() && thd->query_length());
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
}
pthread_mutex_unlock(&LOCK_event_metadata);
@@ -670,8 +670,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
if (event_queue)
event_queue->drop_event(thd, dbname, name);
/* Binlog the drop event. */
- DBUG_ASSERT(thd->query && thd->query_length);
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ DBUG_ASSERT(thd->query() && thd->query_length());
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
pthread_mutex_unlock(&LOCK_event_metadata);
DBUG_RETURN(ret);
@@ -757,7 +757,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
field_list.push_back(
new Item_empty_string("Database Collation", MY_CS_NAME_SIZE));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -925,7 +925,6 @@ Events::init(my_bool opt_noacl_or_bootstrap)
*/
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/*
We will need Event_db_repository anyway, even if the scheduler is
diff --git a/sql/field.cc b/sql/field.cc
index 3a51636cfa8..dc32624db10 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1016,6 +1016,36 @@ Item_result Field::result_merge_type(enum_field_types field_type)
Static help functions
*****************************************************************************/
+/**
+ Output a warning for erroneous conversion of strings to numerical
+ values. For use with ER_TRUNCATED_WRONG_VALUE[_FOR_FIELD]
+
+ @param thd THD object
+ @param str pointer to string that failed to be converted
+ @param length length of string
+ @param cs charset for string
+ @param typestr string describing type converted to
+ @param error error value to output
+ @param field_name (for *_FOR_FIELD) name of field
+ @param row_num (for *_FOR_FIELD) row number
+ */
+static void push_numerical_conversion_warning(THD* thd, const char* str,
+ uint length, CHARSET_INFO* cs,
+ const char* typestr, int error,
+ const char* field_name="UNKNOWN",
+ ulong row_num=0)
+{
+ char buf[max(max(DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE,
+ LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE),
+ DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE)];
+
+ String tmp(buf, sizeof(buf), cs);
+ tmp.copy(str, length, cs);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ error, ER(error), typestr, tmp.c_ptr(),
+ field_name, row_num);
+}
+
/**
Check whether a field type can be partially indexed by a key.
@@ -1775,7 +1805,7 @@ bool Field::optimize_range(uint idx, uint part)
}
-Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type __attribute__((unused)))
{
Field *tmp;
@@ -1796,7 +1826,7 @@ Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table,
}
-Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field::new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
@@ -1813,7 +1843,7 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
/* This is used to generate a field in TABLE from TABLE_SHARE */
-Field *Field::clone(MEM_ROOT *root, struct st_table *new_table)
+Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
{
Field *tmp;
if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
@@ -2483,97 +2513,12 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg,
{
precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
set_if_smaller(precision, DECIMAL_MAX_PRECISION);
- DBUG_ASSERT(precision >= dec);
DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
(dec <= DECIMAL_MAX_SCALE));
bin_size= my_decimal_get_binary_size(precision, dec);
}
-/**
- Create a field to hold a decimal value from an item.
-
- @remark The MySQL DECIMAL data type has a characteristic that needs to be
- taken into account when deducing the type from a Item_decimal.
-
- But first, let's briefly recap what is the new MySQL DECIMAL type:
-
- The declaration syntax for a decimal is DECIMAL(M,D), where:
-
- * M is the maximum number of digits (the precision).
- It has a range of 1 to 65.
- * D is the number of digits to the right of the decimal separator (the scale).
- It has a range of 0 to 30 and must be no larger than M.
-
- D and M are used to determine the storage requirements for the integer
- and fractional parts of each value. The integer part is to the left of
- the decimal separator and to the right is the fractional part. Hence:
-
- M is the number of digits for the integer and fractional part.
- D is the number of digits for the fractional part.
-
- Consequently, M - D is the number of digits for the integer part. For
- example, a DECIMAL(20,10) column has ten digits on either side of
- the decimal separator.
-
- The characteristic that needs to be taken into account is that the
- backing type for Item_decimal is a my_decimal that has a higher
- precision (DECIMAL_MAX_POSSIBLE_PRECISION, see my_decimal.h) than
- DECIMAL.
-
- Drawing a comparison between my_decimal and DECIMAL:
-
- * M has a range of 1 to 81.
- * D has a range of 0 to 81.
-
- There can be a difference in range if the decimal contains a integer
- part. This is because the fractional part must always be on a group
- boundary, leaving at least one group for the integer part. Since each
- group is 9 (DIG_PER_DEC1) digits and there are 9 (DECIMAL_BUFF_LENGTH)
- groups, the fractional part is limited to 72 digits if there is at
- least one digit in the integral part.
-
- Although the backing type for a DECIMAL is also my_decimal, every
- time a my_decimal is stored in a DECIMAL field, the precision and
- scale are explicitly capped at 65 (DECIMAL_MAX_PRECISION) and 30
- (DECIMAL_MAX_SCALE) digits, following my_decimal truncation procedure
- (FIX_INTG_FRAC_ERROR).
-*/
-
-Field_new_decimal *
-Field_new_decimal::new_decimal_field(const Item *item)
-{
- uint32 len;
- uint intg= item->decimal_int_part(), scale= item->decimals;
-
- DBUG_ASSERT(item->decimal_precision() >= item->decimals);
-
- /*
- Employ a procedure along the lines of the my_decimal truncation process:
- - If the integer part is equal to or bigger than the maximum precision:
- Truncate integer part to fit and the fractional becomes zero.
- - Otherwise:
- Truncate fractional part to fit.
- */
- if (intg >= DECIMAL_MAX_PRECISION)
- {
- intg= DECIMAL_MAX_PRECISION;
- scale= 0;
- }
- else
- {
- uint room= min(DECIMAL_MAX_PRECISION - intg, DECIMAL_MAX_SCALE);
- if (scale > room)
- scale= room;
- }
-
- len= my_decimal_precision_to_length(intg + scale, scale, item->unsigned_flag);
-
- return new Field_new_decimal(len, item->maybe_null, item->name, scale,
- item->unsigned_flag);
-}
-
-
int Field_new_decimal::reset(void)
{
store_value(&decimal_zero);
@@ -6357,6 +6302,7 @@ check_string_copy_error(Field_str *field,
return FALSE;
convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
+
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
@@ -6546,20 +6492,9 @@ uint Field::is_equal(Create_field *new_field)
}
-/* If one of the fields is binary and the other one isn't return 1 else 0 */
-
-bool Field_str::compare_str_field_flags(Create_field *new_field, uint32 flag_arg)
-{
- return (((new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
- !(flag_arg & (BINCMP_FLAG | BINARY_FLAG))) ||
- (!(new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
- (flag_arg & (BINCMP_FLAG | BINARY_FLAG))));
-}
-
-
uint Field_str::is_equal(Create_field *new_field)
{
- if (compare_str_field_flags(new_field, flags))
+ if (field_flags_are_binary() != new_field->field_flags_are_binary())
return 0;
return ((new_field->sql_type == real_type()) &&
@@ -6734,9 +6669,8 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
void Field_string::sort_string(uchar *to,uint length)
{
- IF_DBUG(uint tmp=) my_strnxfrm(field_charset,
- to, length,
- ptr, field_length);
+ uint tmp __attribute__((unused))=
+ my_strnxfrm(field_charset, to, length, ptr, field_length);
DBUG_ASSERT(tmp == length);
}
@@ -6992,7 +6926,7 @@ uint Field_string::get_key_image(uchar *buff, uint length, imagetype type_arg)
}
-Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field_string::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type)
{
Field *field;
@@ -7103,22 +7037,46 @@ int Field_varstring::store(longlong nr, bool unsigned_val)
double Field_varstring::val_real(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
- int not_used;
- char *end_not_used;
+ int error;
+ char *end;
+ double result;
+ CHARSET_INFO* cs= charset();
+
uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
- return my_strntod(field_charset, (char*) ptr+length_bytes, length,
- &end_not_used, &not_used);
+ result= my_strntod(cs, (char*)ptr+length_bytes, length, &end, &error);
+
+ if (!table->in_use->no_errors &&
+ (error || (length != (uint)(end - (char*)ptr+length_bytes) &&
+ !check_if_only_end_space(cs, end, (char*)ptr+length_bytes+length))))
+ {
+ push_numerical_conversion_warning(current_thd, (char*)ptr+length_bytes,
+ length, cs,"DOUBLE",
+ ER_TRUNCATED_WRONG_VALUE);
+ }
+ return result;
}
longlong Field_varstring::val_int(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
- int not_used;
- char *end_not_used;
+ int error;
+ char *end;
+ CHARSET_INFO *cs= charset();
+
uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
- return my_strntoll(field_charset, (char*) ptr+length_bytes, length, 10,
- &end_not_used, &not_used);
+ longlong result= my_strntoll(cs, (char*) ptr+length_bytes, length, 10,
+ &end, &error);
+
+ if (!table->in_use->no_errors &&
+ (error || (length != (uint)(end - (char*)ptr+length_bytes) &&
+ !check_if_only_end_space(cs, end, (char*)ptr+length_bytes+length))))
+ {
+ push_numerical_conversion_warning(current_thd, (char*)ptr+length_bytes,
+ length, cs, "INTEGER",
+ ER_TRUNCATED_WRONG_VALUE);
+ }
+ return result;
}
String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
@@ -7134,9 +7092,17 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value)
{
ASSERT_COLUMN_MARKED_FOR_READ;
+ CHARSET_INFO *cs= charset();
uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
- str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length,
- charset(), decimal_value);
+ int error= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length,
+ cs, decimal_value);
+
+ if (!table->in_use->no_errors && error)
+ {
+ push_numerical_conversion_warning(current_thd, (char*)ptr+length_bytes,
+ length, cs, "DECIMAL",
+ ER_TRUNCATED_WRONG_VALUE);
+ }
return decimal_value;
}
@@ -7538,7 +7504,7 @@ int Field_varstring::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
}
-Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field_varstring::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type)
{
Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
@@ -7550,7 +7516,7 @@ Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
Field *Field_varstring::new_key_field(MEM_ROOT *root,
- struct st_table *new_table,
+ TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
@@ -8318,7 +8284,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
uint Field_blob::is_equal(Create_field *new_field)
{
- if (compare_str_field_flags(new_field, flags))
+ if (field_flags_are_binary() != new_field->field_flags_are_binary())
return 0;
return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
@@ -8680,7 +8646,7 @@ void Field_enum::sql_type(String &res) const
}
-Field *Field_enum::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field_enum::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type)
{
Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
@@ -8878,7 +8844,7 @@ uint Field_enum::is_equal(Create_field *new_field)
The fields are compatible if they have the same flags,
type, charset and have the same underlying length.
*/
- if (compare_str_field_flags(new_field, flags) ||
+ if (new_field->field_flags_are_binary() != field_flags_are_binary() ||
new_field->sql_type != real_type() ||
new_field->charset != field_charset ||
new_field->pack_length != pack_length())
@@ -9021,7 +8987,7 @@ Field_bit::do_last_null_byte() const
Field *Field_bit::new_key_field(MEM_ROOT *root,
- struct st_table *new_table,
+ TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
@@ -9647,7 +9613,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
if (length == 0)
- fld_length= 0; /* purecov: inspected */
+ fld_length= NULL; /* purecov: inspected */
}
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
@@ -9799,8 +9765,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_TIMESTAMP:
if (fld_length == NULL)
{
- /* Compressed date YYYYMMDDHHMMSS */
- length= MAX_DATETIME_COMPRESSED_WIDTH;
+ length= MAX_DATETIME_WIDTH;
}
else if (length != MAX_DATETIME_WIDTH)
{
@@ -9861,11 +9826,10 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
break;
case MYSQL_TYPE_DATE:
/* Old date type. */
- if (protocol_version != PROTOCOL_VERSION-1)
- sql_type= MYSQL_TYPE_NEWDATE;
+ sql_type= MYSQL_TYPE_NEWDATE;
/* fall trough */
case MYSQL_TYPE_NEWDATE:
- length= 10;
+ length= MAX_DATE_WIDTH;
break;
case MYSQL_TYPE_TIME:
length= 10;
@@ -9946,6 +9910,17 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
DBUG_RETURN(TRUE);
}
+ switch (fld_type) {
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ charset= &my_charset_bin;
+ flags|= BINCMP_FLAG;
+ default: break;
+ }
+
DBUG_RETURN(FALSE); /* success */
}
diff --git a/sql/field.h b/sql/field.h
index 8bf641a8649..7235115a888 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1,7 +1,7 @@
#ifndef FIELD_INCLUDED
#define FIELD_INCLUDED
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -63,8 +63,8 @@ public:
Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
*/
- struct st_table *table; // Pointer for table
- struct st_table *orig_table; // Pointer to original table
+ TABLE *table; // Pointer for table
+ TABLE *orig_table; // Pointer to original table
const char **table_name, *field_name;
LEX_STRING comment;
/* Field is part of the following keys */
@@ -304,12 +304,12 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table,
+ virtual Field *new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type);
- virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
- Field *clone(MEM_ROOT *mem_root, struct st_table *new_table);
+ Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
@@ -613,15 +613,17 @@ protected:
handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first);
return from + sizeof(int64);
}
+
+ bool field_flags_are_binary()
+ {
+ return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
+ }
+
};
class Field_num :public Field {
public:
- /**
- The scale of the Field's value, i.e. the number of digits to the right
- of the decimal point.
- */
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
@@ -672,7 +674,6 @@ public:
friend class Create_field;
my_decimal *val_decimal(my_decimal *);
virtual bool str_needs_quotes() { return TRUE; }
- bool compare_str_field_flags(Create_field *new_field, uint32 flags);
uint is_equal(Create_field *new_field);
};
@@ -780,11 +781,6 @@ public:
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const char *field_name_arg, uint8 dec_arg,
bool unsigned_arg);
- /*
- Create a field to hold a decimal value from an item.
- Truncates the precision and/or scale if necessary.
- */
- static Field_new_decimal *new_decimal_field(const Item *item);
enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
@@ -1287,12 +1283,12 @@ public:
Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
CHARSET_INFO *cs)
- :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
+ :Field_str(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, cs)
{}
Field_date(bool maybe_null_arg, const char *field_name_arg,
CHARSET_INFO *cs)
- :Field_str((uchar*) 0,10, maybe_null_arg ? (uchar*) "": 0,0,
+ :Field_str((uchar*) 0, MAX_DATE_WIDTH, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, cs) {}
enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
@@ -1402,12 +1398,12 @@ public:
Field_datetime(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
CHARSET_INFO *cs)
- :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg,
+ :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, cs)
{}
Field_datetime(bool maybe_null_arg, const char *field_name_arg,
CHARSET_INFO *cs)
- :Field_str((uchar*) 0,19, maybe_null_arg ? (uchar*) "": 0,0,
+ :Field_str((uchar*) 0, MAX_DATETIME_WIDTH, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, cs) {}
enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
#ifdef HAVE_LONG_LONG
@@ -1516,7 +1512,7 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
virtual uint get_key_image(uchar *buff,uint length, imagetype type);
private:
int do_save_field_metadata(uchar *first_byte);
@@ -1603,8 +1599,8 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
- Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
+ Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
uint is_equal(Create_field *new_field);
@@ -1843,7 +1839,7 @@ public:
{
flags|=ENUM_FLAG;
}
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum Item_result cast_to_int_type () const { return INT_RESULT; }
@@ -1980,7 +1976,7 @@ public:
uint param_data, bool low_byte_first);
virtual void set_default();
- Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg)
@@ -2082,6 +2078,11 @@ public:
Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type);
+
+ bool field_flags_are_binary()
+ {
+ return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
+ }
};
@@ -2089,7 +2090,7 @@ public:
A class for sending info to the client
*/
-class Send_field {
+class Send_field :public Sql_alloc {
public:
const char *db_name;
const char *table_name,*org_table_name;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 439688cdadf..f83e40ec402 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -355,8 +355,8 @@ Thd_ndb::Thd_ndb()
m_error_code= 0;
query_state&= NDB_QUERY_NORMAL;
options= 0;
- (void) hash_init(&open_tables, &my_charset_bin, 5, 0, 0,
- (hash_get_key)thd_ndb_share_get_key, 0, 0);
+ (void) my_hash_init(&open_tables, &my_charset_bin, 5, 0, 0,
+ (my_hash_get_key)thd_ndb_share_get_key, 0, 0);
}
Thd_ndb::~Thd_ndb()
@@ -380,7 +380,7 @@ Thd_ndb::~Thd_ndb()
ndb= NULL;
}
changed_tables.empty();
- hash_free(&open_tables);
+ my_hash_free(&open_tables);
}
void
@@ -4316,7 +4316,7 @@ int ha_ndbcluster::end_bulk_insert()
}
else
{
- IF_DBUG(int res=) trans->restart();
+ int res __attribute__((unused))= trans->restart();
DBUG_ASSERT(res == 0);
}
}
@@ -4587,9 +4587,9 @@ int ha_ndbcluster::init_handler_for_statement(THD *thd, Thd_ndb *thd_ndb)
const void *key= m_table;
HASH_SEARCH_STATE state;
THD_NDB_SHARE *thd_ndb_share=
- (THD_NDB_SHARE*)hash_first(&thd_ndb->open_tables, (uchar *)&key, sizeof(key), &state);
+ (THD_NDB_SHARE*)my_hash_first(&thd_ndb->open_tables, (uchar *)&key, sizeof(key), &state);
while (thd_ndb_share && thd_ndb_share->key != key)
- thd_ndb_share= (THD_NDB_SHARE*)hash_next(&thd_ndb->open_tables, (uchar *)&key, sizeof(key), &state);
+ thd_ndb_share= (THD_NDB_SHARE*)my_hash_next(&thd_ndb->open_tables, (uchar *)&key, sizeof(key), &state);
if (thd_ndb_share == 0)
{
thd_ndb_share= (THD_NDB_SHARE *) alloc_root(&thd->transaction.mem_root,
@@ -5523,8 +5523,8 @@ int ha_ndbcluster::create(const char *name,
*/
{
uint length= (uint) strlen(name);
- if ((share= (NDB_SHARE*) hash_search(&ndbcluster_open_tables,
- (uchar*) name, length)))
+ if ((share= (NDB_SHARE*) my_hash_search(&ndbcluster_open_tables,
+ (uchar*) name, length)))
handle_trailing_share(share);
}
/*
@@ -5580,7 +5580,7 @@ int ha_ndbcluster::create(const char *name,
if (share && !do_event_op)
share->flags|= NSF_NO_BINLOG;
ndbcluster_log_schema_op(thd, share,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
share->db, share->table_name,
m_table->getObjectId(),
m_table->getObjectVersion(),
@@ -5928,7 +5928,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
{
DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u",
share->key, share->use_count));
- IF_DBUG(int r=) rename_share(share, to);
+ int r __attribute__((unused))= rename_share(share, to);
DBUG_ASSERT(r == 0);
}
#endif
@@ -5952,7 +5952,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
#ifdef HAVE_NDB_BINLOG
if (share)
{
- IF_DBUG(int ret=) rename_share(share, from);
+ int ret __attribute__((unused))= rename_share(share, from);
DBUG_ASSERT(ret == 0);
/* ndb_share reference temporary free */
DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u",
@@ -6022,7 +6022,8 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
*/
if (!is_old_table_tmpfile)
ndbcluster_log_schema_op(current_thd, share,
- current_thd->query, current_thd->query_length,
+ current_thd->query(),
+ current_thd->query_length(),
old_dbname, m_tabname,
ndb_table_id, ndb_table_version,
SOT_RENAME_TABLE,
@@ -6217,7 +6218,7 @@ retry_temporary_error1:
current_thd->lex->sql_command != SQLCOM_TRUNCATE)
{
ndbcluster_log_schema_op(thd, share,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
share->db, share->table_name,
ndb_table_id, ndb_table_version,
SOT_DROP_TABLE, 0, 0, 1);
@@ -6939,7 +6940,7 @@ static void ndbcluster_drop_database(handlerton *hton, char *path)
THD *thd= current_thd;
ha_ndbcluster::set_dbname(path, db);
ndbcluster_log_schema_op(thd, 0,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
db, "", 0, 0, SOT_DROP_DB, 0, 0, 0);
#endif
DBUG_VOID_RETURN;
@@ -6951,7 +6952,6 @@ int ndb_create_table_from_engine(THD *thd, const char *db,
LEX *old_lex= thd->lex, newlex;
thd->lex= &newlex;
newlex.current_select= NULL;
- lex_start(thd);
int res= ha_create_table_from_engine(thd, db, table_name);
thd->lex= old_lex;
return res;
@@ -7118,18 +7118,18 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
NdbDictionary::Object::UserTable) != 0)
ERR_RETURN(dict->getNdbError());
- if (hash_init(&ndb_tables, system_charset_info,list.count,0,0,
- (hash_get_key)tables_get_key,0,0))
+ if (my_hash_init(&ndb_tables, system_charset_info,list.count,0,0,
+ (my_hash_get_key)tables_get_key,0,0))
{
DBUG_PRINT("error", ("Failed to init HASH ndb_tables"));
DBUG_RETURN(-1);
}
- if (hash_init(&ok_tables, system_charset_info,32,0,0,
- (hash_get_key)tables_get_key,0,0))
+ if (my_hash_init(&ok_tables, system_charset_info,32,0,0,
+ (my_hash_get_key)tables_get_key,0,0))
{
DBUG_PRINT("error", ("Failed to init HASH ok_tables"));
- hash_free(&ndb_tables);
+ my_hash_free(&ndb_tables);
DBUG_RETURN(-1);
}
@@ -7170,7 +7170,8 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
{
bool file_on_disk= FALSE;
DBUG_PRINT("info", ("%s", file_name->str));
- if (hash_search(&ndb_tables, (uchar*) file_name->str, file_name->length))
+ if (my_hash_search(&ndb_tables, (uchar*) file_name->str,
+ file_name->length))
{
build_table_filename(name, sizeof(name) - 1, db,
file_name->str, reg_ext, 0);
@@ -7205,10 +7206,10 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
if (file_on_disk)
{
// Ignore this ndb table
- uchar *record= hash_search(&ndb_tables, (uchar*) file_name->str,
- file_name->length);
+ uchar *record= my_hash_search(&ndb_tables, (uchar*) file_name->str,
+ file_name->length);
DBUG_ASSERT(record);
- hash_delete(&ndb_tables, record);
+ my_hash_delete(&ndb_tables, record);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,
"Local table %s.%s shadows ndb table",
@@ -7242,7 +7243,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
build_table_filename(name, sizeof(name) - 1, db, "", "", 0);
for (i= 0; i < ok_tables.records; i++)
{
- file_name_str= (char*)hash_element(&ok_tables, i);
+ file_name_str= (char*)my_hash_element(&ok_tables, i);
end= end1 +
tablename_to_filename(file_name_str, end1, sizeof(name) - (end1 - name));
pthread_mutex_lock(&LOCK_open);
@@ -7258,8 +7259,9 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
List<char> create_list;
for (i= 0 ; i < ndb_tables.records ; i++)
{
- file_name_str= (char*) hash_element(&ndb_tables, i);
- if (!hash_search(&ok_tables, (uchar*) file_name_str, strlen(file_name_str)))
+ file_name_str= (char*) my_hash_element(&ndb_tables, i);
+ if (!my_hash_search(&ok_tables, (uchar*) file_name_str,
+ strlen(file_name_str)))
{
build_table_filename(name, sizeof(name) - 1,
db, file_name_str, reg_ext, 0);
@@ -7313,8 +7315,8 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
pthread_mutex_unlock(&LOCK_open);
- hash_free(&ok_tables);
- hash_free(&ndb_tables);
+ my_hash_free(&ok_tables);
+ my_hash_free(&ndb_tables);
// Delete schema file from files
if (!strcmp(db, NDB_REP_DB))
@@ -7478,8 +7480,8 @@ static int ndbcluster_init(void *p)
goto ndbcluster_init_error;
}
- (void) hash_init(&ndbcluster_open_tables,system_charset_info,32,0,0,
- (hash_get_key) ndbcluster_get_key,0,0);
+ (void) my_hash_init(&ndbcluster_open_tables,system_charset_info,32,0,0,
+ (my_hash_get_key) ndbcluster_get_key,0,0);
#ifdef HAVE_NDB_BINLOG
/* start the ndb injector thread */
if (ndbcluster_binlog_start())
@@ -7492,7 +7494,7 @@ static int ndbcluster_init(void *p)
if (pthread_create(&tmp, &connection_attrib, ndb_util_thread_func, 0))
{
DBUG_PRINT("error", ("Could not create ndb utility thread"));
- hash_free(&ndbcluster_open_tables);
+ my_hash_free(&ndbcluster_open_tables);
pthread_mutex_destroy(&ndbcluster_mutex);
pthread_mutex_destroy(&LOCK_ndb_util_thread);
pthread_cond_destroy(&COND_ndb_util_thread);
@@ -7509,7 +7511,7 @@ static int ndbcluster_init(void *p)
if (!ndb_util_thread_running)
{
DBUG_PRINT("error", ("ndb utility thread exited prematurely"));
- hash_free(&ndbcluster_open_tables);
+ my_hash_free(&ndbcluster_open_tables);
pthread_mutex_destroy(&ndbcluster_mutex);
pthread_mutex_destroy(&LOCK_ndb_util_thread);
pthread_cond_destroy(&COND_ndb_util_thread);
@@ -7560,7 +7562,7 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type)
while (ndbcluster_open_tables.records)
{
NDB_SHARE *share=
- (NDB_SHARE*) hash_element(&ndbcluster_open_tables, 0);
+ (NDB_SHARE*) my_hash_element(&ndbcluster_open_tables, 0);
#ifndef DBUG_OFF
fprintf(stderr, "NDB: table share %s with use_count %d not freed\n",
share->key, share->use_count);
@@ -7570,7 +7572,7 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type)
pthread_mutex_unlock(&ndbcluster_mutex);
}
#endif
- hash_free(&ndbcluster_open_tables);
+ my_hash_free(&ndbcluster_open_tables);
if (g_ndb)
{
@@ -7903,9 +7905,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
dbname, tabname, "", 0);
DBUG_PRINT("enter", ("name: %s", name));
pthread_mutex_lock(&ndbcluster_mutex);
- if (!(share=(NDB_SHARE*) hash_search(&ndbcluster_open_tables,
- (uchar*) name,
- strlen(name))))
+ if (!(share=(NDB_SHARE*) my_hash_search(&ndbcluster_open_tables,
+ (uchar*) name,
+ strlen(name))))
{
pthread_mutex_unlock(&ndbcluster_mutex);
DBUG_PRINT("info", ("Table %s not found in ndbcluster_open_tables", name));
@@ -8165,7 +8167,7 @@ static void print_ndbcluster_open_tables()
fprintf(DBUG_FILE, ">ndbcluster_open_tables\n");
for (uint i= 0; i < ndbcluster_open_tables.records; i++)
print_share("",
- (NDB_SHARE*)hash_element(&ndbcluster_open_tables, i));
+ (NDB_SHARE*)my_hash_element(&ndbcluster_open_tables, i));
fprintf(DBUG_FILE, "<ndbcluster_open_tables\n");
DBUG_UNLOCK_FILE;
}
@@ -8276,7 +8278,7 @@ int handle_trailing_share(NDB_SHARE *share)
at the cost of a possible mem leak, by "renaming" the share
- First remove from hash
*/
- hash_delete(&ndbcluster_open_tables, (uchar*) share);
+ my_hash_delete(&ndbcluster_open_tables, (uchar*) share);
/*
now give it a new name, just a running number
@@ -8309,12 +8311,12 @@ static int rename_share(NDB_SHARE *share, const char *new_key)
uint new_length= (uint) strlen(new_key);
DBUG_PRINT("rename_share", ("old_key: %s old__length: %d",
share->key, share->key_length));
- if ((tmp= (NDB_SHARE*) hash_search(&ndbcluster_open_tables,
- (uchar*) new_key, new_length)))
+ if ((tmp= (NDB_SHARE*) my_hash_search(&ndbcluster_open_tables,
+ (uchar*) new_key, new_length)))
handle_trailing_share(tmp);
/* remove the share from hash */
- hash_delete(&ndbcluster_open_tables, (uchar*) share);
+ my_hash_delete(&ndbcluster_open_tables, (uchar*) share);
dbug_print_open_tables();
/* save old stuff if insert should fail */
@@ -8415,9 +8417,9 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table,
if (!have_lock)
pthread_mutex_lock(&ndbcluster_mutex);
- if (!(share= (NDB_SHARE*) hash_search(&ndbcluster_open_tables,
- (uchar*) key,
- length)))
+ if (!(share= (NDB_SHARE*) my_hash_search(&ndbcluster_open_tables,
+ (uchar*) key,
+ length)))
{
if (!create_if_not_exists)
{
@@ -8493,7 +8495,7 @@ void ndbcluster_real_free_share(NDB_SHARE **share)
DBUG_ENTER("ndbcluster_real_free_share");
dbug_print_share("ndbcluster_real_free_share:", *share);
- hash_delete(&ndbcluster_open_tables, (uchar*) *share);
+ my_hash_delete(&ndbcluster_open_tables, (uchar*) *share);
thr_lock_delete(&(*share)->lock);
pthread_mutex_destroy(&(*share)->mutex);
@@ -9269,7 +9271,6 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
thd->thread_stack= (char*)&thd; /* remember where our stack is */
if (thd->store_globals())
goto ndb_util_thread_fail;
- lex_start(thd);
thd->init_for_queries();
thd->version=refresh_version;
thd->main_security_ctx.host_or_ip= "";
@@ -9397,7 +9398,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
}
for (i= 0, open_count= 0; i < record_count; i++)
{
- share= (NDB_SHARE *)hash_element(&ndbcluster_open_tables, i);
+ share= (NDB_SHARE *)my_hash_element(&ndbcluster_open_tables, i);
#ifdef HAVE_NDB_BINLOG
if ((share->use_count - (int) (share->op != 0) - (int) (share->op != 0))
<= 0)
@@ -9783,7 +9784,7 @@ void ha_ndbcluster::set_auto_partitions(partition_info *part_info)
int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info)
{
NDBTAB *tab= (NDBTAB*)tab_ref;
- int32 *range_data= (int32*)my_malloc(part_info->no_parts*sizeof(int32),
+ int32 *range_data= (int32*)my_malloc(part_info->num_parts*sizeof(int32),
MYF(0));
uint i;
int error= 0;
@@ -9792,17 +9793,17 @@ int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info)
if (!range_data)
{
- mem_alloc_error(part_info->no_parts*sizeof(int32));
+ mem_alloc_error(part_info->num_parts*sizeof(int32));
DBUG_RETURN(1);
}
- for (i= 0; i < part_info->no_parts; i++)
+ for (i= 0; i < part_info->num_parts; i++)
{
longlong range_val= part_info->range_int_array[i];
if (unsigned_flag)
range_val-= 0x8000000000000000ULL;
if (range_val < INT_MIN32 || range_val >= INT_MAX32)
{
- if ((i != part_info->no_parts - 1) ||
+ if ((i != part_info->num_parts - 1) ||
(range_val != LONGLONG_MAX))
{
my_error(ER_LIMITED_PART_RANGE, MYF(0), "NDB");
@@ -9813,7 +9814,7 @@ int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info)
}
range_data[i]= (int32)range_val;
}
- tab->setRangeListData(range_data, sizeof(int32)*part_info->no_parts);
+ tab->setRangeListData(range_data, sizeof(int32)*part_info->num_parts);
error:
my_free((char*)range_data, MYF(0));
DBUG_RETURN(error);
@@ -9822,7 +9823,7 @@ error:
int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info)
{
NDBTAB *tab= (NDBTAB*)tab_ref;
- int32 *list_data= (int32*)my_malloc(part_info->no_list_values * 2
+ int32 *list_data= (int32*)my_malloc(part_info->num_list_values * 2
* sizeof(int32), MYF(0));
uint32 *part_id, i;
int error= 0;
@@ -9831,10 +9832,10 @@ int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info)
if (!list_data)
{
- mem_alloc_error(part_info->no_list_values*2*sizeof(int32));
+ mem_alloc_error(part_info->num_list_values*2*sizeof(int32));
DBUG_RETURN(1);
}
- for (i= 0; i < part_info->no_list_values; i++)
+ for (i= 0; i < part_info->num_list_values; i++)
{
LIST_PART_ENTRY *list_entry= &part_info->list_array[i];
longlong list_val= list_entry->list_value;
@@ -9850,7 +9851,7 @@ int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info)
part_id= (uint32*)&list_data[2*i+1];
*part_id= list_entry->partition_id;
}
- tab->setRangeListData(list_data, 2*sizeof(int32)*part_info->no_list_values);
+ tab->setRangeListData(list_data, 2*sizeof(int32)*part_info->num_list_values);
error:
my_free((char*)list_data, MYF(0));
DBUG_RETURN(error);
@@ -9972,11 +9973,11 @@ uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
ng= 0;
ts_names[fd_index]= part_elem->tablespace_name;
frag_data[fd_index++]= ng;
- } while (++j < part_info->no_subparts);
+ } while (++j < part_info->num_subparts);
}
first= FALSE;
- } while (++i < part_info->no_parts);
- tab->setDefaultNoPartitionsFlag(part_info->use_default_no_partitions);
+ } while (++i < part_info->num_parts);
+ tab->setDefaultNoPartitionsFlag(part_info->use_default_num_partitions);
tab->setLinearFlag(part_info->linear_hash_ind);
{
ha_rows max_rows= table_share->max_rows;
@@ -10346,13 +10347,13 @@ int ndbcluster_alter_tablespace(handlerton *hton,
#ifdef HAVE_NDB_BINLOG
if (is_tablespace)
ndbcluster_log_schema_op(thd, 0,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
"", alter_info->tablespace_name,
0, 0,
SOT_TABLESPACE, 0, 0, 0);
else
ndbcluster_log_schema_op(thd, 0,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
"", alter_info->logfile_group_name,
0, 0,
SOT_LOGFILE_GROUP, 0, 0, 0);
@@ -10370,7 +10371,7 @@ ndberror2:
}
-bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts)
+bool ha_ndbcluster::get_no_parts(const char *name, uint *num_parts)
{
Ndb *ndb;
NDBDICT *dict;
@@ -10392,7 +10393,7 @@ bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts)
Ndb_table_guard ndbtab_g(dict= ndb->getDictionary(), m_tabname);
if (!ndbtab_g.get_table())
ERR_BREAK(dict->getNdbError(), err);
- *no_parts= ndbtab_g.get_table()->getFragmentCount();
+ *num_parts= ndbtab_g.get_table()->getFragmentCount();
DBUG_RETURN(FALSE);
}
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index bee806be1b7..a22ce976351 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -241,8 +241,8 @@ static void dbug_print_table(const char *info, TABLE *table)
static void run_query(THD *thd, char *buf, char *end,
const int *no_print_error, my_bool disable_binlog)
{
- ulong save_thd_query_length= thd->query_length;
- char *save_thd_query= thd->query;
+ ulong save_thd_query_length= thd->query_length();
+ char *save_thd_query= thd->query();
ulong save_thread_id= thd->variables.pseudo_thread_id;
struct system_status_var save_thd_status_var= thd->status_var;
THD_TRANS save_thd_transaction_all= thd->transaction.all;
@@ -259,12 +259,12 @@ static void run_query(THD *thd, char *buf, char *end,
if (disable_binlog)
thd->options&= ~OPTION_BIN_LOG;
- DBUG_PRINT("query", ("%s", thd->query));
+ DBUG_PRINT("query", ("%s", thd->query()));
DBUG_ASSERT(!thd->in_sub_stmt);
DBUG_ASSERT(!thd->prelocked_mode);
- mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
+ mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon);
if (no_print_error && thd->is_slave_error)
{
@@ -740,9 +740,9 @@ static NDB_SHARE *ndbcluster_check_ndb_apply_status_share()
{
pthread_mutex_lock(&ndbcluster_mutex);
- void *share= hash_search(&ndbcluster_open_tables,
- (uchar*) NDB_APPLY_TABLE_FILE,
- sizeof(NDB_APPLY_TABLE_FILE) - 1);
+ void *share= my_hash_search(&ndbcluster_open_tables,
+ (uchar*) NDB_APPLY_TABLE_FILE,
+ sizeof(NDB_APPLY_TABLE_FILE) - 1);
DBUG_PRINT("info",("ndbcluster_check_ndb_apply_status_share %s 0x%lx",
NDB_APPLY_TABLE_FILE, (long) share));
pthread_mutex_unlock(&ndbcluster_mutex);
@@ -758,9 +758,9 @@ static NDB_SHARE *ndbcluster_check_ndb_schema_share()
{
pthread_mutex_lock(&ndbcluster_mutex);
- void *share= hash_search(&ndbcluster_open_tables,
- (uchar*) NDB_SCHEMA_TABLE_FILE,
- sizeof(NDB_SCHEMA_TABLE_FILE) - 1);
+ void *share= my_hash_search(&ndbcluster_open_tables,
+ (uchar*) NDB_SCHEMA_TABLE_FILE,
+ sizeof(NDB_SCHEMA_TABLE_FILE) - 1);
DBUG_PRINT("info",("ndbcluster_check_ndb_schema_share %s 0x%lx",
NDB_SCHEMA_TABLE_FILE, (long) share));
pthread_mutex_unlock(&ndbcluster_mutex);
@@ -2184,8 +2184,8 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
{
pthread_mutex_lock(&ndbcluster_mutex);
NDB_SCHEMA_OBJECT *ndb_schema_object=
- (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects,
- (uchar*) key, strlen(key));
+ (NDB_SCHEMA_OBJECT*) my_hash_search(&ndb_schema_objects,
+ (uchar*) key, strlen(key));
if (ndb_schema_object)
{
pthread_mutex_lock(&ndb_schema_object->mutex);
@@ -2571,8 +2571,8 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
pthread_mutex_lock(&ndbcluster_mutex);
/* Handle any trailing share */
- NDB_SHARE *share= (NDB_SHARE*) hash_search(&ndbcluster_open_tables,
- (uchar*) key, key_len);
+ NDB_SHARE *share= (NDB_SHARE*) my_hash_search(&ndbcluster_open_tables,
+ (uchar*) key, key_len);
if (share && share_may_exist)
{
@@ -3390,14 +3390,14 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
if (share->flags & NSF_BLOB_FLAG)
{
my_ptrdiff_t ptrdiff= 0;
- IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[0],
+ int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[0],
blobs_buffer[0],
blobs_buffer_size[0],
ptrdiff);
DBUG_ASSERT(ret == 0);
}
ndb_unpack_record(table, share->ndb_value[0], &b, table->record[0]);
- IF_DBUG(int ret=) trans.write_row(originating_server_id,
+ int ret __attribute__((unused))= trans.write_row(originating_server_id,
injector::transaction::table(table,
TRUE),
&b, n_fields, table->record[0]);
@@ -3429,7 +3429,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
if (share->flags & NSF_BLOB_FLAG)
{
my_ptrdiff_t ptrdiff= table->record[n] - table->record[0];
- IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[n],
+ int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[n],
blobs_buffer[n],
blobs_buffer_size[n],
ptrdiff);
@@ -3437,7 +3437,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
}
ndb_unpack_record(table, share->ndb_value[n], &b, table->record[n]);
DBUG_EXECUTE("info", print_records(table, table->record[n]););
- IF_DBUG(int ret =) trans.delete_row(originating_server_id,
+ int ret __attribute__((unused))= trans.delete_row(originating_server_id,
injector::transaction::table(table,
TRUE),
&b, n_fields, table->record[n]);
@@ -3452,7 +3452,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
if (share->flags & NSF_BLOB_FLAG)
{
my_ptrdiff_t ptrdiff= 0;
- IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[0],
+ int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[0],
blobs_buffer[0],
blobs_buffer_size[0],
ptrdiff);
@@ -3480,7 +3480,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
if (share->flags & NSF_BLOB_FLAG)
{
my_ptrdiff_t ptrdiff= table->record[1] - table->record[0];
- IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[1],
+ int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[1],
blobs_buffer[1],
blobs_buffer_size[1],
ptrdiff);
@@ -3488,7 +3488,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
}
ndb_unpack_record(table, share->ndb_value[1], &b, table->record[1]);
DBUG_EXECUTE("info", print_records(table, table->record[1]););
- IF_DBUG(int ret =) trans.update_row(originating_server_id,
+ int ret __attribute__((unused))= trans.update_row(originating_server_id,
injector::transaction::table(table,
TRUE),
&b, n_fields,
@@ -3558,9 +3558,9 @@ static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key,
if (!have_lock)
pthread_mutex_lock(&ndbcluster_mutex);
while (!(ndb_schema_object=
- (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects,
- (uchar*) key,
- length)))
+ (NDB_SCHEMA_OBJECT*) my_hash_search(&ndb_schema_objects,
+ (uchar*) key,
+ length)))
{
if (!create_if_not_exists)
{
@@ -3609,7 +3609,7 @@ static void ndb_free_schema_object(NDB_SCHEMA_OBJECT **ndb_schema_object,
if (!--(*ndb_schema_object)->use_count)
{
DBUG_PRINT("info", ("use_count: %d", (*ndb_schema_object)->use_count));
- hash_delete(&ndb_schema_objects, (uchar*) *ndb_schema_object);
+ my_hash_delete(&ndb_schema_objects, (uchar*) *ndb_schema_object);
pthread_mutex_destroy(&(*ndb_schema_object)->mutex);
my_free((uchar*) *ndb_schema_object, MYF(0));
*ndb_schema_object= 0;
@@ -3669,7 +3669,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
pthread_exit(0);
return NULL; // Avoid compiler warnings
}
- lex_start(thd);
thd->init_for_queries();
thd->command= COM_DAEMON;
@@ -3715,8 +3714,8 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
}
/* init hash for schema object distribution */
- (void) hash_init(&ndb_schema_objects, system_charset_info, 32, 0, 0,
- (hash_get_key)ndb_schema_objects_get_key, 0, 0);
+ (void) my_hash_init(&ndb_schema_objects, system_charset_info, 32, 0, 0,
+ (my_hash_get_key)ndb_schema_objects_get_key, 0, 0);
/*
Expose global reference to our ndb object.
@@ -3792,7 +3791,7 @@ restart:
{ C_STRING_WITH_LEN("mysqld startup") },
{ C_STRING_WITH_LEN("cluster disconnect")}
};
- IF_DBUG(int error=)
+ int error __attribute__((unused))=
inj->record_incident(thd, INCIDENT_LOST_EVENTS, msg[incident_id]);
DBUG_ASSERT(!error);
break;
@@ -4107,7 +4106,7 @@ restart:
DBUG_PRINT("info", ("use_table: %.*s",
(int) name.length, name.str));
injector::transaction::table tbl(table, TRUE);
- IF_DBUG(int ret=) trans.use_table(::server_id, tbl);
+ int ret __attribute__((unused))= trans.use_table(::server_id, tbl);
DBUG_ASSERT(ret == 0);
}
}
@@ -4123,7 +4122,7 @@ restart:
(int) name.length, name.str));
#endif
injector::transaction::table tbl(table, TRUE);
- IF_DBUG(int ret=) trans.use_table(::server_id, tbl);
+ int ret __attribute__((unused))= trans.use_table(::server_id, tbl);
DBUG_ASSERT(ret == 0);
/*
@@ -4193,7 +4192,7 @@ restart:
else
{
// set injector_ndb database/schema from table internal name
- IF_DBUG(int ret=)
+ int ret __attribute__((unused))=
i_ndb->setDatabaseAndSchemaName(pOp->getEvent()->getTable());
DBUG_ASSERT(ret == 0);
ndb_binlog_thread_handle_non_data_event(thd, i_ndb, pOp, row);
@@ -4367,7 +4366,7 @@ err:
i_ndb= 0;
}
- hash_free(&ndb_schema_objects);
+ my_hash_free(&ndb_schema_objects);
net_end(&thd->net);
thd->cleanup();
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 5ebe5c2faea..7e5eccb2374 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1,4 +1,4 @@
-/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -245,7 +245,7 @@ void ha_partition::init_handler_variables()
/*
this allows blackhole to work properly
*/
- m_no_locks= 0;
+ m_num_locks= 0;
#ifdef DONT_HAVE_TO_BE_INITALIZED
m_start_key.flag= 0;
@@ -580,8 +580,8 @@ int ha_partition::drop_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
char part_name_buff[FN_REFLEN];
- uint no_parts= m_part_info->partitions.elements;
- uint no_subparts= m_part_info->no_subparts;
+ uint num_parts= m_part_info->partitions.elements;
+ uint num_subparts= m_part_info->num_subparts;
uint i= 0;
uint name_variant;
int ret_error;
@@ -611,7 +611,7 @@ int ha_partition::drop_partitions(const char *path)
do
{
partition_element *sub_elem= sub_it++;
- part= i * no_subparts + j;
+ part= i * num_subparts + j;
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name, name_variant);
@@ -621,7 +621,7 @@ int ha_partition::drop_partitions(const char *path)
error= ret_error;
if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
error= 1;
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -640,7 +640,7 @@ int ha_partition::drop_partitions(const char *path)
else
part_elem->part_state= PART_IS_DROPPED;
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
VOID(sync_ddl_log());
DBUG_RETURN(error);
}
@@ -671,9 +671,9 @@ int ha_partition::rename_partitions(const char *path)
List_iterator<partition_element> temp_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
char norm_name_buff[FN_REFLEN];
- uint no_parts= m_part_info->partitions.elements;
+ uint num_parts= m_part_info->partitions.elements;
uint part_count= 0;
- uint no_subparts= m_part_info->no_subparts;
+ uint num_subparts= m_part_info->num_subparts;
uint i= 0;
uint j= 0;
int error= 0;
@@ -722,7 +722,7 @@ int ha_partition::rename_partitions(const char *path)
error= 1;
else
sub_elem->log_entry= NULL; /* Indicate success */
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -778,7 +778,7 @@ int ha_partition::rename_partitions(const char *path)
do
{
sub_elem= sub_it++;
- part= i * no_subparts + j;
+ part= i * num_subparts + j;
create_subpartition_name(norm_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
@@ -807,7 +807,7 @@ int ha_partition::rename_partitions(const char *path)
error= 1;
else
sub_elem->log_entry= NULL;
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -839,7 +839,7 @@ int ha_partition::rename_partitions(const char *path)
part_elem->log_entry= NULL;
}
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
VOID(sync_ddl_log());
DBUG_RETURN(error);
}
@@ -1093,8 +1093,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
uint flag)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
- uint no_parts= m_part_info->no_parts;
- uint no_subparts= m_part_info->no_subparts;
+ uint num_parts= m_part_info->num_parts;
+ uint num_subparts= m_part_info->num_subparts;
uint i= 0;
int error;
DBUG_ENTER("ha_partition::handle_opt_partitions");
@@ -1118,7 +1118,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
do
{
sub_elem= subpart_it++;
- part= i * no_subparts + j;
+ part= i * num_subparts + j;
DBUG_PRINT("info", ("Optimize subpartition %u (%s)",
part, sub_elem->partition_name));
#ifdef NOT_USED
@@ -1148,7 +1148,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
} while (part_elem= part_it++);
DBUG_RETURN(error);
}
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -1183,7 +1183,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
}
part_elem->part_state= PART_NORMAL;
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
DBUG_RETURN(FALSE);
}
@@ -1387,10 +1387,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
List_iterator<partition_element> part_it(m_part_info->partitions);
List_iterator <partition_element> t_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
- uint no_parts= m_part_info->partitions.elements;
- uint no_subparts= m_part_info->no_subparts;
+ uint num_parts= m_part_info->partitions.elements;
+ uint num_subparts= m_part_info->num_subparts;
uint i= 0;
- uint no_remain_partitions, part_count, orig_count;
+ uint num_remain_partitions, part_count, orig_count;
handler **new_file_array;
int error= 1;
bool first;
@@ -1406,7 +1406,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_name_buff)));
m_reorged_parts= 0;
if (!m_part_info->is_sub_partitioned())
- no_subparts= 1;
+ num_subparts= 1;
/*
Step 1:
@@ -1415,7 +1415,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
*/
if (temp_partitions)
{
- m_reorged_parts= temp_partitions * no_subparts;
+ m_reorged_parts= temp_partitions * num_subparts;
}
else
{
@@ -1425,9 +1425,9 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
if (part_elem->part_state == PART_CHANGED ||
part_elem->part_state == PART_REORGED_DROPPED)
{
- m_reorged_parts+= no_subparts;
+ m_reorged_parts+= num_subparts;
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
}
if (m_reorged_parts &&
!(m_reorged_file= (handler**)sql_calloc(sizeof(handler*)*
@@ -1442,10 +1442,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
Calculate number of partitions after change and allocate space for
their handler references.
*/
- no_remain_partitions= 0;
+ num_remain_partitions= 0;
if (temp_partitions)
{
- no_remain_partitions= no_parts * no_subparts;
+ num_remain_partitions= num_parts * num_subparts;
}
else
{
@@ -1458,17 +1458,17 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state == PART_TO_BE_ADDED ||
part_elem->part_state == PART_CHANGED)
{
- no_remain_partitions+= no_subparts;
+ num_remain_partitions+= num_subparts;
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
}
if (!(new_file_array= (handler**)sql_calloc(sizeof(handler*)*
- (2*(no_remain_partitions + 1)))))
+ (2*(num_remain_partitions + 1)))))
{
- mem_alloc_error(sizeof(handler*)*2*(no_remain_partitions+1));
+ mem_alloc_error(sizeof(handler*)*2*(num_remain_partitions+1));
DBUG_RETURN(ER_OUTOFMEMORY);
}
- m_added_file= &new_file_array[no_remain_partitions + 1];
+ m_added_file= &new_file_array[num_remain_partitions + 1];
/*
Step 3:
@@ -1487,9 +1487,9 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state == PART_REORGED_DROPPED)
{
memcpy((void*)&m_reorged_file[part_count],
- (void*)&m_file[i*no_subparts],
- sizeof(handler*)*no_subparts);
- part_count+= no_subparts;
+ (void*)&m_file[i*num_subparts],
+ sizeof(handler*)*num_subparts);
+ part_count+= num_subparts;
}
else if (first && temp_partitions &&
part_elem->part_state == PART_TO_BE_ADDED)
@@ -1504,11 +1504,11 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
ones used to be.
*/
first= FALSE;
- DBUG_ASSERT(((i*no_subparts) + m_reorged_parts) <= m_file_tot_parts);
- memcpy((void*)m_reorged_file, &m_file[i*no_subparts],
+ DBUG_ASSERT(((i*num_subparts) + m_reorged_parts) <= m_file_tot_parts);
+ memcpy((void*)m_reorged_file, &m_file[i*num_subparts],
sizeof(handler*)*m_reorged_parts);
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
}
/*
@@ -1526,11 +1526,11 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
partition_element *part_elem= part_it++;
if (part_elem->part_state == PART_NORMAL)
{
- DBUG_ASSERT(orig_count + no_subparts <= m_file_tot_parts);
+ DBUG_ASSERT(orig_count + num_subparts <= m_file_tot_parts);
memcpy((void*)&new_file_array[part_count], (void*)&m_file[orig_count],
- sizeof(handler*)*no_subparts);
- part_count+= no_subparts;
- orig_count+= no_subparts;
+ sizeof(handler*)*num_subparts);
+ part_count+= num_subparts;
+ orig_count+= num_subparts;
}
else if (part_elem->part_state == PART_CHANGED ||
part_elem->part_state == PART_TO_BE_ADDED)
@@ -1546,16 +1546,16 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
mem_alloc_error(sizeof(handler));
DBUG_RETURN(ER_OUTOFMEMORY);
}
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
if (part_elem->part_state == PART_CHANGED)
- orig_count+= no_subparts;
+ orig_count+= num_subparts;
else if (temp_partitions && first)
{
- orig_count+= (no_subparts * temp_partitions);
+ orig_count+= (num_subparts * temp_partitions);
first= FALSE;
}
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
first= FALSE;
/*
Step 5:
@@ -1592,7 +1592,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->partition_name,
sub_elem->partition_name,
name_variant);
- part= i * no_subparts + j;
+ part= i * num_subparts + j;
DBUG_PRINT("info", ("Add subpartition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
new_file_array[part],
@@ -1603,7 +1603,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
DBUG_RETURN(error);
}
m_added_file[part_count++]= new_file_array[part];
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -1622,7 +1622,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
m_added_file[part_count++]= new_file_array[i];
}
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
/*
Step 6:
@@ -1639,7 +1639,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state= PART_IS_CHANGED;
else if (part_elem->part_state == PART_REORGED_DROPPED)
part_elem->part_state= PART_TO_BE_DROPPED;
- } while (++i < no_parts);
+ } while (++i < num_parts);
for (i= 0; i < temp_partitions; i++)
{
partition_element *part_elem= t_it++;
@@ -1680,9 +1680,9 @@ int ha_partition::copy_partitions(ulonglong * const copied,
if (m_part_info->linear_hash_ind)
{
if (m_part_info->part_type == HASH_PARTITION)
- set_linear_hash_mask(m_part_info, m_part_info->no_parts);
+ set_linear_hash_mask(m_part_info, m_part_info->num_parts);
else
- set_linear_hash_mask(m_part_info, m_part_info->no_subparts);
+ set_linear_hash_mask(m_part_info, m_part_info->num_subparts);
}
while (reorg_part < m_reorged_parts)
@@ -1961,7 +1961,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
uint curr_part_id= 0;
List_iterator_fast <partition_element> part_it(m_part_info->partitions);
- for (i= 0; i < m_part_info->no_parts; i++)
+ for (i= 0; i < m_part_info->num_parts; i++)
{
partition_element *part_elem;
part_elem= part_it++;
@@ -1969,7 +1969,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
{
uint j;
List_iterator_fast <partition_element> sub_it(part_elem->subpartitions);
- for (j= 0; j < m_part_info->no_subparts; j++)
+ for (j= 0; j < m_part_info->num_subparts; j++)
{
part_elem= sub_it++;
if (part_id == curr_part_id++)
@@ -2090,7 +2090,7 @@ bool ha_partition::create_handler_file(const char *name)
{
partition_element *part_elem, *subpart_elem;
uint i, j, part_name_len, subpart_name_len;
- uint tot_partition_words, tot_name_len, no_parts;
+ uint tot_partition_words, tot_name_len, num_parts;
uint tot_parts= 0;
uint tot_len_words, tot_len_byte, chksum, tot_name_words;
char *name_buffer_ptr;
@@ -2103,11 +2103,11 @@ bool ha_partition::create_handler_file(const char *name)
List_iterator_fast <partition_element> part_it(m_part_info->partitions);
DBUG_ENTER("create_handler_file");
- no_parts= m_part_info->partitions.elements;
- DBUG_PRINT("info", ("table name = %s, no_parts = %u", name,
- no_parts));
+ num_parts= m_part_info->partitions.elements;
+ DBUG_PRINT("info", ("table name = %s, num_parts = %u", name,
+ num_parts));
tot_name_len= 0;
- for (i= 0; i < no_parts; i++)
+ for (i= 0; i < num_parts; i++)
{
part_elem= part_it++;
if (part_elem->part_state != PART_NORMAL &&
@@ -2125,7 +2125,7 @@ bool ha_partition::create_handler_file(const char *name)
else
{
List_iterator_fast <partition_element> sub_it(part_elem->subpartitions);
- for (j= 0; j < m_part_info->no_subparts; j++)
+ for (j= 0; j < m_part_info->num_subparts; j++)
{
subpart_elem= sub_it++;
tablename_to_filename(subpart_elem->partition_name,
@@ -2159,7 +2159,7 @@ bool ha_partition::create_handler_file(const char *name)
engine_array= (file_buffer + 12);
name_buffer_ptr= (char*) (file_buffer + ((4 + tot_partition_words) * 4));
part_it.rewind();
- for (i= 0; i < no_parts; i++)
+ for (i= 0; i < num_parts; i++)
{
part_elem= part_it++;
if (part_elem->part_state != PART_NORMAL &&
@@ -2177,7 +2177,7 @@ bool ha_partition::create_handler_file(const char *name)
else
{
List_iterator_fast <partition_element> sub_it(part_elem->subpartitions);
- for (j= 0; j < m_part_info->no_subparts; j++)
+ for (j= 0; j < m_part_info->num_subparts; j++)
{
subpart_elem= sub_it++;
tablename_to_filename(part_elem->partition_name, part_name,
@@ -2313,7 +2313,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
}
m_file_tot_parts= m_tot_parts;
bzero((char*) m_file, alloc_len);
- DBUG_ASSERT(m_part_info->no_parts > 0);
+ DBUG_ASSERT(m_part_info->num_parts > 0);
i= 0;
part_count= 0;
@@ -2326,7 +2326,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
part_elem= part_it++;
if (m_is_sub_partitioned)
{
- for (j= 0; j < m_part_info->no_subparts; j++)
+ for (j= 0; j < m_part_info->num_subparts; j++)
{
if (!(m_file[part_count++]= get_new_handler(table_share, mem_root,
part_elem->engine_type)))
@@ -2343,7 +2343,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
DBUG_PRINT("info", ("engine_type: %u",
(uint) ha_legacy_type(part_elem->engine_type)));
}
- } while (++i < m_part_info->no_parts);
+ } while (++i < m_part_info->num_parts);
if (part_elem->engine_type == myisam_hton)
{
DBUG_PRINT("info", ("MyISAM"));
@@ -2452,6 +2452,21 @@ err1:
/****************************************************************************
MODULE open/close object
****************************************************************************/
+
+
+/**
+ A destructor for partition-specific TABLE_SHARE data.
+*/
+
+void ha_data_partition_destroy(void *ha_data)
+{
+ if (ha_data)
+ {
+ HA_DATA_PARTITION *ha_data_partition= (HA_DATA_PARTITION*) ha_data;
+ pthread_mutex_destroy(&ha_data_partition->mutex);
+ }
+}
+
/*
Open handler object
@@ -2546,7 +2561,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if ((error= (*file)->ha_open(table, (const char*) name_buff, mode,
test_if_locked)))
goto err_handler;
- m_no_locks+= (*file)->lock_count();
+ m_num_locks+= (*file)->lock_count();
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
set_if_bigger(ref_length, ((*file)->ref_length));
/*
@@ -2608,6 +2623,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
}
DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
bzero(ha_data, sizeof(HA_DATA_PARTITION));
+ table_share->ha_data_destroy= ha_data_partition_destroy;
+ pthread_mutex_init(&ha_data->mutex, MY_MUTEX_INIT_FAST);
}
if (is_not_tmp_table)
pthread_mutex_unlock(&table_share->mutex);
@@ -2893,8 +2910,8 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
uint ha_partition::lock_count() const
{
DBUG_ENTER("ha_partition::lock_count");
- DBUG_PRINT("info", ("m_no_locks %d", m_no_locks));
- DBUG_RETURN(m_no_locks);
+ DBUG_PRINT("info", ("m_num_locks %d", m_num_locks));
+ DBUG_RETURN(m_num_locks);
}
@@ -3305,13 +3322,13 @@ int ha_partition::delete_all_rows()
/* ALTER TABLE t TRUNCATE PARTITION ... */
List_iterator<partition_element> part_it(m_part_info->partitions);
int saved_error= 0;
- uint no_parts= m_part_info->no_parts;
- uint no_subparts= m_part_info->no_subparts;
+ uint num_parts= m_part_info->num_parts;
+ uint num_subparts= m_part_info->num_subparts;
uint i= 0;
- uint no_parts_set= alter_info->partition_names.elements;
- uint no_parts_found= set_part_state(alter_info, m_part_info,
- PART_ADMIN);
- if (no_parts_set != no_parts_found &&
+ uint num_parts_set= alter_info->partition_names.elements;
+ uint num_parts_found= set_part_state(alter_info, m_part_info,
+ PART_ADMIN);
+ if (num_parts_set != num_parts_found &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
@@ -3334,7 +3351,7 @@ int ha_partition::delete_all_rows()
do
{
sub_elem= subpart_it++;
- part= i * no_subparts + j;
+ part= i * num_subparts + j;
bitmap_set_bit(&m_part_info->used_partitions, part);
if (!saved_error)
{
@@ -3348,7 +3365,7 @@ int ha_partition::delete_all_rows()
error != HA_ERR_WRONG_COMMAND)
saved_error= error;
}
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -3368,7 +3385,7 @@ int ha_partition::delete_all_rows()
}
part_elem->part_state= PART_NORMAL;
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
DBUG_RETURN(saved_error);
}
truncate= TRUE;
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index c62318daf84..d4579d013fd 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1,7 +1,7 @@
#ifndef HA_PARTITION_INCLUDED
#define HA_PARTITION_INCLUDED
-/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,7 +22,8 @@
enum partition_keywords
{
- PKW_HASH= 0, PKW_RANGE, PKW_LIST, PKW_KEY, PKW_MAXVALUE, PKW_LINEAR
+ PKW_HASH= 0, PKW_RANGE, PKW_LIST, PKW_KEY, PKW_MAXVALUE, PKW_LINEAR,
+ PKW_COLUMNS
};
/*
@@ -48,6 +49,7 @@ typedef struct st_ha_data_partition
{
ulonglong next_auto_inc_val; /**< first non reserved value */
bool auto_inc_initialized;
+ pthread_mutex_t mutex;
} HA_DATA_PARTITION;
#define PARTITION_BYTES_IN_POS 2
@@ -114,7 +116,7 @@ private:
uint m_reorged_parts; // Number of reorganised parts
uint m_tot_parts; // Total number of partitions;
- uint m_no_locks; // For engines like ha_blackhole, which needs no locks
+ uint m_num_locks; // For engines like ha_blackhole, which needs no locks
uint m_last_part; // Last file that we update,write,read
int m_lock_type; // Remembers type of last
// external_lock
@@ -246,10 +248,10 @@ public:
size_t pack_frm_len);
virtual int drop_partitions(const char *path);
virtual int rename_partitions(const char *path);
- bool get_no_parts(const char *name, uint *no_parts)
+ bool get_no_parts(const char *name, uint *num_parts)
{
DBUG_ENTER("ha_partition::get_no_parts");
- *no_parts= m_tot_parts;
+ *num_parts= m_tot_parts;
DBUG_RETURN(0);
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
diff --git a/sql/handler.cc b/sql/handler.cc
index bc8c627a6ae..ad7e1ecfa80 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1341,7 +1341,8 @@ int ha_rollback_trans(THD *thd, bool all)
}
trans->ha_list= 0;
trans->no_2pc=0;
- if (is_real_trans && thd->transaction_rollback_request)
+ if (is_real_trans && thd->transaction_rollback_request &&
+ thd->transaction.xid_state.xa_state != XA_NOTR)
thd->transaction.xid_state.rm_error= thd->stmt_da->sql_errno();
if (all)
thd->variables.tx_isolation=thd->session_tx_isolation;
@@ -1570,7 +1571,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
}
// recovery mode
if (info->commit_list ?
- hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
+ my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
{
#ifndef DBUG_OFF
@@ -1681,12 +1682,12 @@ bool mysql_xa_recover(THD *thd)
field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(1);
pthread_mutex_lock(&LOCK_xid_cache);
- while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
+ while ((xs= (XID_STATE*) my_hash_element(&xid_cache, i++)))
{
if (xs->xa_state==XA_PREPARED)
{
@@ -3009,9 +3010,9 @@ static bool update_frm_version(TABLE *table)
if ((result= my_pwrite(file,(uchar*) version,4,51L,MYF_RW)))
goto err;
- for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
+ for (entry=(TABLE*) my_hash_first(&open_cache,(uchar*) key,key_length, &state);
entry;
- entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
+ entry= (TABLE*) my_hash_next(&open_cache,(uchar*) key,key_length, &state))
entry->s->mysql_version= MYSQL_VERSION_ID;
}
err:
@@ -4467,7 +4468,7 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
field_list.push_back(new Item_empty_string("Status",10));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
return TRUE;
diff --git a/sql/handler.h b/sql/handler.h
index 632c262b59a..05a9e13653c 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -408,7 +408,6 @@ struct xid_t {
my_xid get_my_xid()
{
return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 &&
- !memcmp(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id)) &&
!memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
quick_get_my_xid() : 0;
}
@@ -515,9 +514,8 @@ class st_alter_tablespace : public Sql_alloc
/* The handler for a table type. Will be included in the TABLE structure */
-struct st_table;
-typedef struct st_table TABLE;
-typedef struct st_table_share TABLE_SHARE;
+struct TABLE;
+struct TABLE_SHARE;
struct st_foreign_key_info;
typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
@@ -592,6 +590,7 @@ struct handler_iterator {
void *buffer;
};
+class handler;
/*
handlerton is a singleton structure - one instance per storage engine -
to provide access to storage engine functionality that works on the
@@ -1095,8 +1094,8 @@ class handler :public Sql_alloc
public:
typedef ulonglong Table_flags;
protected:
- struct st_table_share *table_share; /* The table definition */
- struct st_table *table; /* The current open table */
+ TABLE_SHARE *table_share; /* The table definition */
+ TABLE *table; /* The current open table */
Table_flags cached_table_flags; /* Set on init() and open() */
ha_rows estimation_rows_to_insert;
@@ -1172,7 +1171,7 @@ public:
virtual ~handler(void)
{
DBUG_ASSERT(locked == FALSE);
- /* TODO: DBUG_ASSERT(inited == NONE); */
+ DBUG_ASSERT(inited == NONE);
}
virtual handler *clone(MEM_ROOT *mem_root);
/** This is called after create to allow us to set up cached variables */
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index ab13d338695..5d17b880b4d 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -38,8 +38,8 @@ class hash_filo_element
class hash_filo
{
const uint size, key_offset, key_length;
- const hash_get_key get_key;
- hash_free_key free_element;
+ const my_hash_get_key get_key;
+ my_hash_free_key free_element;
bool init;
CHARSET_INFO *hash_charset;
@@ -49,7 +49,7 @@ public:
HASH cache;
hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg,
- hash_get_key get_key_arg, hash_free_key free_element_arg,
+ my_hash_get_key get_key_arg, my_hash_free_key free_element_arg,
CHARSET_INFO *hash_charset_arg)
:size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg),
get_key(get_key_arg), free_element(free_element_arg),init(0),
@@ -63,7 +63,7 @@ public:
if (init)
{
if (cache.array.buffer) /* Avoid problems with thread library */
- (void) hash_free(&cache);
+ (void) my_hash_free(&cache);
pthread_mutex_destroy(&lock);
}
}
@@ -76,8 +76,8 @@ public:
}
if (!locked)
(void) pthread_mutex_lock(&lock);
- (void) hash_free(&cache);
- (void) hash_init(&cache,hash_charset,size,key_offset,
+ (void) my_hash_free(&cache);
+ (void) my_hash_init(&cache,hash_charset,size,key_offset,
key_length, get_key, free_element,0);
if (!locked)
(void) pthread_mutex_unlock(&lock);
@@ -87,7 +87,7 @@ public:
hash_filo_element *search(uchar* key, size_t length)
{
hash_filo_element *entry=(hash_filo_element*)
- hash_search(&cache,(uchar*) key,length);
+ my_hash_search(&cache,(uchar*) key,length);
if (entry)
{ // Found; link it first
if (entry != first_link)
@@ -113,7 +113,7 @@ public:
{
hash_filo_element *tmp=last_link;
last_link=last_link->prev_used;
- hash_delete(&cache,(uchar*) tmp);
+ my_hash_delete(&cache,(uchar*) tmp);
}
if (my_hash_insert(&cache,(uchar*) entry))
{
diff --git a/sql/hostname.cc b/sql/hostname.cc
index c8cf46383a9..45b10d16ce2 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -64,7 +64,7 @@ bool hostname_cache_init()
uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp);
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
sizeof(struct in_addr),NULL,
- (hash_free_key) free,
+ (my_hash_free_key) free,
&my_charset_bin)))
return 1;
hostname_cache->clear();
diff --git a/sql/item.cc b/sql/item.cc
index aca5370529c..b59a82f8045 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -436,26 +436,17 @@ Item::Item(THD *thd, Item *item):
}
-/**
- Decimal precision of the item.
-
- @remark The precision must not be capped as it can be used in conjunction
- with Item::decimals to determine the size of the integer part when
- constructing a decimal data type.
-
- @see Item::decimal_int_part()
- @see Item::decimals
-*/
-
uint Item::decimal_precision() const
{
- uint precision= max_length;
Item_result restype= result_type();
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
- precision= my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
-
- return precision;
+ {
+ uint prec=
+ my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
+ return min(prec, DECIMAL_MAX_PRECISION);
+ }
+ return min(max_length, DECIMAL_MAX_PRECISION);
}
@@ -2586,7 +2577,8 @@ Item_param::Item_param(uint pos_in_query_arg) :
param_type(MYSQL_TYPE_VARCHAR),
pos_in_query(pos_in_query_arg),
set_param_func(default_set_param_func),
- limit_clause_param(FALSE)
+ limit_clause_param(FALSE),
+ m_out_param_info(NULL)
{
name= (char*) "?";
/*
@@ -2668,6 +2660,17 @@ void Item_param::set_decimal(const char *str, ulong length)
DBUG_VOID_RETURN;
}
+void Item_param::set_decimal(const my_decimal *dv)
+{
+ state= DECIMAL_VALUE;
+
+ my_decimal2decimal(dv, &decimal_value);
+
+ decimals= (uint8) decimal_value.frac;
+ unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
+}
/**
Set parameter value from MYSQL_TIME value.
@@ -3290,6 +3293,158 @@ Item_param::set_param_type_and_swap_value(Item_param *src)
str_value_ptr.swap(src->str_value_ptr);
}
+
+/**
+ This operation is intended to store some item value in Item_param to be
+ used later.
+
+ @param thd thread context
+ @param ctx stored procedure runtime context
+ @param it a pointer to an item in the tree
+
+ @return Error status
+ @retval TRUE on error
+ @retval FALSE on success
+*/
+
+bool
+Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ Item *value= *it;
+
+ if (value->is_null())
+ {
+ set_null();
+ return FALSE;
+ }
+
+ null_value= FALSE;
+
+ switch (value->result_type()) {
+ case STRING_RESULT:
+ {
+ char str_buffer[STRING_BUFFER_USUAL_SIZE];
+ String sv_buffer(str_buffer, sizeof(str_buffer), &my_charset_bin);
+ String *sv= value->val_str(&sv_buffer);
+
+ if (!sv)
+ return TRUE;
+
+ set_str(sv->c_ptr_safe(), sv->length());
+ str_value_ptr.set(str_value.ptr(),
+ str_value.length(),
+ str_value.charset());
+ collation.set(str_value.charset(), DERIVATION_COERCIBLE);
+ decimals= 0;
+ param_type= MYSQL_TYPE_STRING;
+
+ break;
+ }
+
+ case REAL_RESULT:
+ set_double(value->val_real());
+ param_type= MYSQL_TYPE_DOUBLE;
+ break;
+
+ case INT_RESULT:
+ set_int(value->val_int(), value->max_length);
+ param_type= MYSQL_TYPE_LONG;
+ break;
+
+ case DECIMAL_RESULT:
+ {
+ my_decimal dv_buf;
+ my_decimal *dv= value->val_decimal(&dv_buf);
+
+ if (!dv)
+ return TRUE;
+
+ set_decimal(dv);
+ param_type= MYSQL_TYPE_NEWDECIMAL;
+
+ break;
+ }
+
+ default:
+ /* That can not happen. */
+
+ DBUG_ASSERT(TRUE); // Abort in debug mode.
+
+ set_null(); // Set to NULL in release mode.
+ return FALSE;
+ }
+
+ item_result_type= value->result_type();
+ item_type= value->type();
+ return FALSE;
+}
+
+
+/**
+ Setter of Item_param::m_out_param_info.
+
+ m_out_param_info is used to store information about store routine
+ OUT-parameters, such as stored routine name, database, stored routine
+ variable name. It is supposed to be set in sp_head::execute() after
+ Item_param::set_value() is called.
+*/
+
+void
+Item_param::set_out_param_info(Send_field *info)
+{
+ m_out_param_info= info;
+}
+
+
+/**
+ Getter of Item_param::m_out_param_info.
+
+ m_out_param_info is used to store information about store routine
+ OUT-parameters, such as stored routine name, database, stored routine
+ variable name. It is supposed to be retrieved in
+ Protocol_binary::send_out_parameters() during creation of OUT-parameter
+ result set.
+*/
+
+const Send_field *
+Item_param::get_out_param_info() const
+{
+ return m_out_param_info;
+}
+
+
+/**
+ Fill meta-data information for the corresponding column in a result set.
+ If this is an OUT-parameter of a stored procedure, preserve meta-data of
+ stored-routine variable.
+
+ @param field container for meta-data to be filled
+*/
+
+void Item_param::make_field(Send_field *field)
+{
+ Item::make_field(field);
+
+ if (!m_out_param_info)
+ return;
+
+ /*
+ This is an OUT-parameter of stored procedure. We should use
+ OUT-parameter info to fill out the names.
+ */
+
+ field->db_name= m_out_param_info->db_name;
+ field->table_name= m_out_param_info->table_name;
+ field->org_table_name= m_out_param_info->org_table_name;
+ field->col_name= m_out_param_info->col_name;
+ field->org_col_name= m_out_param_info->org_col_name;
+ field->length= m_out_param_info->length;
+ field->charsetnr= m_out_param_info->charsetnr;
+ field->flags= m_out_param_info->flags;
+ field->decimals= m_out_param_info->decimals;
+ field->type= m_out_param_info->type;
+}
+
/****************************************************************************
Item_copy
****************************************************************************/
@@ -3521,7 +3676,7 @@ void Item_copy_decimal::copy()
/*
- Functions to convert item to field (for send_fields)
+ Functions to convert item to field (for send_result_set_metadata)
*/
/* ARGSUSED */
@@ -4908,7 +5063,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
- field= Field_new_decimal::new_decimal_field(this);
+ field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0,
+ Field::NONE, name, decimals, 0,
+ unsigned_flag);
break;
case MYSQL_TYPE_TINY:
field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
@@ -6866,52 +7023,61 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
}
/**
- Compare the value stored in field, with the original item.
+ Compare the value stored in field with the expression from the query.
- @param field field which the item is converted and stored in
- @param item original item
+ @param field Field which the Item is stored in after conversion
+ @param item Original expression from query
- @return Return an integer greater than, equal to, or less than 0 if
- the value stored in the field is greater than, equal to,
- or less than the original item
+ @return Returns an integer greater than, equal to, or less than 0 if
+ the value stored in the field is greater than, equal to,
+ or less than the original Item. A 0 may also be returned if
+ out of memory.
@note We only use this on the range optimizer/partition pruning,
because in some cases we can't store the value in the field
without some precision/character loss.
*/
-int stored_field_cmp_to_item(Field *field, Item *item)
+int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
{
-
Item_result res_type=item_cmp_type(field->result_type(),
item->result_type());
if (res_type == STRING_RESULT)
{
char item_buff[MAX_FIELD_WIDTH];
char field_buff[MAX_FIELD_WIDTH];
- String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result;
+
+ String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin);
String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin);
- enum_field_types field_type;
- item_result=item->val_str(&item_tmp);
+ String *item_result= item->val_str(&item_tmp);
+ /*
+ Some implementations of Item::val_str(String*) actually modify
+ the field Item::null_value, hence we can't check it earlier.
+ */
if (item->null_value)
return 0;
- field->val_str(&field_tmp);
+ String *field_result= field->val_str(&field_tmp);
- /*
- If comparing DATE with DATETIME, append the time-part to the DATE.
- So that the strings are equally formatted.
- A DATE converted to string is 10 characters, and a DATETIME converted
- to string is 19 characters.
- */
- field_type= field->type();
- if (field_type == MYSQL_TYPE_DATE &&
- item_result->length() == 19)
- field_tmp.append(" 00:00:00");
- else if (field_type == MYSQL_TYPE_DATETIME &&
- item_result->length() == 10)
- item_result->append(" 00:00:00");
-
- return stringcmp(&field_tmp,item_result);
+ enum_field_types field_type= field->type();
+
+ if (field_type == MYSQL_TYPE_DATE || field_type == MYSQL_TYPE_DATETIME)
+ {
+ enum_mysql_timestamp_type type= MYSQL_TIMESTAMP_ERROR;
+
+ if (field_type == MYSQL_TYPE_DATE)
+ type= MYSQL_TIMESTAMP_DATE;
+
+ if (field_type == MYSQL_TYPE_DATETIME)
+ type= MYSQL_TIMESTAMP_DATETIME;
+
+ const char *field_name= field->field_name;
+ MYSQL_TIME field_time, item_time;
+ get_mysql_time_from_str(thd, field_result, type, field_name, &field_time);
+ get_mysql_time_from_str(thd, item_result, type, field_name, &item_time);
+
+ return my_time_compare(&field_time, &item_time);
+ }
+ return stringcmp(field_result, item_result);
}
if (res_type == INT_RESULT)
return 0; // Both are of type int
diff --git a/sql/item.h b/sql/item.h
index b44e84f4b15..72e4e37342a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -453,6 +453,11 @@ public:
TRUE if error has occured.
*/
virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0;
+
+ virtual void set_out_param_info(Send_field *info) {}
+
+ virtual const Send_field *get_out_param_info() const
+ { return NULL; }
};
@@ -765,10 +770,9 @@ public:
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
- /** Returns the uncapped decimal precision of this item. */
virtual uint decimal_precision() const;
inline int decimal_int_part() const
- { return decimal_precision() - decimals; }
+ { return my_decimal_int_part(decimal_precision(), decimals); }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -1563,7 +1567,8 @@ public:
/* Item represents one placeholder ('?') of prepared statement */
-class Item_param :public Item
+class Item_param :public Item,
+ private Settable_routine_parameter
{
char cnvbuf[MAX_FIELD_WIDTH];
String cnvstr;
@@ -1651,6 +1656,7 @@ public:
void set_int(longlong i, uint32 max_length_arg);
void set_double(double i);
void set_decimal(const char *str, ulong length);
+ void set_decimal(const my_decimal *dv);
bool set_str(const char *str, ulong length);
bool set_longdata(const char *str, ulong length);
void set_time(MYSQL_TIME *tm, timestamp_type type, uint32 max_length_arg);
@@ -1700,6 +1706,25 @@ public:
/** Item is a argument to a limit clause. */
bool limit_clause_param;
void set_param_type_and_swap_value(Item_param *from);
+
+private:
+ virtual inline Settable_routine_parameter *
+ get_settable_routine_parameter()
+ {
+ return this;
+ }
+
+ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+ virtual void set_out_param_info(Send_field *info);
+
+public:
+ virtual const Send_field *get_out_param_info() const;
+
+ virtual void make_field(Send_field *field);
+
+private:
+ Send_field *m_out_param_info;
};
@@ -2057,7 +2082,7 @@ public:
/**
Item_empty_string -- is a utility class to put an item into List<Item>
- which is then used in protocol.send_fields() when sending SHOW output to
+ which is then used in protocol.send_result_set_metadata() when sending SHOW output to
the client.
*/
@@ -3128,6 +3153,6 @@ void mark_select_range_as_dependent(THD *thd,
extern Cached_item *new_Cached_item(THD *thd, Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item);
-extern int stored_field_cmp_to_item(Field *field, Item *item);
+extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item);
#endif /* ITEM_INCLUDED */
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c29031d25b5..c6b88cd8188 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -636,56 +636,51 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
return 0;
}
-
/**
- @brief Convert date provided in a string to the int representation.
-
- @param[in] thd thread handle
- @param[in] str a string to convert
- @param[in] warn_type type of the timestamp for issuing the warning
- @param[in] warn_name field name for issuing the warning
- @param[out] error_arg could not extract a DATE or DATETIME
-
- @details Convert date provided in the string str to the int
- representation. If the string contains wrong date or doesn't
- contain it at all then a warning is issued. The warn_type and
- the warn_name arguments are used as the name and the type of the
- field when issuing the warning. If any input was discarded
- (trailing or non-timestampy characters), was_cut will be non-zero.
- was_type will return the type str_to_datetime() could correctly
- extract.
-
- @return
- converted value. 0 on error and on zero-dates -- check 'failure'
+ Parse date provided in a string to a MYSQL_TIME.
+
+ @param[in] thd Thread handle
+ @param[in] str A string to convert
+ @param[in] warn_type Type of the timestamp for issuing the warning
+ @param[in] warn_name Field name for issuing the warning
+ @param[out] l_time The MYSQL_TIME objects is initialized.
+
+ Parses a date provided in the string str into a MYSQL_TIME object. If the
+ string contains an incorrect date or doesn't correspond to a date at all
+ then a warning is issued. The warn_type and the warn_name arguments are used
+ as the name and the type of the field when issuing the warning. If any input
+ was discarded (trailing or non-timestamp-y characters), return value will be
+ TRUE.
+
+ @return Status flag
+ @retval FALSE Success.
+ @retval True Indicates failure.
*/
-static ulonglong
-get_date_from_str(THD *thd, String *str, timestamp_type warn_type,
- char *warn_name, bool *error_arg)
+bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
+ const char *warn_name, MYSQL_TIME *l_time)
{
- ulonglong value= 0;
+ bool value;
int error;
- MYSQL_TIME l_time;
- enum_mysql_timestamp_type ret;
+ enum_mysql_timestamp_type timestamp_type;
- ret= str_to_datetime(str->ptr(), str->length(), &l_time,
- (TIME_FUZZY_DATE | MODE_INVALID_DATES |
- (thd->variables.sql_mode &
- (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))),
- &error);
+ timestamp_type=
+ str_to_datetime(str->ptr(), str->length(), l_time,
+ (TIME_FUZZY_DATE | MODE_INVALID_DATES |
+ (thd->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))),
+ &error);
- if (ret == MYSQL_TIMESTAMP_DATETIME || ret == MYSQL_TIMESTAMP_DATE)
- {
+ if (timestamp_type == MYSQL_TIMESTAMP_DATETIME ||
+ timestamp_type == MYSQL_TIMESTAMP_DATE)
/*
Do not return yet, we may still want to throw a "trailing garbage"
warning.
*/
- *error_arg= FALSE;
- value= TIME_to_ulonglong_datetime(&l_time);
- }
+ value= FALSE;
else
{
- *error_arg= TRUE;
+ value= TRUE;
error= 1; /* force warning */
}
@@ -698,6 +693,37 @@ get_date_from_str(THD *thd, String *str, timestamp_type warn_type,
}
+/**
+ @brief Convert date provided in a string to the int representation.
+
+ @param[in] thd thread handle
+ @param[in] str a string to convert
+ @param[in] warn_type type of the timestamp for issuing the warning
+ @param[in] warn_name field name for issuing the warning
+ @param[out] error_arg could not extract a DATE or DATETIME
+
+ @details Convert date provided in the string str to the int
+ representation. If the string contains wrong date or doesn't
+ contain it at all then a warning is issued. The warn_type and
+ the warn_name arguments are used as the name and the type of the
+ field when issuing the warning.
+
+ @return
+ converted value. 0 on error and on zero-dates -- check 'failure'
+*/
+static ulonglong get_date_from_str(THD *thd, String *str,
+ timestamp_type warn_type,
+ const char *warn_name, bool *error_arg)
+{
+ MYSQL_TIME l_time;
+ *error_arg= get_mysql_time_from_str(thd, str, warn_type, warn_name, &l_time);
+
+ if (*error_arg)
+ return 0;
+ return TIME_to_ulonglong_datetime(&l_time);
+}
+
+
/*
Check whether compare_datetime() can be used to compare items.
@@ -1559,61 +1585,73 @@ longlong Item_in_optimizer::val_int()
if (cache->null_value)
{
+ /*
+ We're evaluating
+ "<outer_value_list> [NOT] IN (SELECT <inner_value_list>...)"
+ where one or more of the outer values is NULL.
+ */
if (((Item_in_subselect*)args[1])->is_top_level_item())
{
/*
- We're evaluating "NULL IN (SELECT ...)". The result can be NULL or
- FALSE, and we can return one instead of another. Just return NULL.
+ We're evaluating a top level item, e.g.
+ "<outer_value_list> IN (SELECT <inner_value_list>...)",
+ and in this case a NULL value in the outer_value_list means
+ that the result shall be NULL/FALSE (makes no difference for
+ top level items). The cached value is NULL, so just return
+ NULL.
*/
null_value= 1;
}
else
{
- if (!((Item_in_subselect*)args[1])->is_correlated &&
- result_for_null_param != UNKNOWN)
+ /*
+ We're evaluating an item where a NULL value in either the
+ outer or inner value list does not automatically mean that we
+ can return NULL/FALSE. An example of such a query is
+ "<outer_value_list> NOT IN (SELECT <inner_value_list>...)"
+ The result when there is at least one NULL value is: NULL if the
+ SELECT evaluated over the non-NULL values produces at least
+ one row, FALSE otherwise
+ */
+ Item_in_subselect *item_subs=(Item_in_subselect*)args[1];
+ bool all_left_cols_null= true;
+ const uint ncols= cache->cols();
+
+ /*
+ Turn off the predicates that are based on column compares for
+ which the left part is currently NULL
+ */
+ for (uint i= 0; i < ncols; i++)
{
- /* Use cached value from previous execution */
- null_value= result_for_null_param;
+ if (cache->element_index(i)->null_value)
+ item_subs->set_cond_guard_var(i, FALSE);
+ else
+ all_left_cols_null= false;
}
- else
+
+ if (!((Item_in_subselect*)args[1])->is_correlated &&
+ all_left_cols_null && result_for_null_param != UNKNOWN)
{
- /*
- We're evaluating "NULL IN (SELECT ...)". The result is:
- FALSE if SELECT produces an empty set, or
- NULL otherwise.
- We disable the predicates we've pushed down into subselect, run the
- subselect and see if it has produced any rows.
+ /*
+ This is a non-correlated subquery, all values in the outer
+ value list are NULL, and we have already evaluated the
+ subquery for all NULL values: Return the same result we
+ did last time without evaluating the subquery.
*/
- Item_in_subselect *item_subs=(Item_in_subselect*)args[1];
- if (cache->cols() == 1)
- {
- item_subs->set_cond_guard_var(0, FALSE);
- (void) args[1]->val_bool_result();
- result_for_null_param= null_value= !item_subs->engine->no_rows();
- item_subs->set_cond_guard_var(0, TRUE);
- }
- else
- {
- uint i;
- uint ncols= cache->cols();
- /*
- Turn off the predicates that are based on column compares for
- which the left part is currently NULL
- */
- for (i= 0; i < ncols; i++)
- {
- if (cache->element_index(i)->null_value)
- item_subs->set_cond_guard_var(i, FALSE);
- }
-
- (void) args[1]->val_bool_result();
- result_for_null_param= null_value= !item_subs->engine->no_rows();
-
- /* Turn all predicates back on */
- for (i= 0; i < ncols; i++)
- item_subs->set_cond_guard_var(i, TRUE);
- }
+ null_value= result_for_null_param;
+ }
+ else
+ {
+ /* The subquery has to be evaluated */
+ (void) args[1]->val_bool_result();
+ null_value= !item_subs->engine->no_rows();
+ if (all_left_cols_null)
+ result_for_null_param= null_value;
}
+
+ /* Turn all predicates back on */
+ for (uint i= 0; i < ncols; i++)
+ item_subs->set_cond_guard_var(i, TRUE);
}
return 0;
}
@@ -2191,7 +2229,7 @@ uint Item_func_ifnull::decimal_precision() const
int arg1_int_part= args[1]->decimal_int_part();
int max_int_part= max(arg0_int_part, arg1_int_part);
int precision= max_int_part + decimals;
- return precision;
+ return min(precision, DECIMAL_MAX_PRECISION);
}
@@ -2375,7 +2413,7 @@ uint Item_func_if::decimal_precision() const
int arg1_prec= args[1]->decimal_int_part();
int arg2_prec= args[2]->decimal_int_part();
int precision=max(arg1_prec,arg2_prec) + decimals;
- return precision;
+ return min(precision, DECIMAL_MAX_PRECISION);
}
@@ -2783,7 +2821,7 @@ uint Item_func_case::decimal_precision() const
if (else_expr_num != -1)
set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
- return max_int_part + decimals;
+ return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 3462bed94a2..8354f6a5d30 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1725,4 +1725,7 @@ inline Item *and_conds(Item *a, Item *b)
Item *and_expressions(Item *a, Item *b, Item **org_item);
+bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
+ const char *warn_name, MYSQL_TIME *l_time);
+
#endif /* ITEM_CMPFUNC_INCLUDED */
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 2f80d16b928..070ab5263dd 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -2052,6 +2052,18 @@ protected:
virtual ~Create_func_to_days() {}
};
+class Create_func_to_seconds : public Create_func_arg1
+{
+public:
+ virtual Item* create(THD *thd, Item *arg1);
+
+ static Create_func_to_seconds s_singleton;
+
+protected:
+ Create_func_to_seconds() {}
+ virtual ~Create_func_to_seconds() {}
+};
+
#ifdef HAVE_SPATIAL
class Create_func_touches : public Create_func_arg2
@@ -4505,6 +4517,15 @@ Create_func_to_days::create(THD *thd, Item *arg1)
}
+Create_func_to_seconds Create_func_to_seconds::s_singleton;
+
+Item*
+Create_func_to_seconds::create(THD *thd, Item *arg1)
+{
+ return new (thd->mem_root) Item_func_to_seconds(arg1);
+}
+
+
#ifdef HAVE_SPATIAL
Create_func_touches Create_func_touches::s_singleton;
@@ -4942,6 +4963,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("TIME_TO_SEC") }, BUILDER(Create_func_time_to_sec)},
{ { C_STRING_WITH_LEN("TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
{ { C_STRING_WITH_LEN("TO_DAYS") }, BUILDER(Create_func_to_days)},
+ { { C_STRING_WITH_LEN("TO_SECONDS") }, BUILDER(Create_func_to_seconds)},
{ { C_STRING_WITH_LEN("UCASE") }, BUILDER(Create_func_ucase)},
{ { C_STRING_WITH_LEN("UNCOMPRESS") }, BUILDER(Create_func_uncompress)},
{ { C_STRING_WITH_LEN("UNCOMPRESSED_LENGTH") }, BUILDER(Create_func_uncompressed_length)},
@@ -4985,14 +5007,14 @@ int item_create_init()
DBUG_ENTER("item_create_init");
- if (hash_init(& native_functions_hash,
- system_charset_info,
- array_elements(func_array),
- 0,
- 0,
- (hash_get_key) get_native_fct_hash_key,
- NULL, /* Nothing to free */
- MYF(0)))
+ if (my_hash_init(& native_functions_hash,
+ system_charset_info,
+ array_elements(func_array),
+ 0,
+ 0,
+ (my_hash_get_key) get_native_fct_hash_key,
+ NULL, /* Nothing to free */
+ MYF(0)))
DBUG_RETURN(1);
for (func= func_array; func->builder != NULL; func++)
@@ -5004,7 +5026,7 @@ int item_create_init()
#ifndef DBUG_OFF
for (uint i=0 ; i < native_functions_hash.records ; i++)
{
- func= (Native_func_registry*) hash_element(& native_functions_hash, i);
+ func= (Native_func_registry*) my_hash_element(& native_functions_hash, i);
DBUG_PRINT("info", ("native function: %s length: %u",
func->name.str, (uint) func->name.length));
}
@@ -5022,7 +5044,7 @@ int item_create_init()
void item_create_cleanup()
{
DBUG_ENTER("item_create_cleanup");
- hash_free(& native_functions_hash);
+ my_hash_free(& native_functions_hash);
DBUG_VOID_RETURN;
}
@@ -5033,9 +5055,9 @@ find_native_function_builder(THD *thd, LEX_STRING name)
Create_func *builder= NULL;
/* Thread safe */
- func= (Native_func_registry*) hash_search(& native_functions_hash,
- (uchar*) name.str,
- name.length);
+ func= (Native_func_registry*) my_hash_search(& native_functions_hash,
+ (uchar*) name.str,
+ name.length);
if (func)
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index c0d5fc6480d..23af528c256 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -451,8 +451,45 @@ Field *Item_func::tmp_table_field(TABLE *table)
return make_string_field(table);
break;
case DECIMAL_RESULT:
- field= Field_new_decimal::new_decimal_field(this);
+ {
+ uint8 dec= decimals;
+ uint8 intg= decimal_precision() - dec;
+ uint32 len= max_length;
+
+ /*
+ Trying to put too many digits overall in a DECIMAL(prec,dec)
+ will always throw a warning. We must limit dec to
+ DECIMAL_MAX_SCALE however to prevent an assert() later.
+ */
+
+ if (dec > 0)
+ {
+ int overflow;
+
+ dec= min(dec, DECIMAL_MAX_SCALE);
+
+ /*
+ If the value still overflows the field with the corrected dec,
+ we'll throw out decimals rather than integers. This is still
+ bad and of course throws a truncation warning.
+ */
+
+ const int required_length=
+ my_decimal_precision_to_length(intg + dec, dec,
+ unsigned_flag);
+
+ overflow= required_length - len;
+
+ if (overflow > 0)
+ dec= max(0, dec - overflow); // too long, discard fract
+ else
+ /* Corrected value fits. */
+ len= required_length;
+ }
+
+ field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag);
break;
+ }
case ROW_RESULT:
default:
// This case should never be chosen
@@ -3283,7 +3320,7 @@ public:
{
if (key)
{
- hash_delete(&hash_user_locks,(uchar*) this);
+ my_hash_delete(&hash_user_locks,(uchar*) this);
my_free(key, MYF(0));
}
pthread_cond_destroy(&cond);
@@ -3307,8 +3344,8 @@ static bool item_user_lock_inited= 0;
void item_user_lock_init(void)
{
pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
- hash_init(&hash_user_locks,system_charset_info,
- 16,0,0,(hash_get_key) ull_get_key,NULL,0);
+ my_hash_init(&hash_user_locks,system_charset_info,
+ 16,0,0,(my_hash_get_key) ull_get_key,NULL,0);
item_user_lock_inited= 1;
}
@@ -3317,7 +3354,7 @@ void item_user_lock_free(void)
if (item_user_lock_inited)
{
item_user_lock_inited= 0;
- hash_free(&hash_user_locks);
+ my_hash_free(&hash_user_locks);
pthread_mutex_destroy(&LOCK_user_locks);
}
}
@@ -3384,9 +3421,9 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
this case, we will not be waiting, but rather, just waste CPU and
memory on the whole deal
*/
- if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
- (uchar*) lock_name,
- lock_name_len))))
+ if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks,
+ (uchar*) lock_name,
+ lock_name_len))))
{
pthread_mutex_unlock(&LOCK_user_locks);
return;
@@ -3487,9 +3524,9 @@ longlong Item_func_get_lock::val_int()
thd->ull=0;
}
- if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks,
- (uchar*) res->ptr(),
- (size_t) res->length()))))
+ if (!(ull= ((User_level_lock *) my_hash_search(&hash_user_locks,
+ (uchar*) res->ptr(),
+ (size_t) res->length()))))
{
ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(),
thd->thread_id);
@@ -3591,9 +3628,9 @@ longlong Item_func_release_lock::val_int()
result=0;
pthread_mutex_lock(&LOCK_user_locks);
- if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
- (const uchar*) res->ptr(),
- (size_t) res->length()))))
+ if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks,
+ (const uchar*) res->ptr(),
+ (size_t) res->length()))))
{
null_value=1;
}
@@ -3773,12 +3810,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
{
user_var_entry *entry;
- if (!(entry = (user_var_entry*) hash_search(hash, (uchar*) name.str,
- name.length)) &&
+ if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name.str,
+ name.length)) &&
create_if_not_exists)
{
uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
- if (!hash_inited(hash))
+ if (!my_hash_inited(hash))
return 0;
if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
return 0;
@@ -4739,19 +4776,6 @@ void Item_func_get_user_var::fix_length_and_dec()
}
-uint Item_func_get_user_var::decimal_precision() const
-{
- uint precision= max_length;
- Item_result restype= result_type();
-
- /* Default to maximum as the precision is unknown a priori. */
- if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
- precision= DECIMAL_MAX_PRECISION;
-
- return precision;
-}
-
-
bool Item_func_get_user_var::const_item() const
{
return (!var_entry || current_thd->query_id != var_entry->update_query_id);
@@ -5707,8 +5731,8 @@ longlong Item_func_is_free_lock::val_int()
}
pthread_mutex_lock(&LOCK_user_locks);
- ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(),
- (size_t) res->length());
+ ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
+ (size_t) res->length());
pthread_mutex_unlock(&LOCK_user_locks);
if (!ull || !ull->locked)
return 1;
@@ -5726,8 +5750,8 @@ longlong Item_func_is_used_lock::val_int()
return 0;
pthread_mutex_lock(&LOCK_user_locks);
- ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(),
- (size_t) res->length());
+ ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
+ (size_t) res->length());
pthread_mutex_unlock(&LOCK_user_locks);
if (!ull || !ull->locked)
return 0;
diff --git a/sql/item_func.h b/sql/item_func.h
index 628878bcaed..6f2b3f0bfc2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1396,7 +1396,6 @@ public:
table_map used_tables() const
{ return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
- uint decimal_precision() const;
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index a34204b7181..3c5990eb359 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -84,7 +84,9 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY)
{
- return args[0]->val_str(str);
+ String *str_ret= args[0]->val_str(str);
+ null_value= args[0]->null_value;
+ return str_ret;
}
wkb= args[0]->val_str(&arg_val);
@@ -94,7 +96,10 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
str->set_charset(&my_charset_bin);
if (str->reserve(SRID_SIZE, 512))
- return 0;
+ {
+ null_value= TRUE; /* purecov: inspected */
+ return 0; /* purecov: inspected */
+ }
str->length(0);
str->q_append(srid);
if ((null_value=
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index da651cec70c..0ce9c555fea 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -311,9 +311,14 @@ void Item_subselect::update_used_tables()
void Item_subselect::print(String *str, enum_query_type query_type)
{
- str->append('(');
- engine->print(str, query_type);
- str->append(')');
+ if (engine)
+ {
+ str->append('(');
+ engine->print(str, query_type);
+ str->append(')');
+ }
+ else
+ str->append("(...)");
}
@@ -1863,7 +1868,8 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
DBUG_ASSERT(0);
}
-int init_read_record_seq(JOIN_TAB *tab);
+int read_first_record_seq(JOIN_TAB *tab);
+int rr_sequential(READ_RECORD *info);
int join_read_always_key_or_null(JOIN_TAB *tab);
int join_read_next_same_or_null(READ_RECORD *info);
@@ -1945,10 +1951,12 @@ int subselect_single_select_engine::exec()
/* Change the access method to full table scan */
tab->save_read_first_record= tab->read_first_record;
tab->save_read_record= tab->read_record.read_record;
- tab->read_first_record= init_read_record_seq;
+ tab->read_record.read_record= rr_sequential;
+ tab->read_first_record= read_first_record_seq;
tab->read_record.record= tab->table->record[0];
tab->read_record.thd= join->thd;
tab->read_record.ref_length= tab->table->file->ref_length;
+ tab->read_record.unlock_row= rr_unlock_row;
*(last_changed_tab++)= tab;
break;
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 273e996a6a0..f72b64fc66e 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -29,6 +29,18 @@
#include "sql_select.h"
/**
+ Calculate the affordable RAM limit for structures like TREE or Unique
+ used in Item_sum_*
+*/
+
+ulonglong Item_sum::ram_limitation(THD *thd)
+{
+ return min(thd->variables.tmp_table_size,
+ thd->variables.max_heap_table_size);
+}
+
+
+/**
Prepare an aggregate function item for checking context conditions.
The function initializes the members of the Item_sum object created
@@ -522,7 +534,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
name, table->s, collation.collation);
break;
case DECIMAL_RESULT:
- field= Field_new_decimal::new_decimal_field(this);
+ field= new Field_new_decimal(max_length, maybe_null, name,
+ decimals, unsigned_flag);
break;
case ROW_RESULT:
default:
@@ -832,7 +845,7 @@ bool Aggregator_distinct::setup(THD *thd)
}
DBUG_ASSERT(tree == 0);
tree= new Unique(compare_key, cmp_arg, tree_key_length,
- thd->variables.max_heap_table_size);
+ item_sum->ram_limitation(thd));
/*
The only time tree_key_length could be 0 is if someone does
count(distinct) on a char(0) field - stupid thing to do,
@@ -901,7 +914,7 @@ bool Aggregator_distinct::setup(THD *thd)
are converted to binary representation as well.
*/
tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
- thd->variables.max_heap_table_size);
+ item_sum->ram_limitation(thd));
DBUG_RETURN(tree == 0);
}
@@ -3513,7 +3526,7 @@ bool Item_func_group_concat::setup(THD *thd)
unique_filter= new Unique(group_concat_key_cmp_with_distinct,
(void*)this,
tree_key_length,
- thd->variables.max_heap_table_size);
+ ram_limitation(thd));
DBUG_RETURN(FALSE);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 6d7418204fc..9e062ce1d16 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -364,6 +364,7 @@ protected:
Item **orig_args, *tmp_orig_args[2];
table_map used_tables_cache;
bool forced_const;
+ static ulonglong ram_limitation(THD *thd);
public:
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index eefc8429f5e..84ddc88487d 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -936,6 +936,48 @@ longlong Item_func_to_days::val_int()
}
+longlong Item_func_to_seconds::val_int_endpoint(bool left_endp,
+ bool *incl_endp)
+{
+ DBUG_ASSERT(fixed == 1);
+ MYSQL_TIME ltime;
+ longlong seconds;
+ longlong days;
+ int dummy; /* unused */
+ if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
+ {
+ /* got NULL, leave the incl_endp intact */
+ return LONGLONG_MIN;
+ }
+ seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
+ seconds= ltime.neg ? -seconds : seconds;
+ days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day);
+ seconds+= days * 24L * 3600L;
+ /* Set to NULL if invalid date, but keep the value */
+ null_value= check_date(&ltime,
+ (ltime.year || ltime.month || ltime.day),
+ (TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE),
+ &dummy);
+ /*
+ Even if the evaluation return NULL, seconds is useful for pruning
+ */
+ return seconds;
+}
+
+longlong Item_func_to_seconds::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ MYSQL_TIME ltime;
+ longlong seconds;
+ longlong days;
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
+ return 0;
+ seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
+ seconds=ltime.neg ? -seconds : seconds;
+ days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day);
+ return seconds + days * 24L * 3600L;
+}
+
/*
Get information about this Item tree monotonicity
@@ -962,6 +1004,17 @@ enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
return NON_MONOTONIC;
}
+enum_monotonicity_info Item_func_to_seconds::get_monotonicity_info() const
+{
+ if (args[0]->type() == Item::FIELD_ITEM)
+ {
+ if (args[0]->field_type() == MYSQL_TYPE_DATE ||
+ args[0]->field_type() == MYSQL_TYPE_DATETIME)
+ return MONOTONIC_STRICT_INCREASING_NOT_NULL;
+ }
+ return NON_MONOTONIC;
+}
+
longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
{
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 05e8d899472..cdd74c8c601 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -76,6 +76,24 @@ public:
};
+class Item_func_to_seconds :public Item_int_func
+{
+public:
+ Item_func_to_seconds(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "to_seconds"; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ }
+ enum_monotonicity_info get_monotonicity_info() const;
+ longlong val_int_endpoint(bool left_endp, bool *incl_endp);
+ bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+};
+
+
class Item_func_dayofmonth :public Item_int_func
{
public:
diff --git a/sql/lock.cc b/sql/lock.cc
index 93d8b868688..c0cda1dbf03 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -1029,11 +1029,11 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
if (check_in_use)
{
/* Only insert the table if we haven't insert it already */
- for (table=(TABLE*) hash_first(&open_cache, (uchar*)key,
- key_length, &state);
+ for (table=(TABLE*) my_hash_first(&open_cache, (uchar*)key,
+ key_length, &state);
table ;
- table = (TABLE*) hash_next(&open_cache,(uchar*) key,
- key_length, &state))
+ table = (TABLE*) my_hash_next(&open_cache,(uchar*) key,
+ key_length, &state))
{
if (table->in_use == thd)
{
@@ -1060,7 +1060,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list)
{
if (table_list->table)
{
- hash_delete(&open_cache, (uchar*) table_list->table);
+ my_hash_delete(&open_cache, (uchar*) table_list->table);
broadcast_refresh();
}
}
@@ -1235,11 +1235,11 @@ is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
HASH_SEARCH_STATE state;
TABLE *table;
- for (table= (TABLE*) hash_first(&open_cache, key,
- key_length, &state);
+ for (table= (TABLE*) my_hash_first(&open_cache, key,
+ key_length, &state);
table ;
- table= (TABLE*) hash_next(&open_cache, key,
- key_length, &state))
+ table= (TABLE*) my_hash_next(&open_cache, key,
+ key_length, &state))
{
if (table->in_use == thd &&
table->open_placeholder == 1 &&
diff --git a/sql/log.cc b/sql/log.cc
index 4f5230b82cc..e7deebad196 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -110,9 +110,16 @@ sql_print_message_func sql_print_message_handlers[3] =
};
+/**
+ Create the name of the default general log file
+
+ @param[IN] buff Location for building new string.
+ @param[IN] log_ext The extension for the file (e.g .log)
+ @returns Pointer to a new string containing the name
+*/
char *make_default_log_name(char *buff,const char* log_ext)
{
- strmake(buff, pidfile_name, FN_REFLEN-5);
+ strmake(buff, default_logfile_name, FN_REFLEN-5);
return fn_format(buff, buff, mysql_data_home, log_ext,
MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
}
@@ -1555,7 +1562,6 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
trx_data->at_least_one_stmt_committed = my_b_tell(&trx_data->trans_log) > 0;
-end:
if (!all)
trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit
DBUG_RETURN(error);
@@ -1723,7 +1729,7 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv)
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
int const error=
thd->binlog_query(THD::STMT_QUERY_TYPE,
- thd->query, thd->query_length, TRUE, FALSE, errcode);
+ thd->query(), thd->query_length(), TRUE, FALSE, errcode);
DBUG_RETURN(error);
}
@@ -1742,7 +1748,7 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
int error=
thd->binlog_query(THD::STMT_QUERY_TYPE,
- thd->query, thd->query_length, TRUE, FALSE, errcode);
+ thd->query(), thd->query_length(), TRUE, FALSE, errcode);
DBUG_RETURN(error);
}
binlog_trans_log_truncate(thd, *(my_off_t*)sv);
@@ -3610,7 +3616,7 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
}
old_name=name;
name=0; // Don't free name
- close(LOG_CLOSE_TO_BE_OPENED);
+ close(LOG_CLOSE_TO_BE_OPENED | LOG_CLOSE_INDEX);
/*
Note that at this point, log_state != LOG_CLOSED (important for is_open()).
@@ -3625,8 +3631,10 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
trigger temp tables deletion on slaves.
*/
- open(old_name, log_type, new_name_ptr,
- io_cache_type, no_auto_events, max_size, 1);
+ /* reopen index binlog file, BUG#34582 */
+ if (!open_index_file(index_file_name, 0))
+ open(old_name, log_type, new_name_ptr,
+ io_cache_type, no_auto_events, max_size, 1);
my_free(old_name,MYF(0));
end:
@@ -5493,8 +5501,8 @@ int TC_LOG_MMAP::recover()
goto err1;
}
- if (hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0,
- sizeof(my_xid), 0, 0, MYF(0)))
+ if (my_hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0,
+ sizeof(my_xid), 0, 0, MYF(0)))
goto err1;
for ( ; p < end_p ; p++)
@@ -5507,12 +5515,12 @@ int TC_LOG_MMAP::recover()
if (ha_recover(&xids))
goto err2;
- hash_free(&xids);
+ my_hash_free(&xids);
bzero(data, (size_t)file_length);
return 0;
err2:
- hash_free(&xids);
+ my_hash_free(&xids);
err1:
sql_print_error("Crash recovery failed. Either correct the problem "
"(if it's, for example, out of memory error) and restart, "
@@ -5696,8 +5704,8 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
MEM_ROOT mem_root;
if (! fdle->is_valid() ||
- hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
- sizeof(my_xid), 0, 0, MYF(0)))
+ my_hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
+ sizeof(my_xid), 0, 0, MYF(0)))
goto err1;
init_alloc_root(&mem_root, TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE);
@@ -5722,12 +5730,12 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
goto err2;
free_root(&mem_root, MYF(0));
- hash_free(&xids);
+ my_hash_free(&xids);
return 0;
err2:
free_root(&mem_root, MYF(0));
- hash_free(&xids);
+ my_hash_free(&xids);
err1:
sql_print_error("Crash recovery failed. Either correct the problem "
"(if it's, for example, out of memory error) and restart, "
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 10a1ee431b4..3a54717a45f 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1200,14 +1200,14 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
*/
if (description_event->event_type_permutation)
{
- IF_DBUG({
- int new_event_type=
- description_event->event_type_permutation[event_type];
- DBUG_PRINT("info",
- ("converting event type %d to %d (%s)",
- event_type, new_event_type,
- get_type_str((Log_event_type)new_event_type)));
- });
+#ifndef DBUG_OFF
+ int new_event_type=
+ description_event->event_type_permutation[event_type];
+ DBUG_PRINT("info",
+ ("converting event type %d to %d (%s)",
+ event_type, new_event_type,
+ get_type_str((Log_event_type)new_event_type)));
+#endif
event_type= description_event->event_type_permutation[event_type];
}
@@ -3060,7 +3060,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
thd->query_id = next_query_id();
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->variables.pseudo_thread_id= thread_id; // for temp tables
- DBUG_PRINT("query",("%s",thd->query));
+ DBUG_PRINT("query",("%s", thd->query()));
if (ignored_error_code((expected_error= error_code)) ||
!unexpected_error_code(expected_error))
@@ -3154,7 +3154,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
/* Execute the query (note that we bypass dispatch_command()) */
const char* found_semicolon= NULL;
- mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
+ mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon);
log_slow_statement(thd);
}
else
@@ -3166,7 +3166,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
we exit gracefully; otherwise we warn about the bad error and tell DBA
to check/fix it.
*/
- if (mysql_test_parse_for_slave(thd, thd->query, thd->query_length))
+ if (mysql_test_parse_for_slave(thd, thd->query(), thd->query_length()))
clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); /* Can ignore query */
else
{
@@ -3176,7 +3176,7 @@ Query partially completed on the master (error on master: %d) \
and was aborted. There is a chance that your master is inconsistent at this \
point. If you are sure that your master is ok, run this query manually on the \
slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \
-START SLAVE; . Query: '%s'", expected_error, thd->query);
+START SLAVE; . Query: '%s'", expected_error, thd->query());
thd->is_slave_error= 1;
}
goto end;
@@ -3184,7 +3184,7 @@ START SLAVE; . Query: '%s'", expected_error, thd->query);
/* If the query was not ignored, it is printed to the general log */
if (!thd->is_error() || thd->stmt_da->sql_errno() != ER_SLAVE_IGNORED_TABLE)
- general_log_write(thd, COM_QUERY, thd->query, thd->query_length);
+ general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
compare_errors:
@@ -3609,10 +3609,12 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
*/
if (post_header_len)
{
+#ifndef DBUG_OFF
// Allows us to sanity-check that all events initialized their
// events (see the end of this 'if' block).
- IF_DBUG(memset(post_header_len, 255,
- number_of_event_types*sizeof(uint8)););
+ memset(post_header_len, 255,
+ number_of_event_types*sizeof(uint8));
+#endif
/* Note: all event types must explicitly fill in their lengths here. */
post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
@@ -3666,11 +3668,9 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
post_header_len[HEARTBEAT_LOG_EVENT-1]= 0;
// Sanity-check that all post header lengths are initialized.
- IF_DBUG({
- int i;
- for (i=0; i<number_of_event_types; i++)
- assert(post_header_len[i] != 255);
- });
+ int i;
+ for (i=0; i<number_of_event_types; i++)
+ DBUG_ASSERT(post_header_len[i] != 255);
}
break;
@@ -4531,8 +4531,8 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
new_db.length= db_len;
new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length);
thd->set_db(new_db.str, new_db.length);
- DBUG_ASSERT(thd->query == 0);
- thd->query_length= 0; // Should not be needed
+ DBUG_ASSERT(thd->query() == 0);
+ thd->set_query_inner(NULL, 0); // Should not be needed
thd->is_slave_error= 0;
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
@@ -7550,7 +7550,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
}
if (get_flags(STMT_END_F))
- if (error= rows_event_stmt_cleanup(rli, thd))
+ if ((error= rows_event_stmt_cleanup(rli, thd)))
rli->report(ERROR_LEVEL, error,
"Error in %s event: commit of row events failed, "
"table `%s`.`%s`",
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index e6888af9cfc..fbcbb388236 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -1814,7 +1814,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
are involved, commit the transaction and flush the pending event to the
binlog.
*/
- if (error= ha_autocommit_or_rollback(thd, 0))
+ if ((error= ha_autocommit_or_rollback(thd, 0)))
rli->report(ERROR_LEVEL, error,
"Error in %s event: commit of row events failed, "
"table `%s`.`%s`",
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index b1df1395dcd..21669e82c44 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -48,12 +48,10 @@ C_MODE_END
digits * number of decimal digits in one our big digit - number of decimal
digits in one our big digit decreased by 1 (because we always put decimal
point on the border of our big digits))
-
- This value is 65 due to historical reasons partly due to it being used
- as the maximum allowed precision and not the actual maximum precision.
*/
#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
#define DECIMAL_MAX_SCALE 30
+#define DECIMAL_NOT_SPECIFIED 31
/**
maximum length of string representation (number of maximum decimal
@@ -77,6 +75,12 @@ inline uint my_decimal_size(uint precision, uint scale)
}
+inline int my_decimal_int_part(uint precision, uint decimals)
+{
+ return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
+}
+
+
/**
my_decimal class limits 'decimal_t' type to what we need in MySQL.
@@ -180,7 +184,7 @@ inline uint my_decimal_length_to_precision(uint length, uint scale,
}
inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
- uint scale,
+ uint8 scale,
bool unsigned_flag)
{
/*
@@ -192,7 +196,7 @@ inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
(unsigned_flag || !precision ? 0 : 1));
}
-inline uint32 my_decimal_precision_to_length(uint precision, uint scale,
+inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
bool unsigned_flag)
{
/*
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b95e5e50f5a..3cb26c30e13 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -28,6 +28,16 @@
#ifndef MYSQL_CLIENT
+/*
+ the following #define adds server-only members to enum_mysql_show_type,
+ that is defined in mysql/plugin.h
+ it has to be before mysql/plugin.h is included.
+*/
+#define SHOW_always_last SHOW_KEY_CACHE_LONG, \
+ SHOW_KEY_CACHE_LONGLONG, SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, \
+ SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \
+ SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS
+
#include <my_global.h>
#include <mysql_version.h>
#include <mysql_embed.h>
@@ -295,7 +305,7 @@ protected:
#define TABLE_OPEN_CACHE_DEFAULT 400
#define TABLE_DEF_CACHE_DEFAULT 400
/**
- We must have room for at least 256 table definitions in the table
+ We must have room for at least 400 table definitions in the table
cache, since otherwise there is no chance prepared
statements that use these many tables can work.
Prepared statements use table definition cache ids (table_map_id)
@@ -662,7 +672,6 @@ enum enum_parsing_place
IN_ON
};
-struct st_table;
#define thd_proc_info(thd, msg) set_thd_proc_info(thd, msg, __func__, __FILE__, __LINE__)
class THD;
@@ -902,6 +911,7 @@ bool general_log_write(THD *thd, enum enum_server_command command,
#include "tztime.h"
#ifdef MYSQL_SERVER
#include "sql_servers.h"
+#include "records.h"
#include "opt_range.h"
#ifdef HAVE_QUERY_CACHE
@@ -909,7 +919,7 @@ struct Query_cache_query_flags
{
unsigned int client_long_flag:1;
unsigned int client_protocol_41:1;
- unsigned int result_in_binary_protocol:1;
+ unsigned int protocol_type:2;
unsigned int more_results_exists:1;
unsigned int in_trans:1;
unsigned int autocommit:1;
@@ -928,6 +938,8 @@ struct Query_cache_query_flags
};
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
#include "sql_cache.h"
+#define query_cache_abort(A) query_cache.abort(A)
+#define query_cache_end_of_result(A) query_cache.end_of_result(A)
#define query_cache_store_query(A, B) query_cache.store_query(A, B)
#define query_cache_destroy() query_cache.destroy()
#define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
@@ -1049,9 +1061,11 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
- bool no_grant, bool no_errors, bool schema_db);
-bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
- uint number, bool no_errors);
+ bool no_grant, bool no_errors, bool schema_db);
+bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
+ bool any_combination_of_privileges_will_do,
+ uint number,
+ bool no_errors);
#else
inline bool check_access(THD *thd, ulong access, const char *db,
ulong *save_priv, bool no_grant, bool no_errors,
@@ -1061,8 +1075,10 @@ inline bool check_access(THD *thd, ulong access, const char *db,
*save_priv= GLOBAL_ACLS;
return false;
}
-inline bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
- uint number, bool no_errors)
+inline bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
+ bool no_errors,
+ bool any_combination_of_privileges_will_do,
+ uint number)
{ return false; }
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
@@ -1155,6 +1171,8 @@ int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
int *timestamps, int *timestamps_with_niladic,
longlong table_flags);
+CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+ HA_CREATE_INFO *create_info);
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
@@ -1326,7 +1344,6 @@ void remove_status_vars(SHOW_VAR *list);
void init_status_vars();
void free_status_vars();
void reset_status_vars();
-
/* information schema */
extern LEX_STRING INFORMATION_SCHEMA_NAME;
/* log tables */
@@ -1353,19 +1370,6 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
#define is_schema_db(X) \
!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, (X))
-/* sql_prepare.cc */
-
-void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length);
-void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length);
-void mysqld_stmt_close(THD *thd, char *packet);
-void mysql_sql_stmt_prepare(THD *thd);
-void mysql_sql_stmt_execute(THD *thd);
-void mysql_sql_stmt_close(THD *thd);
-void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length);
-void mysqld_stmt_reset(THD *thd, char *packet);
-void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
-void reinit_stmt_before_use(THD *thd, LEX *lex);
-
/* sql_handler.cc */
bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen);
bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
@@ -1544,6 +1548,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
handlerton *old_db_type,
bool *partition_changed,
uint *fast_alter_partition);
+char *generate_partition_syntax(partition_info *part_info,
+ uint *buf_length, bool use_sql_alloc,
+ bool show_partition_options,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info);
#endif
/* bits for last argument to remove_table_from_cache() */
@@ -1865,6 +1874,7 @@ extern MYSQL_PLUGIN_IMPORT uint reg_ext_length;
#ifdef MYSQL_SERVER
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
+extern char default_logfile_name[FN_REFLEN];
extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
extern ulonglong log_10_int[20];
extern ulonglong keybuff_size;
@@ -2015,7 +2025,7 @@ extern uint sql_command_flags[];
extern TYPELIB log_output_typelib;
/* optional things, have_* variables */
-extern SHOW_COMP_OPTION have_community_features;
+extern SHOW_COMP_OPTION have_profiling;
extern handlerton *partition_hton;
extern handlerton *myisam_hton;
@@ -2166,12 +2176,6 @@ longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(uchar *,uint,char,char);
-void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
- SQL_SELECT *select, int use_record_cache,
- bool print_errors, bool disable_rr_cache);
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
- bool print_error, uint idx);
-void end_read_record(READ_RECORD *info);
ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
uint s_length, SQL_SELECT *select,
ha_rows max_rows, bool sort_positions,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c432b3d9e0a..3a3eee9737d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -582,6 +582,7 @@ const char *log_output_str= "FILE";
time_t server_start_time, flush_status_time;
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
+char default_logfile_name[FN_REFLEN];
char *default_tz_name;
char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
char mysql_real_data_home[FN_REFLEN],
@@ -647,7 +648,7 @@ MY_LOCALE *my_default_lc_time_names;
SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
SHOW_COMP_OPTION have_geometry, have_rtree_keys;
SHOW_COMP_OPTION have_crypt, have_compress;
-SHOW_COMP_OPTION have_community_features;
+SHOW_COMP_OPTION have_profiling;
/* Thread specific variables */
@@ -2525,7 +2526,7 @@ terribly wrong...\n");
}
fprintf(stderr, "Trying to get some variables.\n\
Some pointers may be invalid and cause the dump to abort...\n");
- my_safe_print_str("thd->query", thd->query, 1024);
+ my_safe_print_str("thd->query", thd->query(), 1024);
fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id);
fprintf(stderr, "thd->killed=%s\n", kreason);
}
@@ -3195,10 +3196,13 @@ static int init_common_variables(const char *conf_file_name, int argc,
strmake(glob_hostname, STRING_WITH_LEN("localhost"));
sql_print_warning("gethostname failed, using '%s' as hostname",
glob_hostname);
- strmake(pidfile_name, STRING_WITH_LEN("mysql"));
+ strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
}
else
- strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
+ strmake(default_logfile_name, glob_hostname,
+ sizeof(default_logfile_name)-5);
+
+ strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name)-5);
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
/*
@@ -3238,7 +3242,8 @@ static int init_common_variables(const char *conf_file_name, int argc,
orig_argc=argc;
orig_argv=argv;
- load_defaults(conf_file_name, groups, &argc, &argv);
+ if (load_defaults(conf_file_name, groups, &argc, &argv))
+ return 1;
defaults_argv=argv;
defaults_argc=argc;
if (get_options(&defaults_argc, defaults_argv))
@@ -3484,7 +3489,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
&& !(log_output_options & LOG_NONE))
sql_print_warning("Although a path was specified for the "
- "--log_slow_queries option, log tables are used. "
+ "--log-slow-queries option, log tables are used. "
"To enable logging to files use the --log-output=file option.");
s= opt_logname ? opt_logname : make_default_log_name(buff, ".log");
@@ -4943,9 +4948,6 @@ static void create_new_thread(THD *thd)
NET *net=&thd->net;
DBUG_ENTER("create_new_thread");
- if (protocol_version > 9)
- net->return_errno=1;
-
/*
Don't allow too many connections. We roughly check here that we allow
only (max_connections + 1) connections.
@@ -5871,10 +5873,6 @@ struct my_option my_long_options[] =
"Set the default storage engine (table type) for tables.",
(uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"default-table-type", OPT_STORAGE_ENGINE,
- "(deprecated) Use --default-storage-engine.",
- (uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.",
(uchar**) &default_tz_name, (uchar**) &default_tz_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
@@ -6063,14 +6061,14 @@ Disable with --skip-super-large-pages.",
(uchar**) &opt_log_slow_slave_statements,
(uchar**) &opt_log_slow_slave_statements,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"log_slow_queries", OPT_SLOW_QUERY_LOG,
- "Log slow queries to a table or log file. Defaults logging to table "
- "mysql.slow_log or hostname-slow.log if --log-output=file is used. "
- "Must be enabled to activate other slow log options. "
- "(deprecated option, use --slow_query_log/--slow_query_log_file instead)",
+ {"log-slow-queries", OPT_SLOW_QUERY_LOG,
+ "Log slow queries to a table or log file. Defaults logging to table "
+ "mysql.slow_log or hostname-slow.log if --log-output=file is used. "
+ "Must be enabled to activate other slow log options. "
+ "Deprecated option, use --slow-query-log/--slow-query-log-file instead.",
(uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
- {"slow_query_log_file", OPT_SLOW_QUERY_LOG_FILE,
+ {"slow-query-log-file", OPT_SLOW_QUERY_LOG_FILE,
"Log slow queries to given log file. Defaults logging to hostname-slow.log. Must be enabled to activate other slow log options.",
(uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -6308,7 +6306,7 @@ master-ssl",
"Maximum time in seconds to wait for the port to become free. "
"(Default: no wait)", (uchar**) &mysqld_port_timeout,
(uchar**) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
{"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory",
(uchar**) &global_system_variables.profiling_history_size,
(uchar**) &max_system_variables.profiling_history_size,
@@ -6791,7 +6789,7 @@ The minimum value for this variable is 4096.",
(uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG,
REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0},
{"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
- "Don't log queries which examine less than min_examined_row_limit rows to file.",
+ "Don't write queries to slow log that examine fewer than min_examined_row_limit rows.",
(uchar**) &global_system_variables.min_examined_row_limit,
(uchar**) &max_system_variables.min_examined_row_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0},
@@ -7136,7 +7134,7 @@ static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
return 0;
}
-#ifdef COMMUNITY_SERVER
+#ifdef ENABLED_PROFILING
static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
{
var->type= SHOW_LONG;
@@ -7631,7 +7629,7 @@ SHOW_VAR status_vars[]= {
{"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH},
{"Threads_running", (char*) &thread_running, SHOW_INT},
{"Uptime", (char*) &show_starttime, SHOW_FUNC},
-#ifdef COMMUNITY_SERVER
+#ifdef ENABLED_PROFILING
{"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC},
#endif
{NullS, NullS, SHOW_LONG}
@@ -7863,10 +7861,10 @@ static int mysql_init_variables(void)
"d:t:i:o,/tmp/mysqld.trace");
#endif
opt_error_log= IF_WIN(1,0);
-#ifdef COMMUNITY_SERVER
- have_community_features = SHOW_OPTION_YES;
+#ifdef ENABLED_PROFILING
+ have_profiling = SHOW_OPTION_YES;
#else
- have_community_features = SHOW_OPTION_NO;
+ have_profiling = SHOW_OPTION_NO;
#endif
global_system_variables.ndb_index_stat_enable=FALSE;
max_system_variables.ndb_index_stat_enable=TRUE;
@@ -7984,7 +7982,7 @@ mysqld_get_one_option(int optid,
default_collation_name= 0;
break;
case 'l':
- WARN_DEPRECATED(NULL, "7.0", "--log", "'--general_log'/'--general_log_file'");
+ WARN_DEPRECATED(NULL, "7.0", "--log", "'--general-log'/'--general-log-file'");
opt_log=1;
break;
case 'h':
@@ -8158,7 +8156,8 @@ mysqld_get_one_option(int optid,
}
#endif /* HAVE_REPLICATION */
case (int) OPT_SLOW_QUERY_LOG:
- WARN_DEPRECATED(NULL, "7.0", "--log_slow_queries", "'--slow_query_log'/'--slow_query_log_file'");
+ WARN_DEPRECATED(NULL, "7.0", "--log-slow-queries",
+ "'--slow-query-log'/'--slow-query-log-file'");
opt_slow_log= 1;
break;
#ifdef WITH_CSV_STORAGE_ENGINE
@@ -8986,9 +8985,7 @@ void refresh_status(THD *thd)
/* Reset the counters of all key caches (default and named). */
process_key_caches(reset_key_cache_counters);
-#ifdef COMMUNITY_SERVER
flush_status_time= time((time_t*) 0);
-#endif
pthread_mutex_unlock(&LOCK_status);
/*
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 3902f9c34bd..5cf3597c638 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -94,8 +94,8 @@ extern ulong bytes_sent, bytes_received, net_big_packet_count;
#ifndef MYSQL_INSTANCE_MANAGER
#ifdef HAVE_QUERY_CACHE
#define USE_QUERY_CACHE
-extern void query_cache_init_query(NET *net);
-extern void query_cache_insert(NET *net, const char *packet, ulong length);
+extern void query_cache_insert(const char *packet, ulong length,
+ unsigned pkt_nr);
#endif // HAVE_QUERY_CACHE
#define update_statistics(A) A
#endif /* MYSQL_INSTANCE_MANGER */
@@ -124,18 +124,14 @@ my_bool my_net_init(NET *net, Vio* vio)
MYF(MY_WME))))
DBUG_RETURN(1);
net->buff_end=net->buff+net->max_packet;
- net->error=0; net->return_errno=0; net->return_status=0;
+ net->error=0; net->return_status=0;
net->pkt_nr=net->compress_pkt_nr=0;
net->write_pos=net->read_pos = net->buff;
net->last_error[0]=0;
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
-#ifdef USE_QUERY_CACHE
- query_cache_init_query(net);
-#else
- net->query_cache_query= 0;
-#endif
+ net->unused= 0;
if (vio != 0) /* If real connection */
{
@@ -585,7 +581,7 @@ net_real_write(NET *net,const uchar *packet, size_t len)
DBUG_ENTER("net_real_write");
#if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
- query_cache_insert(net, (char*) packet, len);
+ query_cache_insert((char*) packet, len, net->pkt_nr);
#endif
if (net->error == 2)
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e1c7d4b38aa..731e9872aa5 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -438,35 +438,55 @@ public:
return 0;
}
- /* returns a number of keypart values appended to the key buffer */
- int store_min_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
+ /*
+ Returns a number of keypart values appended to the key buffer
+ for min key and max key. This function is used by both Range
+ Analysis and Partition pruning. For partition pruning we have
+ to ensure that we don't store also subpartition fields. Thus
+ we have to stop at the last partition part and not step into
+ the subpartition fields. For Range Analysis we set last_part
+ to MAX_KEY which we should never reach.
+ */
+ int store_min_key(KEY_PART *key,
+ uchar **range_key,
+ uint *range_key_flag,
+ uint last_part)
{
SEL_ARG *key_tree= first();
uint res= key_tree->store_min(key[key_tree->part].store_length,
range_key, *range_key_flag);
*range_key_flag|= key_tree->min_flag;
if (key_tree->next_key_part &&
+ key_tree->part != last_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
- res+= key_tree->next_key_part->store_min_key(key, range_key,
- range_key_flag);
+ res+= key_tree->next_key_part->store_min_key(key,
+ range_key,
+ range_key_flag,
+ last_part);
return res;
}
/* returns a number of keypart values appended to the key buffer */
- int store_max_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
+ int store_max_key(KEY_PART *key,
+ uchar **range_key,
+ uint *range_key_flag,
+ uint last_part)
{
SEL_ARG *key_tree= last();
uint res=key_tree->store_max(key[key_tree->part].store_length,
range_key, *range_key_flag);
(*range_key_flag)|= key_tree->max_flag;
if (key_tree->next_key_part &&
- key_tree->next_key_part->part == key_tree->part+1 &&
- !(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
- key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
- res+= key_tree->next_key_part->store_max_key(key, range_key,
- range_key_flag);
+ key_tree->part != last_part &&
+ key_tree->next_key_part->part == key_tree->part+1 &&
+ !(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
+ key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
+ res+= key_tree->next_key_part->store_max_key(key,
+ range_key,
+ range_key_flag,
+ last_part);
return res;
}
@@ -634,6 +654,14 @@ public:
using_real_indexes==TRUE
*/
uint real_keynr[MAX_KEY];
+
+ /*
+ Used to store 'current key tuples', in both range analysis and
+ partitioning (list) analysis
+ */
+ uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
+ max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
+
/* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
uint alloced_sel_args;
};
@@ -645,8 +673,6 @@ public:
longlong baseflag;
uint max_key_part, range_count;
- uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
- max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
bool quick; // Don't calulate possible keys
uint fields_bitmap_size;
@@ -2604,6 +2630,8 @@ typedef struct st_part_prune_param
/* Same as above for subpartitioning */
my_bool *is_subpart_keypart;
+ my_bool ignore_part_fields; /* Ignore rest of partioning fields */
+
/***************************************************************
Following fields form find_used_partitions() recursion context:
**************************************************************/
@@ -2617,8 +2645,13 @@ typedef struct st_part_prune_param
/* Iterator to be used to obtain the "current" set of used partitions */
PARTITION_ITERATOR part_iter;
- /* Initialized bitmap of no_subparts size */
+ /* Initialized bitmap of num_subparts size */
MY_BITMAP subparts_bitmap;
+
+ uchar *cur_min_key;
+ uchar *cur_max_key;
+
+ uint cur_min_flag, cur_max_flag;
} PART_PRUNE_PARAM;
static bool create_partition_index_description(PART_PRUNE_PARAM *prune_par);
@@ -2736,6 +2769,11 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
prune_param.arg_stack_end= prune_param.arg_stack;
prune_param.cur_part_fields= 0;
prune_param.cur_subpart_fields= 0;
+
+ prune_param.cur_min_key= prune_param.range_param.min_key;
+ prune_param.cur_max_key= prune_param.range_param.max_key;
+ prune_param.cur_min_flag= prune_param.cur_max_flag= 0;
+
init_all_partitions_iterator(part_info, &prune_param.part_iter);
if (!tree->keys[0] || (-1 == (res= find_used_partitions(&prune_param,
tree->keys[0]))))
@@ -2873,8 +2911,8 @@ static void mark_full_partition_used_no_parts(partition_info* part_info,
static void mark_full_partition_used_with_parts(partition_info *part_info,
uint32 part_id)
{
- uint32 start= part_id * part_info->no_subparts;
- uint32 end= start + part_info->no_subparts;
+ uint32 start= part_id * part_info->num_subparts;
+ uint32 end= start + part_info->num_subparts;
DBUG_ENTER("mark_full_partition_used_with_parts");
for (; start != end; start++)
@@ -2972,6 +3010,11 @@ int find_used_partitions_imerge(PART_PRUNE_PARAM *ppar, SEL_IMERGE *imerge)
ppar->arg_stack_end= ppar->arg_stack;
ppar->cur_part_fields= 0;
ppar->cur_subpart_fields= 0;
+
+ ppar->cur_min_key= ppar->range_param.min_key;
+ ppar->cur_max_key= ppar->range_param.max_key;
+ ppar->cur_min_flag= ppar->cur_max_flag= 0;
+
init_all_partitions_iterator(ppar->part_info, &ppar->part_iter);
SEL_ARG *key_tree= (*ptree)->keys[0];
if (!key_tree || (-1 == (res |= find_used_partitions(ppar, key_tree))))
@@ -3095,9 +3138,14 @@ static
int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
{
int res, left_res=0, right_res=0;
- int partno= (int)key_tree->part;
- bool pushed= FALSE;
+ int key_tree_part= (int)key_tree->part;
bool set_full_part_if_bad_ret= FALSE;
+ bool ignore_part_fields= ppar->ignore_part_fields;
+ bool did_set_ignore_part_fields= FALSE;
+ RANGE_OPT_PARAM *range_par= &(ppar->range_param);
+
+ if (check_stack_overrun(range_par->thd, 3*STACK_MIN_SIZE, NULL))
+ return -1;
if (key_tree->left != &null_element)
{
@@ -3105,56 +3153,177 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
return -1;
}
+ /* Push SEL_ARG's to stack to enable looking backwards as well */
+ ppar->cur_part_fields+= ppar->is_part_keypart[key_tree_part];
+ ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part];
+ *(ppar->arg_stack_end++)= key_tree;
+
if (key_tree->type == SEL_ARG::KEY_RANGE)
{
- if (partno == 0 && (NULL != ppar->part_info->get_part_iter_for_interval))
+ if (ppar->part_info->get_part_iter_for_interval &&
+ key_tree->part <= ppar->last_part_partno)
{
- /*
- Partitioning is done by RANGE|INTERVAL(monotonic_expr(fieldX)), and
- we got "const1 CMP fieldX CMP const2" interval <-- psergey-todo: change
+ if (ignore_part_fields)
+ {
+ /*
+ We come here when a condition on the first partitioning
+ fields led to evaluating the partitioning condition
+ (due to finding a condition of the type a < const or
+ b > const). Thus we must ignore the rest of the
+ partitioning fields but we still want to analyse the
+ subpartitioning fields.
+ */
+ if (key_tree->next_key_part)
+ res= find_used_partitions(ppar, key_tree->next_key_part);
+ else
+ res= -1;
+ goto pop_and_go_right;
+ }
+ /* Collect left and right bound, their lengths and flags */
+ uchar *min_key= ppar->cur_min_key;
+ uchar *max_key= ppar->cur_max_key;
+ uchar *tmp_min_key= min_key;
+ uchar *tmp_max_key= max_key;
+ key_tree->store_min(ppar->key[key_tree->part].store_length,
+ &tmp_min_key, ppar->cur_min_flag);
+ key_tree->store_max(ppar->key[key_tree->part].store_length,
+ &tmp_max_key, ppar->cur_max_flag);
+ uint flag;
+ if (key_tree->next_key_part &&
+ key_tree->next_key_part->part == key_tree->part+1 &&
+ key_tree->next_key_part->part <= ppar->last_part_partno &&
+ key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
+ {
+ /*
+ There are more key parts for partition pruning to handle
+ This mainly happens when the condition is an equality
+ condition.
+ */
+ if ((tmp_min_key - min_key) == (tmp_max_key - max_key) &&
+ (memcmp(min_key, max_key, (uint)(tmp_max_key - max_key)) == 0) &&
+ !key_tree->min_flag && !key_tree->max_flag)
+ {
+ /* Set 'parameters' */
+ ppar->cur_min_key= tmp_min_key;
+ ppar->cur_max_key= tmp_max_key;
+ uint save_min_flag= ppar->cur_min_flag;
+ uint save_max_flag= ppar->cur_max_flag;
+
+ ppar->cur_min_flag|= key_tree->min_flag;
+ ppar->cur_max_flag|= key_tree->max_flag;
+
+ res= find_used_partitions(ppar, key_tree->next_key_part);
+
+ /* Restore 'parameters' back */
+ ppar->cur_min_key= min_key;
+ ppar->cur_max_key= max_key;
+
+ ppar->cur_min_flag= save_min_flag;
+ ppar->cur_max_flag= save_max_flag;
+ goto pop_and_go_right;
+ }
+ /* We have arrived at the last field in the partition pruning */
+ uint tmp_min_flag= key_tree->min_flag,
+ tmp_max_flag= key_tree->max_flag;
+ if (!tmp_min_flag)
+ key_tree->next_key_part->store_min_key(ppar->key,
+ &tmp_min_key,
+ &tmp_min_flag,
+ ppar->last_part_partno);
+ if (!tmp_max_flag)
+ key_tree->next_key_part->store_max_key(ppar->key,
+ &tmp_max_key,
+ &tmp_max_flag,
+ ppar->last_part_partno);
+ flag= tmp_min_flag | tmp_max_flag;
+ }
+ else
+ flag= key_tree->min_flag | key_tree->max_flag;
+
+ if (tmp_min_key != range_par->min_key)
+ flag&= ~NO_MIN_RANGE;
+ else
+ flag|= NO_MIN_RANGE;
+ if (tmp_max_key != range_par->max_key)
+ flag&= ~NO_MAX_RANGE;
+ else
+ flag|= NO_MAX_RANGE;
+
+ /*
+ We need to call the interval mapper if we have a condition which
+ makes sense to prune on. In the example of COLUMNS on a and
+ b it makes sense if we have a condition on a, or conditions on
+ both a and b. If we only have conditions on b it might make sense
+ but this is a harder case we will solve later. For the harder case
+ this clause then turns into use of all partitions and thus we
+ simply set res= -1 as if the mapper had returned that.
+ TODO: What to do here is defined in WL#4065.
*/
- DBUG_EXECUTE("info", dbug_print_segment_range(key_tree,
- ppar->range_param.
- key_parts););
- res= ppar->part_info->
- get_part_iter_for_interval(ppar->part_info,
- FALSE,
- key_tree->min_value,
- key_tree->max_value,
- key_tree->min_flag | key_tree->max_flag,
- &ppar->part_iter);
- if (!res)
- goto go_right; /* res==0 --> no satisfying partitions */
+ if (ppar->arg_stack[0]->part == 0)
+ {
+ uint32 i;
+ uint32 store_length_array[MAX_KEY];
+ uint32 num_keys= ppar->part_fields;
+
+ for (i= 0; i < num_keys; i++)
+ store_length_array[i]= ppar->key[i].store_length;
+ res= ppar->part_info->
+ get_part_iter_for_interval(ppar->part_info,
+ FALSE,
+ store_length_array,
+ range_par->min_key,
+ range_par->max_key,
+ tmp_min_key - range_par->min_key,
+ tmp_max_key - range_par->max_key,
+ flag,
+ &ppar->part_iter);
+ if (!res)
+ goto pop_and_go_right; /* res==0 --> no satisfying partitions */
+ }
+ else
+ res= -1;
+
if (res == -1)
{
- //get a full range iterator
+ /* get a full range iterator */
init_all_partitions_iterator(ppar->part_info, &ppar->part_iter);
}
/*
Save our intent to mark full partition as used if we will not be able
to obtain further limits on subpartitions
*/
+ if (key_tree_part < ppar->last_part_partno)
+ {
+ /*
+ We need to ignore the rest of the partitioning fields in all
+ evaluations after this
+ */
+ did_set_ignore_part_fields= TRUE;
+ ppar->ignore_part_fields= TRUE;
+ }
set_full_part_if_bad_ret= TRUE;
goto process_next_key_part;
}
- if (partno == ppar->last_subpart_partno &&
+ if (key_tree_part == ppar->last_subpart_partno &&
(NULL != ppar->part_info->get_subpart_iter_for_interval))
{
PARTITION_ITERATOR subpart_iter;
DBUG_EXECUTE("info", dbug_print_segment_range(key_tree,
- ppar->range_param.
- key_parts););
+ range_par->key_parts););
res= ppar->part_info->
get_subpart_iter_for_interval(ppar->part_info,
TRUE,
+ NULL, /* Currently not used here */
key_tree->min_value,
key_tree->max_value,
- key_tree->min_flag | key_tree->max_flag,
+ 0, 0, /* Those are ignored here */
+ key_tree->min_flag |
+ key_tree->max_flag,
&subpart_iter);
DBUG_ASSERT(res); /* We can't get "no satisfying subpartitions" */
if (res == -1)
- return -1; /* all subpartitions satisfy */
+ goto pop_and_go_right; /* all subpartitions satisfy */
uint32 subpart_id;
bitmap_clear_all(&ppar->subparts_bitmap);
@@ -3167,23 +3336,19 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) !=
NOT_A_PARTITION_ID)
{
- for (uint i= 0; i < ppar->part_info->no_subparts; i++)
+ for (uint i= 0; i < ppar->part_info->num_subparts; i++)
if (bitmap_is_set(&ppar->subparts_bitmap, i))
bitmap_set_bit(&ppar->part_info->used_partitions,
- part_id * ppar->part_info->no_subparts + i);
+ part_id * ppar->part_info->num_subparts + i);
}
- goto go_right;
+ goto pop_and_go_right;
}
if (key_tree->is_singlepoint())
{
- pushed= TRUE;
- ppar->cur_part_fields+= ppar->is_part_keypart[partno];
- ppar->cur_subpart_fields+= ppar->is_subpart_keypart[partno];
- *(ppar->arg_stack_end++) = key_tree;
-
- if (partno == ppar->last_part_partno &&
- ppar->cur_part_fields == ppar->part_fields)
+ if (key_tree_part == ppar->last_part_partno &&
+ ppar->cur_part_fields == ppar->part_fields &&
+ ppar->part_info->get_part_iter_for_interval == NULL)
{
/*
Ok, we've got "fieldN<=>constN"-type SEL_ARGs for all partitioning
@@ -3212,7 +3377,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
goto process_next_key_part;
}
- if (partno == ppar->last_subpart_partno &&
+ if (key_tree_part == ppar->last_subpart_partno &&
ppar->cur_subpart_fields == ppar->subpart_fields)
{
/*
@@ -3236,7 +3401,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
NOT_A_PARTITION_ID)
{
bitmap_set_bit(&part_info->used_partitions,
- part_id * part_info->no_subparts + subpart_id);
+ part_id * part_info->num_subparts + subpart_id);
}
res= 1; /* Some partitions were marked as used */
goto pop_and_go_right;
@@ -3249,8 +3414,11 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
we're processing subpartititoning's key parts, this means we'll not be
able to infer any suitable condition, so bail out.
*/
- if (partno >= ppar->last_part_partno)
- return -1;
+ if (key_tree_part >= ppar->last_part_partno)
+ {
+ res= -1;
+ goto pop_and_go_right;
+ }
}
}
@@ -3259,7 +3427,17 @@ process_next_key_part:
res= find_used_partitions(ppar, key_tree->next_key_part);
else
res= -1;
-
+
+ if (did_set_ignore_part_fields)
+ {
+ /*
+ We have returned from processing all key trees linked to our next
+ key part. We are ready to be moving down (using right pointers) and
+ this tree is a new evaluation requiring its own decision on whether
+ to ignore partitioning fields.
+ */
+ ppar->ignore_part_fields= FALSE;
+ }
if (set_full_part_if_bad_ret)
{
if (res == -1)
@@ -3282,18 +3460,14 @@ process_next_key_part:
init_all_partitions_iterator(ppar->part_info, &ppar->part_iter);
}
- if (pushed)
- {
pop_and_go_right:
- /* Pop this key part info off the "stack" */
- ppar->arg_stack_end--;
- ppar->cur_part_fields-= ppar->is_part_keypart[partno];
- ppar->cur_subpart_fields-= ppar->is_subpart_keypart[partno];
- }
+ /* Pop this key part info off the "stack" */
+ ppar->arg_stack_end--;
+ ppar->cur_part_fields-= ppar->is_part_keypart[key_tree_part];
+ ppar->cur_subpart_fields-= ppar->is_subpart_keypart[key_tree_part];
if (res == -1)
return -1;
-go_right:
if (key_tree->right != &null_element)
{
if (-1 == (right_res= find_used_partitions(ppar,key_tree->right)))
@@ -3375,13 +3549,14 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
uint used_part_fields, used_subpart_fields;
used_part_fields= fields_ok_for_partition_index(part_info->part_field_array) ?
- part_info->no_part_fields : 0;
+ part_info->num_part_fields : 0;
used_subpart_fields=
fields_ok_for_partition_index(part_info->subpart_field_array)?
- part_info->no_subpart_fields : 0;
+ part_info->num_subpart_fields : 0;
uint total_parts= used_part_fields + used_subpart_fields;
+ ppar->ignore_part_fields= FALSE;
ppar->part_fields= used_part_fields;
ppar->last_part_partno= (int)used_part_fields - 1;
@@ -3416,10 +3591,10 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
if (ppar->subpart_fields)
{
my_bitmap_map *buf;
- uint32 bufsize= bitmap_buffer_size(ppar->part_info->no_subparts);
+ uint32 bufsize= bitmap_buffer_size(ppar->part_info->num_subparts);
if (!(buf= (my_bitmap_map*) alloc_root(alloc, bufsize)))
return TRUE;
- bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->no_subparts,
+ bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->num_subparts,
FALSE);
}
range_par->key_parts= key_part;
@@ -3430,12 +3605,8 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
{
key_part->key= 0;
key_part->part= part;
- key_part->store_length= key_part->length= (uint16) (*field)->key_length();
- if ((*field)->real_maybe_null())
- key_part->store_length+= HA_KEY_NULL_LENGTH;
- if ((*field)->type() == MYSQL_TYPE_BLOB ||
- (*field)->real_type() == MYSQL_TYPE_VARCHAR)
- key_part->store_length+= HA_KEY_BLOB_LENGTH;
+ key_part->length= (uint16)(*field)->key_length();
+ key_part->store_length= (uint16)get_partition_field_store_length(*field);
DBUG_PRINT("info", ("part %u length %u store_length %u", part,
key_part->length, key_part->store_length));
@@ -5711,9 +5882,31 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
value->result_type() == STRING_RESULT &&
key_part->image_type == Field::itRAW &&
((Field_str*)field)->charset() != conf_func->compare_collation() &&
- !(conf_func->compare_collation()->state & MY_CS_BINSORT))
+ !(conf_func->compare_collation()->state & MY_CS_BINSORT &&
+ (type == Item_func::EQUAL_FUNC || type == Item_func::EQ_FUNC)))
goto end;
+ if (key_part->image_type == Field::itMBR)
+ {
+ switch (type) {
+ case Item_func::SP_EQUALS_FUNC:
+ case Item_func::SP_DISJOINT_FUNC:
+ case Item_func::SP_INTERSECTS_FUNC:
+ case Item_func::SP_TOUCHES_FUNC:
+ case Item_func::SP_CROSSES_FUNC:
+ case Item_func::SP_WITHIN_FUNC:
+ case Item_func::SP_CONTAINS_FUNC:
+ case Item_func::SP_OVERLAPS_FUNC:
+ break;
+ default:
+ /*
+ We cannot involve spatial indexes for queries that
+ don't use MBREQUALS(), MBRDISJOINT(), etc. functions.
+ */
+ goto end;
+ }
+ }
+
if (param->using_real_indexes)
optimize_range= field->optimize_range(param->real_keynr[key_part->key],
key_part->part);
@@ -5896,6 +6089,17 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
goto end;
}
field->table->in_use->variables.sql_mode= orig_sql_mode;
+
+ /*
+ Any sargable predicate except "<=>" involving NULL as a constant is always
+ FALSE
+ */
+ if (type != Item_func::EQUAL_FUNC && field->is_real_null())
+ {
+ tree= &null_element;
+ goto end;
+ }
+
str= (uchar*) alloc_root(alloc, key_part->store_length+1);
if (!str)
goto end;
@@ -5941,7 +6145,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
switch (type) {
case Item_func::LT_FUNC:
- if (stored_field_cmp_to_item(field,value) == 0)
+ if (stored_field_cmp_to_item(param->thd, field, value) == 0)
tree->max_flag=NEAR_MAX;
/* fall through */
case Item_func::LE_FUNC:
@@ -5956,14 +6160,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
case Item_func::GT_FUNC:
/* Don't use open ranges for partial key_segments */
if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
- (stored_field_cmp_to_item(field, value) <= 0))
+ (stored_field_cmp_to_item(param->thd, field, value) <= 0))
tree->min_flag=NEAR_MIN;
tree->max_flag= NO_MAX_RANGE;
break;
case Item_func::GE_FUNC:
/* Don't use open ranges for partial key_segments */
if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
- (stored_field_cmp_to_item(field,value) < 0))
+ (stored_field_cmp_to_item(param->thd, field, value) < 0))
tree->min_flag= NEAR_MIN;
tree->max_flag=NO_MAX_RANGE;
break;
@@ -7553,12 +7757,16 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
tmp_min_keypart+=
- key_tree->next_key_part->store_min_key(param->key[idx], &tmp_min_key,
- &tmp_min_flag);
+ key_tree->next_key_part->store_min_key(param->key[idx],
+ &tmp_min_key,
+ &tmp_min_flag,
+ MAX_KEY);
if (!tmp_max_flag)
tmp_max_keypart+=
- key_tree->next_key_part->store_max_key(param->key[idx], &tmp_max_key,
- &tmp_max_flag);
+ key_tree->next_key_part->store_max_key(param->key[idx],
+ &tmp_max_key,
+ &tmp_max_flag,
+ MAX_KEY);
min_key_length= (uint) (tmp_min_key - param->min_key);
max_key_length= (uint) (tmp_max_key - param->max_key);
}
@@ -7828,11 +8036,15 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
{
uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
- min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
- &tmp_min_flag);
+ min_part+= key_tree->next_key_part->store_min_key(key,
+ &tmp_min_key,
+ &tmp_min_flag,
+ MAX_KEY);
if (!tmp_max_flag)
- max_part+= key_tree->next_key_part->store_max_key(key, &tmp_max_key,
- &tmp_max_flag);
+ max_part+= key_tree->next_key_part->store_max_key(key,
+ &tmp_max_key,
+ &tmp_max_flag,
+ MAX_KEY);
flag=tmp_min_flag | tmp_max_flag;
}
}
diff --git a/sql/partition_element.h b/sql/partition_element.h
index 5575eb93bfb..73f85ac275f 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -1,7 +1,7 @@
#ifndef PARTITION_ELEMENT_INCLUDED
#define PARTITION_ELEMENT_INCLUDED
-/* Copyright (C) 2006 MySQL AB
+/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,6 +40,35 @@ enum partition_state {
};
/*
+ This struct is used to keep track of column expressions as part
+ of the COLUMNS concept in conjunction with RANGE and LIST partitioning.
+ The value can be either of MINVALUE, MAXVALUE and an expression that
+ must be constant and evaluate to the same type as the column it
+ represents.
+
+ The data in this fixed in two steps. The parser will only fill in whether
+ it is a max_value or provide an expression. Filling in
+ column_value, part_info, partition_id, null_value is done by the
+ function fix_column_value_function. However the item tree needs
+ fixed also before writing it into the frm file (in add_column_list_values).
+ To distinguish between those two variants, fixed= 1 after the
+ fixing in add_column_list_values and fixed= 2 otherwise. This is
+ since the fixing in add_column_list_values isn't a complete fixing.
+*/
+
+typedef struct p_column_list_val
+{
+ void* column_value;
+ Item* item_expression;
+ partition_info *part_info;
+ uint partition_id;
+ bool max_value;
+ bool null_value;
+ char fixed;
+} part_column_list_val;
+
+
+/*
This struct is used to contain the value of an element
in the VALUES IN struct. It needs to keep knowledge of
whether it is a signed/unsigned value and whether it is
@@ -49,8 +78,10 @@ enum partition_state {
typedef struct p_elem_val
{
longlong value;
+ uint added_items;
bool null_value;
bool unsigned_flag;
+ part_column_list_val *col_val_array;
} part_elem_value;
struct st_ddl_log_memory_entry;
@@ -72,8 +103,9 @@ public:
enum partition_state part_state;
uint16 nodegroup_id;
bool has_null_value;
- bool signed_flag;/* Indicate whether this partition uses signed constants */
- bool max_value; /* Indicate whether this partition uses MAXVALUE */
+ /* signed_flag and max_value only relevant for subpartitions */
+ bool signed_flag;
+ bool max_value;
partition_element()
: part_max_rows(0), part_min_rows(0), range_value(0),
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index ba9ea0e876e..355a4ba6b68 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 MySQL AB
+/* Copyright (C) 2006-2008 MySQL AB, Sun Microsystems Inc. 2008-2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -75,7 +75,7 @@ partition_info *partition_info::get_clone()
SYNOPSIS
create_default_partition_names()
part_no Partition number for subparts
- no_parts Number of partitions
+ num_parts Number of partitions
start_no Starting partition number
subpart Is it subpartitions
@@ -91,10 +91,10 @@ partition_info *partition_info::get_clone()
#define MAX_PART_NAME_SIZE 8
char *partition_info::create_default_partition_names(uint part_no,
- uint no_parts_arg,
+ uint num_parts_arg,
uint start_no)
{
- char *ptr= (char*) sql_calloc(no_parts_arg*MAX_PART_NAME_SIZE);
+ char *ptr= (char*) sql_calloc(num_parts_arg*MAX_PART_NAME_SIZE);
char *move_ptr= ptr;
uint i= 0;
DBUG_ENTER("create_default_partition_names");
@@ -105,11 +105,11 @@ char *partition_info::create_default_partition_names(uint part_no,
{
my_sprintf(move_ptr, (move_ptr,"p%u", (start_no + i)));
move_ptr+=MAX_PART_NAME_SIZE;
- } while (++i < no_parts_arg);
+ } while (++i < num_parts_arg);
}
else
{
- mem_alloc_error(no_parts_arg*MAX_PART_NAME_SIZE);
+ mem_alloc_error(num_parts_arg*MAX_PART_NAME_SIZE);
}
DBUG_RETURN(ptr);
}
@@ -189,19 +189,19 @@ bool partition_info::set_up_default_partitions(handler *file,
goto end;
}
- if ((no_parts == 0) &&
- ((no_parts= file->get_default_no_partitions(info)) == 0))
+ if ((num_parts == 0) &&
+ ((num_parts= file->get_default_no_partitions(info)) == 0))
{
my_error(ER_PARTITION_NOT_DEFINED_ERROR, MYF(0), "partitions");
goto end;
}
- if (unlikely(no_parts > MAX_PARTITIONS))
+ if (unlikely(num_parts > MAX_PARTITIONS))
{
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
goto end;
}
- if (unlikely((!(default_name= create_default_partition_names(0, no_parts,
+ if (unlikely((!(default_name= create_default_partition_names(0, num_parts,
start_no)))))
goto end;
i= 0;
@@ -220,7 +220,7 @@ bool partition_info::set_up_default_partitions(handler *file,
mem_alloc_error(sizeof(partition_element));
goto end;
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
result= FALSE;
end:
DBUG_RETURN(result);
@@ -259,9 +259,9 @@ bool partition_info::set_up_default_subpartitions(handler *file,
List_iterator<partition_element> part_it(partitions);
DBUG_ENTER("partition_info::set_up_default_subpartitions");
- if (no_subparts == 0)
- no_subparts= file->get_default_no_partitions(info);
- if (unlikely((no_parts * no_subparts) > MAX_PARTITIONS))
+ if (num_subparts == 0)
+ num_subparts= file->get_default_no_partitions(info);
+ if (unlikely((num_parts * num_subparts) > MAX_PARTITIONS))
{
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
goto end;
@@ -288,8 +288,8 @@ bool partition_info::set_up_default_subpartitions(handler *file,
mem_alloc_error(sizeof(partition_element));
goto end;
}
- } while (++j < no_subparts);
- } while (++i < no_parts);
+ } while (++j < num_subparts);
+ } while (++i < num_parts);
result= FALSE;
end:
DBUG_RETURN(result);
@@ -334,6 +334,49 @@ bool partition_info::set_up_defaults_for_partitioning(handler *file,
/*
+ Support routine for check_partition_info
+
+ SYNOPSIS
+ has_unique_fields
+ no parameters
+
+ RETURN VALUE
+ Erroneus field name Error, there are two fields with same name
+ NULL Ok, no field defined twice
+
+ DESCRIPTION
+ Check that the user haven't defined the same field twice in
+ key or column list partitioning.
+*/
+char* partition_info::has_unique_fields()
+{
+ char *field_name_outer, *field_name_inner;
+ List_iterator<char> it_outer(part_field_list);
+ uint num_fields= part_field_list.elements;
+ uint i,j;
+ DBUG_ENTER("partition_info::has_unique_fields");
+
+ for (i= 0; i < num_fields; i++)
+ {
+ field_name_outer= it_outer++;
+ List_iterator<char> it_inner(part_field_list);
+ for (j= 0; j < num_fields; j++)
+ {
+ field_name_inner= it_inner++;
+ if (i >= j)
+ continue;
+ if (!(my_strcasecmp(system_charset_info,
+ field_name_outer,
+ field_name_inner)))
+ {
+ DBUG_RETURN(field_name_outer);
+ }
+ }
+ }
+ DBUG_RETURN(NULL);
+}
+
+/*
A support function to check if a partition element's name is unique
SYNOPSIS
@@ -518,12 +561,12 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
{
handlerton *old_engine_type= engine_type;
bool first= TRUE;
- uint no_parts= partitions.elements;
+ uint num_parts= partitions.elements;
DBUG_ENTER("partition_info::check_engine_mix");
DBUG_PRINT("info", ("in: engine_type = %s, table_engine_set = %u",
ha_resolve_storage_engine_name(engine_type),
table_engine_set));
- if (no_parts)
+ if (num_parts)
{
List_iterator<partition_element> part_it(partitions);
uint i= 0;
@@ -536,7 +579,7 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
if (is_sub_partitioned() &&
part_elem->subpartitions.elements)
{
- uint no_subparts= part_elem->subpartitions.elements;
+ uint num_subparts= part_elem->subpartitions.elements;
uint j= 0;
List_iterator<partition_element> sub_it(part_elem->subpartitions);
do
@@ -548,7 +591,7 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
if (check_engine_condition(sub_elem, table_engine_set,
&engine_type, &first))
goto error;
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
/* ensure that the partition also has correct engine */
if (check_engine_condition(part_elem, table_engine_set,
&engine_type, &first))
@@ -557,7 +600,7 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
else if (check_engine_condition(part_elem, table_engine_set,
&engine_type, &first))
goto error;
- } while (++i < no_parts);
+ } while (++i < num_parts);
}
DBUG_PRINT("info", ("engine_type = %s",
ha_resolve_storage_engine_name(engine_type)));
@@ -589,6 +632,7 @@ error:
SYNOPSIS
check_range_constants()
+ thd Thread object
RETURN VALUE
TRUE An error occurred during creation of range constants
@@ -601,76 +645,112 @@ error:
called for RANGE PARTITIONed tables.
*/
-bool partition_info::check_range_constants()
+bool partition_info::check_range_constants(THD *thd)
{
partition_element* part_def;
- longlong current_largest;
- longlong part_range_value;
bool first= TRUE;
uint i;
List_iterator<partition_element> it(partitions);
- bool result= TRUE;
- bool signed_flag= !part_expr->unsigned_flag;
+ int result= TRUE;
DBUG_ENTER("partition_info::check_range_constants");
- DBUG_PRINT("enter", ("INT_RESULT with %d parts", no_parts));
-
- LINT_INIT(current_largest);
+ DBUG_PRINT("enter", ("RANGE with %d parts, column_list = %u", num_parts,
+ column_list));
- part_result_type= INT_RESULT;
- range_int_array= (longlong*)sql_alloc(no_parts * sizeof(longlong));
- if (unlikely(range_int_array == NULL))
+ if (column_list)
{
- mem_alloc_error(no_parts * sizeof(longlong));
- goto end;
- }
- i= 0;
- do
- {
- part_def= it++;
- if ((i != (no_parts - 1)) || !defined_max_value)
+ part_column_list_val *loc_range_col_array;
+ part_column_list_val *current_largest_col_val;
+ uint num_column_values= part_field_list.elements;
+ uint size_entries= sizeof(part_column_list_val) * num_column_values;
+ range_col_array= (part_column_list_val*)sql_calloc(num_parts *
+ size_entries);
+ LINT_INIT(current_largest_col_val);
+ if (unlikely(range_col_array == NULL))
{
- part_range_value= part_def->range_value;
- if (!signed_flag)
- part_range_value-= 0x8000000000000000ULL;
+ mem_alloc_error(num_parts * size_entries);
+ goto end;
}
- else
- part_range_value= LONGLONG_MAX;
- if (first)
+ loc_range_col_array= range_col_array;
+ i= 0;
+ do
{
- current_largest= part_range_value;
- range_int_array[0]= part_range_value;
+ part_def= it++;
+ {
+ List_iterator<part_elem_value> list_val_it(part_def->list_val_list);
+ part_elem_value *range_val= list_val_it++;
+ part_column_list_val *col_val= range_val->col_val_array;
+
+ if (fix_column_value_functions(thd, range_val, i))
+ goto end;
+ memcpy(loc_range_col_array, (const void*)col_val, size_entries);
+ loc_range_col_array+= num_column_values;
+ if (!first)
+ {
+ if (compare_column_values((const void*)current_largest_col_val,
+ (const void*)col_val) >= 0)
+ goto range_not_increasing_error;
+ }
+ current_largest_col_val= col_val;
+ }
first= FALSE;
+ } while (++i < num_parts);
+ }
+ else
+ {
+ longlong current_largest;
+ longlong part_range_value;
+ bool signed_flag= !part_expr->unsigned_flag;
+
+ LINT_INIT(current_largest);
+
+ part_result_type= INT_RESULT;
+ range_int_array= (longlong*)sql_alloc(num_parts * sizeof(longlong));
+ if (unlikely(range_int_array == NULL))
+ {
+ mem_alloc_error(num_parts * sizeof(longlong));
+ goto end;
}
- else
+ i= 0;
+ do
{
- if (likely(current_largest < part_range_value))
+ part_def= it++;
+ if ((i != (num_parts - 1)) || !defined_max_value)
{
- current_largest= part_range_value;
- range_int_array[i]= part_range_value;
- }
- else if (defined_max_value &&
- current_largest == part_range_value &&
- part_range_value == LONGLONG_MAX &&
- i == (no_parts - 1))
- {
- range_int_array[i]= part_range_value;
+ part_range_value= part_def->range_value;
+ if (!signed_flag)
+ part_range_value-= 0x8000000000000000ULL;
}
else
+ part_range_value= LONGLONG_MAX;
+
+ if (!first)
{
- my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0));
- goto end;
+ if (unlikely(current_largest > part_range_value) ||
+ (unlikely(current_largest == part_range_value) &&
+ (part_range_value < LONGLONG_MAX ||
+ i != (num_parts - 1) ||
+ !defined_max_value)))
+ goto range_not_increasing_error;
}
- }
- } while (++i < no_parts);
+ range_int_array[i]= part_range_value;
+ current_largest= part_range_value;
+ first= FALSE;
+ } while (++i < num_parts);
+ }
result= FALSE;
end:
DBUG_RETURN(result);
+
+range_not_increasing_error:
+ my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0));
+ goto end;
}
/*
Support routines for check_list_constants used by qsort to sort the
- constant list expressions. One routine for unsigned and one for signed.
+ constant list expressions. One routine for integers and one for
+ column lists.
SYNOPSIS
list_part_cmp()
@@ -695,6 +775,54 @@ int partition_info::list_part_cmp(const void* a, const void* b)
return 0;
}
+ /*
+ Compare two lists of column values in RANGE/LIST partitioning
+ SYNOPSIS
+ compare_column_values()
+ first First column list argument
+ second Second column list argument
+ RETURN VALUES
+ 0 Equal
+ -1 First argument is smaller
+ +1 First argument is larger
+*/
+
+int partition_info::compare_column_values(const void *first_arg,
+ const void *second_arg)
+{
+ const part_column_list_val *first= (part_column_list_val*)first_arg;
+ const part_column_list_val *second= (part_column_list_val*)second_arg;
+ partition_info *part_info= first->part_info;
+ Field **field;
+
+ for (field= part_info->part_field_array; *field;
+ field++, first++, second++)
+ {
+ if (first->max_value || second->max_value)
+ {
+ if (first->max_value && second->max_value)
+ continue;
+ if (second->max_value)
+ return -1;
+ else
+ return +1;
+ }
+ if (first->null_value || second->null_value)
+ {
+ if (first->null_value && second->null_value)
+ continue;
+ if (second->null_value)
+ return +1;
+ else
+ return -1;
+ }
+ int res= (*field)->cmp((const uchar*)first->column_value,
+ (const uchar*)second->column_value);
+ if (res)
+ return res;
+ }
+ return 0;
+}
/*
This routine allocates an array for all list constants to achieve a fast
@@ -704,6 +832,7 @@ int partition_info::list_part_cmp(const void* a, const void* b)
SYNOPSIS
check_list_constants()
+ thd Thread object
RETURN VALUE
TRUE An error occurred during creation of list constants
@@ -716,20 +845,23 @@ int partition_info::list_part_cmp(const void* a, const void* b)
called for LIST PARTITIONed tables.
*/
-bool partition_info::check_list_constants()
+bool partition_info::check_list_constants(THD *thd)
{
- uint i;
+ uint i, size_entries, num_column_values;
uint list_index= 0;
part_elem_value *list_value;
bool result= TRUE;
- longlong curr_value, prev_value, type_add, calc_value;
+ longlong type_add, calc_value;
+ void *curr_value, *prev_value;
partition_element* part_def;
bool found_null= FALSE;
+ int (*compare_func)(const void *, const void*);
+ void *ptr;
List_iterator<partition_element> list_func_it(partitions);
DBUG_ENTER("partition_info::check_list_constants");
part_result_type= INT_RESULT;
- no_list_values= 0;
+ num_list_values= 0;
/*
We begin by calculating the number of list values that have been
defined in the first step.
@@ -762,51 +894,86 @@ bool partition_info::check_list_constants()
}
List_iterator<part_elem_value> list_val_it1(part_def->list_val_list);
while (list_val_it1++)
- no_list_values++;
- } while (++i < no_parts);
+ num_list_values++;
+ } while (++i < num_parts);
list_func_it.rewind();
- list_array= (LIST_PART_ENTRY*)sql_alloc((no_list_values+1) *
- sizeof(LIST_PART_ENTRY));
- if (unlikely(list_array == NULL))
+ num_column_values= part_field_list.elements;
+ size_entries= column_list ?
+ (num_column_values * sizeof(part_column_list_val)) :
+ sizeof(LIST_PART_ENTRY);
+ ptr= sql_calloc((num_list_values+1) * size_entries);
+ if (unlikely(ptr == NULL))
{
- mem_alloc_error(no_list_values * sizeof(LIST_PART_ENTRY));
+ mem_alloc_error(num_list_values * size_entries);
goto end;
}
-
- i= 0;
- /*
- Fix to be able to reuse signed sort functions also for unsigned
- partition functions.
- */
- type_add= (longlong)(part_expr->unsigned_flag ?
+ if (column_list)
+ {
+ part_column_list_val *loc_list_col_array;
+ loc_list_col_array= (part_column_list_val*)ptr;
+ list_col_array= (part_column_list_val*)ptr;
+ compare_func= compare_column_values;
+ i= 0;
+ do
+ {
+ part_def= list_func_it++;
+ List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
+ while ((list_value= list_val_it2++))
+ {
+ part_column_list_val *col_val= list_value->col_val_array;
+ if (unlikely(fix_column_value_functions(thd, list_value, i)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ memcpy(loc_list_col_array, (const void*)col_val, size_entries);
+ loc_list_col_array+= num_column_values;
+ }
+ } while (++i < num_parts);
+ }
+ else
+ {
+ compare_func= list_part_cmp;
+ list_array= (LIST_PART_ENTRY*)ptr;
+ i= 0;
+ /*
+ Fix to be able to reuse signed sort functions also for unsigned
+ partition functions.
+ */
+ type_add= (longlong)(part_expr->unsigned_flag ?
0x8000000000000000ULL :
0ULL);
- do
- {
- part_def= list_func_it++;
- List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
- while ((list_value= list_val_it2++))
+ do
{
- calc_value= list_value->value - type_add;
- list_array[list_index].list_value= calc_value;
- list_array[list_index++].partition_id= i;
- }
- } while (++i < no_parts);
-
- if (fixed && no_list_values)
+ part_def= list_func_it++;
+ List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
+ while ((list_value= list_val_it2++))
+ {
+ calc_value= list_value->value - type_add;
+ list_array[list_index].list_value= calc_value;
+ list_array[list_index++].partition_id= i;
+ }
+ } while (++i < num_parts);
+ }
+ DBUG_ASSERT(fixed);
+ if (num_list_values)
{
bool first= TRUE;
- my_qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY),
- &list_part_cmp);
-
+ /*
+ list_array and list_col_array are unions, so this works for both
+ variants of LIST partitioning.
+ */
+ my_qsort((void*)list_array, num_list_values, size_entries,
+ compare_func);
+
i= 0;
LINT_INIT(prev_value);
do
{
- DBUG_ASSERT(i < no_list_values);
- curr_value= list_array[i].list_value;
- if (likely(first || prev_value != curr_value))
+ DBUG_ASSERT(i < num_list_values);
+ curr_value= column_list ? (void*)&list_col_array[num_column_values * i] :
+ (void*)&list_array[i];
+ if (likely(first || compare_func(curr_value, prev_value)))
{
prev_value= curr_value;
first= FALSE;
@@ -816,7 +983,7 @@ bool partition_info::check_list_constants()
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
goto end;
}
- } while (++i < no_list_values);
+ } while (++i < num_list_values);
}
result= FALSE;
end:
@@ -829,10 +996,11 @@ end:
SYNOPSIS
check_partition_info()
+ thd Thread object
+ eng_type Return value for used engine in partitions
file A reference to a handler of the table
info Create info
- engine_type Return value for used engine in partitions
- check_partition_function Should we check the partition function
+ add_or_reorg_part Is it ALTER TABLE ADD/REORGANIZE command
RETURN VALUE
TRUE Error, something went wrong
@@ -848,7 +1016,7 @@ end:
bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
handler *file, HA_CREATE_INFO *info,
- bool check_partition_function)
+ bool add_or_reorg_part)
{
handlerton *table_engine= default_engine_type;
uint i, tot_partitions;
@@ -859,11 +1027,11 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
DBUG_PRINT("info", ("default table_engine = %s",
ha_resolve_storage_engine_name(table_engine)));
- if (check_partition_function)
+ if (!add_or_reorg_part)
{
int err= 0;
- if (part_type != HASH_PARTITION || !list_of_part_fields)
+ if (!list_of_part_fields)
{
DBUG_ASSERT(part_expr);
err= part_expr->walk(&Item::check_partition_func_processor, 0,
@@ -877,9 +1045,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
goto end;
}
+ if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
+ fix_parser_data(thd))
+ goto end;
}
if (unlikely(!is_sub_partitioned() &&
- !(use_default_subpartitions && use_default_no_subpartitions)))
+ !(use_default_subpartitions && use_default_num_subpartitions)))
{
my_error(ER_SUBPARTITION_ERROR, MYF(0));
goto end;
@@ -937,6 +1108,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
}
}
+ if (part_field_list.elements > 0 &&
+ (same_name= has_unique_fields()))
+ {
+ my_error(ER_SAME_NAME_PARTITION_FIELD, MYF(0), same_name);
+ goto end;
+ }
if ((same_name= has_unique_names()))
{
my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
@@ -945,8 +1122,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
i= 0;
{
List_iterator<partition_element> part_it(partitions);
- uint no_parts_not_set= 0;
- uint prev_no_subparts_not_set= no_subparts + 1;
+ uint num_parts_not_set= 0;
+ uint prev_num_subparts_not_set= num_subparts + 1;
do
{
partition_element *part_elem= part_it++;
@@ -968,7 +1145,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
{
if (part_elem->engine_type == NULL)
{
- no_parts_not_set++;
+ num_parts_not_set++;
part_elem->engine_type= default_engine_type;
}
if (check_table_name(part_elem->partition_name,
@@ -983,7 +1160,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
else
{
uint j= 0;
- uint no_subparts_not_set= 0;
+ uint num_subparts_not_set= 0;
List_iterator<partition_element> sub_it(part_elem->subpartitions);
partition_element *sub_elem;
do
@@ -1002,44 +1179,45 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
else
{
sub_elem->engine_type= default_engine_type;
- no_subparts_not_set++;
+ num_subparts_not_set++;
}
}
DBUG_PRINT("info", ("part = %d sub = %d engine = %s", i, j,
ha_resolve_storage_engine_name(sub_elem->engine_type)));
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
- if (prev_no_subparts_not_set == (no_subparts + 1) &&
- (no_subparts_not_set == 0 || no_subparts_not_set == no_subparts))
- prev_no_subparts_not_set= no_subparts_not_set;
+ if (prev_num_subparts_not_set == (num_subparts + 1) &&
+ (num_subparts_not_set == 0 ||
+ num_subparts_not_set == num_subparts))
+ prev_num_subparts_not_set= num_subparts_not_set;
if (!table_engine_set &&
- prev_no_subparts_not_set != no_subparts_not_set)
+ prev_num_subparts_not_set != num_subparts_not_set)
{
- DBUG_PRINT("info", ("no_subparts_not_set = %u no_subparts = %u",
- no_subparts_not_set, no_subparts));
+ DBUG_PRINT("info", ("num_subparts_not_set = %u num_subparts = %u",
+ num_subparts_not_set, num_subparts));
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
}
if (part_elem->engine_type == NULL)
{
- if (no_subparts_not_set == 0)
+ if (num_subparts_not_set == 0)
part_elem->engine_type= sub_elem->engine_type;
else
{
- no_parts_not_set++;
+ num_parts_not_set++;
part_elem->engine_type= default_engine_type;
}
}
}
- } while (++i < no_parts);
+ } while (++i < num_parts);
if (!table_engine_set &&
- no_parts_not_set != 0 &&
- no_parts_not_set != no_parts)
+ num_parts_not_set != 0 &&
+ num_parts_not_set != num_parts)
{
- DBUG_PRINT("info", ("no_parts_not_set = %u no_parts = %u",
- no_parts_not_set, no_subparts));
+ DBUG_PRINT("info", ("num_parts_not_set = %u num_parts = %u",
+ num_parts_not_set, num_subparts));
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
}
@@ -1062,10 +1240,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
list constants.
*/
- if (fixed)
+ if (add_or_reorg_part)
{
- if (unlikely((part_type == RANGE_PARTITION && check_range_constants()) ||
- (part_type == LIST_PARTITION && check_list_constants())))
+ if (unlikely((part_type == RANGE_PARTITION &&
+ check_range_constants(thd)) ||
+ (part_type == LIST_PARTITION &&
+ check_list_constants(thd))))
goto end;
}
result= FALSE;
@@ -1096,20 +1276,101 @@ void partition_info::print_no_partition_found(TABLE *table)
if (check_single_table_access(current_thd,
SELECT_ACL, &table_list, TRUE))
+ {
my_message(ER_NO_PARTITION_FOR_GIVEN_VALUE,
ER(ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT), MYF(0));
+ }
else
{
- my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
- if (part_expr->null_value)
- buf_ptr= (char*)"NULL";
+ if (column_list)
+ buf_ptr= (char*)"from column_list";
else
- longlong2str(err_value, buf,
- part_expr->unsigned_flag ? 10 : -10);
+ {
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+ if (part_expr->null_value)
+ buf_ptr= (char*)"NULL";
+ else
+ longlong2str(err_value, buf,
+ part_expr->unsigned_flag ? 10 : -10);
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+ }
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf_ptr);
- dbug_tmp_restore_column_map(table->read_set, old_map);
}
}
+
+
+/*
+ Set fields related to partition expression
+ SYNOPSIS
+ set_part_expr()
+ start_token Start of partition function string
+ item_ptr Pointer to item tree
+ end_token End of partition function string
+ is_subpart Subpartition indicator
+ RETURN VALUES
+ TRUE Memory allocation error
+ FALSE Success
+*/
+
+bool partition_info::set_part_expr(char *start_token, Item *item_ptr,
+ char *end_token, bool is_subpart)
+{
+ uint expr_len= end_token - start_token;
+ char *func_string= (char*) sql_memdup(start_token, expr_len);
+
+ if (!func_string)
+ {
+ mem_alloc_error(expr_len);
+ return TRUE;
+ }
+ if (is_subpart)
+ {
+ list_of_subpart_fields= FALSE;
+ subpart_expr= item_ptr;
+ subpart_func_string= func_string;
+ subpart_func_len= expr_len;
+ }
+ else
+ {
+ list_of_part_fields= FALSE;
+ part_expr= item_ptr;
+ part_func_string= func_string;
+ part_func_len= expr_len;
+ }
+ return FALSE;
+}
+
+
+/*
+ Check that partition fields and subpartition fields are not too long
+
+ SYNOPSIS
+ check_partition_field_length()
+
+ RETURN VALUES
+ TRUE Total length was too big
+ FALSE Length is ok
+*/
+
+bool partition_info::check_partition_field_length()
+{
+ uint store_length= 0;
+ uint i;
+ DBUG_ENTER("partition_info::check_partition_field_length");
+
+ for (i= 0; i < num_part_fields; i++)
+ store_length+= get_partition_field_store_length(part_field_array[i]);
+ if (store_length > MAX_KEY_LENGTH)
+ DBUG_RETURN(TRUE);
+ store_length= 0;
+ for (i= 0; i < num_subpart_fields; i++)
+ store_length+= get_partition_field_store_length(subpart_field_array[i]);
+ if (store_length > MAX_KEY_LENGTH)
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
+}
+
+
/*
Set up buffers and arrays for fields requiring preparation
SYNOPSIS
@@ -1221,46 +1482,6 @@ bool partition_info::set_up_charset_field_preps()
}
subpart_charset_field_array[i]= NULL;
}
- if (tot_fields)
- {
- uint k;
- size= tot_fields*sizeof(char**);
- if (!(char_ptrs= (uchar**)sql_calloc(size)))
- goto error;
- full_part_field_buffers= char_ptrs;
- if (!(char_ptrs= (uchar**)sql_calloc(size)))
- goto error;
- restore_full_part_field_ptrs= char_ptrs;
- size= (tot_fields + 1) * sizeof(char**);
- if (!(char_ptrs= (uchar**)sql_calloc(size)))
- goto error;
- full_part_charset_field_array= (Field**)char_ptrs;
- for (i= 0; i < tot_part_fields; i++)
- {
- full_part_charset_field_array[i]= part_charset_field_array[i];
- full_part_field_buffers[i]= part_field_buffers[i];
- }
- k= tot_part_fields;
- for (i= 0; i < tot_subpart_fields; i++)
- {
- uint j;
- bool found= FALSE;
- field= subpart_charset_field_array[i];
-
- for (j= 0; j < tot_part_fields; j++)
- {
- if (field == part_charset_field_array[i])
- found= TRUE;
- }
- if (!found)
- {
- full_part_charset_field_array[k]= subpart_charset_field_array[i];
- full_part_field_buffers[k]= subpart_field_buffers[i];
- k++;
- }
- }
- full_part_charset_field_array[k]= NULL;
- }
DBUG_RETURN(FALSE);
error:
mem_alloc_error(size);
@@ -1321,5 +1542,636 @@ id_err:
return 1;
}
+/*
+ Create a new column value in current list with maxvalue
+ Called from parser
+
+ SYNOPSIS
+ add_max_value()
+ RETURN
+ TRUE Error
+ FALSE Success
+*/
+
+int partition_info::add_max_value()
+{
+ DBUG_ENTER("partition_info::add_max_value");
+
+ part_column_list_val *col_val;
+ if (!(col_val= add_column_value()))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ col_val->max_value= TRUE;
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ Create a new column value in current list
+ Called from parser
+
+ SYNOPSIS
+ add_column_value()
+ RETURN
+ >0 A part_column_list_val object which have been
+ inserted into its list
+ 0 Memory allocation failure
+*/
+
+part_column_list_val *partition_info::add_column_value()
+{
+ uint max_val= num_columns ? num_columns : MAX_REF_PARTS;
+ DBUG_ENTER("add_column_value");
+ DBUG_PRINT("enter", ("num_columns = %u, curr_list_object %u, max_val = %u",
+ num_columns, curr_list_object, max_val));
+ if (curr_list_object < max_val)
+ {
+ curr_list_val->added_items++;
+ DBUG_RETURN(&curr_list_val->col_val_array[curr_list_object++]);
+ }
+ if (!num_columns && part_type == LIST_PARTITION)
+ {
+ /*
+ We're trying to add more than MAX_REF_PARTS, this can happen
+ in ALTER TABLE using List partitions where the first partition
+ uses VALUES IN (1,2,3...,17) where the number of fields in
+ the list is more than MAX_REF_PARTS, in this case we know
+ that the number of columns must be 1 and we thus reorganize
+ into the structure used for 1 column. After this we call
+ ourselves recursively which should always succeed.
+ */
+ if (!reorganize_into_single_field_col_val())
+ {
+ DBUG_RETURN(add_column_value());
+ }
+ DBUG_RETURN(NULL);
+ }
+ if (column_list)
+ {
+ my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
+ }
+ else
+ {
+ if (part_type == RANGE_PARTITION)
+ my_error(ER_TOO_MANY_VALUES_ERROR, MYF(0), "RANGE");
+ else
+ my_error(ER_TOO_MANY_VALUES_ERROR, MYF(0), "LIST");
+ }
+ DBUG_RETURN(NULL);
+}
+
+
+/*
+ Initialise part_elem_value object at setting of a new object
+ (Helper functions to functions called by parser)
+
+ SYNOPSIS
+ init_col_val
+ col_val Column value object to be initialised
+ item Item object representing column value
+
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+*/
+void partition_info::init_col_val(part_column_list_val *col_val, Item *item)
+{
+ DBUG_ENTER("partition_info::init_col_val");
+
+ col_val->item_expression= item;
+ col_val->null_value= item->null_value;
+ if (item->result_type() == INT_RESULT)
+ {
+ /*
+ This could be both column_list partitioning and function
+ partitioning, but it doesn't hurt to set the function
+ partitioning flags about unsignedness.
+ */
+ curr_list_val->value= item->val_int();
+ curr_list_val->unsigned_flag= TRUE;
+ if (!item->unsigned_flag &&
+ curr_list_val->value < 0)
+ curr_list_val->unsigned_flag= FALSE;
+ if (!curr_list_val->unsigned_flag)
+ curr_part_elem->signed_flag= TRUE;
+ }
+ col_val->part_info= NULL;
+ DBUG_VOID_RETURN;
+}
+/*
+ Add a column value in VALUES LESS THAN or VALUES IN
+ (Called from parser)
+
+ SYNOPSIS
+ add_column_list_value()
+ lex Parser's lex object
+ thd Thread object
+ item Item object representing column value
+
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+*/
+bool partition_info::add_column_list_value(THD *thd, Item *item)
+{
+ part_column_list_val *col_val;
+ Name_resolution_context *context= &thd->lex->current_select->context;
+ TABLE_LIST *save_list= context->table_list;
+ const char *save_where= thd->where;
+ DBUG_ENTER("partition_info::add_column_list_value");
+
+ if (part_type == LIST_PARTITION &&
+ num_columns == 1U)
+ {
+ if (init_column_part())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ context->table_list= 0;
+ if (column_list)
+ thd->where= "field list";
+ else
+ thd->where= "partition function";
+
+ if (item->walk(&Item::check_partition_func_processor, 0,
+ NULL))
+ {
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (item->fix_fields(thd, (Item**)0) ||
+ ((context->table_list= save_list), FALSE) ||
+ (!item->const_item()))
+ {
+ context->table_list= save_list;
+ thd->where= save_where;
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ thd->where= save_where;
+
+ if (!(col_val= add_column_value()))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ init_col_val(col_val, item);
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ Initialise part_info object for receiving a set of column values
+ for a partition, called when parser reaches VALUES LESS THAN or
+ VALUES IN.
+
+ SYNOPSIS
+ init_column_part()
+ lex Parser's lex object
+
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+*/
+bool partition_info::init_column_part()
+{
+ partition_element *p_elem= curr_part_elem;
+ part_column_list_val *col_val_array;
+ part_elem_value *list_val;
+ uint loc_num_columns;
+ DBUG_ENTER("partition_info::init_column_part");
+
+ if (!(list_val=
+ (part_elem_value*)sql_calloc(sizeof(part_elem_value))) ||
+ p_elem->list_val_list.push_back(list_val))
+ {
+ mem_alloc_error(sizeof(part_elem_value));
+ DBUG_RETURN(TRUE);
+ }
+ if (num_columns)
+ loc_num_columns= num_columns;
+ else
+ loc_num_columns= MAX_REF_PARTS;
+ if (!(col_val_array=
+ (part_column_list_val*)sql_calloc(loc_num_columns *
+ sizeof(part_column_list_val))))
+ {
+ mem_alloc_error(loc_num_columns * sizeof(part_elem_value));
+ DBUG_RETURN(TRUE);
+ }
+ list_val->col_val_array= col_val_array;
+ list_val->added_items= 0;
+ curr_list_val= list_val;
+ curr_list_object= 0;
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ In the case of ALTER TABLE ADD/REORGANIZE PARTITION for LIST
+ partitions we can specify list values as:
+ VALUES IN (v1, v2,,,, v17) if we're using the first partitioning
+ variant with a function or a column list partitioned table with
+ one partition field. In this case the parser knows not the
+ number of columns start with and allocates MAX_REF_PARTS in the
+ array. If we try to allocate something beyond MAX_REF_PARTS we
+ will call this function to reorganize into a structure with
+ num_columns = 1. Also when the parser knows that we used LIST
+ partitioning and we used a VALUES IN like above where number of
+ values was smaller than MAX_REF_PARTS or equal, then we will
+ reorganize after discovering this in the parser.
+
+ SYNOPSIS
+ reorganize_into_single_field_col_val()
+
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+*/
+int partition_info::reorganize_into_single_field_col_val()
+{
+ part_column_list_val *col_val, *new_col_val;
+ part_elem_value *val= curr_list_val;
+ uint loc_num_columns= num_columns;
+ uint i;
+ DBUG_ENTER("partition_info::reorganize_into_single_field_col_val");
+
+ num_columns= 1;
+ val->added_items= 1U;
+ col_val= &val->col_val_array[0];
+ init_col_val(col_val, col_val->item_expression);
+ for (i= 1; i < loc_num_columns; i++)
+ {
+ col_val= &val->col_val_array[i];
+ DBUG_ASSERT(part_type == LIST_PARTITION);
+ if (init_column_part())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if (!(new_col_val= add_column_value()))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ memcpy(new_col_val, col_val, sizeof(*col_val));
+ init_col_val(new_col_val, col_val->item_expression);
+ }
+ curr_list_val= val;
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ This function handles the case of function-based partitioning.
+ It fixes some data structures created in the parser and puts
+ them in the format required by the rest of the partitioning
+ code.
+
+ SYNOPSIS
+ fix_func_partition()
+ thd Thread object
+ col_val Array of one value
+ part_elem The partition instance
+ part_id Id of partition instance
+
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+*/
+int partition_info::fix_func_partition(THD *thd,
+ part_elem_value *val,
+ partition_element *part_elem,
+ uint part_id)
+{
+ part_column_list_val *col_val= val->col_val_array;
+ DBUG_ENTER("partition_info::fix_func_partition");
+
+ if (col_val->fixed)
+ {
+ DBUG_RETURN(FALSE);
+ }
+ if (val->added_items != 1)
+ {
+ my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (col_val->max_value)
+ {
+ /* The parser ensures we're not LIST partitioned here */
+ DBUG_ASSERT(part_type == RANGE_PARTITION);
+ if (defined_max_value)
+ {
+ my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (part_id == (num_parts - 1))
+ {
+ defined_max_value= TRUE;
+ part_elem->max_value= TRUE;
+ part_elem->range_value= LONGLONG_MAX;
+ }
+ else
+ {
+ my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ }
+ else
+ {
+ Item *item_expr= col_val->item_expression;
+ if ((val->null_value= item_expr->null_value))
+ {
+ if (part_elem->has_null_value)
+ {
+ my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ part_elem->has_null_value= TRUE;
+ }
+ else if (item_expr->result_type() != INT_RESULT)
+ {
+ my_error(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (part_type == RANGE_PARTITION)
+ {
+ if (part_elem->has_null_value)
+ {
+ my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ part_elem->range_value= val->value;
+ }
+ }
+ col_val->fixed= 2;
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ Get column item with a proper character set according to the field
+
+ SYNOPSIS
+ get_column_item()
+ item Item object to start with
+ field Field for which the item will be compared to
+
+ RETURN VALUES
+ NULL Error
+ item Returned item
+*/
+
+Item* partition_info::get_column_item(Item *item, Field *field)
+{
+ if (field->result_type() == STRING_RESULT &&
+ item->collation.collation != field->charset())
+ {
+ if (!(item= convert_charset_partition_constant(item,
+ field->charset())))
+ {
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ return NULL;
+ }
+ }
+ return item;
+}
+
+
+/*
+ Evaluate VALUES functions for column list values
+ SYNOPSIS
+ fix_column_value_functions()
+ thd Thread object
+ col_val List of column values
+ part_id Partition id we are fixing
+
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ Fix column VALUES and store in memory array adapted to the data type
+*/
+
+bool partition_info::fix_column_value_functions(THD *thd,
+ part_elem_value *val,
+ uint part_id)
+{
+ uint num_columns= part_field_list.elements;
+ bool result= FALSE;
+ uint i;
+ part_column_list_val *col_val= val->col_val_array;
+ DBUG_ENTER("partition_info::fix_column_value_functions");
+
+ if (col_val->fixed > 1)
+ {
+ DBUG_RETURN(FALSE);
+ }
+ for (i= 0; i < num_columns; col_val++, i++)
+ {
+ Item *column_item= col_val->item_expression;
+ Field *field= part_field_array[i];
+ col_val->part_info= this;
+ col_val->partition_id= part_id;
+ if (col_val->max_value)
+ col_val->column_value= NULL;
+ else
+ {
+ col_val->column_value= NULL;
+ if (!col_val->null_value)
+ {
+ uchar *val_ptr;
+ uint len= field->pack_length();
+ ulong save_sql_mode;
+ bool save_got_warning;
+
+ if (!(column_item= get_column_item(column_item,
+ field)))
+ {
+ result= TRUE;
+ goto end;
+ }
+ save_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode= 0;
+ save_got_warning= thd->got_warning;
+ thd->got_warning= 0;
+ if (column_item->save_in_field(field, TRUE) ||
+ thd->got_warning)
+ {
+ my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
+ result= TRUE;
+ goto end;
+ }
+ thd->got_warning= save_got_warning;
+ thd->variables.sql_mode= save_sql_mode;
+ if (!(val_ptr= (uchar*) sql_calloc(len)))
+ {
+ mem_alloc_error(len);
+ result= TRUE;
+ goto end;
+ }
+ col_val->column_value= val_ptr;
+ memcpy(val_ptr, field->ptr, len);
+ }
+ }
+ col_val->fixed= 2;
+ }
+end:
+ DBUG_RETURN(result);
+}
+
+/*
+ The parser generates generic data structures, we need to set them up
+ as the rest of the code expects to find them. This is in reality part
+ of the syntax check of the parser code.
+
+ It is necessary to call this function in the case of a CREATE TABLE
+ statement, in this case we do it early in the check_partition_info
+ function.
+
+ It is necessary to call this function for ALTER TABLE where we
+ assign a completely new partition structure, in this case we do it
+ in prep_alter_part_table after discovering that the partition
+ structure is entirely redefined.
+
+ It's necessary to call this method also for ALTER TABLE ADD/REORGANIZE
+ of partitions, in this we call it in prep_alter_part_table after
+ making some initial checks but before going deep to check the partition
+ info, we also assign the column_list variable before calling this function
+ here.
+
+ Finally we also call it immediately after returning from parsing the
+ partitioning text found in the frm file.
+
+ This function mainly fixes the VALUES parts, these are handled differently
+ whether or not we use column list partitioning. Since the parser doesn't
+ know which we are using we need to set-up the old data structures after
+ the parser is complete when we know if what type of partitioning the
+ base table is using.
+
+ For column lists we will handle this in the fix_column_value_function.
+ For column lists it is sufficient to verify that the number of columns
+ and number of elements are in synch with each other. So only partitioning
+ using functions need to be set-up to their data structures.
+
+ SYNOPSIS
+ fix_parser_data()
+ thd Thread object
+
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+*/
+
+int partition_info::fix_parser_data(THD *thd)
+{
+ List_iterator<partition_element> it(partitions);
+ partition_element *part_elem;
+ uint num_elements;
+ uint i= 0, j, k;
+ DBUG_ENTER("partition_info::fix_parser_data");
+
+ if (!(part_type == RANGE_PARTITION ||
+ part_type == LIST_PARTITION))
+ {
+ /* Nothing to do for HASH/KEY partitioning */
+ DBUG_RETURN(FALSE);
+ }
+ do
+ {
+ part_elem= it++;
+ List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
+ j= 0;
+ num_elements= part_elem->list_val_list.elements;
+ DBUG_ASSERT(part_type == RANGE_PARTITION ?
+ num_elements == 1U : TRUE);
+ do
+ {
+ part_elem_value *val= list_val_it++;
+ if (column_list)
+ {
+ if (val->added_items != num_columns)
+ {
+ my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ for (k= 0; k < num_columns; k++)
+ {
+ part_column_list_val *col_val= &val->col_val_array[k];
+ if (col_val->null_value && part_type == RANGE_PARTITION)
+ {
+ my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ else
+ {
+ if (fix_func_partition(thd, val, part_elem, i))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if (val->null_value)
+ {
+ /*
+ Null values aren't required in the value part, they are kept per
+ partition instance, only LIST partitions have NULL values.
+ */
+ list_val_it.remove();
+ }
+ }
+ } while (++j < num_elements);
+ } while (++i < num_parts);
+ DBUG_RETURN(FALSE);
+}
+
+void partition_info::print_debug(const char *str, uint *value)
+{
+ DBUG_ENTER("print_debug");
+ if (value)
+ DBUG_PRINT("info", ("parser: %s, val = %u", str, *value));
+ else
+ DBUG_PRINT("info", ("parser: %s", str));
+ DBUG_VOID_RETURN;
+}
+#else /* WITH_PARTITION_STORAGE_ENGINE */
+ /*
+ For builds without partitioning we need to define these functions
+ since we they are called from the parser. The parser cannot
+ remove code parts using ifdef, but the code parts cannot be called
+ so we simply need to add empty functions to make the linker happy.
+ */
+part_column_list_val *partition_info::add_column_value()
+{
+ return NULL;
+}
+
+bool partition_info::set_part_expr(char *start_token, Item *item_ptr,
+ char *end_token, bool is_subpart)
+{
+ (void)start_token;
+ (void)item_ptr;
+ (void)end_token;
+ (void)is_subpart;
+ return FALSE;
+}
+
+int partition_info::reorganize_into_single_field_col_val()
+{
+ return 0;
+}
+
+bool partition_info::init_column_part()
+{
+ return FALSE;
+}
+
+bool partition_info::add_column_list_value(THD *thd, Item *item)
+{
+ return FALSE;
+}
+int partition_info::add_max_value()
+{
+ return 0;
+}
+
+void partition_info::print_debug(const char *str, uint *value)
+{
+}
#endif /* WITH_PARTITION_STORAGE_ENGINE */
diff --git a/sql/partition_info.h b/sql/partition_info.h
index b5a6c4a0961..0ac8dec4945 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -1,7 +1,7 @@
#ifndef PARTITION_INFO_INCLUDED
#define PARTITION_INFO_INCLUDED
-/* Copyright 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -67,10 +67,9 @@ public:
/*
When we have various string fields we might need some preparation
before and clean-up after calling the get_part_id_func's. We need
- one such method for get_partition_id and one for
- get_part_partition_id and one for get_subpartition_id.
+ one such method for get_part_partition_id and one for
+ get_subpartition_id.
*/
- get_part_id_func get_partition_id_charset;
get_part_id_func get_part_partition_id_charset;
get_subpart_id_func get_subpartition_id_charset;
@@ -84,7 +83,6 @@ public:
without duplicates, NULL-terminated.
*/
Field **full_part_field_array;
- Field **full_part_charset_field_array;
/*
Set of all fields used in partition and subpartition expression.
Required for testing of partition fields in write_set when
@@ -100,10 +98,8 @@ public:
*/
uchar **part_field_buffers;
uchar **subpart_field_buffers;
- uchar **full_part_field_buffers;
uchar **restore_part_field_ptrs;
uchar **restore_subpart_field_ptrs;
- uchar **restore_full_part_field_ptrs;
Item *part_expr;
Item *subpart_expr;
@@ -127,6 +123,8 @@ public:
union {
longlong *range_int_array;
LIST_PART_ENTRY *list_array;
+ part_column_list_val *range_col_array;
+ part_column_list_val *list_col_array;
};
/********************************************
@@ -157,6 +155,10 @@ public:
partition_element *curr_part_elem;
partition_element *current_partition;
+ part_elem_value *curr_list_val;
+ uint curr_list_object;
+ uint num_columns;
+
/*
These key_map's are used for Partitioning to enable quick decisions
on whether we can derive more information about which partition to
@@ -175,17 +177,17 @@ public:
uint part_func_len;
uint subpart_func_len;
- uint no_parts;
- uint no_subparts;
+ uint num_parts;
+ uint num_subparts;
uint count_curr_subparts;
uint part_error_code;
- uint no_list_values;
+ uint num_list_values;
- uint no_part_fields;
- uint no_subpart_fields;
- uint no_full_part_fields;
+ uint num_part_fields;
+ uint num_subpart_fields;
+ uint num_full_part_fields;
uint has_null_part_id;
/*
@@ -196,9 +198,9 @@ public:
uint16 linear_hash_mask;
bool use_default_partitions;
- bool use_default_no_partitions;
+ bool use_default_num_partitions;
bool use_default_subpartitions;
- bool use_default_no_subpartitions;
+ bool use_default_num_subpartitions;
bool default_partitions_setup;
bool defined_max_value;
bool list_of_part_fields;
@@ -208,7 +210,7 @@ public:
bool is_auto_partitioned;
bool from_openfrm;
bool has_null_value;
-
+ bool column_list;
partition_info()
: get_partition_id(NULL), get_part_partition_id(NULL),
@@ -217,11 +219,8 @@ public:
part_charset_field_array(NULL),
subpart_charset_field_array(NULL),
full_part_field_array(NULL),
- full_part_charset_field_array(NULL),
part_field_buffers(NULL), subpart_field_buffers(NULL),
- full_part_field_buffers(NULL),
restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL),
- restore_full_part_field_ptrs(NULL),
part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL),
list_array(NULL), err_value(0),
@@ -229,22 +228,23 @@ public:
part_func_string(NULL), subpart_func_string(NULL),
part_state(NULL),
curr_part_elem(NULL), current_partition(NULL),
+ curr_list_object(0), num_columns(0),
default_engine_type(NULL),
part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
part_info_len(0), part_state_len(0),
part_func_len(0), subpart_func_len(0),
- no_parts(0), no_subparts(0),
+ num_parts(0), num_subparts(0),
count_curr_subparts(0), part_error_code(0),
- no_list_values(0), no_part_fields(0), no_subpart_fields(0),
- no_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
- use_default_partitions(TRUE), use_default_no_partitions(TRUE),
- use_default_subpartitions(TRUE), use_default_no_subpartitions(TRUE),
+ num_list_values(0), num_part_fields(0), num_subpart_fields(0),
+ num_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
+ use_default_partitions(TRUE), use_default_num_partitions(TRUE),
+ use_default_subpartitions(TRUE), use_default_num_subpartitions(TRUE),
default_partitions_setup(FALSE), defined_max_value(FALSE),
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
linear_hash_ind(FALSE), fixed(FALSE),
is_auto_partitioned(FALSE), from_openfrm(FALSE),
- has_null_value(FALSE)
+ has_null_value(FALSE), column_list(FALSE)
{
all_fields_in_PF.clear_all();
all_fields_in_PPF.clear_all();
@@ -267,27 +267,47 @@ public:
/* Returns the total number of partitions on the leaf level */
uint get_tot_partitions()
{
- return no_parts * (is_sub_partitioned() ? no_subparts : 1);
+ return num_parts * (is_sub_partitioned() ? num_subparts : 1);
}
bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info,
uint start_no);
+ char *has_unique_fields();
char *has_unique_names();
bool check_engine_mix(handlerton *engine_type, bool default_engine);
- bool check_range_constants();
- bool check_list_constants();
+ bool check_range_constants(THD *thd);
+ bool check_list_constants(THD *thd);
bool check_partition_info(THD *thd, handlerton **eng_type,
handler *file, HA_CREATE_INFO *info,
bool check_partition_function);
void print_no_partition_found(TABLE *table);
+ void print_debug(const char *str, uint*);
+ Item* get_column_item(Item *item, Field *field);
+ int fix_func_partition(THD *thd,
+ part_elem_value *val,
+ partition_element *part_elem,
+ uint part_id);
+ bool fix_column_value_functions(THD *thd,
+ part_elem_value *val,
+ uint part_id);
+ int fix_parser_data(THD *thd);
+ int add_max_value();
+ void init_col_val(part_column_list_val *col_val, Item *item);
+ int reorganize_into_single_field_col_val();
+ part_column_list_val *add_column_value();
+ bool set_part_expr(char *start_token, Item *item_ptr,
+ char *end_token, bool is_subpart);
+ static int compare_column_values(const void *a, const void *b);
bool set_up_charset_field_preps();
+ bool check_partition_field_length();
+ bool init_column_part();
+ bool add_column_list_value(THD *thd, Item *item);
private:
static int list_part_cmp(const void* a, const void* b);
- static int list_part_cmp_unsigned(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
uint start_no);
bool set_up_default_subpartitions(handler *file, HA_CREATE_INFO *info);
- char *create_default_partition_names(uint part_no, uint no_parts,
+ char *create_default_partition_names(uint part_no, uint num_parts,
uint start_no);
char *create_subpartition_name(uint subpart_no, const char *part_name);
bool has_unique_name(partition_element *element);
@@ -313,7 +333,7 @@ void init_all_partitions_iterator(partition_info *part_info,
PARTITION_ITERATOR *part_iter)
{
part_iter->part_nums.start= part_iter->part_nums.cur= 0;
- part_iter->part_nums.end= part_info->no_parts;
+ part_iter->part_nums.end= part_info->num_parts;
part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
part_iter->get_next= get_next_partition_id_range;
}
diff --git a/sql/procedure.h b/sql/procedure.h
index c6f50493876..25b30ac593d 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -26,7 +26,7 @@
#define PROC_NO_SORT 1 /**< Bits in flags */
#define PROC_GROUP 2 /**< proc must have group */
-/* Procedure items used by procedures to store values for send_fields */
+/* Procedure items used by procedures to store values for send_result_set_metadata */
class Item_proc :public Item
{
diff --git a/sql/protocol.cc b/sql/protocol.cc
index fcfa14310bb..5990f0f001a 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -28,6 +28,7 @@
#include <stdarg.h>
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
+/* Declared non-static only because of the embedded library. */
bool net_send_error_packet(THD *, uint, const char *, const char *);
/* Declared non-static only because of the embedded library. */
bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *);
@@ -141,6 +142,7 @@ bool Protocol::net_store_data(const uchar *from, size_t length,
bool net_send_error(THD *thd, uint sql_errno, const char *err,
const char* sqlstate)
{
+ bool error;
DBUG_ENTER("net_send_error");
DBUG_ASSERT(!thd->spcont);
@@ -148,7 +150,6 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err,
DBUG_ASSERT(err);
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
- bool error;
if (sqlstate == NULL)
sqlstate= mysql_errno_to_sqlstate(sql_errno);
@@ -397,32 +398,24 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
DBUG_RETURN(FALSE);
}
- if (net->return_errno)
- { // new client code; Add errno before message
- int2store(buff,sql_errno);
- pos= buff+2;
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- /* The first # is to make the protocol backward compatible */
- buff[2]= '#';
- pos= (uchar*) strmov((char*) buff+3, sqlstate);
- }
- converted_err_len= convert_error_message((char*)converted_err,
- sizeof(converted_err),
- thd->variables.character_set_results,
- err, strlen(err),
- system_charset_info, &error);
- length= (uint) (strmake((char*) pos, (char*)converted_err, MYSQL_ERRMSG_SIZE) -
- (char*) buff);
- err= (char*) buff;
- }
- else
+ int2store(buff,sql_errno);
+ pos= buff+2;
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
- length=(uint) strlen(err);
- set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
+ /* The first # is to make the protocol backward compatible */
+ buff[2]= '#';
+ pos= (uchar*) strmov((char*) buff+3, sqlstate);
}
+ converted_err_len= convert_error_message((char*)converted_err,
+ sizeof(converted_err),
+ thd->variables.character_set_results,
+ err, strlen(err),
+ system_charset_info, &error);
+ length= (uint) (strmake((char*) pos, (char*)converted_err, MYSQL_ERRMSG_SIZE) -
+ (char*) buff);
+ err= (char*) buff;
DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
- length));
+ length));
}
#endif /* EMBEDDED_LIBRARY */
@@ -486,6 +479,12 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
packet is "buffered" in the diagnostics area and sent to the client
in the end of statement.
+ @note This method defines a template, but delegates actual
+ sending of data to virtual Protocol::send_{ok,eof,error}. This
+ allows for implementation of protocols that "intercept" ok/eof/error
+ messages, and store them in memory, etc, instead of sending to
+ the client.
+
@pre The diagnostics area is assigned or disabled. It can not be empty
-- we assume that every SQL statement or COM_* command
generates OK, ERROR, or EOF status.
@@ -500,47 +499,94 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
Diagnostics_area::is_sent is set for debugging purposes only.
*/
-void net_end_statement(THD *thd)
+void Protocol::end_statement()
{
+ DBUG_ENTER("Protocol::end_statement");
DBUG_ASSERT(! thd->stmt_da->is_sent);
+ bool error= FALSE;
/* Can not be true, but do not take chances in production. */
if (thd->stmt_da->is_sent)
- return;
-
- bool error= FALSE;
+ DBUG_VOID_RETURN;
switch (thd->stmt_da->status()) {
case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */
- error= net_send_error(thd,
- thd->stmt_da->sql_errno(),
- thd->stmt_da->message(),
- thd->stmt_da->get_sqlstate());
+ error= send_error(thd->stmt_da->sql_errno(),
+ thd->stmt_da->message(),
+ thd->stmt_da->get_sqlstate());
break;
case Diagnostics_area::DA_EOF:
- error= net_send_eof(thd,
- thd->stmt_da->server_status(),
- thd->stmt_da->statement_warn_count());
+ error= send_eof(thd->stmt_da->server_status(),
+ thd->stmt_da->statement_warn_count());
break;
case Diagnostics_area::DA_OK:
- error= net_send_ok(thd,
- thd->stmt_da->server_status(),
- thd->stmt_da->statement_warn_count(),
- thd->stmt_da->affected_rows(),
- thd->stmt_da->last_insert_id(),
- thd->stmt_da->message());
+ error= send_ok(thd->stmt_da->server_status(),
+ thd->stmt_da->statement_warn_count(),
+ thd->stmt_da->affected_rows(),
+ thd->stmt_da->last_insert_id(),
+ thd->stmt_da->message());
break;
case Diagnostics_area::DA_DISABLED:
break;
case Diagnostics_area::DA_EMPTY:
default:
DBUG_ASSERT(0);
- error= net_send_ok(thd, thd->server_status, 0, 0, 0, NULL);
+ error= send_ok(thd->server_status, 0, 0, 0, NULL);
break;
}
if (!error)
thd->stmt_da->is_sent= TRUE;
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ A default implementation of "OK" packet response to the client.
+
+ Currently this implementation is re-used by both network-oriented
+ protocols -- the binary and text one. They do not differ
+ in their OK packet format, which allows for a significant simplification
+ on client side.
+*/
+
+bool Protocol::send_ok(uint server_status, uint statement_warn_count,
+ ulonglong affected_rows, ulonglong last_insert_id,
+ const char *message)
+{
+ DBUG_ENTER("Protocol::send_ok");
+
+ DBUG_RETURN(net_send_ok(thd, server_status, statement_warn_count,
+ affected_rows, last_insert_id, message));
+}
+
+
+/**
+ A default implementation of "EOF" packet response to the client.
+
+ Binary and text protocol do not differ in their EOF packet format.
+*/
+
+bool Protocol::send_eof(uint server_status, uint statement_warn_count)
+{
+ DBUG_ENTER("Protocol::send_eof");
+
+ DBUG_RETURN(net_send_eof(thd, server_status, statement_warn_count));
+}
+
+
+/**
+ A default implementation of "ERROR" packet response to the client.
+
+ Binary and text protocol do not differ in ERROR packet format.
+*/
+
+bool Protocol::send_error(uint sql_errno, const char *err_msg,
+ const char *sql_state)
+{
+ DBUG_ENTER("Protocol::send_error");
+
+ DBUG_RETURN(net_send_error_packet(thd, sql_errno, err_msg, sql_state));
}
@@ -597,9 +643,10 @@ void Protocol::init(THD *thd_arg)
for the error.
*/
-void Protocol::end_partial_result_set(THD *thd)
+void Protocol::end_partial_result_set(THD *thd_arg)
{
- net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
+ net_send_eof(thd_arg, thd_arg->server_status,
+ 0 /* no warnings, we're inside SP */);
}
@@ -632,16 +679,16 @@ bool Protocol::flush()
1 Error (Note that in this case the error is not sent to the
client)
*/
-bool Protocol::send_fields(List<Item> *list, uint flags)
+bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
- uchar buff[80];
+ uchar buff[MAX_FIELD_WIDTH];
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
Protocol_text prot(thd);
String *local_packet= prot.storage_packet();
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
- DBUG_ENTER("send_fields");
+ DBUG_ENTER("send_result_set_metadata");
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
@@ -786,7 +833,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
write_eof_packet(thd, &thd->net, thd->server_status,
thd->warning_info->statement_warn_count());
}
- DBUG_RETURN(prepare_for_send(list));
+ DBUG_RETURN(prepare_for_send(list->elements));
err:
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
@@ -805,6 +852,47 @@ bool Protocol::write()
/**
+ Send one result set row.
+
+ @param row_items a collection of column values for that row
+
+ @return Error status.
+ @retval TRUE Error.
+ @retval FALSE Success.
+*/
+
+bool Protocol::send_result_set_row(List<Item> *row_items)
+{
+ char buffer[MAX_FIELD_WIDTH];
+ String str_buffer(buffer, sizeof (buffer), &my_charset_bin);
+ List_iterator_fast<Item> it(*row_items);
+
+ DBUG_ENTER("Protocol::send_result_set_row");
+
+ for (Item *item= it++; item; item= it++)
+ {
+ if (item->send(this, &str_buffer))
+ {
+ // If we're out of memory, reclaim some, to help us recover.
+ this->free();
+ DBUG_RETURN(TRUE);
+ }
+ /* Item::send() may generate an error. If so, abort the loop. */
+ if (thd->is_error())
+ DBUG_RETURN(TRUE);
+
+ /*
+ Reset str_buffer to its original state, as it may have been altered in
+ Item::send().
+ */
+ str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
Send \\0 end terminated string.
@param from NullS or \\0 terminated string
@@ -850,7 +938,6 @@ bool Protocol::store(I_List<i_string>* str_list)
return store((char*) tmp.ptr(), len, tmp.charset());
}
-
/****************************************************************************
Functions to handle the simple (default) protocol where everything is
This protocol is the one that is used by default between the MySQL server
@@ -1129,6 +1216,53 @@ bool Protocol_text::store_time(MYSQL_TIME *tm)
return net_store_data((uchar*) buff, length);
}
+/**
+ Assign OUT-parameters to user variables.
+
+ @param sp_params List of PS/SP parameters (both input and output).
+
+ @return Error status.
+ @retval FALSE Success.
+ @retval TRUE Error.
+*/
+
+bool Protocol_text::send_out_parameters(List<Item_param> *sp_params)
+{
+ DBUG_ASSERT(sp_params->elements ==
+ thd->lex->prepared_stmt_params.elements);
+
+ List_iterator_fast<Item_param> item_param_it(*sp_params);
+ List_iterator_fast<LEX_STRING> user_var_name_it(thd->lex->prepared_stmt_params);
+
+ while (true)
+ {
+ Item_param *item_param= item_param_it++;
+ LEX_STRING *user_var_name= user_var_name_it++;
+
+ if (!item_param || !user_var_name)
+ break;
+
+ if (!item_param->get_out_param_info())
+ continue; // It's an IN-parameter.
+
+ Item_func_set_user_var *suv=
+ new Item_func_set_user_var(*user_var_name, item_param);
+ /*
+ Item_func_set_user_var is not fixed after construction, call
+ fix_fields().
+ */
+ if (suv->fix_fields(thd, NULL))
+ return TRUE;
+
+ if (suv->check(FALSE))
+ return TRUE;
+
+ if (suv->update())
+ return TRUE;
+ }
+
+ return FALSE;
+}
/****************************************************************************
Functions to handle the binary protocol used with prepared statements
@@ -1149,14 +1283,13 @@ bool Protocol_text::store_time(MYSQL_TIME *tm)
[..]..[[length]data] data
****************************************************************************/
-bool Protocol_binary::prepare_for_send(List<Item> *item_list)
+bool Protocol_binary::prepare_for_send(uint num_columns)
{
- Protocol::prepare_for_send(item_list);
+ Protocol::prepare_for_send(num_columns);
bit_fields= (field_count+9)/8;
- if (packet->alloc(bit_fields+1))
- return 1;
+ return packet->alloc(bit_fields+1);
+
/* prepare_for_resend will be called after this one */
- return 0;
}
@@ -1344,3 +1477,80 @@ bool Protocol_binary::store_time(MYSQL_TIME *tm)
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
}
+
+/**
+ Send a result set with OUT-parameter values by means of PS-protocol.
+
+ @param sp_params List of PS/SP parameters (both input and output).
+
+ @return Error status.
+ @retval FALSE Success.
+ @retval TRUE Error.
+*/
+
+bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
+{
+ if (!(thd->client_capabilities & CLIENT_PS_MULTI_RESULTS))
+ {
+ /* The client does not support OUT-parameters. */
+ return FALSE;
+ }
+
+ List<Item> out_param_lst;
+
+ {
+ List_iterator_fast<Item_param> item_param_it(*sp_params);
+
+ while (true)
+ {
+ Item_param *item_param= item_param_it++;
+
+ if (!item_param)
+ break;
+
+ if (!item_param->get_out_param_info())
+ continue; // It's an IN-parameter.
+
+ if (out_param_lst.push_back(item_param))
+ return TRUE;
+ }
+ }
+
+ if (!out_param_lst.elements)
+ return FALSE;
+
+ /*
+ We have to set SERVER_PS_OUT_PARAMS in THD::server_status, because it
+ is used in send_result_set_metadata().
+ */
+
+ thd->server_status|= SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS;
+
+ /* Send meta-data. */
+ if (send_result_set_metadata(&out_param_lst, SEND_NUM_ROWS | SEND_EOF))
+ return TRUE;
+
+ /* Send data. */
+
+ prepare_for_resend();
+
+ if (send_result_set_row(&out_param_lst))
+ return TRUE;
+
+ if (write())
+ return TRUE;
+
+ /* Restore THD::server_status. */
+ thd->server_status&= ~SERVER_PS_OUT_PARAMS;
+
+ /*
+ Reset SERVER_MORE_RESULTS_EXISTS bit, because this is the last packet
+ for sure.
+ */
+ thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
+
+ /* Send EOF-packet. */
+ net_send_eof(thd, thd->server_status, 0);
+
+ return FALSE;
+}
diff --git a/sql/protocol.h b/sql/protocol.h
index 2857ee2e3ca..142f7919d6f 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -24,6 +24,7 @@
class i_string;
class THD;
+class Item_param;
typedef struct st_mysql_field MYSQL_FIELD;
typedef struct st_mysql_rows MYSQL_ROWS;
@@ -50,6 +51,16 @@ protected:
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
bool store_string_aux(const char *from, size_t length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
+
+ virtual bool send_ok(uint server_status, uint statement_warn_count,
+ ulonglong affected_rows, ulonglong last_insert_id,
+ const char *message);
+
+ virtual bool send_eof(uint server_status, uint statement_warn_count);
+
+ virtual bool send_error(uint sql_errno, const char *err_msg,
+ const char *sql_state);
+
public:
Protocol() {}
Protocol(THD *thd_arg) { init(thd_arg); }
@@ -57,7 +68,8 @@ public:
void init(THD* thd_arg);
enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 };
- virtual bool send_fields(List<Item> *list, uint flags);
+ virtual bool send_result_set_metadata(List<Item> *list, uint flags);
+ bool send_result_set_row(List<Item> *row_items);
bool store(I_List<i_string> *str_list);
bool store(const char *from, CHARSET_INFO *cs);
@@ -75,9 +87,9 @@ public:
inline bool store(String *str)
{ return store((char*) str->ptr(), str->length(), str->charset()); }
- virtual bool prepare_for_send(List<Item> *item_list)
+ virtual bool prepare_for_send(uint num_columns)
{
- field_count=item_list->elements;
+ field_count= num_columns;
return 0;
}
virtual bool flush();
@@ -99,6 +111,8 @@ public:
virtual bool store_date(MYSQL_TIME *time)=0;
virtual bool store_time(MYSQL_TIME *time)=0;
virtual bool store(Field *field)=0;
+
+ virtual bool send_out_parameters(List<Item_param> *sp_params)=0;
#ifdef EMBEDDED_LIBRARY
int begin_dataset();
virtual void remove_last_row() {}
@@ -107,13 +121,15 @@ public:
#endif
enum enum_protocol_type
{
- PROTOCOL_TEXT= 0, PROTOCOL_BINARY= 1
/*
- before adding here or change the values, consider that it is cast to a
- bit in sql_cache.cc.
+ Before adding a new type, please make sure
+ there is enough storage for it in Query_cache_query_flags.
*/
+ PROTOCOL_TEXT= 0, PROTOCOL_BINARY= 1, PROTOCOL_LOCAL= 2
};
virtual enum enum_protocol_type type()= 0;
+
+ void end_statement();
};
@@ -140,6 +156,8 @@ public:
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
+
+ virtual bool send_out_parameters(List<Item_param> *sp_params);
#ifdef EMBEDDED_LIBRARY
void remove_last_row();
#endif
@@ -154,7 +172,7 @@ private:
public:
Protocol_binary() {}
Protocol_binary(THD *thd_arg) :Protocol(thd_arg) {}
- virtual bool prepare_for_send(List<Item> *item_list);
+ virtual bool prepare_for_send(uint num_columns);
virtual void prepare_for_resend();
#ifdef EMBEDDED_LIBRARY
virtual bool write();
@@ -175,13 +193,15 @@ public:
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
+
+ virtual bool send_out_parameters(List<Item_param> *sp_params);
+
virtual enum enum_protocol_type type() { return PROTOCOL_BINARY; };
};
void send_warning(THD *thd, uint sql_errno, const char *err=0);
bool net_send_error(THD *thd, uint sql_errno, const char *err,
const char* sqlstate);
-void net_end_statement(THD *thd);
bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
uchar *net_store_data(uchar *to,int32 from);
diff --git a/sql/records.cc b/sql/records.cc
index 9e040de3fda..8fd63d104a4 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -13,6 +13,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifdef USE_PRAGMA_INTERFACE
+#pragma implementation /* gcc class implementation */
+#endif
/**
@file
@@ -21,8 +24,10 @@
Functions for easy reading of records, possible through a cache
*/
+#include "records.h"
#include "mysql_priv.h"
+
static int rr_quick(READ_RECORD *info);
int rr_sequential(READ_RECORD *info);
static int rr_from_tempfile(READ_RECORD *info);
@@ -57,10 +62,12 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
{
empty_record(table);
bzero((char*) info,sizeof(*info));
+ info->thd= thd;
info->table= table;
info->file= table->file;
info->record= table->record[0];
info->print_error= print_error;
+ info->unlock_row= rr_unlock_row;
table->status=0; /* And it's always found */
if (!table->file->inited)
@@ -186,6 +193,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
}
info->select=select;
info->print_error=print_error;
+ info->unlock_row= rr_unlock_row;
info->ignore_not_found_rows= 0;
table->status=0; /* And it's always found */
@@ -292,6 +300,12 @@ void end_read_record(READ_RECORD *info)
static int rr_handle_error(READ_RECORD *info, int error)
{
+ if (info->thd->killed)
+ {
+ info->thd->send_kill_message();
+ return 1;
+ }
+
if (error == HA_ERR_END_OF_FILE)
error= -1;
else
@@ -312,12 +326,7 @@ static int rr_quick(READ_RECORD *info)
int tmp;
while ((tmp= info->select->quick->get_next()))
{
- if (info->thd->killed)
- {
- my_error(ER_SERVER_SHUTDOWN, MYF(0));
- return 1;
- }
- if (tmp != HA_ERR_RECORD_DELETED)
+ if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
{
tmp= rr_handle_error(info, tmp);
break;
@@ -380,16 +389,11 @@ int rr_sequential(READ_RECORD *info)
int tmp;
while ((tmp=info->file->rnd_next(info->record)))
{
- if (info->thd->killed)
- {
- info->thd->send_kill_message();
- return 1;
- }
/*
rnd_next can return RECORD_DELETED for MyISAM when one thread is
reading and another deleting without locks.
*/
- if (tmp != HA_ERR_RECORD_DELETED)
+ if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
{
tmp= rr_handle_error(info, tmp);
break;
diff --git a/sql/records.h b/sql/records.h
new file mode 100644
index 00000000000..ae81a31ee1a
--- /dev/null
+++ b/sql/records.h
@@ -0,0 +1,79 @@
+#ifndef SQL_RECORDS_H
+#define SQL_RECORDS_H
+/* Copyright (C) 2008 Sun/MySQL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+#include <my_global.h> /* for uint typedefs */
+
+struct st_join_table;
+class handler;
+struct TABLE;
+class THD;
+class SQL_SELECT;
+
+/**
+ A context for reading through a single table using a chosen access method:
+ index read, scan, etc, use of cache, etc.
+
+ Use by:
+ READ_RECORD read_record;
+ init_read_record(&read_record, ...);
+ while (read_record.read_record())
+ {
+ ...
+ }
+ end_read_record();
+*/
+
+struct READ_RECORD
+{
+ typedef int (*Read_func)(READ_RECORD*);
+ typedef void (*Unlock_row_func)(st_join_table *);
+ typedef int (*Setup_func)(struct st_join_table*);
+
+ TABLE *table; /* Head-form */
+ handler *file;
+ TABLE **forms; /* head and ref forms */
+ Unlock_row_func unlock_row;
+ Read_func read_record;
+ THD *thd;
+ SQL_SELECT *select;
+ uint cache_records;
+ uint ref_length,struct_length,reclength,rec_cache_size,error_offset;
+ uint index;
+ uchar *ref_pos; /* pointer to form->refpos */
+ uchar *record;
+ uchar *rec_buf; /* to read field values after filesort */
+ uchar *cache,*cache_pos,*cache_end,*read_positions;
+ struct st_io_cache *io_cache;
+ bool print_error, ignore_not_found_rows;
+
+public:
+ READ_RECORD() {}
+};
+
+void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
+ SQL_SELECT *select, int use_record_cache,
+ bool print_errors, bool disable_rr_cache);
+void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+ bool print_error, uint idx);
+void end_read_record(READ_RECORD *info);
+
+void rr_unlock_row(st_join_table *tab);
+
+#endif /* SQL_RECORDS_H */
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 8963532e192..c6c7f185080 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -146,10 +146,10 @@ void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
pthread_mutex_lock(&LOCK_slave_list);
SLAVE_INFO* old_si;
- if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
- (uchar*)&thd->server_id, 4)) &&
+ if ((old_si = (SLAVE_INFO*)my_hash_search(&slave_list,
+ (uchar*)&thd->server_id, 4)) &&
(!only_mine || old_si->thd == thd))
- hash_delete(&slave_list, (uchar*)old_si);
+ my_hash_delete(&slave_list, (uchar*)old_si);
if (need_mutex)
pthread_mutex_unlock(&LOCK_slave_list);
@@ -221,17 +221,18 @@ extern "C" void slave_info_free(void *s)
void init_slave_list()
{
- hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
- (hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0);
+ my_hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
+ (my_hash_get_key) slave_list_key,
+ (my_hash_free_key) slave_info_free, 0);
pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
}
void end_slave_list()
{
/* No protection by a mutex needed as we are only called at shutdown */
- if (hash_inited(&slave_list))
+ if (my_hash_inited(&slave_list))
{
- hash_free(&slave_list);
+ my_hash_free(&slave_list);
pthread_mutex_destroy(&LOCK_slave_list);
}
}
@@ -470,7 +471,7 @@ bool show_new_master(THD* thd)
field_list.push_back(new Item_empty_string("Log_name", 20));
field_list.push_back(new Item_return_int("Log_pos", 10,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
@@ -547,8 +548,8 @@ HOSTS";
uint32 log_server_id;
SLAVE_INFO* si, *old_si;
log_server_id = atoi(row[0]);
- if ((old_si= (SLAVE_INFO*)hash_search(&slave_list,
- (uchar*)&log_server_id,4)))
+ if ((old_si= (SLAVE_INFO*)my_hash_search(&slave_list,
+ (uchar*)&log_server_id,4)))
si = old_si;
else
{
@@ -676,7 +677,7 @@ bool show_slave_hosts(THD* thd)
field_list.push_back(new Item_return_int("Master_id", 10,
MYSQL_TYPE_LONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -684,7 +685,7 @@ bool show_slave_hosts(THD* thd)
for (uint i = 0; i < slave_list.records; ++i)
{
- SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
+ SLAVE_INFO* si = (SLAVE_INFO*) my_hash_element(&slave_list, i);
protocol->prepare_for_resend();
protocol->store((uint32) si->server_id);
protocol->store(si->host, &my_charset_bin);
diff --git a/sql/replication.h b/sql/replication.h
index 6b7be58a5b1..eea77ef9f8e 100644
--- a/sql/replication.h
+++ b/sql/replication.h
@@ -16,6 +16,8 @@
#ifndef REPLICATION_H
#define REPLICATION_H
+typedef struct st_mysql MYSQL;
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -483,6 +485,64 @@ const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond,
*/
void thd_exit_cond(MYSQL_THD thd, const char *old_msg);
+/**
+ Get the value of user variable as an integer.
+
+ This function will return the value of variable @a name as an
+ integer. If the original value of the variable is not an integer,
+ the value will be converted into an integer.
+
+ @param name user variable name
+ @param value pointer to return the value
+ @param null_value if not NULL, the function will set it to true if
+ the value of variable is null, set to false if not
+
+ @retval 0 Success
+ @retval 1 Variable not found
+*/
+int get_user_var_int(const char *name,
+ long long int *value, int *null_value);
+
+/**
+ Get the value of user variable as a double precision float number.
+
+ This function will return the value of variable @a name as real
+ number. If the original value of the variable is not a real number,
+ the value will be converted into a real number.
+
+ @param name user variable name
+ @param value pointer to return the value
+ @param null_value if not NULL, the function will set it to true if
+ the value of variable is null, set to false if not
+
+ @retval 0 Success
+ @retval 1 Variable not found
+*/
+int get_user_var_real(const char *name,
+ double *value, int *null_value);
+
+/**
+ Get the value of user variable as a string.
+
+ This function will return the value of variable @a name as
+ string. If the original value of the variable is not a string,
+ the value will be converted into a string.
+
+ @param name user variable name
+ @param value pointer to the value buffer
+ @param len length of the value buffer
+ @param precision precision of the value if it is a float number
+ @param null_value if not NULL, the function will set it to true if
+ the value of variable is null, set to false if not
+
+ @retval 0 Success
+ @retval 1 Variable not found
+*/
+int get_user_var_str(const char *name,
+ char *value, unsigned long len,
+ unsigned int precision, int *null_value);
+
+
#ifdef __cplusplus
}
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
index 68272c58bb1..392d8baf50e 100644
--- a/sql/rpl_filter.cc
+++ b/sql/rpl_filter.cc
@@ -32,9 +32,9 @@ Rpl_filter::Rpl_filter() :
Rpl_filter::~Rpl_filter()
{
if (do_table_inited)
- hash_free(&do_table);
+ my_hash_free(&do_table);
if (ignore_table_inited)
- hash_free(&ignore_table);
+ my_hash_free(&ignore_table);
if (wild_do_table_inited)
free_string_array(&wild_do_table);
if (wild_ignore_table_inited)
@@ -103,12 +103,12 @@ Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables)
len= (uint) (strmov(end, tables->table_name) - hash_key);
if (do_table_inited) // if there are any do's
{
- if (hash_search(&do_table, (uchar*) hash_key, len))
+ if (my_hash_search(&do_table, (uchar*) hash_key, len))
DBUG_RETURN(1);
}
if (ignore_table_inited) // if there are any ignores
{
- if (hash_search(&ignore_table, (uchar*) hash_key, len))
+ if (my_hash_search(&ignore_table, (uchar*) hash_key, len))
DBUG_RETURN(0);
}
if (wild_do_table_inited &&
@@ -387,7 +387,7 @@ void free_table_ent(void* a)
void
Rpl_filter::init_table_rule_hash(HASH* h, bool* h_inited)
{
- hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
+ my_hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
get_table_key, free_table_ent, 0);
*h_inited = 1;
}
@@ -458,7 +458,7 @@ Rpl_filter::table_rule_ent_hash_to_str(String* s, HASH* h, bool inited)
{
for (uint i= 0; i < h->records; i++)
{
- TABLE_RULE_ENT* e= (TABLE_RULE_ENT*) hash_element(h, i);
+ TABLE_RULE_ENT* e= (TABLE_RULE_ENT*) my_hash_element(h, i);
if (s->length())
s->append(',');
s->append(e->db,e->key_len);
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index da7aade5b99..b8b82bc2f98 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -44,7 +44,7 @@ int get_user_var_int(const char *name,
{
my_bool null_val;
user_var_entry *entry=
- (user_var_entry*) hash_search(&current_thd->user_vars,
+ (user_var_entry*) my_hash_search(&current_thd->user_vars,
(uchar*) name, strlen(name));
if (!entry)
return 1;
@@ -59,7 +59,7 @@ int get_user_var_real(const char *name,
{
my_bool null_val;
user_var_entry *entry=
- (user_var_entry*) hash_search(&current_thd->user_vars,
+ (user_var_entry*) my_hash_search(&current_thd->user_vars,
(uchar*) name, strlen(name));
if (!entry)
return 1;
@@ -75,7 +75,7 @@ int get_user_var_str(const char *name, char *value,
String str;
my_bool null_val;
user_var_entry *entry=
- (user_var_entry*) hash_search(&current_thd->user_vars,
+ (user_var_entry*) my_hash_search(&current_thd->user_vars,
(uchar*) name, strlen(name));
if (!entry)
return 1;
diff --git a/sql/rpl_injector.h b/sql/rpl_injector.h
index 4ece092c5b8..a0c71fee099 100644
--- a/sql/rpl_injector.h
+++ b/sql/rpl_injector.h
@@ -25,9 +25,8 @@
/* Forward declarations */
class handler;
class MYSQL_BIN_LOG;
-struct st_table;
+struct TABLE;
-typedef st_table TABLE;
/*
Injector to inject rows into the MySQL server.
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc
index a004c354263..8b7fea3b40e 100644
--- a/sql/rpl_tblmap.cc
+++ b/sql/rpl_tblmap.cc
@@ -34,10 +34,10 @@ table_mapping::table_mapping()
No "free_element" function for entries passed here, as the entries are
allocated in a MEM_ROOT (freed as a whole in the destructor), they cannot
be freed one by one.
- Note that below we don't test if hash_init() succeeded. This constructor
- is called at startup only.
+ Note that below we don't test if my_hash_init() succeeded. This
+ constructor is called at startup only.
*/
- (void) hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
+ (void) my_hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
offsetof(entry,table_id),sizeof(ulong),
0,0,0);
/* We don't preallocate any block, this is consistent with m_free=0 above */
@@ -49,7 +49,7 @@ table_mapping::~table_mapping()
#ifdef MYSQL_CLIENT
clear_tables();
#endif
- hash_free(&m_table_ids);
+ my_hash_free(&m_table_ids);
free_root(&m_mem_root, MYF(0));
}
@@ -115,7 +115,7 @@ int table_mapping::set_table(ulong table_id, TABLE* table)
#ifdef MYSQL_CLIENT
free_table_map_log_event(e->table);
#endif
- hash_delete(&m_table_ids,(uchar *)e);
+ my_hash_delete(&m_table_ids,(uchar *)e);
}
e->table_id= table_id;
e->table= table;
@@ -132,7 +132,7 @@ int table_mapping::remove_table(ulong table_id)
entry *e= find_entry(table_id);
if (e)
{
- hash_delete(&m_table_ids,(uchar *)e);
+ my_hash_delete(&m_table_ids,(uchar *)e);
/* we add this entry to the chain of free (free for use) entries */
e->next= m_free;
m_free= e;
@@ -150,7 +150,7 @@ void table_mapping::clear_tables()
DBUG_ENTER("table_mapping::clear_tables()");
for (uint i= 0; i < m_table_ids.records; i++)
{
- entry *e= (entry *)hash_element(&m_table_ids, i);
+ entry *e= (entry *)my_hash_element(&m_table_ids, i);
#ifdef MYSQL_CLIENT
free_table_map_log_event(e->table);
#endif
diff --git a/sql/rpl_tblmap.h b/sql/rpl_tblmap.h
index 3b5b10be580..a6ec8bcbc9b 100644
--- a/sql/rpl_tblmap.h
+++ b/sql/rpl_tblmap.h
@@ -18,8 +18,7 @@
/* Forward declarations */
#ifndef MYSQL_CLIENT
-struct st_table;
-typedef st_table TABLE;
+struct TABLE;
#else
class Table_map_log_event;
typedef Table_map_log_event TABLE;
@@ -91,9 +90,9 @@ private:
entry *find_entry(ulong table_id)
{
- return (entry *)hash_search(&m_table_ids,
- (uchar*)&table_id,
- sizeof(table_id));
+ return (entry *) my_hash_search(&m_table_ids,
+ (uchar*)&table_id,
+ sizeof(table_id));
}
int expand();
diff --git a/sql/set_var.cc b/sql/set_var.cc
index e21aaac1da5..36597658077 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -125,8 +125,10 @@ static void fix_net_read_timeout(THD *thd, enum_var_type type);
static void fix_net_write_timeout(THD *thd, enum_var_type type);
static void fix_net_retry_count(THD *thd, enum_var_type type);
static void fix_max_join_size(THD *thd, enum_var_type type);
+#ifdef HAVE_QUERY_CACHE
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
+#endif
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
static void fix_max_binlog_size(THD *thd, enum_var_type type);
static void fix_max_relay_log_size(THD *thd, enum_var_type type);
@@ -493,9 +495,6 @@ static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment",
&SV::div_precincrement);
static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank",
&rpl_recovery_rank);
-static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size",
- &query_cache_size,
- fix_query_cache_size);
static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size",
&SV::range_alloc_block_size);
@@ -557,14 +556,20 @@ sys_var_enum_const sys_thread_handling(&vars, "thread_handling",
NULL);
#ifdef HAVE_QUERY_CACHE
+static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size",
+ &query_cache_size,
+ fix_query_cache_size);
static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit",
- &query_cache.query_cache_limit);
-static sys_var_long_ptr sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
- &query_cache_min_res_unit,
- fix_query_cache_min_res_unit);
+ &query_cache.query_cache_limit);
+static sys_var_long_ptr
+ sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
+ &query_cache_min_res_unit,
+ fix_query_cache_min_res_unit);
+static int check_query_cache_type(THD *thd, set_var *var);
static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type",
&SV::query_cache_type,
- &query_cache_type_typelib);
+ &query_cache_type_typelib, NULL,
+ check_query_cache_type);
static sys_var_thd_bool
sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
&SV::query_cache_wlock_invalidate);
@@ -768,7 +773,7 @@ static sys_var_thd_bit sys_unique_checks(&vars, "unique_checks", 0,
OPTION_RELAXED_UNIQUE_CHECKS,
1,
sys_var::SESSION_VARIABLE_IN_BINLOG);
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
static sys_var_thd_bit sys_profiling(&vars, "profiling", NULL,
set_option_bit,
ulonglong(OPTION_PROFILING));
@@ -873,9 +878,9 @@ static sys_var_have_plugin sys_have_ndbcluster(&vars, "have_ndbcluster", C_STRIN
static sys_var_have_variable sys_have_openssl(&vars, "have_openssl", &have_ssl);
static sys_var_have_variable sys_have_ssl(&vars, "have_ssl", &have_ssl);
static sys_var_have_plugin sys_have_partition_db(&vars, "have_partitioning", C_STRING_WITH_LEN("partition"), MYSQL_STORAGE_ENGINE_PLUGIN);
+static sys_var_have_variable sys_have_profiling(&vars, "have_profiling", &have_profiling);
static sys_var_have_variable sys_have_query_cache(&vars, "have_query_cache",
&have_query_cache);
-static sys_var_have_variable sys_have_community_features(&vars, "have_community_features", &have_community_features);
static sys_var_have_variable sys_have_rtree_keys(&vars, "have_rtree_keys", &have_rtree_keys);
static sys_var_have_variable sys_have_symlink(&vars, "have_symlink", &have_symlink);
/* Global read-only variable describing server license */
@@ -1131,10 +1136,9 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)),
{}
#endif /* HAVE_REPLICATION */
-
+#ifdef HAVE_QUERY_CACHE
static void fix_query_cache_size(THD *thd, enum_var_type type)
{
-#ifdef HAVE_QUERY_CACHE
ulong new_cache_size= query_cache.resize(query_cache_size);
/*
@@ -1148,11 +1152,35 @@ static void fix_query_cache_size(THD *thd, enum_var_type type)
query_cache_size, new_cache_size);
query_cache_size= new_cache_size;
-#endif
}
-#ifdef HAVE_QUERY_CACHE
+/**
+ Trigger before query_cache_type variable is updated.
+ @param thd Thread handler
+ @param var Pointer to the new variable status
+
+ @return Status code
+ @retval 1 Failure
+ @retval 0 Success
+*/
+
+static int check_query_cache_type(THD *thd, set_var *var)
+{
+ /*
+ Don't allow changes of the query_cache_type if the query cache
+ is disabled.
+ */
+ if (query_cache.is_disabled())
+ {
+ my_error(ER_QUERY_CACHE_DISABLED,MYF(0));
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
{
query_cache_min_res_unit=
@@ -2573,9 +2601,20 @@ bool update_sys_var_str_path(THD *thd, sys_var_str *var_str,
{
MYSQL_QUERY_LOG *file_log;
char buff[FN_REFLEN];
- char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
+ char *res= 0, *old_value= 0;
bool result= 0;
- uint str_length= (var ? var->value->str_value.length() : 0);
+ uint str_length= 0;
+
+ if (var)
+ {
+ String str(buff, sizeof(buff), system_charset_info), *newval;
+
+ newval= var->value->val_str(&str);
+ old_value= newval->c_ptr_safe();
+ str_length= strlen(old_value);
+ }
+
+
switch (log_type) {
case QUERY_LOG_SLOW:
@@ -3353,7 +3392,7 @@ int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options)
error:
for (; first != var; first= first->next)
- hash_delete(&system_variable_hash, (uchar*) first);
+ my_hash_delete(&system_variable_hash, (uchar*) first);
return 1;
}
@@ -3377,7 +3416,7 @@ int mysql_del_sys_var_chain(sys_var *first)
/* A write lock should be held on LOCK_system_variables_hash */
for (sys_var *var= first; var; var= var->next)
- result|= hash_delete(&system_variable_hash, (uchar*) var);
+ result|= my_hash_delete(&system_variable_hash, (uchar*) var);
return result;
}
@@ -3414,7 +3453,7 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted)
for (i= 0; i < count; i++)
{
- sys_var *var= (sys_var*) hash_element(&system_variable_hash, i);
+ sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i);
show->name= var->name;
show->value= (char*) var;
show->type= SHOW_SYS;
@@ -3451,8 +3490,8 @@ int set_var_init()
for (sys_var *var=vars.first; var; var= var->next, count++) ;
- if (hash_init(&system_variable_hash, system_charset_info, count, 0,
- 0, (hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
+ if (my_hash_init(&system_variable_hash, system_charset_info, count, 0,
+ 0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
goto error;
vars.last->next= NULL;
@@ -3477,7 +3516,7 @@ error:
void set_var_free()
{
- hash_free(&system_variable_hash);
+ my_hash_free(&system_variable_hash);
}
@@ -3503,7 +3542,7 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error)
This function is only called from the sql_plugin.cc.
A lock on LOCK_system_variable_hash should be held
*/
- var= (sys_var*) hash_search(&system_variable_hash,
+ var= (sys_var*) my_hash_search(&system_variable_hash,
(uchar*) str, length ? length : strlen(str));
if (!(var || no_error))
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
@@ -3590,6 +3629,16 @@ bool not_all_support_one_shot(List<set_var_base> *var_list)
Functions to handle SET mysql_internal_variable=const_expr
*****************************************************************************/
+/**
+ Verify that the supplied value is correct.
+
+ @param thd Thread handler
+
+ @return status code
+ @retval -1 Failure
+ @retval 0 Success
+*/
+
int set_var::check(THD *thd)
{
if (var->is_readonly())
@@ -4017,7 +4066,8 @@ ulong fix_sql_mode(ulong sql_mode)
if (sql_mode & MODE_TRADITIONAL)
sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
- MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER);
+ MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER |
+ MODE_NO_ENGINE_SUBSTITUTION);
return sql_mode;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index a83de6425ae..c08097521d2 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -543,10 +543,16 @@ public:
{ chain_sys_var(chain); }
bool check(THD *thd, set_var *var)
{
- int ret= 0;
- if (check_func)
- ret= (*check_func)(thd, var);
- return ret ? ret : check_enum(thd, var, enum_names);
+ /*
+ check_enum fails if the character representation supplied was wrong
+ or that the integer value was wrong or missing.
+ */
+ if (check_enum(thd, var, enum_names))
+ return TRUE;
+ else if ((check_func && (*check_func)(thd, var)))
+ return TRUE;
+ else
+ return FALSE;
}
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 2b2d60c0657..4260efdeb56 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6240,4 +6240,23 @@ ER_UNKNOWN_LOCALE
ER_SLAVE_IGNORE_SERVER_IDS
eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id"
-
+ER_QUERY_CACHE_DISABLED
+ eng "Query cache is disabled; restart the server with query_cache_type=1 to enable it"
+ER_SAME_NAME_PARTITION_FIELD
+ eng "Duplicate partition field name '%-.192s'"
+ER_PARTITION_COLUMN_LIST_ERROR
+ eng "Inconsistency in usage of column lists for partitioning"
+ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+ eng "Partition column values of incorrect type"
+ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
+ eng "Too many fields in '%-.192s'"
+ER_MAXVALUE_IN_VALUES_IN
+ eng "Cannot use MAXVALUE as value in VALUES IN"
+ER_TOO_MANY_VALUES_ERROR
+ eng "Cannot have more than one value for this type of %-.64s partitioning"
+ER_ROW_SINGLE_PARTITION_FIELD_ERROR
+ eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
+ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
+ eng "Field '%-.192s' is of a not allowed type for this type of partitioning"
+ER_PARTITION_FIELDS_TOO_LONG
+ eng "The total length of the partitioning fields is too large"
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 317087854c1..034f987e0e7 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6241,3 +6241,21 @@ ER_UNKNOWN_LOCALE
ER_SLAVE_IGNORE_SERVER_IDS
eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id"
+ER_SAME_NAME_PARTITION_FIELD
+ eng "Duplicate partition field name '%-.192s'"
+ER_PARTITION_COLUMN_LIST_ERROR
+ eng "Inconsistency in usage of column lists for partitioning"
+ER_WRONG_TYPE_COLUMN_VALUE_ERROR
+ eng "Partition column values of incorrect type"
+ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
+ eng "Too many fields in '%-.192s'"
+ER_MAXVALUE_IN_VALUES_IN
+ eng "Cannot use MAXVALUE as value in VALUES IN"
+ER_TOO_MANY_VALUES_ERROR
+ eng "Cannot have more than one value for this type of %-.64s partitioning"
+ER_ROW_SINGLE_PARTITION_FIELD_ERROR
+ eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
+ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
+ eng "Field '%-.192s' is of a not allowed type for this type of partitioning"
+ER_PARTITION_FIELDS_TOO_LONG
+ eng "The total length of the partitioning fields is too large"
diff --git a/sql/slave.cc b/sql/slave.cc
index 8c82dcaabe0..d49031ef066 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -583,7 +583,7 @@ terminate_slave_thread(THD *thd,
EINVAL: invalid signal number (can't happen)
ESRCH: thread already killed (can happen, should be ignored)
*/
- IF_DBUG(int err= ) pthread_kill(thd->real_id, thr_client_alarm);
+ int err __attribute__((unused))= pthread_kill(thd->real_id, thr_client_alarm);
DBUG_ASSERT(err != EINVAL);
#endif
thd->awake(THD::NOT_KILLED);
@@ -1087,7 +1087,7 @@ static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info)
if (io_slave_killed(thd, mi))
{
if (info && global_system_variables.log_warnings)
- sql_print_information(info);
+ sql_print_information("%s", info);
return TRUE;
}
return FALSE;
@@ -1552,7 +1552,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
thd->db = (char*)db;
DBUG_ASSERT(thd->db != 0);
thd->db_length= strlen(thd->db);
- mysql_parse(thd, thd->query, packet_len, &found_semicolon); // run create table
+ /* run create table */
+ mysql_parse(thd, thd->query(), packet_len, &found_semicolon);
thd->db = save_db; // leave things the way the were before
thd->db_length= save_db_length;
thd->options = save_options;
@@ -1873,7 +1874,7 @@ bool show_master_info(THD* thd, Master_info* mi)
field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong),
MYSQL_TYPE_LONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -2120,7 +2121,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
thd->cleanup();
DBUG_RETURN(-1);
}
- lex_start(thd);
if (thd_type == SLAVE_THD_SQL)
thd_proc_info(thd, "Waiting for the next event in relay log");
diff --git a/sql/sp.cc b/sql/sp.cc
index 6c268e87711..f756e8ddb18 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1010,7 +1010,7 @@ sp_drop_routine(THD *thd, int type, sp_name *name)
if (ret == SP_OK)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
sp_cache_invalidate();
}
@@ -1080,7 +1080,7 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
if (ret == SP_OK)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
sp_cache_invalidate();
}
@@ -1505,11 +1505,11 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
const LEX_STRING *key,
TABLE_LIST *belong_to_view)
{
- hash_init_opt(&lex->sroutines, system_charset_info,
- Query_tables_list::START_SROUTINES_HASH_SIZE,
- 0, 0, sp_sroutine_key, 0, 0);
+ my_hash_init_opt(&lex->sroutines, system_charset_info,
+ Query_tables_list::START_SROUTINES_HASH_SIZE,
+ 0, 0, sp_sroutine_key, 0, 0);
- if (!hash_search(&lex->sroutines, (uchar *)key->str, key->length))
+ if (!my_hash_search(&lex->sroutines, (uchar *)key->str, key->length))
{
Sroutine_hash_entry *rn=
(Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) +
@@ -1574,7 +1574,7 @@ void sp_remove_not_own_routines(LEX *lex)
but we want to be more future-proof.
*/
next_rt= not_own_rt->next;
- hash_delete(&lex->sroutines, (uchar *)not_own_rt);
+ my_hash_delete(&lex->sroutines, (uchar *)not_own_rt);
}
*(Sroutine_hash_entry **)lex->sroutines_list_own_last= NULL;
@@ -1603,8 +1603,8 @@ void sp_update_sp_used_routines(HASH *dst, HASH *src)
{
for (uint i=0 ; i < src->records ; i++)
{
- Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
- if (!hash_search(dst, (uchar *)rt->key.str, rt->key.length))
+ Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i);
+ if (!my_hash_search(dst, (uchar *)rt->key.str, rt->key.length))
my_hash_insert(dst, (uchar *)rt);
}
}
@@ -1630,7 +1630,7 @@ sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src,
{
for (uint i=0 ; i < src->records ; i++)
{
- Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
+ Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i);
(void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view);
}
}
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index 64898915b7e..d9a23d2be4e 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -44,7 +44,8 @@ public:
inline sp_head *lookup(char *name, uint namelen)
{
- return (sp_head *)hash_search(&m_hashtable, (const uchar *)name, namelen);
+ return (sp_head *) my_hash_search(&m_hashtable, (const uchar *)name,
+ namelen);
}
#ifdef NOT_USED
@@ -255,15 +256,15 @@ sp_cache::sp_cache()
sp_cache::~sp_cache()
{
- hash_free(&m_hashtable);
+ my_hash_free(&m_hashtable);
}
void
sp_cache::init()
{
- hash_init(&m_hashtable, system_charset_info, 0, 0, 0,
- hash_get_key_for_sp_head, hash_free_sp_head, 0);
+ my_hash_init(&m_hashtable, system_charset_info, 0, 0, 0,
+ hash_get_key_for_sp_head, hash_free_sp_head, 0);
version= 0;
}
@@ -271,5 +272,5 @@ sp_cache::init()
void
sp_cache::cleanup()
{
- hash_free(&m_hashtable);
+ my_hash_free(&m_hashtable);
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index e063b6863f4..3d2486cd98f 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -14,6 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
+#include "sql_prepare.h"
#include "probes_mysql.h"
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation
@@ -335,16 +336,18 @@ bool
sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
{
Item *expr_item;
+ enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
+ bool save_abort_on_warning= thd->abort_on_warning;
+ bool save_stmt_modified_non_trans_table=
+ thd->transaction.stmt.modified_non_trans_table;
DBUG_ENTER("sp_eval_expr");
if (!*expr_item_ptr)
- DBUG_RETURN(TRUE);
+ goto error;
if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
- DBUG_RETURN(TRUE);
-
- bool err_status= FALSE;
+ goto error;
/*
Set THD flags to emit warnings/errors in case of overflow/type errors
@@ -353,10 +356,6 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
Save original values and restore them after save.
*/
- enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
- bool save_abort_on_warning= thd->abort_on_warning;
- bool save_stmt_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table;
-
thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
thd->abort_on_warning=
thd->variables.sql_mode &
@@ -371,13 +370,18 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
thd->abort_on_warning= save_abort_on_warning;
thd->transaction.stmt.modified_non_trans_table= save_stmt_modified_non_trans_table;
- if (thd->is_error())
- {
- /* Return error status if something went wrong. */
- err_status= TRUE;
- }
+ if (!thd->is_error())
+ DBUG_RETURN(FALSE);
- DBUG_RETURN(err_status);
+error:
+ /*
+ In case of error during evaluation, leave the result field set to NULL.
+ Sic: we can't do it in the beginning of the function because the
+ result field might be needed for its own re-evaluation, e.g. case of
+ set x = x + 1;
+ */
+ result_field->set_null();
+ DBUG_RETURN (TRUE);
}
@@ -531,8 +535,9 @@ sp_head::sp_head()
m_backpatch.empty();
m_cont_backpatch.empty();
m_lex.empty();
- hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
- hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
+ my_hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
+ my_hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key,
+ 0, 0);
m_body_utf8.str= NULL;
m_body_utf8.length= 0;
@@ -781,8 +786,8 @@ sp_head::destroy()
m_thd->lex= lex;
}
- hash_free(&m_sptabs);
- hash_free(&m_sroutines);
+ my_hash_free(&m_sptabs);
+ my_hash_free(&m_sroutines);
DBUG_VOID_RETURN;
}
@@ -1207,7 +1212,7 @@ sp_head::execute(THD *thd)
*/
thd->spcont->callers_arena= &backup_arena;
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
/* Discard the initial part of executing routines. */
thd->profiling.discard_current_query();
#endif
@@ -1216,7 +1221,7 @@ sp_head::execute(THD *thd)
sp_instr *i;
uint hip; // Handler ip
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
/*
Treat each "instr" of a routine as discrete unit that could be profiled.
Profiling only records information for segments of code that set the
@@ -1229,7 +1234,7 @@ sp_head::execute(THD *thd)
i = get_instr(ip); // Returns NULL when we're done.
if (i == NULL)
{
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.discard_current_query();
#endif
break;
@@ -1312,7 +1317,7 @@ sp_head::execute(THD *thd)
}
} while (!err_status && !thd->killed && !thd->is_fatal_error);
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
thd->profiling.start_new_query("tail end of routine");
#endif
@@ -1957,15 +1962,19 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
}
}
- /*
- Okay, got values for all arguments. Close tables that might be used by
- arguments evaluation. If arguments evaluation required prelocking mode,
+ /*
+ Okay, got values for all arguments. Close tables that might be used by
+ arguments evaluation. If arguments evaluation required prelocking mode,
we'll leave it here.
*/
if (!thd->in_sub_stmt)
{
thd->lex->unit.cleanup();
- close_thread_tables(thd);
+
+ thd_proc_info(thd, "closing tables");
+ close_thread_tables(thd);
+ thd_proc_info(thd, 0);
+
thd->rollback_item_tree_changes();
}
@@ -2038,6 +2047,16 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
err_status= TRUE;
break;
}
+
+ Send_field *out_param_info= new (thd->mem_root) Send_field();
+ nctx->get_item(i)->make_field(out_param_info);
+ out_param_info->db_name= m_db.str;
+ out_param_info->table_name= m_name.str;
+ out_param_info->org_table_name= m_name.str;
+ out_param_info->col_name= spvar->name.str;
+ out_param_info->org_col_name= spvar->name.str;
+
+ srp->set_out_param_info(out_param_info);
}
}
@@ -2362,7 +2381,8 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
bzero((char*) &tables,sizeof(tables));
tables.db= (char*) "mysql";
tables.table_name= tables.alias= (char*) "proc";
- *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) ||
+ *full_access= (!check_table_access(thd, SELECT_ACL, &tables, FALSE,
+ 1, TRUE) ||
(!strcmp(sp->m_definer_user.str,
thd->security_ctx->priv_user) &&
!strcmp(sp->m_definer_host.str,
@@ -2445,7 +2465,7 @@ sp_head::show_create_routine(THD *thd, int type)
fields.push_back(new Item_empty_string("Database Collation",
MY_CS_NAME_SIZE));
- if (protocol->send_fields(&fields,
+ if (protocol->send_result_set_metadata(&fields,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
DBUG_RETURN(TRUE);
@@ -2631,8 +2651,8 @@ sp_head::show_routine_code(THD *thd)
field_list.push_back(new Item_uint("Pos", 9));
// 1024 is for not to confuse old clients
field_list.push_back(new Item_empty_string("Instruction",
- max(buffer.length(), 1024)));
- if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ max(buffer.length(), 1024)));
+ if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
DBUG_RETURN(1);
@@ -2808,7 +2828,7 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
Check whenever we have access to tables for this statement
and open and lock them before executing instructions core function.
*/
- if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)
+ if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, tables))
result= -1;
else
@@ -2842,9 +2862,9 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
DBUG_ENTER("sp_instr_stmt::execute");
DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command()));
- query= thd->query;
- query_length= thd->query_length;
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+ query= thd->query();
+ query_length= thd->query_length();
+#if defined(ENABLED_PROFILING)
/* This s-p instr is profilable and will be captured. */
thd->profiling.set_query_source(m_query.str, m_query.length);
#endif
@@ -2856,15 +2876,16 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
queries with SP vars can't be cached)
*/
if (unlikely((thd->options & OPTION_LOG_OFF)==0))
- general_log_write(thd, COM_QUERY, thd->query, thd->query_length);
+ general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
if (query_cache_send_result_to_client(thd,
- thd->query, thd->query_length) <= 0)
+ thd->query(),
+ thd->query_length()) <= 0)
{
res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
if (thd->stmt_da->is_eof())
- net_end_statement(thd);
+ thd->protocol->end_statement();
query_cache_end_of_result(thd);
@@ -2918,7 +2939,7 @@ sp_instr_stmt::print(String *str)
int
sp_instr_stmt::exec_core(THD *thd, uint *nextp)
{
- MYSQL_QUERY_EXEC_START(thd->query,
+ MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
(char *) (thd->db ? thd->db : ""),
thd->security_ctx->priv_user,
@@ -3820,7 +3841,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
for (uint i= 0 ; i < m_sptabs.records ; i++)
{
- tab= (SP_TABLE *)hash_element(&m_sptabs, i);
+ tab= (SP_TABLE*) my_hash_element(&m_sptabs, i);
tab->query_lock_count= 0;
}
@@ -3854,8 +3875,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
(and therefore should not be prelocked). Otherwise we will erroneously
treat table with same name but with different alias as non-temporary.
*/
- if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname, tlen)) ||
- ((tab= (SP_TABLE *)hash_search(&m_sptabs, (uchar *)tname,
+ if ((tab= (SP_TABLE*) my_hash_search(&m_sptabs, (uchar *)tname, tlen)) ||
+ ((tab= (SP_TABLE*) my_hash_search(&m_sptabs, (uchar *)tname,
tlen - alen - 1)) &&
tab->temp))
{
@@ -3940,7 +3961,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
{
char *tab_buff, *key_buff;
TABLE_LIST *table;
- SP_TABLE *stab= (SP_TABLE *)hash_element(&m_sptabs, i);
+ SP_TABLE *stab= (SP_TABLE*) my_hash_element(&m_sptabs, i);
if (stab->temp)
continue;
@@ -3984,7 +4005,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
/**
- Simple function for adding an explicetly named (systems) table to
+ Simple function for adding an explicitly named (systems) table to
the global table list, e.g. "mysql", "proc".
*/
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index da2232d1478..1e5eeec7dbc 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -261,10 +261,9 @@ my_bool acl_init(bool dont_read_acl_tables)
DBUG_ENTER("acl_init");
acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0,
- (hash_get_key) acl_entry_get_key,
- (hash_free_key) free,
- lower_case_file_system ?
- system_charset_info : &my_charset_bin);
+ (my_hash_get_key) acl_entry_get_key,
+ (my_hash_free_key) free,
+ &my_charset_utf8_bin);
if (dont_read_acl_tables)
{
DBUG_RETURN(0); /* purecov: tested */
@@ -277,7 +276,6 @@ my_bool acl_init(bool dont_read_acl_tables)
DBUG_RETURN(1); /* purecov: inspected */
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/*
It is safe to call acl_reload() since acl_* arrays and hashes which
will be freed there are global static objects and thus are initialized
@@ -638,7 +636,7 @@ void acl_free(bool end)
delete_dynamic(&acl_users);
delete_dynamic(&acl_dbs);
delete_dynamic(&acl_wild_hosts);
- hash_free(&acl_check_hosts);
+ my_hash_free(&acl_check_hosts);
if (!end)
acl_cache->clear(1); /* purecov: inspected */
else
@@ -714,7 +712,7 @@ my_bool acl_reload(THD *thd)
old_acl_dbs=acl_dbs;
old_mem=mem;
delete_dynamic(&acl_wild_hosts);
- hash_free(&acl_check_hosts);
+ my_hash_free(&acl_check_hosts);
if ((return_val= acl_load(thd, tables)))
{ // Error. Revert to old list
@@ -1429,8 +1427,8 @@ static void init_check_host(void)
DBUG_ENTER("init_check_host");
VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip),
acl_users.elements,1));
- VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0,
- (hash_get_key) check_get_key,0,0));
+ VOID(my_hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0,
+ (my_hash_get_key) check_get_key,0,0));
if (!allow_all_hosts)
{
for (uint i=0 ; i < acl_users.elements ; i++)
@@ -1452,8 +1450,9 @@ static void init_check_host(void)
if (j == acl_wild_hosts.elements) // If new
(void) push_dynamic(&acl_wild_hosts,(uchar*) &acl_user->host);
}
- else if (!hash_search(&acl_check_hosts,(uchar*) acl_user->host.hostname,
- strlen(acl_user->host.hostname)))
+ else if (!my_hash_search(&acl_check_hosts,(uchar*)
+ acl_user->host.hostname,
+ strlen(acl_user->host.hostname)))
{
if (my_hash_insert(&acl_check_hosts,(uchar*) acl_user))
{ // End of memory
@@ -1480,7 +1479,7 @@ static void init_check_host(void)
void rebuild_check_host(void)
{
delete_dynamic(&acl_wild_hosts);
- hash_free(&acl_check_hosts);
+ my_hash_free(&acl_check_hosts);
init_check_host();
}
@@ -1493,8 +1492,8 @@ bool acl_check_host(const char *host, const char *ip)
return 0;
VOID(pthread_mutex_lock(&acl_cache->lock));
- if ((host && hash_search(&acl_check_hosts,(uchar*) host,strlen(host))) ||
- (ip && hash_search(&acl_check_hosts,(uchar*) ip, strlen(ip))))
+ if ((host && my_hash_search(&acl_check_hosts,(uchar*) host,strlen(host))) ||
+ (ip && my_hash_search(&acl_check_hosts,(uchar*) ip, strlen(ip))))
{
VOID(pthread_mutex_unlock(&acl_cache->lock));
return 0; // Found host
@@ -1879,7 +1878,7 @@ static bool test_if_create_new_users(THD *thd)
sctx->priv_user, tl.db, 0);
if (!(db_access & INSERT_ACL))
{
- if (check_grant(thd, INSERT_ACL, &tl, 0, UINT_MAX, 1))
+ if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE))
create_new_users=0;
}
}
@@ -2251,10 +2250,13 @@ public:
ulong sort;
size_t key_length;
GRANT_NAME(const char *h, const char *d,const char *u,
- const char *t, ulong p);
- GRANT_NAME (TABLE *form);
+ const char *t, ulong p, bool is_routine);
+ GRANT_NAME (TABLE *form, bool is_routine);
virtual ~GRANT_NAME() {};
virtual bool ok() { return privs != 0; }
+ void set_user_details(const char *h, const char *d,
+ const char *u, const char *t,
+ bool is_routine);
};
@@ -2272,38 +2274,48 @@ public:
};
-
-GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u,
- const char *t, ulong p)
- :privs(p)
+void GRANT_NAME::set_user_details(const char *h, const char *d,
+ const char *u, const char *t,
+ bool is_routine)
{
/* Host given by user */
update_hostname(&host, strdup_root(&memex, h));
- db = strdup_root(&memex,d);
+ if (db != d)
+ {
+ db= strdup_root(&memex, d);
+ if (lower_case_table_names)
+ my_casedn_str(files_charset_info, db);
+ }
user = strdup_root(&memex,u);
sort= get_sort(3,host.hostname,db,user);
- tname= strdup_root(&memex,t);
- if (lower_case_table_names)
+ if (tname != t)
{
- my_casedn_str(files_charset_info, db);
- my_casedn_str(files_charset_info, tname);
+ tname= strdup_root(&memex, t);
+ if (lower_case_table_names || is_routine)
+ my_casedn_str(files_charset_info, tname);
}
key_length= strlen(d) + strlen(u)+ strlen(t)+3;
hash_key= (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
}
+GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u,
+ const char *t, ulong p, bool is_routine)
+ :db(0), tname(0), privs(p)
+{
+ set_user_details(h, d, u, t, is_routine);
+}
GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
const char *t, ulong p, ulong c)
- :GRANT_NAME(h,d,u,t,p), cols(c)
+ :GRANT_NAME(h,d,u,t,p, FALSE), cols(c)
{
- (void) hash_init2(&hash_columns,4,system_charset_info,
- 0,0,0, (hash_get_key) get_key_column,0,0);
+ (void) my_hash_init2(&hash_columns,4,system_charset_info,
+ 0,0,0, (my_hash_get_key) get_key_column,0,0);
}
-GRANT_NAME::GRANT_NAME(TABLE *form)
+GRANT_NAME::GRANT_NAME(TABLE *form, bool is_routine)
{
update_hostname(&host, get_field(&memex, form->field[0]));
db= get_field(&memex,form->field[1]);
@@ -2321,6 +2333,9 @@ GRANT_NAME::GRANT_NAME(TABLE *form)
if (lower_case_table_names)
{
my_casedn_str(files_charset_info, db);
+ }
+ if (lower_case_table_names || is_routine)
+ {
my_casedn_str(files_charset_info, tname);
}
key_length= (strlen(db) + strlen(user) + strlen(tname) + 3);
@@ -2332,22 +2347,22 @@ GRANT_NAME::GRANT_NAME(TABLE *form)
GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
- :GRANT_NAME(form)
+ :GRANT_NAME(form, FALSE)
{
uchar key[MAX_KEY_LENGTH];
if (!db || !tname)
{
/* Wrong table row; Ignore it */
- hash_clear(&hash_columns); /* allow for destruction */
+ my_hash_clear(&hash_columns); /* allow for destruction */
cols= 0;
return;
}
cols= (ulong) form->field[7]->val_int();
cols = fix_rights_for_column(cols);
- (void) hash_init2(&hash_columns,4,system_charset_info,
- 0,0,0, (hash_get_key) get_key_column,0,0);
+ (void) my_hash_init2(&hash_columns,4,system_charset_info,
+ 0,0,0, (my_hash_get_key) get_key_column,0,0);
if (cols)
{
uint key_prefix_len;
@@ -2399,7 +2414,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
GRANT_TABLE::~GRANT_TABLE()
{
- hash_free(&hash_columns);
+ my_hash_free(&hash_columns);
}
@@ -2413,7 +2428,7 @@ static uchar* get_grant_table(GRANT_NAME *buff, size_t *length,
void free_grant_table(GRANT_TABLE *grant_table)
{
- hash_free(&grant_table->hash_columns);
+ my_hash_free(&grant_table->hash_columns);
}
@@ -2431,11 +2446,11 @@ static GRANT_NAME *name_hash_search(HASH *name_hash,
HASH_SEARCH_STATE state;
len = (uint) (strmov(strmov(strmov(helping,user)+1,db)+1,tname)-helping)+ 1;
- for (grant_name= (GRANT_NAME*) hash_first(name_hash, (uchar*) helping,
- len, &state);
+ for (grant_name= (GRANT_NAME*) my_hash_first(name_hash, (uchar*) helping,
+ len, &state);
grant_name ;
- grant_name= (GRANT_NAME*) hash_next(name_hash,(uchar*) helping,
- len, &state))
+ grant_name= (GRANT_NAME*) my_hash_next(name_hash,(uchar*) helping,
+ len, &state))
{
if (exact)
{
@@ -2479,7 +2494,8 @@ table_hash_search(const char *host, const char *ip, const char *db,
inline GRANT_COLUMN *
column_hash_search(GRANT_TABLE *t, const char *cname, uint length)
{
- return (GRANT_COLUMN*) hash_search(&t->hash_columns, (uchar*) cname,length);
+ return (GRANT_COLUMN*) my_hash_search(&t->hash_columns,
+ (uchar*) cname, length);
}
@@ -2659,7 +2675,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
goto end; /* purecov: deadcode */
}
if (grant_column)
- hash_delete(&g_t->hash_columns,(uchar*) grant_column);
+ my_hash_delete(&g_t->hash_columns,(uchar*) grant_column);
}
}
} while (!table->file->index_next(table->record[0]) &&
@@ -2785,7 +2801,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
else
{
- hash_delete(&column_priv_hash,(uchar*) grant_table);
+ my_hash_delete(&column_priv_hash,(uchar*) grant_table);
}
DBUG_RETURN(0);
@@ -2906,7 +2922,8 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
}
else
{
- hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*) grant_name);
+ my_hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(uchar*)
+ grant_name);
}
DBUG_RETURN(0);
@@ -3147,8 +3164,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
column_priv= 0;
for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++)
{
- grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns,
- idx);
+ grant_column= (GRANT_COLUMN*)
+ my_hash_element(&grant_table->hash_columns, idx);
grant_column->rights&= ~rights; // Fix other columns
column_priv|= grant_column->rights;
}
@@ -3184,7 +3201,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (!result) /* success */
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
rw_unlock(&LOCK_grant);
@@ -3327,7 +3344,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
}
grant_name= new GRANT_NAME(Str->host.str, db_name,
Str->user.str, table_name,
- rights);
+ rights, TRUE);
if (!grant_name)
{
result= TRUE;
@@ -3349,7 +3366,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
if (write_to_binlog)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
rw_unlock(&LOCK_grant);
@@ -3461,7 +3478,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
if (!result)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
rw_unlock(&LOCK_grant);
@@ -3479,9 +3496,9 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
void grant_free(void)
{
DBUG_ENTER("grant_free");
- hash_free(&column_priv_hash);
- hash_free(&proc_priv_hash);
- hash_free(&func_priv_hash);
+ my_hash_free(&column_priv_hash);
+ my_hash_free(&proc_priv_hash);
+ my_hash_free(&func_priv_hash);
free_root(&memex,MYF(0));
DBUG_VOID_RETURN;
}
@@ -3506,7 +3523,6 @@ my_bool grant_init()
DBUG_RETURN(1); /* purecov: deadcode */
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
return_val= grant_reload(thd);
delete thd;
/* Remember that we don't have a THD */
@@ -3538,12 +3554,12 @@ static my_bool grant_load_procs_priv(TABLE *p_table)
MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,
THR_MALLOC);
DBUG_ENTER("grant_load_procs_priv");
- (void) hash_init(&proc_priv_hash,system_charset_info,
- 0,0,0, (hash_get_key) get_grant_table,
- 0,0);
- (void) hash_init(&func_priv_hash,system_charset_info,
- 0,0,0, (hash_get_key) get_grant_table,
- 0,0);
+ (void) my_hash_init(&proc_priv_hash, &my_charset_utf8_bin,
+ 0,0,0, (my_hash_get_key) get_grant_table,
+ 0,0);
+ (void) my_hash_init(&func_priv_hash, &my_charset_utf8_bin,
+ 0,0,0, (my_hash_get_key) get_grant_table,
+ 0,0);
p_table->file->ha_index_init(0, 1);
p_table->use_all_columns();
@@ -3555,7 +3571,7 @@ static my_bool grant_load_procs_priv(TABLE *p_table)
{
GRANT_NAME *mem_check;
HASH *hash;
- if (!(mem_check=new (memex_ptr) GRANT_NAME(p_table)))
+ if (!(mem_check=new (memex_ptr) GRANT_NAME(p_table, TRUE)))
{
/* This could only happen if we are out memory */
goto end_unlock;
@@ -3639,9 +3655,9 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables)
thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
- (void) hash_init(&column_priv_hash,system_charset_info,
- 0,0,0, (hash_get_key) get_grant_table,
- (hash_free_key) free_grant_table,0);
+ (void) my_hash_init(&column_priv_hash, &my_charset_utf8_bin,
+ 0,0,0, (my_hash_get_key) get_grant_table,
+ (my_hash_free_key) free_grant_table,0);
t_table = tables[0].table;
c_table = tables[1].table;
@@ -3744,8 +3760,8 @@ static my_bool grant_reload_procs_priv(THD *thd)
}
else
{
- hash_free(&old_proc_priv_hash);
- hash_free(&old_func_priv_hash);
+ my_hash_free(&old_proc_priv_hash);
+ my_hash_free(&old_func_priv_hash);
}
rw_unlock(&LOCK_grant);
@@ -3814,7 +3830,7 @@ my_bool grant_reload(THD *thd)
}
else
{
- hash_free(&old_column_priv_hash);
+ my_hash_free(&old_column_priv_hash);
free_root(&old_mem,MYF(0));
}
rw_unlock(&LOCK_grant);
@@ -3835,40 +3851,52 @@ end:
DBUG_RETURN(return_val);
}
-/****************************************************************************
- Check table level grants
- SYNOPSIS
- bool check_grant()
- thd Thread handler
- want_access Bits of privileges user needs to have
- tables List of tables to check. The user should have 'want_access'
- to all tables in list.
- show_table <> 0 if we are in show table. In this case it's enough to have
- any privilege for the table
- number Check at most this number of tables.
- no_errors If 0 then we write an error. The error is sent directly to
- the client
+/**
+ @brief Check table level grants
- RETURN
- 0 ok
- 1 Error: User did not have the requested privileges
+ @param thd Thread handler
+ @param want_access Bits of privileges user needs to have.
+ @param tables List of tables to check. The user should have
+ 'want_access' to all tables in list.
+ @param any_combination_will_do TRUE if it's enough to have any privilege for
+ any combination of the table columns.
+ @param number Check at most this number of tables.
+ @param no_errors TRUE if no error should be sent directly to the client.
- NOTE
- This functions assumes that either number of tables to be inspected
+ If table->grant.want_privilege != 0 then the requested privileges where
+ in the set of COL_ACLS but access was not granted on the table level. As
+ a consequence an extra check of column privileges is required.
+
+ Specifically if this function returns FALSE the user has some kind of
+ privilege on a combination of columns in each table.
+
+ This function is usually preceeded by check_access which establish the
+ User-, Db- and Host access rights.
+
+ @see check_access
+ @see check_table_access
+
+ @note This functions assumes that either number of tables to be inspected
by it is limited explicitly (i.e. is is not UINT_MAX) or table list
used and thd->lex->query_tables_own_last value correspond to each
other (the latter should be either 0 or point to next_global member
of one of elements of this table list).
-****************************************************************************/
+
+ @return Access status
+ @retval FALSE Access granted; But column privileges might need to be
+ checked.
+ @retval TRUE The user did not have the requested privileges on any of the
+ tables.
+
+*/
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
- uint show_table, uint number, bool no_errors)
+ bool any_combination_will_do, uint number, bool no_errors)
{
TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table();
Security_context *sctx= thd->security_ctx;
uint i;
- ulong orig_want_access= want_access;
DBUG_ENTER("check_grant");
DBUG_ASSERT(number > 0);
@@ -3886,7 +3914,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
i < number && table != first_not_own_table;
table= table->next_global, i++)
{
- /* Remove SHOW_VIEW_ACL, because it will be checked during making view */
+ /*
+ Save a copy of the privileges without the SHOW_VIEW_ACL attribute.
+ It will be checked during making view.
+ */
table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
}
@@ -3899,7 +3930,6 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
sctx = test(table->security_ctx) ?
table->security_ctx : thd->security_ctx;
- want_access= orig_want_access;
want_access&= ~sctx->master_access;
if (!want_access)
continue; // ok
@@ -3929,8 +3959,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
want_access &= ~table->grant.privilege;
goto err; // No grants
}
- if (show_table)
- continue; // We have some priv on this
+
+ /*
+ For SHOW COLUMNS, SHOW INDEX it is enough to have some
+ privileges on any column combination on the table.
+ */
+ if (any_combination_will_do)
+ continue;
table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version;
@@ -3948,7 +3983,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
}
rw_unlock(&LOCK_grant);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
rw_unlock(&LOCK_grant);
@@ -3962,7 +3997,97 @@ err:
sctx->host_or_ip,
table ? table->get_table_name() : "unknown");
}
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
+}
+
+
+/**
+ Check if all tables in the table list has any of the requested table level
+ privileges matching the current user.
+
+ @param thd A pointer to the thread context.
+ @param required_access Set of privileges to compare against.
+ @param tables[in,out] A list of tables to be checked.
+
+ @note If the table grant hash contains any grant table, this table will be
+ attached to the corresponding TABLE_LIST object in 'tables'.
+
+ @return
+ @retval TRUE There is a privilege on the table level granted to the
+ current user.
+ @retval FALSE There are no privileges on the table level granted to the
+ current user.
+*/
+
+bool has_any_table_level_privileges(THD *thd, ulong required_access,
+ TABLE_LIST *tables)
+{
+
+ Security_context *sctx;
+ GRANT_TABLE *grant_table;
+ TABLE_LIST *table;
+
+ /* For each table in tables */
+ for (table= tables; table; table= table->next_global)
+ {
+ /*
+ If this table is a VIEW, then it will supply its own security context.
+ This is because VIEWs can have a DEFINER or an INVOKER security role.
+ */
+ sctx= table->security_ctx ? table->security_ctx : thd->security_ctx;
+
+ /*
+ Get privileges from table_priv and column_priv tables by searching
+ the cache.
+ */
+ rw_rdlock(&LOCK_grant);
+ grant_table= table_hash_search(sctx->host, sctx->ip,
+ table->db, sctx->priv_user,
+ table->table_name,0);
+ rw_unlock(&LOCK_grant);
+
+ /* Stop if there are no grants for the current user */
+ if (!grant_table)
+ return FALSE;
+
+ /*
+ Save a pointer to the found grant_table in the table object.
+ This pointer can later be used to verify other access requirements
+ without having to look up the grant table in the hash.
+ */
+ table->grant.grant_table= grant_table;
+ table->grant.version= grant_version;
+ table->grant.privilege|= grant_table->privs;
+ /*
+ Save all privileges which might be subject to column privileges
+ but not which aren't yet granted by table level ACLs.
+ This is can later be used for column privilege checks.
+ */
+ table->grant.want_privilege= ((required_access & COL_ACLS)
+ & ~table->grant.privilege);
+
+ /*
+ If the requested privileges share any intersection with the current
+ table privileges we have found at least one common privilege on the
+ table level.
+ */
+ if (grant_table->privs & required_access)
+ continue; /* Check next table */
+
+ /*
+ There are no table level privileges which satisfies any of the
+ requested privileges. There might still be column privileges which
+ does though.
+ */
+ return FALSE;
+ }
+
+ /*
+ All tables in TABLE_LIST satisfy the requirement of having any
+ privilege on the table level.
+ */
+
+ return TRUE;
}
@@ -4209,7 +4334,7 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash)
for (uint idx= 0; idx < hash->records; ++idx)
{
- GRANT_NAME *item= (GRANT_NAME*) hash_element(hash, idx);
+ GRANT_NAME *item= (GRANT_NAME*) my_hash_element(hash, idx);
if (strcmp(item->user, sctx->priv_user) == 0 &&
strcmp(item->db, db) == 0 &&
@@ -4242,8 +4367,9 @@ bool check_grant_db(THD *thd,const char *db)
for (uint idx=0 ; idx < column_priv_hash.records ; idx++)
{
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
- idx);
+ GRANT_TABLE *grant_table= (GRANT_TABLE*)
+ my_hash_element(&column_priv_hash,
+ idx);
if (len < grant_table->key_length &&
!memcmp(grant_table->hash_key,helping,len) &&
compare_hostname(&grant_table->host, sctx->host, sctx->ip))
@@ -4466,13 +4592,13 @@ static const char *command_array[]=
"ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES",
"LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT",
"CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE",
- "CREATE USER", "EVENT", "TRIGGER"
+ "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE"
};
static uint command_lengths[]=
{
6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9,
- 14, 13, 11, 5, 7
+ 14, 13, 11, 5, 7, 17
};
@@ -4527,7 +4653,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
strxmov(buff,"Grants for ",lex_user->user.str,"@",
lex_user->host.str,NullS);
field_list.push_back(field);
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
VOID(pthread_mutex_unlock(&acl_cache->lock));
@@ -4715,8 +4841,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
for (index=0 ; index < column_priv_hash.records ; index++)
{
const char *user, *host;
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
- index);
+ GRANT_TABLE *grant_table= (GRANT_TABLE*)
+ my_hash_element(&column_priv_hash, index);
if (!(user=grant_table->user))
user= "";
@@ -4769,7 +4895,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
col_index++)
{
GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
- hash_element(&grant_table->hash_columns,col_index);
+ my_hash_element(&grant_table->hash_columns,col_index);
if (grant_column->rights & j)
{
if (!found_col)
@@ -4859,7 +4985,7 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
for (index=0 ; index < hash->records ; index++)
{
const char *user, *host;
- GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, index);
+ GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, index);
if (!(user=grant_proc->user))
user= "";
@@ -5372,13 +5498,13 @@ static int handle_grant_struct(uint struct_no, bool drop,
break;
case 2:
- grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx);
+ grant_name= (GRANT_NAME*) my_hash_element(&column_priv_hash, idx);
user= grant_name->user;
host= grant_name->host.hostname;
break;
case 3:
- grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx);
+ grant_name= (GRANT_NAME*) my_hash_element(&proc_priv_hash, idx);
user= grant_name->user;
host= grant_name->host.hostname;
break;
@@ -5411,11 +5537,11 @@ static int handle_grant_struct(uint struct_no, bool drop,
break;
case 2:
- hash_delete(&column_priv_hash, (uchar*) grant_name);
+ my_hash_delete(&column_priv_hash, (uchar*) grant_name);
break;
case 3:
- hash_delete(&proc_priv_hash, (uchar*) grant_name);
+ my_hash_delete(&proc_priv_hash, (uchar*) grant_name);
break;
}
elements--;
@@ -5436,9 +5562,21 @@ static int handle_grant_struct(uint struct_no, bool drop,
case 2:
case 3:
- grant_name->user= strdup_root(&mem, user_to->user.str);
- update_hostname(&grant_name->host,
- strdup_root(&mem, user_to->host.str));
+ /*
+ Update the grant structure with the new user name and
+ host name
+ */
+ grant_name->set_user_details(user_to->host.str, grant_name->db,
+ user_to->user.str, grant_name->tname,
+ TRUE);
+
+ /*
+ Since username is part of the hash key, when the user name
+ is renamed, the hash key is changed. Update the hash to
+ ensure that the position matches the new hash key value
+ */
+ my_hash_update(&column_priv_hash, (uchar*) grant_name,
+ (uchar*) grant_name->hash_key, grant_name->key_length);
break;
}
}
@@ -5663,7 +5801,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe());
if (some_users_created)
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
@@ -5736,7 +5874,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe());
if (some_users_deleted)
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
@@ -5821,7 +5959,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe());
if (some_users_renamed && mysql_bin_log.is_open())
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
@@ -5929,8 +6067,8 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
for (counter= 0, revoked= 0 ; counter < column_priv_hash.records ; )
{
const char *user,*host;
- GRANT_TABLE *grant_table= (GRANT_TABLE*)hash_element(&column_priv_hash,
- counter);
+ GRANT_TABLE *grant_table=
+ (GRANT_TABLE*) my_hash_element(&column_priv_hash, counter);
if (!(user=grant_table->user))
user= "";
if (!(host=grant_table->host.hostname))
@@ -5976,7 +6114,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
for (counter= 0, revoked= 0 ; counter < hash->records ; )
{
const char *user,*host;
- GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter);
+ GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter);
if (!(user=grant_proc->user))
user= "";
if (!(host=grant_proc->host.hostname))
@@ -6003,7 +6141,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
VOID(pthread_mutex_unlock(&acl_cache->lock));
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
@@ -6124,8 +6262,8 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
{
for (counter= 0, revoked= 0 ; counter < hash->records ; )
{
- GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter);
- if (!my_strcasecmp(system_charset_info, grant_proc->db, sp_db) &&
+ GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter);
+ if (!my_strcasecmp(&my_charset_utf8_bin, grant_proc->db, sp_db) &&
!my_strcasecmp(system_charset_info, grant_proc->tname, sp_name))
{
LEX_USER lex_user;
@@ -6515,7 +6653,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
for (index=0 ; index < column_priv_hash.records ; index++)
{
const char *user, *host, *is_grantable= "YES";
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash,
index);
if (!(user=grant_table->user))
user= "";
@@ -6598,7 +6736,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
for (index=0 ; index < column_priv_hash.records ; index++)
{
const char *user, *host, *is_grantable= "YES";
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash,
index);
if (!(user=grant_table->user))
user= "";
@@ -6633,7 +6771,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
col_index++)
{
GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
- hash_element(&grant_table->hash_columns,col_index);
+ my_hash_element(&grant_table->hash_columns,col_index);
if ((grant_column->rights & j) && (table_access & j))
{
if (update_schema_privilege(thd, table, buff, grant_table->db,
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index c0622bd747c..5c1f34b0b34 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -46,6 +46,7 @@
#define CREATE_USER_ACL (1L << 25)
#define EVENT_ACL (1L << 26)
#define TRIGGER_ACL (1L << 27)
+#define CREATE_TABLESPACE_ACL (1L << 28)
/*
don't forget to update
1. static struct show_privileges_st sys_privileges[]
@@ -54,7 +55,6 @@
4. acl_init() or whatever - to define behaviour for old privilege tables
5. sql_yacc.yy - for GRANT/REVOKE to work
*/
-#define EXTRA_ACL (1L << 29)
#define NO_ACCESS (1L << 30)
#define DB_ACLS \
(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
@@ -82,11 +82,17 @@
REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \
CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \
EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | CREATE_PROC_ACL | \
- ALTER_PROC_ACL | CREATE_USER_ACL | EVENT_ACL | TRIGGER_ACL)
+ ALTER_PROC_ACL | CREATE_USER_ACL | EVENT_ACL | TRIGGER_ACL | \
+ CREATE_TABLESPACE_ACL)
#define DEFAULT_CREATE_PROC_ACLS \
(ALTER_PROC_ACL | EXECUTE_ACL)
+#define SHOW_CREATE_TABLE_ACLS \
+(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | \
+ CREATE_ACL | DROP_ACL | ALTER_ACL | INDEX_ACL | \
+ TRIGGER_ACL | REFERENCES_ACL | GRANT_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL)
+
/*
Defines to change the above bits to how things are stored in tables
This is needed as the 'host' and 'db' table is missing a few privileges
@@ -241,7 +247,7 @@ my_bool grant_init();
void grant_free(void);
my_bool grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
- uint show_command, uint number, bool dont_print_error);
+ bool any_combination_will_do, uint number, bool no_errors);
bool check_grant_column (THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name,
const char *name, uint length, Security_context *sctx);
@@ -272,8 +278,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
bool check_routine_level_acl(THD *thd, const char *db, const char *name,
bool is_proc);
bool is_acl_user(const char *host, const char *user);
+bool has_any_table_level_privileges(THD *thd, ulong required_access,
+ TABLE_LIST *tables);
+
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E,F) 0
#define check_grant_db(A,B) 0
+#define has_any_table_level_privileges(A,B,C) 0
#endif
#endif /* SQL_ACL_INCLUDED */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 26bcd83d235..787ea3cdc92 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -22,9 +22,11 @@
#include "sp_head.h"
#include "sp.h"
#include "sql_trigger.h"
+#include "sql_prepare.h"
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
+#include "rpl_filter.h"
#ifdef __WIN__
#include <io.h>
#endif
@@ -127,9 +129,9 @@ extern "C" uchar *table_cache_key(const uchar *record, size_t *length,
bool table_cache_init(void)
{
- return hash_init(&open_cache, &my_charset_bin, table_cache_size+16,
- 0, 0, table_cache_key,
- (hash_free_key) free_cache_entry, 0) != 0;
+ return my_hash_init(&open_cache, &my_charset_bin, table_cache_size+16,
+ 0, 0, table_cache_key,
+ (my_hash_free_key) free_cache_entry, 0) != 0;
}
void table_cache_free(void)
@@ -139,7 +141,7 @@ void table_cache_free(void)
{
close_cached_tables(NULL, NULL, FALSE, FALSE, FALSE);
if (!open_cache.records) // Safety first
- hash_free(&open_cache);
+ my_hash_free(&open_cache);
}
DBUG_VOID_RETURN;
}
@@ -174,7 +176,7 @@ static void check_unused(void)
}
for (idx=0 ; idx < open_cache.records ; idx++)
{
- TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
+ TABLE *entry=(TABLE*) my_hash_element(&open_cache,idx);
if (!entry->in_use)
count--;
if (entry->file)
@@ -287,9 +289,9 @@ bool table_def_init(void)
oldest_unused_share= &end_of_unused_share;
end_of_unused_share.prev= &oldest_unused_share;
- return hash_init(&table_def_cache, &my_charset_bin, table_def_size,
- 0, 0, table_def_key,
- (hash_free_key) table_def_free_entry, 0) != 0;
+ return my_hash_init(&table_def_cache, &my_charset_bin, table_def_size,
+ 0, 0, table_def_key,
+ (my_hash_free_key) table_def_free_entry, 0) != 0;
}
@@ -300,7 +302,7 @@ void table_def_free(void)
{
table_def_inited= 0;
pthread_mutex_destroy(&LOCK_table_share);
- hash_free(&table_def_cache);
+ my_hash_free(&table_def_cache);
}
DBUG_VOID_RETURN;
}
@@ -346,8 +348,8 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
*error= 0;
/* Read table definition from cache */
- if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key,
- key_length)))
+ if ((share= (TABLE_SHARE*) my_hash_search(&table_def_cache,(uchar*) key,
+ key_length)))
goto found;
if (!(share= alloc_table_share(table_list, key, key_length)))
@@ -384,7 +386,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (open_table_def(thd, share, db_flags))
{
*error= share->error;
- (void) hash_delete(&table_def_cache, (uchar*) share);
+ (void) my_hash_delete(&table_def_cache, (uchar*) share);
DBUG_RETURN(0);
}
share->ref_count++; // Mark in use
@@ -436,7 +438,7 @@ found:
oldest_unused_share->next)
{
pthread_mutex_lock(&oldest_unused_share->mutex);
- VOID(hash_delete(&table_def_cache, (uchar*) oldest_unused_share));
+ VOID(my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share));
}
DBUG_PRINT("exit", ("share: 0x%lx ref_count: %u",
@@ -591,7 +593,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
if (to_be_deleted)
{
DBUG_PRINT("info", ("Deleting share"));
- hash_delete(&table_def_cache, (uchar*) share);
+ my_hash_delete(&table_def_cache, (uchar*) share);
DBUG_VOID_RETURN;
}
pthread_mutex_unlock(&share->mutex);
@@ -622,7 +624,8 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name)
table_list.db= (char*) db;
table_list.table_name= (char*) table_name;
key_length= create_table_def_key((THD*) 0, key, &table_list, 0);
- return (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, key_length);
+ return (TABLE_SHARE*) my_hash_search(&table_def_cache,
+ (uchar*) key, key_length);
}
@@ -719,7 +722,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild)
for (uint idx=0 ; result == 0 && idx < open_cache.records; idx++)
{
OPEN_TABLE_LIST *table;
- TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
+ TABLE *entry=(TABLE*) my_hash_element(&open_cache,idx);
TABLE_SHARE *share= entry->s;
if (db && my_strcasecmp(system_charset_info, db, share->db.str))
@@ -732,7 +735,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild)
table_list.table_name= share->table_name.str;
table_list.grant.privilege=0;
- if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list, 1, TRUE))
+ if (check_table_access(thd,SELECT_ACL,&table_list, TRUE, 1, TRUE))
continue;
/* need to check if we haven't already listed it */
for (table= open_list ; table ; table=table->next)
@@ -868,17 +871,17 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
while (unused_tables)
{
#ifdef EXTRA_DEBUG
- if (hash_delete(&open_cache,(uchar*) unused_tables))
+ if (my_hash_delete(&open_cache,(uchar*) unused_tables))
printf("Warning: Couldn't delete open table from hash\n");
#else
- VOID(hash_delete(&open_cache,(uchar*) unused_tables));
+ VOID(my_hash_delete(&open_cache,(uchar*) unused_tables));
#endif
}
/* Free table shares */
while (oldest_unused_share->next)
{
pthread_mutex_lock(&oldest_unused_share->mutex);
- VOID(hash_delete(&table_def_cache, (uchar*) oldest_unused_share));
+ VOID(my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share));
}
DBUG_PRINT("tcache", ("incremented global refresh_version to: %lu",
refresh_version));
@@ -923,7 +926,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
*/
for (uint idx=0 ; idx < open_cache.records ; idx++)
{
- TABLE *table=(TABLE*) hash_element(&open_cache,idx);
+ TABLE *table=(TABLE*) my_hash_element(&open_cache,idx);
if (table->in_use)
table->in_use->some_tables_deleted= 1;
}
@@ -968,7 +971,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
found=0;
for (uint idx=0 ; idx < open_cache.records ; idx++)
{
- TABLE *table=(TABLE*) hash_element(&open_cache,idx);
+ TABLE *table=(TABLE*) my_hash_element(&open_cache,idx);
/* Avoid a self-deadlock. */
if (table->in_use == thd)
continue;
@@ -1050,7 +1053,7 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh,
for (idx= 0; idx < table_def_cache.records; idx++)
{
- TABLE_SHARE *share= (TABLE_SHARE *) hash_element(&table_def_cache, idx);
+ TABLE_SHARE *share= (TABLE_SHARE *) my_hash_element(&table_def_cache, idx);
/* Ignore if table is not open or does not have a connect_string */
if (!share->connect_string.length || !share->ref_count)
@@ -1206,7 +1209,7 @@ static void close_open_tables(THD *thd)
/* Free tables to hold down open files */
while (open_cache.records > table_cache_size && unused_tables)
- VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */
+ VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */
check_unused();
if (found_old_table)
{
@@ -1392,7 +1395,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
if (table->needs_reopen_or_name_lock() ||
thd->version != refresh_version || !table->db_stat)
{
- VOID(hash_delete(&open_cache,(uchar*) table));
+ VOID(my_hash_delete(&open_cache,(uchar*) table));
found_old_table=1;
}
else
@@ -1553,6 +1556,7 @@ void close_temporary_tables(THD *thd)
s_query.length() - 1 /* to remove trailing ',' */,
0, FALSE, 0);
qinfo.db= db.ptr();
+ qinfo.db_len= db.length();
thd->variables.character_set_client= cs_save;
mysql_bin_log.write(&qinfo);
thd->variables.pseudo_thread_id= save_pseudo_thread_id;
@@ -2095,7 +2099,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock)
/* Remove table from open_tables list. */
*prev= list->next;
/* Close table. */
- VOID(hash_delete(&open_cache,(uchar*) list)); // Close table
+ VOID(my_hash_delete(&open_cache,(uchar*) list)); // Close table
}
else
{
@@ -2401,7 +2405,7 @@ bool lock_table_name_if_not_cached(THD *thd, const char *db,
key_length= (uint)(strmov(strmov(key, db) + 1, table_name) - key) + 1;
VOID(pthread_mutex_lock(&LOCK_open));
- if (hash_search(&open_cache, (uchar *)key, key_length))
+ if (my_hash_search(&open_cache, (uchar *)key, key_length))
{
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_PRINT("info", ("Table is cached, name-lock is not obtained"));
@@ -2528,9 +2532,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
HASH_SEARCH_STATE state;
DBUG_ENTER("open_table");
- /* Parsing of partitioning information from .frm needs thd->lex set up. */
- DBUG_ASSERT(thd->lex->is_lex_started);
-
/* find a unused table in the open table cache */
if (refresh)
*refresh=0;
@@ -2756,11 +2757,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
an implicit "pending locks queue" - see
wait_for_locked_table_names for details.
*/
- for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length,
- &state);
+ for (table= (TABLE*) my_hash_first(&open_cache, (uchar*) key, key_length,
+ &state);
table && table->in_use ;
- table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length,
- &state))
+ table= (TABLE*) my_hash_next(&open_cache, (uchar*) key, key_length,
+ &state))
{
DBUG_PRINT("tcache", ("in_use table: '%s'.'%s' 0x%lx", table->s->db.str,
table->s->table_name.str, (long) table));
@@ -2872,7 +2873,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
DBUG_PRINT("tcache", ("opening new table"));
/* Free cache if too big */
while (open_cache.records > table_cache_size && unused_tables)
- VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */
+ VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */
if (table_list->create)
{
@@ -2930,7 +2931,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
Set 1 as a flag here
*/
if (error < 0)
- table_list->view= (st_lex*)1;
+ table_list->view= (LEX*)1;
my_free((uchar*)table, MYF(0));
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -3330,7 +3331,7 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
*/
if (table->child_l || table->parent)
detach_merge_children(table, TRUE);
- VOID(hash_delete(&open_cache,(uchar*) table));
+ VOID(my_hash_delete(&open_cache,(uchar*) table));
error=1;
}
else
@@ -3359,7 +3360,7 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
{
while (err_tables)
{
- VOID(hash_delete(&open_cache, (uchar*) err_tables));
+ VOID(my_hash_delete(&open_cache, (uchar*) err_tables));
err_tables= err_tables->next;
}
}
@@ -3511,11 +3512,11 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
DBUG_PRINT("loop", ("table_name: %s", table->alias));
HASH_SEARCH_STATE state;
- for (TABLE *search= (TABLE*) hash_first(&open_cache, (uchar*) key,
- key_length, &state);
+ for (TABLE *search= (TABLE*) my_hash_first(&open_cache, (uchar*) key,
+ key_length, &state);
search ;
- search= (TABLE*) hash_next(&open_cache, (uchar*) key,
- key_length, &state))
+ search= (TABLE*) my_hash_next(&open_cache, (uchar*) key,
+ key_length, &state))
{
DBUG_PRINT("info", ("share: 0x%lx "
"open_placeholder: %d locked_by_name: %d "
@@ -3641,7 +3642,7 @@ TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name)
else
{
/* We already have a name lock, remove copy */
- VOID(hash_delete(&open_cache,(uchar*) table));
+ VOID(my_hash_delete(&open_cache,(uchar*) table));
}
}
else
@@ -4614,7 +4615,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
Let us free memory used by 'sroutines' hash here since we never
call destructor for this LEX.
*/
- hash_free(&tables->view->sroutines);
+ my_hash_free(&tables->view->sroutines);
goto process_view_routines;
}
@@ -5103,7 +5104,16 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table)
int decide_logging_format(THD *thd, TABLE_LIST *tables)
{
- if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
+ /*
+ In SBR mode, we are only proceeding if we are binlogging this
+ statement, ie, the filtering rules won't later filter this out.
+
+ This check here is needed to prevent some spurious error to be
+ raised in some cases (See BUG#42829).
+ */
+ if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG) &&
+ (thd->variables.binlog_format != BINLOG_FORMAT_STMT ||
+ binlog_filter->db_ok(thd->db)))
{
/*
Compute the starting vectors for the computations by creating a
@@ -5882,8 +5892,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
field_ptr= table->field + cached_field_index;
else if (table->s->name_hash.records)
{
- field_ptr= (Field**) hash_search(&table->s->name_hash, (uchar*) name,
- length);
+ field_ptr= (Field**) my_hash_search(&table->s->name_hash, (uchar*) name,
+ length);
if (field_ptr)
{
/*
@@ -6131,8 +6141,8 @@ Field *find_field_in_table_sef(TABLE *table, const char *name)
Field **field_ptr;
if (table->s->name_hash.records)
{
- field_ptr= (Field**)hash_search(&table->s->name_hash,(uchar*) name,
- strlen(name));
+ field_ptr= (Field**)my_hash_search(&table->s->name_hash,(uchar*) name,
+ strlen(name));
if (field_ptr)
{
/*
@@ -8374,7 +8384,7 @@ void remove_db_from_cache(const char *db)
{
for (uint idx=0 ; idx < open_cache.records ; idx++)
{
- TABLE *table=(TABLE*) hash_element(&open_cache,idx);
+ TABLE *table=(TABLE*) my_hash_element(&open_cache,idx);
if (!strcmp(table->s->db.str, db))
{
table->s->version= 0L; /* Free when thread is ready */
@@ -8383,7 +8393,7 @@ void remove_db_from_cache(const char *db)
}
}
while (unused_tables && !unused_tables->s->version)
- VOID(hash_delete(&open_cache,(uchar*) unused_tables));
+ VOID(my_hash_delete(&open_cache,(uchar*) unused_tables));
}
@@ -8399,7 +8409,7 @@ void flush_tables()
{
(void) pthread_mutex_lock(&LOCK_open);
while (unused_tables)
- hash_delete(&open_cache,(uchar*) unused_tables);
+ my_hash_delete(&open_cache,(uchar*) unused_tables);
(void) pthread_mutex_unlock(&LOCK_open);
}
@@ -8436,11 +8446,11 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
HASH_SEARCH_STATE state;
result= signalled= 0;
- for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length,
- &state);
+ for (table= (TABLE*) my_hash_first(&open_cache, (uchar*) key, key_length,
+ &state);
table;
- table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length,
- &state))
+ table= (TABLE*) my_hash_next(&open_cache, (uchar*) key, key_length,
+ &state))
{
THD *in_use;
DBUG_PRINT("tcache", ("found table: '%s'.'%s' 0x%lx", table->s->db.str,
@@ -8507,12 +8517,12 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
}
}
while (unused_tables && !unused_tables->s->version)
- VOID(hash_delete(&open_cache,(uchar*) unused_tables));
+ VOID(my_hash_delete(&open_cache,(uchar*) unused_tables));
DBUG_PRINT("info", ("Removing table from table_def_cache"));
/* Remove table from table definition cache if it's not in use */
- if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key,
- key_length)))
+ if ((share= (TABLE_SHARE*) my_hash_search(&table_def_cache,(uchar*) key,
+ key_length)))
{
DBUG_PRINT("info", ("share version: %lu ref_count: %u",
share->version, share->ref_count));
@@ -8520,7 +8530,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
if (share->ref_count == 0)
{
pthread_mutex_lock(&share->mutex);
- VOID(hash_delete(&table_def_cache, (uchar*) share));
+ VOID(my_hash_delete(&table_def_cache, (uchar*) share));
}
}
@@ -8768,11 +8778,11 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table
key_length=(uint) (strmov(strmov(key,lpt->db)+1,lpt->table_name)-key)+1;
VOID(pthread_mutex_lock(&LOCK_open));
HASH_SEARCH_STATE state;
- for (table= (TABLE*) hash_first(&open_cache,(uchar*) key,key_length,
- &state) ;
+ for (table= (TABLE*) my_hash_first(&open_cache,(uchar*) key,key_length,
+ &state) ;
table;
- table= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length,
- &state))
+ table= (TABLE*) my_hash_next(&open_cache,(uchar*) key,key_length,
+ &state))
{
THD *in_use= table->in_use;
table->s->version= 0L;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 049c541d284..35d2c886119 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -286,6 +286,7 @@ functions:
if (and only if) this query has a registered result set writer
(thd->net.query_cache_query).
4. Query_cache::invalidate
+ Query_cache::invalidate_locked_for_write
- Called from various places to invalidate query cache based on data-
base, table and myisam file name. During an on going invalidation
the query cache is temporarily disabled.
@@ -789,19 +790,20 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length,
Note on double-check locking (DCL) usage.
Below, in query_cache_insert(), query_cache_abort() and
- query_cache_end_of_result() we use what is called double-check
- locking (DCL) for NET::query_cache_query. I.e. we test it first
- without a lock, and, if positive, test again under the lock.
+ Query_cache::end_of_result() we use what is called double-check
+ locking (DCL) for Query_cache_tls::first_query_block.
+ I.e. we test it first without a lock, and, if positive, test again
+ under the lock.
- This means that if we see 'NET::query_cache_query == 0' without a
+ This means that if we see 'first_query_block == 0' without a
lock we will skip the operation. But this is safe here: when we
started to cache a query, we called Query_cache::store_query(), and
- NET::query_cache_query was set to non-zero in this thread (and the
+ 'first_query_block' was set to non-zero in this thread (and the
thread always sees results of its memory operations, mutex or not).
- If later we see 'NET::query_cache_query == 0' without locking a
+ If later we see 'first_query_block == 0' without locking a
mutex, that may only mean that some other thread have reset it by
invalidating the query. Skipping the operation in this case is the
- right thing to do, as NET::query_cache_query won't get non-zero for
+ right thing to do, as first_query_block won't get non-zero for
this query again.
See also comments in Query_cache::store_query() and
@@ -810,56 +812,71 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length,
NOTE, however, that double-check locking is not applicable in
'invalidate' functions, as we may erroneously skip invalidation,
because the thread doing invalidation may never see non-zero
- NET::query_cache_query.
+ 'first_query_block'.
*/
-void query_cache_init_query(NET *net)
+/**
+ libmysql convenience wrapper to insert data into query cache.
+*/
+void query_cache_insert(const char *packet, ulong length,
+ unsigned pkt_nr)
{
+ THD *thd= current_thd;
+
/*
- It is safe to initialize 'NET::query_cache_query' without a lock
- here, because before it will be accessed from different threads it
- will be set in this thread under a lock, and access from the same
- thread is always safe.
+ Current_thd can be NULL when a new connection is immediately ended
+ due to "Too many connections". thd->store_globals() has not been
+ called at this time and hence my_pthread_setspecific_ptr(THR_THD,
+ this) has not been called for this thread.
*/
- net->query_cache_query= 0;
+
+ if (!thd)
+ return;
+
+ query_cache.insert(&thd->query_cache_tls,
+ packet, length,
+ pkt_nr);
}
-/*
+/**
Insert the packet into the query cache.
*/
-void query_cache_insert(NET *net, const char *packet, ulong length)
+void
+Query_cache::insert(Query_cache_tls *query_cache_tls,
+ const char *packet, ulong length,
+ unsigned pkt_nr)
{
- DBUG_ENTER("query_cache_insert");
+ DBUG_ENTER("Query_cache::insert");
/* See the comment on double-check locking usage above. */
- if (net->query_cache_query == 0)
+ if (is_disabled() || query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN;
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
debug_wait_for_kill("wait_in_query_cache_insert"); );
- if (query_cache.try_lock())
+
+ if (try_lock())
DBUG_VOID_RETURN;
- Query_cache_block *query_block= (Query_cache_block*)net->query_cache_query;
- if (!query_block)
+ Query_cache_block *query_block = query_cache_tls->first_query_block;
+ if (query_block == NULL)
{
/*
We lost the writer and the currently processed query has been
invalidated; there is nothing left to do.
*/
- query_cache.unlock();
+ unlock();
DBUG_VOID_RETURN;
}
-
BLOCK_LOCK_WR(query_block);
Query_cache_query *header= query_block->query();
Query_cache_block *result= header->result();
- DUMP(&query_cache);
+ DUMP(this);
DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
/*
@@ -867,8 +884,8 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
still need structure_guard_mutex to free the query, and therefore unlock
it later in this function.
*/
- if (!query_cache.append_result_data(&result, length, (uchar*) packet,
- query_block))
+ if (!append_result_data(&result, length, (uchar*) packet,
+ query_block))
{
DBUG_PRINT("warning", ("Can't append data"));
header->result(result);
@@ -877,60 +894,63 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
query_cache.free_query(query_block);
query_cache.refused++;
// append_result_data no success => we need unlock
- query_cache.unlock();
+ unlock();
DBUG_VOID_RETURN;
}
header->result(result);
- header->last_pkt_nr= net->pkt_nr;
+ header->last_pkt_nr= pkt_nr;
BLOCK_UNLOCK_WR(query_block);
- DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
+ DBUG_EXECUTE("check_querycache",check_integrity(0););
DBUG_VOID_RETURN;
}
-void query_cache_abort(NET *net)
+void
+Query_cache::abort(Query_cache_tls *query_cache_tls)
{
DBUG_ENTER("query_cache_abort");
THD *thd= current_thd;
/* See the comment on double-check locking usage above. */
- if (net->query_cache_query == 0)
+ if (is_disabled() || query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN;
- if (query_cache.try_lock())
+ if (try_lock())
DBUG_VOID_RETURN;
/*
While we were waiting another thread might have changed the status
of the writer. Make sure the writer still exists before continue.
*/
- Query_cache_block *query_block= ((Query_cache_block*)
- net->query_cache_query);
+ Query_cache_block *query_block= query_cache_tls->first_query_block;
if (query_block)
{
thd_proc_info(thd, "storing result in query cache");
- DUMP(&query_cache);
+ DUMP(this);
BLOCK_LOCK_WR(query_block);
// The following call will remove the lock on query_block
- query_cache.free_query(query_block);
- net->query_cache_query= 0;
- DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
+ free_query(query_block);
+ query_cache_tls->first_query_block= NULL;
+ DBUG_EXECUTE("check_querycache", check_integrity(1););
}
- query_cache.unlock();
+ unlock();
+
DBUG_VOID_RETURN;
}
-void query_cache_end_of_result(THD *thd)
+void Query_cache::end_of_result(THD *thd)
{
Query_cache_block *query_block;
- DBUG_ENTER("query_cache_end_of_result");
+ Query_cache_tls *query_cache_tls= &thd->query_cache_tls;
+ ulonglong limit_found_rows= thd->limit_found_rows;
+ DBUG_ENTER("Query_cache::end_of_result");
/* See the comment on double-check locking usage above. */
- if (thd->net.query_cache_query == 0)
+ if (query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN;
/* Ensure that only complete results are cached. */
@@ -938,19 +958,19 @@ void query_cache_end_of_result(THD *thd)
if (thd->killed)
{
- query_cache_abort(&thd->net);
+ query_cache_abort(&thd->query_cache_tls);
DBUG_VOID_RETURN;
}
#ifdef EMBEDDED_LIBRARY
- query_cache_insert(&thd->net, (char*)thd,
- emb_count_querycache_size(thd));
+ insert(query_cache_tls, (char*)thd,
+ emb_count_querycache_size(thd), 0);
#endif
- if (query_cache.try_lock())
+ if (try_lock())
DBUG_VOID_RETURN;
- query_block= ((Query_cache_block*) thd->net.query_cache_query);
+ query_block= query_cache_tls->first_query_block;
if (query_block)
{
/*
@@ -959,7 +979,7 @@ void query_cache_end_of_result(THD *thd)
block, the writer should be dropped.
*/
thd_proc_info(thd, "storing result in query cache");
- DUMP(&query_cache);
+ DUMP(this);
BLOCK_LOCK_WR(query_block);
Query_cache_query *header= query_block->query();
Query_cache_block *last_result_block;
@@ -976,8 +996,8 @@ void query_cache_end_of_result(THD *thd)
and removed from QC.
*/
DBUG_ASSERT(0);
- query_cache.free_query(query_block);
- query_cache.unlock();
+ free_query(query_block);
+ unlock();
DBUG_VOID_RETURN;
}
last_result_block= header->result()->prev;
@@ -986,17 +1006,17 @@ void query_cache_end_of_result(THD *thd)
if (last_result_block->length >= query_cache.min_allocation_unit + len)
query_cache.split_block(last_result_block,len);
- header->found_rows(current_thd->limit_found_rows);
+ header->found_rows(limit_found_rows);
header->result()->type= Query_cache_block::RESULT;
/* Drop the writer. */
header->writer(0);
- thd->net.query_cache_query= 0;
+ query_cache_tls->first_query_block= NULL;
BLOCK_UNLOCK_WR(query_block);
- DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
-
+ DBUG_EXECUTE("check_querycache", check_integrity(1););
}
- query_cache.unlock();
+
+ unlock();
DBUG_VOID_RETURN;
}
@@ -1036,7 +1056,7 @@ Query_cache::Query_cache(ulong query_cache_limit_arg,
min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
- initialized(0)
+ initialized(0), m_query_cache_is_disabled(FALSE)
{
ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_block_table)) +
@@ -1074,7 +1094,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
Drop the writer; this will cancel any attempts to store
the processed statement associated with this writer.
*/
- query->writer()->query_cache_query= 0;
+ query->writer()->first_query_block= NULL;
query->writer(0);
refused++;
}
@@ -1120,8 +1140,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
DBUG_VOID_RETURN;
uint8 tables_type= 0;
- if ((local_tables= is_cacheable(thd, thd->query_length,
- thd->query, thd->lex, tables_used,
+ if ((local_tables= is_cacheable(thd, thd->query_length(),
+ thd->query(), thd->lex, tables_used,
&tables_type)))
{
NET *net= &thd->net;
@@ -1136,7 +1156,9 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
protocol (COM_EXECUTE) cannot be served to statements asking for results
in the text protocol (COM_QUERY) and vice-versa.
*/
- flags.result_in_binary_protocol= (unsigned int) thd->protocol->type();
+ flags.protocol_type= (unsigned int) thd->protocol->type();
+ /* PROTOCOL_LOCAL results are not cached. */
+ DBUG_ASSERT(flags.protocol_type != (unsigned int) Protocol::PROTOCOL_LOCAL);
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
@@ -1165,7 +1187,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
- (int)flags.result_in_binary_protocol,
+ (int)flags.protocol_type,
(int)flags.more_results_exists,
flags.pkt_nr,
flags.character_set_client_num,
@@ -1211,7 +1233,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
/* Key is query + database + flag */
if (thd->db_length)
{
- memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length);
+ memcpy(thd->query() + thd->query_length() + 1, thd->db,
+ thd->db_length);
DBUG_PRINT("qcache", ("database: %s length: %u",
thd->db, (unsigned) thd->db_length));
}
@@ -1219,24 +1242,24 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
{
DBUG_PRINT("qcache", ("No active database"));
}
- tot_length= thd->query_length + thd->db_length + 1 +
+ tot_length= thd->query_length() + thd->db_length + 1 +
QUERY_CACHE_FLAGS_SIZE;
/*
We should only copy structure (don't use it location directly)
because of alignment issue
*/
- memcpy((void *)(thd->query + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
+ memcpy((void*) (thd->query() + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
&flags, QUERY_CACHE_FLAGS_SIZE);
/* Check if another thread is processing the same query? */
Query_cache_block *competitor = (Query_cache_block *)
- hash_search(&queries, (uchar*) thd->query, tot_length);
+ my_hash_search(&queries, (uchar*) thd->query(), tot_length);
DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor));
if (competitor == 0)
{
/* Query is not in cache and no one is working with it; Store it */
Query_cache_block *query_block;
- query_block= write_block_data(tot_length, (uchar*) thd->query,
+ query_block= write_block_data(tot_length, (uchar*) thd->query(),
ALIGN_SIZE(sizeof(Query_cache_query)),
Query_cache_block::QUERY, local_tables);
if (query_block != 0)
@@ -1259,7 +1282,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
{
refused++;
DBUG_PRINT("warning", ("tables list including failed"));
- hash_delete(&queries, (uchar *) query_block);
+ my_hash_delete(&queries, (uchar *) query_block);
header->unlock_n_destroy();
free_memory_block(query_block);
unlock();
@@ -1268,8 +1291,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
double_linked_list_simple_include(query_block, &queries_blocks);
inserts++;
queries_in_cache++;
- net->query_cache_query= (uchar*) query_block;
- header->writer(net);
+ thd->query_cache_tls.first_query_block= query_block;
+ header->writer(&thd->query_cache_tls);
header->tables_type(tables_type);
unlock();
@@ -1325,7 +1348,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{
ulonglong engine_data;
Query_cache_query *query;
- Query_cache_block *first_result_block, *result_block;
+#ifndef EMBEDDED_LIBRARY
+ Query_cache_block *first_result_block;
+#endif
+ Query_cache_block *result_block;
Query_cache_block_table *block_table, *block_table_end;
ulong tot_length;
Query_cache_query_flags flags;
@@ -1338,8 +1364,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
See also a note on double-check locking usage above.
*/
- if (thd->locked_tables || thd->variables.query_cache_type == 0 ||
- query_cache_size == 0)
+ if (is_disabled() || thd->locked_tables ||
+ thd->variables.query_cache_type == 0 || query_cache_size == 0)
goto err;
if (!thd->lex->safe_to_cache_query)
@@ -1396,12 +1422,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
if (query_cache_size == 0)
goto err_unlock;
- /*
- Check that we haven't forgot to reset the query cache variables;
- make sure there are no attached query cache writer to this thread.
- */
- DBUG_ASSERT(thd->net.query_cache_query == 0);
-
Query_cache_block *query_block;
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
@@ -1423,7 +1443,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
flags.client_protocol_41= test(thd->client_capabilities &
CLIENT_PROTOCOL_41);
- flags.result_in_binary_protocol= (unsigned int)thd->protocol->type();
+ flags.protocol_type= (unsigned int) thd->protocol->type();
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
@@ -1450,7 +1470,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
- (int)flags.result_in_binary_protocol,
+ (int)flags.protocol_type,
(int)flags.more_results_exists,
flags.pkt_nr,
flags.character_set_client_num,
@@ -1467,8 +1487,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.autocommit));
memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
(uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
- query_block = (Query_cache_block *) hash_search(&queries, (uchar*) sql,
- tot_length);
+ query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql,
+ tot_length);
/* Quick abort on unlocked data */
if (query_block == 0 ||
query_block->query()->result() == 0 ||
@@ -1483,7 +1503,10 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
BLOCK_LOCK_RD(query_block);
query = query_block->query();
- result_block= first_result_block= query->result();
+ result_block= query->result();
+#ifndef EMBEDDED_LIBRARY
+ first_result_block= result_block;
+#endif
if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
{
@@ -1545,7 +1568,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
table_list.db = table->db();
table_list.alias= table_list.table_name= table->table();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (check_table_access(thd,SELECT_ACL,&table_list, 1, TRUE))
+ if (check_table_access(thd,SELECT_ACL,&table_list, FALSE, 1,TRUE))
{
DBUG_PRINT("qcache",
("probably no SELECT access to %s.%s => return to normal processing",
@@ -1629,13 +1652,13 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
thd->stmt_da->disable_status();
BLOCK_UNLOCK_RD(query_block);
- MYSQL_QUERY_CACHE_HIT(thd->query, (ulong) thd->limit_found_rows);
+ MYSQL_QUERY_CACHE_HIT(thd->query(), (ulong) thd->limit_found_rows);
DBUG_RETURN(1); // Result sent to client
err_unlock:
unlock();
err:
- MYSQL_QUERY_CACHE_MISS(thd->query);
+ MYSQL_QUERY_CACHE_MISS(thd->query());
DBUG_RETURN(0); // Query was not cached
}
@@ -1648,6 +1671,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
my_bool using_transactions)
{
DBUG_ENTER("Query_cache::invalidate (table list)");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
using_transactions= using_transactions &&
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
@@ -1678,6 +1703,9 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
{
DBUG_ENTER("Query_cache::invalidate (changed table list)");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
+
THD *thd= current_thd;
for (; tables_used; tables_used= tables_used->next)
{
@@ -1703,8 +1731,11 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
*/
void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
{
- THD *thd= current_thd;
DBUG_ENTER("Query_cache::invalidate_locked_for_write");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
+
+ THD *thd= current_thd;
for (; tables_used; tables_used= tables_used->next_local)
{
thd_proc_info(thd, "invalidating query cache entries (table)");
@@ -1725,7 +1756,9 @@ void Query_cache::invalidate(THD *thd, TABLE *table,
my_bool using_transactions)
{
DBUG_ENTER("Query_cache::invalidate (table)");
-
+ if (is_disabled())
+ DBUG_VOID_RETURN;
+
using_transactions= using_transactions &&
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
if (using_transactions &&
@@ -1742,6 +1775,8 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
my_bool using_transactions)
{
DBUG_ENTER("Query_cache::invalidate (key)");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
using_transactions= using_transactions &&
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
@@ -1760,9 +1795,12 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
void Query_cache::invalidate(char *db)
{
- bool restart= FALSE;
+
DBUG_ENTER("Query_cache::invalidate (db)");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
+ bool restart= FALSE;
/*
Lock the query cache and queue all invalidation attempts to avoid
the risk of a race between invalidation, cache inserts and flushes.
@@ -1847,6 +1885,9 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
void Query_cache::flush()
{
DBUG_ENTER("Query_cache::flush");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
+
DBUG_EXECUTE_IF("wait_in_query_cache_flush1",
debug_wait_for_kill("wait_in_query_cache_flush1"););
@@ -1878,6 +1919,9 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit)
{
DBUG_ENTER("Query_cache::pack");
+ if (is_disabled())
+ DBUG_VOID_RETURN;
+
/*
If the entire qc is being invalidated we can bail out early
instead of waiting for the lock.
@@ -1935,6 +1979,15 @@ void Query_cache::init()
pthread_cond_init(&COND_cache_status_changed, NULL);
m_cache_lock_status= Query_cache::UNLOCKED;
initialized = 1;
+ /*
+ If we explicitly turn off query cache from the command line query cache will
+ be disabled for the reminder of the server life time. This is because we
+ want to avoid locking the QC specific mutex if query cache isn't going to
+ be used.
+ */
+ if (global_system_variables.query_cache_type == 0)
+ query_cache.disable_query_cache();
+
DBUG_VOID_RETURN;
}
@@ -2073,8 +2126,8 @@ ulong Query_cache::init_cache()
DUMP(this);
- VOID(hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0,
- query_cache_query_get_key, 0, 0));
+ VOID(my_hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0,
+ query_cache_query_get_key, 0, 0));
#ifndef FN_NO_CASE_SENCE
/*
If lower_case_table_names!=0 then db and table names are already
@@ -2084,8 +2137,8 @@ ulong Query_cache::init_cache()
lower_case_table_names == 0 then we should distinguish my_table
and MY_TABLE cases and so again can use binary collation.
*/
- VOID(hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0,
- query_cache_table_get_key, 0, 0));
+ VOID(my_hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0,
+ query_cache_table_get_key, 0, 0));
#else
/*
On windows, OS/2, MacOS X with HFS+ or any other case insensitive
@@ -2095,10 +2148,10 @@ ulong Query_cache::init_cache()
file system) and so should use case insensitive collation for
comparison.
*/
- VOID(hash_init(&tables,
- lower_case_table_names ? &my_charset_bin :
- files_charset_info,
- def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0));
+ VOID(my_hash_init(&tables,
+ lower_case_table_names ? &my_charset_bin :
+ files_charset_info,
+ def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0));
#endif
queries_in_cache = 0;
@@ -2148,8 +2201,8 @@ void Query_cache::free_cache()
my_free((uchar*) cache, MYF(MY_ALLOW_ZERO_PTR));
make_disabled();
- hash_free(&queries);
- hash_free(&tables);
+ my_hash_free(&queries);
+ my_hash_free(&tables);
DBUG_VOID_RETURN;
}
@@ -2261,7 +2314,7 @@ void Query_cache::free_query_internal(Query_cache_block *query_block)
if (query->writer() != 0)
{
/* Tell MySQL that this query should not be cached anymore */
- query->writer()->query_cache_query= 0;
+ query->writer()->first_query_block= NULL;
query->writer(0);
}
double_linked_list_exclude(query_block, &queries_blocks);
@@ -2324,7 +2377,7 @@ void Query_cache::free_query(Query_cache_block *query_block)
(ulong) query_block,
query_block->query()->length() ));
- hash_delete(&queries,(uchar *) query_block);
+ my_hash_delete(&queries,(uchar *) query_block);
free_query_internal(query_block);
DBUG_VOID_RETURN;
@@ -2653,7 +2706,7 @@ void
Query_cache::invalidate_table_internal(THD *thd, uchar *key, uint32 key_length)
{
Query_cache_block *table_block=
- (Query_cache_block*)hash_search(&tables, key, key_length);
+ (Query_cache_block*)my_hash_search(&tables, key, key_length);
if (table_block)
{
Query_cache_block_table *list_root= table_block->table(0);
@@ -2851,7 +2904,7 @@ Query_cache::insert_table(uint key_len, char *key,
THD *thd= current_thd;
Query_cache_block *table_block=
- (Query_cache_block *)hash_search(&tables, (uchar*) key, key_len);
+ (Query_cache_block *) my_hash_search(&tables, (uchar*) key, key_len);
if (table_block &&
table_block->table()->engine_data() != engine_data)
@@ -2967,7 +3020,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node)
Query_cache_block *table_block= neighbour->block();
double_linked_list_exclude(table_block,
&tables_blocks);
- hash_delete(&tables,(uchar *) table_block);
+ my_hash_delete(&tables,(uchar *) table_block);
free_memory_block(table_block);
}
DBUG_VOID_RETURN;
@@ -3474,7 +3527,8 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
*/
TABLE_COUNTER_TYPE
-Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
+Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query,
+ LEX *lex,
TABLE_LIST *tables_used, uint8 *tables_type)
{
TABLE_COUNTER_TYPE table_count;
@@ -3651,7 +3705,7 @@ my_bool Query_cache::move_by_type(uchar **border,
uchar *key;
size_t key_length;
key=query_cache_table_get_key((uchar*) block, &key_length, 0);
- hash_first(&tables, (uchar*) key, key_length, &record_idx);
+ my_hash_first(&tables, (uchar*) key, key_length, &record_idx);
block->destroy();
new_block->init(len);
@@ -3685,7 +3739,7 @@ my_bool Query_cache::move_by_type(uchar **border,
/* Fix pointer to table name */
new_block->table()->table(new_block->table()->db() + tablename_offset);
/* Fix hash to point at moved block */
- hash_replace(&tables, &record_idx, (uchar*) new_block);
+ my_hash_replace(&tables, &record_idx, (uchar*) new_block);
DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
len, (ulong) new_block, (ulong) *border));
@@ -3711,7 +3765,7 @@ my_bool Query_cache::move_by_type(uchar **border,
uchar *key;
size_t key_length;
key=query_cache_query_get_key((uchar*) block, &key_length, 0);
- hash_first(&queries, (uchar*) key, key_length, &record_idx);
+ my_hash_first(&queries, (uchar*) key, key_length, &record_idx);
// Move table of used tables
memmove((char*) new_block->table(0), (char*) block->table(0),
ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
@@ -3773,13 +3827,13 @@ my_bool Query_cache::move_by_type(uchar **border,
If someone is writing to this block, inform the writer that the block
has been moved.
*/
- NET *net = new_block->query()->writer();
- if (net != 0)
+ Query_cache_tls *query_cache_tls= new_block->query()->writer();
+ if (query_cache_tls != NULL)
{
- net->query_cache_query= (uchar*) new_block;
+ query_cache_tls->first_query_block= new_block;
}
/* Fix hash to point at moved block */
- hash_replace(&queries, &record_idx, (uchar*) new_block);
+ my_hash_replace(&queries, &record_idx, (uchar*) new_block);
DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
len, (ulong) new_block, (ulong) *border));
break;
@@ -4190,13 +4244,13 @@ my_bool Query_cache::check_integrity(bool locked)
if (!locked)
lock_and_suspend();
- if (hash_check(&queries))
+ if (my_hash_check(&queries))
{
DBUG_PRINT("error", ("queries hash is damaged"));
result = 1;
}
- if (hash_check(&tables))
+ if (my_hash_check(&tables))
{
DBUG_PRINT("error", ("tables hash is damaged"));
result = 1;
@@ -4363,7 +4417,7 @@ my_bool Query_cache::check_integrity(bool locked)
(ulong) block, (uint) block->type));
size_t length;
uchar *key = query_cache_query_get_key((uchar*) block, &length, 0);
- uchar* val = hash_search(&queries, key, length);
+ uchar* val = my_hash_search(&queries, key, length);
if (((uchar*)block) != val)
{
DBUG_PRINT("error", ("block 0x%lx found in queries hash like 0x%lx",
@@ -4398,7 +4452,7 @@ my_bool Query_cache::check_integrity(bool locked)
(ulong) block, (uint) block->type));
size_t length;
uchar *key = query_cache_table_get_key((uchar*) block, &length, 0);
- uchar* val = hash_search(&tables, key, length);
+ uchar* val = my_hash_search(&tables, key, length);
if (((uchar*)block) != val)
{
DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx",
@@ -4638,3 +4692,4 @@ err2:
#endif /* DBUG_OFF */
#endif /*HAVE_QUERY_CACHE*/
+
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 777ddd39280..6b187ebd6c2 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -64,6 +64,8 @@ struct Query_cache_table;
struct Query_cache_query;
struct Query_cache_result;
class Query_cache;
+struct Query_cache_tls;
+struct LEX;
/**
This class represents a node in the linked chain of queries
@@ -137,7 +139,7 @@ struct Query_cache_query
ulonglong limit_found_rows;
rw_lock_t lock;
Query_cache_block *res;
- NET *wri;
+ Query_cache_tls *wri;
ulong len;
uint8 tbls_type;
unsigned int last_pkt_nr;
@@ -149,8 +151,8 @@ struct Query_cache_query
inline void found_rows(ulonglong rows) { limit_found_rows= rows; }
inline Query_cache_block *result() { return res; }
inline void result(Query_cache_block *p) { res= p; }
- inline NET *writer() { return wri; }
- inline void writer(NET *p) { wri= p; }
+ inline Query_cache_tls *writer() { return wri; }
+ inline void writer(Query_cache_tls *p) { wri= p; }
inline uint8 tables_type() { return tbls_type; }
inline void tables_type(uint8 type) { tbls_type= type; }
inline ulong length() { return len; }
@@ -279,8 +281,11 @@ private:
enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED };
Cache_lock_status m_cache_lock_status;
+ bool m_query_cache_is_disabled;
+
void free_query_internal(Query_cache_block *point);
void invalidate_table_internal(THD *thd, uchar *key, uint32 key_length);
+ void disable_query_cache(void) { m_query_cache_is_disabled= TRUE; }
protected:
/*
@@ -407,7 +412,8 @@ protected:
If query is cacheable return number tables in query
(query without tables not cached)
*/
- TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query,
+ TABLE_COUNTER_TYPE is_cacheable(THD *thd, size_t query_len,
+ const char *query,
LEX *lex, TABLE_LIST *tables_used,
uint8 *tables_type);
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
@@ -423,6 +429,8 @@ protected:
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
+ bool is_disabled(void) { return m_query_cache_is_disabled; }
+
/* initialize cache (mutex) */
void init();
/* resize query cache (return real query size, 0 if disabled) */
@@ -462,10 +470,13 @@ protected:
void destroy();
- friend void query_cache_init_query(NET *net);
- friend void query_cache_insert(NET *net, const char *packet, ulong length);
- friend void query_cache_end_of_result(THD *thd);
- friend void query_cache_abort(NET *net);
+ void insert(Query_cache_tls *query_cache_tls,
+ const char *packet,
+ ulong length,
+ unsigned pkt_nr);
+
+ void end_of_result(THD *thd);
+ void abort(Query_cache_tls *query_cache_tls);
/*
The following functions are only used when debugging
@@ -493,9 +504,4 @@ protected:
extern Query_cache query_cache;
extern TYPELIB query_cache_type_typelib;
-void query_cache_init_query(NET *net);
-void query_cache_insert(NET *net, const char *packet, ulong length);
-void query_cache_end_of_result(THD *thd);
-void query_cache_abort(NET *net);
-
#endif
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 95bdbc5e093..a944b65e74d 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -91,7 +91,9 @@ extern "C" void free_user_var(user_var_entry *entry)
bool Key_part_spec::operator==(const Key_part_spec& other) const
{
- return length == other.length && !strcmp(field_name, other.field_name);
+ return length == other.length &&
+ !my_strcasecmp(system_charset_info, field_name.str,
+ other.field_name.str);
}
/**
@@ -258,7 +260,7 @@ const char *set_thd_proc_info(THD *thd, const char *info,
const char *old_info= thd->proc_info;
DBUG_PRINT("proc_info", ("%s:%d %s", calling_file, calling_line,
(info != NULL) ? info : "(null)"));
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.status_change(info, calling_function, calling_file, calling_line);
#endif
thd->proc_info= info;
@@ -272,12 +274,7 @@ const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond,
if (!thd)
thd= current_thd;
- const char* old_msg = thd->proc_info;
- safe_mutex_assert_owner(mutex);
- thd->mysys_var->current_mutex = mutex;
- thd->mysys_var->current_cond = cond;
- thd->proc_info = msg;
- return old_msg;
+ return thd->enter_cond(cond, mutex, msg);
}
extern "C"
@@ -286,18 +283,7 @@ void thd_exit_cond(MYSQL_THD thd, const char *old_msg)
if (!thd)
thd= current_thd;
- /*
- Putting the mutex unlock in thd_exit_cond() ensures that
- mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
- locked (if that would not be the case, you'll get a deadlock if someone
- does a THD::awake() on you).
- */
- pthread_mutex_unlock(thd->mysys_var->current_mutex);
- pthread_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex = 0;
- thd->mysys_var->current_cond = 0;
- thd->proc_info = old_msg;
- pthread_mutex_unlock(&thd->mysys_var->mutex);
+ thd->exit_cond(old_msg);
return;
}
@@ -399,14 +385,14 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
str.append(proc_info);
}
- if (thd->query)
+ if (thd->query())
{
if (max_query_len < 1)
- len= thd->query_length;
+ len= thd->query_length();
else
- len= min(thd->query_length, max_query_len);
+ len= min(thd->query_length(), max_query_len);
str.append('\n');
- str.append(thd->query, len);
+ str.append(thd->query(), len);
}
if (str.c_ptr_safe() == buffer)
return buffer;
@@ -425,7 +411,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
/**
- Implementation of Drop_table_error_handler::handle_error().
+ Implementation of Drop_table_error_handler::handle_condition().
The reason in having this implementation is to silence technical low-level
warnings during DROP TABLE operation. Currently we don't want to expose
the following warnings during DROP TABLE:
@@ -503,7 +489,7 @@ THD::THD()
killed= NOT_KILLED;
col_access=0;
is_slave_error= thread_specific_used= FALSE;
- hash_clear(&handler_tables_hash);
+ my_hash_clear(&handler_tables_hash);
tmp_table=0;
used_tables=0;
cuted_fields= 0L;
@@ -536,9 +522,6 @@ THD::THD()
net.vio=0;
#endif
client_capabilities= 0; // minimalistic client
-#ifdef HAVE_QUERY_CACHE
- query_cache_init_query(&net); // If error on boot
-#endif
ull=0;
system_thread= NON_SYSTEM_THREAD;
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
@@ -559,13 +542,13 @@ THD::THD()
*scramble= '\0';
init();
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
profiling.set_thd(this);
#endif
user_connect=(USER_CONN *)0;
- hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
- (hash_get_key) get_var_key,
- (hash_free_key) free_user_var, 0);
+ my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
+ (my_hash_get_key) get_var_key,
+ (my_hash_free_key) free_user_var, 0);
sp_proc_cache= NULL;
sp_func_cache= NULL;
@@ -831,7 +814,7 @@ THD::raise_condition_no_handler(uint sql_errno,
MYSQL_ERROR *cond= NULL;
DBUG_ENTER("THD::raise_condition_no_handler");
- query_cache_abort(& net);
+ query_cache_abort(&query_cache_tls);
/* FIXME: broken special case */
if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
@@ -985,9 +968,9 @@ void THD::change_user(void)
cleanup_done= 0;
init();
stmt_map.reset();
- hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
- (hash_get_key) get_var_key,
- (hash_free_key) free_user_var, 0);
+ my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
+ (my_hash_get_key) get_var_key,
+ (my_hash_free_key) free_user_var, 0);
sp_cache_clear(&sp_proc_cache);
sp_cache_clear(&sp_func_cache);
}
@@ -1024,7 +1007,7 @@ void THD::cleanup(void)
mysql_ha_cleanup(this);
delete_dynamic(&user_var_events);
- hash_free(&user_vars);
+ my_hash_free(&user_vars);
close_temporary_tables(this);
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
@@ -1542,8 +1525,8 @@ int THD::send_explain_fields(select_result *result)
}
item->maybe_null= 1;
field_list.push_back(new Item_empty_string("Extra", 255, cs));
- return (result->send_fields(field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
+ return (result->send_result_set_metadata(field_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -1670,10 +1653,10 @@ bool sql_exchange::escaped_given(void)
}
-bool select_send::send_fields(List<Item> &list, uint flags)
+bool select_send::send_result_set_metadata(List<Item> &list, uint flags)
{
bool res;
- if (!(res= thd->protocol->send_fields(&list, flags)))
+ if (!(res= thd->protocol->send_result_set_metadata(&list, flags)))
is_result_set_started= 1;
return res;
}
@@ -1714,10 +1697,13 @@ void select_send::cleanup()
bool select_send::send_data(List<Item> &items)
{
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("select_send::send_data");
+
if (unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
- return 0;
+ DBUG_RETURN(FALSE);
}
/*
@@ -1727,36 +1713,18 @@ bool select_send::send_data(List<Item> &items)
*/
ha_release_temporary_latches(thd);
- List_iterator_fast<Item> li(items);
- Protocol *protocol= thd->protocol;
- char buff[MAX_FIELD_WIDTH];
- String buffer(buff, sizeof(buff), &my_charset_bin);
- DBUG_ENTER("select_send::send_data");
-
protocol->prepare_for_resend();
- Item *item;
- while ((item=li++))
- {
- if (item->send(protocol, &buffer))
- {
- protocol->free(); // Free used buffer
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- break;
- }
- /*
- Reset buffer to its original state, as it may have been altered in
- Item::send().
- */
- buffer.set(buff, sizeof(buff), &my_charset_bin);
- }
- thd->sent_row_count++;
- if (thd->is_error())
+ if (protocol->send_result_set_row(&items))
{
protocol->remove_last_row();
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
+
+ thd->sent_row_count++;
+
if (thd->vio_ok())
DBUG_RETURN(protocol->write());
+
DBUG_RETURN(0);
}
@@ -2530,12 +2498,12 @@ Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
id(id_arg),
mark_used_columns(MARK_COLUMNS_READ),
lex(lex_arg),
- query(0),
- query_length(0),
cursor(0),
db(NULL),
db_length(0)
{
+ query_string.length= 0;
+ query_string.str= NULL;
name.str= NULL;
}
@@ -2551,8 +2519,7 @@ void Statement::set_statement(Statement *stmt)
id= stmt->id;
mark_used_columns= stmt->mark_used_columns;
lex= stmt->lex;
- query= stmt->query;
- query_length= stmt->query_length;
+ query_string= stmt->query_string;
cursor= stmt->cursor;
}
@@ -2576,6 +2543,15 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
}
+/** Assign a new value to thd->query. */
+
+void Statement::set_query_inner(char *query_arg, uint32 query_length_arg)
+{
+ query_string.str= query_arg;
+ query_string.length= query_length_arg;
+}
+
+
void THD::end_statement()
{
/* Cleanup SQL processing state to reuse this statement in next query. */
@@ -2654,12 +2630,12 @@ Statement_map::Statement_map() :
START_STMT_HASH_SIZE = 16,
START_NAME_HASH_SIZE = 16
};
- hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0,
- get_statement_id_as_hash_key,
- delete_statement_as_hash_key, MYF(0));
- hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
- (hash_get_key) get_stmt_name_hash_key,
- NULL,MYF(0));
+ my_hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0,
+ get_statement_id_as_hash_key,
+ delete_statement_as_hash_key, MYF(0));
+ my_hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
+ (my_hash_get_key) get_stmt_name_hash_key,
+ NULL,MYF(0));
}
@@ -2724,9 +2700,9 @@ int Statement_map::insert(THD *thd, Statement *statement)
err_max:
if (statement->name.str)
- hash_delete(&names_hash, (uchar*) statement);
+ my_hash_delete(&names_hash, (uchar*) statement);
err_names_hash:
- hash_delete(&st_hash, (uchar*) statement);
+ my_hash_delete(&st_hash, (uchar*) statement);
err_st_hash:
return 1;
}
@@ -2747,9 +2723,9 @@ void Statement_map::erase(Statement *statement)
if (statement == last_found_statement)
last_found_statement= 0;
if (statement->name.str)
- hash_delete(&names_hash, (uchar *) statement);
+ my_hash_delete(&names_hash, (uchar *) statement);
- hash_delete(&st_hash, (uchar *) statement);
+ my_hash_delete(&st_hash, (uchar *) statement);
pthread_mutex_lock(&LOCK_prepared_stmt_count);
DBUG_ASSERT(prepared_stmt_count > 0);
prepared_stmt_count--;
@@ -2779,8 +2755,8 @@ Statement_map::~Statement_map()
prepared_stmt_count-= st_hash.records;
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
- hash_free(&names_hash);
- hash_free(&st_hash);
+ my_hash_free(&names_hash);
+ my_hash_free(&st_hash);
}
bool select_dumpvar::send_data(List<Item> &items)
@@ -2811,9 +2787,11 @@ bool select_dumpvar::send_data(List<Item> &items)
else
{
Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
- suv->fix_fields(thd, 0);
+ if (suv->fix_fields(thd, 0))
+ DBUG_RETURN (1);
suv->save_item_result(item);
- suv->update();
+ if (suv->update())
+ DBUG_RETURN (1);
}
}
DBUG_RETURN(thd->is_error());
@@ -3089,9 +3067,24 @@ extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd)
return(thd->charset());
}
+/**
+ OBSOLETE : there's no way to ensure the string is null terminated.
+ Use thd_query_string instead()
+*/
extern "C" char **thd_query(MYSQL_THD thd)
{
- return(&thd->query);
+ return(&thd->query_string.str);
+}
+
+/**
+ Get the current query string for the thread.
+
+ @param The MySQL internal thread pointer
+ @return query string and length. May be non-null-terminated.
+*/
+extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd)
+{
+ return(&thd->query_string);
}
extern "C" int thd_slave_thread(const MYSQL_THD thd)
@@ -3116,6 +3109,11 @@ extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
{
mark_transaction_to_rollback(thd, all);
}
+
+extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd)
+{
+ return binlog_filter->db_ok(thd->db);
+}
#endif // INNODB_COMPATIBILITY_HOOKS */
/****************************************************************************
@@ -3270,8 +3268,7 @@ void THD::set_statement(Statement *stmt)
void THD::set_query(char *query_arg, uint32 query_length_arg)
{
pthread_mutex_lock(&LOCK_thd_data);
- query= query_arg;
- query_length= query_length_arg;
+ set_query_inner(query_arg, query_length_arg);
pthread_mutex_unlock(&LOCK_thd_data);
}
@@ -3289,6 +3286,16 @@ void mark_transaction_to_rollback(THD *thd, bool all)
{
thd->is_fatal_sub_stmt_error= TRUE;
thd->transaction_rollback_request= all;
+ /*
+ Aborted transactions can not be IGNOREd.
+ Switch off the IGNORE flag for the current
+ SELECT_LEX. This should allow my_error()
+ to report the error and abort the execution
+ flow, even in presence
+ of IGNORE clause.
+ */
+ if (thd->lex->current_select)
+ thd->lex->current_select->no_error= FALSE;
}
}
/***************************************************************************
@@ -3317,15 +3324,15 @@ void xid_free_hash(void *ptr)
bool xid_cache_init()
{
pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
- return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
- xid_get_hash_key, xid_free_hash, 0) != 0;
+ return my_hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
+ xid_get_hash_key, xid_free_hash, 0) != 0;
}
void xid_cache_free()
{
- if (hash_inited(&xid_cache))
+ if (my_hash_inited(&xid_cache))
{
- hash_free(&xid_cache);
+ my_hash_free(&xid_cache);
pthread_mutex_destroy(&LOCK_xid_cache);
}
}
@@ -3333,7 +3340,8 @@ void xid_cache_free()
XID_STATE *xid_cache_search(XID *xid)
{
pthread_mutex_lock(&LOCK_xid_cache);
- XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
+ XID_STATE *res=(XID_STATE *)my_hash_search(&xid_cache, xid->key(),
+ xid->key_length());
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
}
@@ -3344,7 +3352,7 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state)
XID_STATE *xs;
my_bool res;
pthread_mutex_lock(&LOCK_xid_cache);
- if (hash_search(&xid_cache, xid->key(), xid->key_length()))
+ if (my_hash_search(&xid_cache, xid->key(), xid->key_length()))
res=0;
else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
res=1;
@@ -3363,8 +3371,8 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state)
bool xid_cache_insert(XID_STATE *xid_state)
{
pthread_mutex_lock(&LOCK_xid_cache);
- DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(),
- xid_state->xid.key_length())==0);
+ DBUG_ASSERT(my_hash_search(&xid_cache, xid_state->xid.key(),
+ xid_state->xid.key_length())==0);
my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
pthread_mutex_unlock(&LOCK_xid_cache);
return res;
@@ -3374,7 +3382,7 @@ bool xid_cache_insert(XID_STATE *xid_state)
void xid_cache_delete(XID_STATE *xid_state)
{
pthread_mutex_lock(&LOCK_xid_cache);
- hash_delete(&xid_cache, (uchar *)xid_state);
+ my_hash_delete(&xid_cache, (uchar *)xid_state);
pthread_mutex_unlock(&LOCK_xid_cache);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index cefa65925d2..5359cabde6b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -25,54 +25,9 @@
#include "log.h"
#include "rpl_tblmap.h"
-#include "replication.h"
-
-/**
- An interface that is used to take an action when
- the locking module notices that a table version has changed
- since the last execution. "Table" here may refer to any kind of
- table -- a base table, a temporary table, a view or an
- information schema table.
-
- When we open and lock tables for execution of a prepared
- statement, we must verify that they did not change
- since statement prepare. If some table did change, the statement
- parse tree *may* be no longer valid, e.g. in case it contains
- optimizations that depend on table metadata.
-
- This class provides an interface (a method) that is
- invoked when such a situation takes place.
- The implementation of the method simply reports an error, but
- the exact details depend on the nature of the SQL statement.
-
- At most 1 instance of this class is active at a time, in which
- case THD::m_reprepare_observer is not NULL.
-
- @sa check_and_update_table_version() for details of the
- version tracking algorithm
-
- @sa Open_tables_state::m_reprepare_observer for the life cycle
- of metadata observers.
-*/
-
-class Reprepare_observer
-{
-public:
- Reprepare_observer() {}
- /**
- Check if a change of metadata is OK. In future
- the signature of this method may be extended to accept the old
- and the new versions, but since currently the check is very
- simple, we only need the THD to report an error.
- */
- bool report_error(THD *thd);
- bool is_invalidated() const { return m_invalidated; }
- void reset_reprepare_observer() { m_invalidated= FALSE; }
-private:
- bool m_invalidated;
-};
+class Reprepare_observer;
class Relay_log_info;
class Query_log_event;
@@ -99,6 +54,8 @@ extern char internal_table_name[2];
extern char empty_c_string[1];
extern MYSQL_PLUGIN_IMPORT const char **errmesg;
+extern bool volatile shutdown_in_progress;
+
#define TC_LOG_PAGE_SIZE 8192
#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE)
@@ -150,9 +107,14 @@ typedef struct st_copy_info {
class Key_part_spec :public Sql_alloc {
public:
- const char *field_name;
+ LEX_STRING field_name;
uint length;
- Key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {}
+ Key_part_spec(const LEX_STRING &name, uint len)
+ : field_name(name), length(len)
+ {}
+ Key_part_spec(const char *name, const size_t name_len, uint len)
+ : length(len)
+ { field_name.str= (char *)name; field_name.length= name_len; }
bool operator==(const Key_part_spec& other) const;
/**
Construct a copy of this Key_part_spec. field_name is copied
@@ -205,15 +167,24 @@ public:
enum Keytype type;
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
- const char *name;
+ LEX_STRING name;
bool generated;
- Key(enum Keytype type_par, const char *name_arg,
+ Key(enum Keytype type_par, const LEX_STRING &name_arg,
KEY_CREATE_INFO *key_info_arg,
bool generated_arg, List<Key_part_spec> &cols)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
name(name_arg), generated(generated_arg)
{}
+ Key(enum Keytype type_par, const char *name_arg, size_t name_len_arg,
+ KEY_CREATE_INFO *key_info_arg, bool generated_arg,
+ List<Key_part_spec> &cols)
+ :type(type_par), key_create_info(*key_info_arg), columns(cols),
+ generated(generated_arg)
+ {
+ name.str= (char *)name_arg;
+ name.length= name_len_arg;
+ }
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
/* Equality comparison of keys (ignoring name) */
@@ -238,7 +209,7 @@ public:
Table_ident *ref_table;
List<Key_part_spec> ref_columns;
uint delete_opt, update_opt, match_opt;
- Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
+ Foreign_key(const LEX_STRING &name_arg, List<Key_part_spec> &cols,
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
@@ -271,6 +242,27 @@ public:
LEX_COLUMN (const String& x,const uint& y ): column (x),rights (y) {}
};
+/**
+ Query_cache_tls -- query cache thread local data.
+*/
+
+struct Query_cache_block;
+
+struct Query_cache_tls
+{
+ /*
+ 'first_query_block' should be accessed only via query cache
+ functions and methods to maintain proper locking.
+ */
+ Query_cache_block *first_query_block;
+ void set_first_query_block(Query_cache_block *first_query_block_arg)
+ {
+ first_query_block= first_query_block_arg;
+ }
+
+ Query_cache_tls() :first_query_block(NULL) {}
+};
+
/* SIGNAL / RESIGNAL / GET DIAGNOSTICS */
/**
@@ -685,10 +677,13 @@ public:
This printing is needed at least in SHOW PROCESSLIST and SHOW
ENGINE INNODB STATUS.
*/
- char *query;
- uint32 query_length; // current query length
+ LEX_STRING query_string;
Server_side_cursor *cursor;
+ inline char *query() { return query_string.str; }
+ inline uint32 query_length() { return query_string.length; }
+ void set_query_inner(char *query_arg, uint32 query_length_arg);
+
/**
Name of the current (default) database.
@@ -744,8 +739,8 @@ public:
Statement *find_by_name(LEX_STRING *name)
{
Statement *stmt;
- stmt= (Statement*)hash_search(&names_hash, (uchar*)name->str,
- name->length);
+ stmt= (Statement*)my_hash_search(&names_hash, (uchar*)name->str,
+ name->length);
return stmt;
}
@@ -754,7 +749,7 @@ public:
if (last_found_statement == 0 || id != last_found_statement->id)
{
Statement *stmt;
- stmt= (Statement *) hash_search(&st_hash, (uchar *) &id, sizeof(id));
+ stmt= (Statement *) my_hash_search(&st_hash, (uchar *) &id, sizeof(id));
if (stmt && stmt->name.str)
return NULL;
last_found_statement= stmt;
@@ -1233,6 +1228,9 @@ public:
*/
struct st_mysql_stmt *current_stmt;
#endif
+#ifdef HAVE_QUERY_CACHE
+ Query_cache_tls query_cache_tls;
+#endif
NET net; // client connection descriptor
Protocol *protocol; // Current protocol
Protocol_text protocol_text; // Normal protocol
@@ -1651,7 +1649,7 @@ public:
CHARSET_INFO *db_charset;
Warning_info *warning_info;
Diagnostics_area *stmt_da;
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
PROFILING profiling;
#endif
@@ -1886,11 +1884,28 @@ public:
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
const char* msg)
{
- return thd_enter_cond(this, cond, mutex, msg);
+ const char* old_msg = proc_info;
+ safe_mutex_assert_owner(mutex);
+ mysys_var->current_mutex = mutex;
+ mysys_var->current_cond = cond;
+ proc_info = msg;
+ return old_msg;
}
inline void exit_cond(const char* old_msg)
{
- thd_exit_cond(this, old_msg);
+ /*
+ Putting the mutex unlock in thd->exit_cond() ensures that
+ mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
+ locked (if that would not be the case, you'll get a deadlock if someone
+ does a THD::awake() on you).
+ */
+ pthread_mutex_unlock(mysys_var->current_mutex);
+ pthread_mutex_lock(&mysys_var->mutex);
+ mysys_var->current_mutex = 0;
+ mysys_var->current_cond = 0;
+ proc_info = old_msg;
+ pthread_mutex_unlock(&mysys_var->mutex);
+ return;
}
inline time_t query_start() { query_start_used=1; return start_time; }
inline void set_time()
@@ -2037,7 +2052,11 @@ public:
{
int err= killed_errno();
if (err)
+ {
+ if ((err == KILL_CONNECTION) && !shutdown_in_progress)
+ err = KILL_QUERY;
my_message(err, ER(err), MYF(0));
+ }
}
/* return TRUE if we will abort query if we make a warning now */
inline bool really_abort_on_warning()
@@ -2397,7 +2416,7 @@ public:
*/
virtual uint field_count(List<Item> &fields) const
{ return fields.elements; }
- virtual bool send_fields(List<Item> &list, uint flags)=0;
+ virtual bool send_result_set_metadata(List<Item> &list, uint flags)=0;
virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; }
virtual void send_error(uint errcode,const char *err);
@@ -2436,7 +2455,7 @@ class select_result_interceptor: public select_result
public:
select_result_interceptor() {} /* Remove gcc warning */
uint field_count(List<Item> &fields) const { return 0; }
- bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
+ bool send_result_set_metadata(List<Item> &fields, uint flag) { return FALSE; }
};
@@ -2449,7 +2468,7 @@ class select_send :public select_result {
bool is_result_set_started;
public:
select_send() :is_result_set_started(FALSE) {}
- bool send_fields(List<Item> &list, uint flags);
+ bool send_result_set_metadata(List<Item> &list, uint flags);
bool send_data(List<Item> &items);
bool send_eof();
virtual bool check_simple_select() const { return FALSE; }
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 742bafed0c1..959209df412 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -61,7 +61,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
user_len= strlen(user);
temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
(void) pthread_mutex_lock(&LOCK_user_conn);
- if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
+ if (!(uc = (struct user_conn *) my_hash_search(&hash_user_connections,
(uchar*) temp_user, temp_len)))
{
/* First connection for user; Create a user connection object */
@@ -151,7 +151,15 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
end:
if (error)
+ {
uc->connections--; // no need for decrease_user_connections() here
+ /*
+ The thread may returned back to the pool and assigned to a user
+ that doesn't have a limit. Ensure the user is not using resources
+ of someone else.
+ */
+ thd->user_connect= NULL;
+ }
(void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_RETURN(error);
}
@@ -183,7 +191,7 @@ void decrease_user_connections(USER_CONN *uc)
if (!--uc->connections && !mqh_used)
{
/* Last connection for user; Delete it */
- (void) hash_delete(&hash_user_connections,(uchar*) uc);
+ (void) my_hash_delete(&hash_user_connections,(uchar*) uc);
}
(void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_VOID_RETURN;
@@ -462,7 +470,10 @@ check_user(THD *thd, enum enum_server_command command,
{
/* mysql_change_db() has pushed the error message. */
if (thd->user_connect)
+ {
decrease_user_connections(thd->user_connect);
+ thd->user_connect= 0;
+ }
DBUG_RETURN(1);
}
}
@@ -525,10 +536,10 @@ extern "C" void free_user(struct user_conn *uc)
void init_max_user_conn(void)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
- 0,0,
- (hash_get_key) get_key_conn, (hash_free_key) free_user,
- 0);
+ (void)
+ my_hash_init(&hash_user_connections,system_charset_info,max_connections,
+ 0,0, (my_hash_get_key) get_key_conn,
+ (my_hash_free_key) free_user, 0);
#endif
}
@@ -536,7 +547,7 @@ void init_max_user_conn(void)
void free_max_user_conn(void)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- hash_free(&hash_user_connections);
+ my_hash_free(&hash_user_connections);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -554,8 +565,9 @@ void reset_mqh(LEX_USER *lu, bool get_them= 0)
memcpy(temp_user,lu->user.str,lu->user.length);
memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
- if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
- (uchar*) temp_user, temp_len)))
+ if ((uc = (struct user_conn *) my_hash_search(&hash_user_connections,
+ (uchar*) temp_user,
+ temp_len)))
{
uc->questions=0;
get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
@@ -568,8 +580,8 @@ void reset_mqh(LEX_USER *lu, bool get_them= 0)
/* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
for (uint idx=0;idx < hash_user_connections.records; idx++)
{
- USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
- idx);
+ USER_CONN *uc=(struct user_conn *)
+ my_hash_element(&hash_user_connections, idx);
if (get_them)
get_mqh(uc->user,uc->host,uc);
uc->questions=0;
@@ -957,7 +969,7 @@ static bool login_connection(THD *thd)
my_net_set_write_timeout(net, connect_timeout);
error= check_connection(thd);
- net_end_statement(thd);
+ thd->protocol->end_statement();
if (error)
{ // Wrong permissions
@@ -987,7 +999,15 @@ static void end_connection(THD *thd)
NET *net= &thd->net;
plugin_thdvar_cleanup(thd);
if (thd->user_connect)
+ {
decrease_user_connections(thd->user_connect);
+ /*
+ The thread may returned back to the pool and assigned to a user
+ that doesn't have a limit. Ensure the user is not using resources
+ of someone else.
+ */
+ thd->user_connect= NULL;
+ }
if (thd->killed || (net->error && net->vio != 0))
{
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 553342f155b..ffc3fafe55f 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -90,7 +90,7 @@ class Materialized_cursor: public Server_side_cursor
public:
Materialized_cursor(select_result *result, TABLE *table);
- int fill_item_list(THD *thd, List<Item> &send_fields);
+ int fill_item_list(THD *thd, List<Item> &send_result_set_metadata);
virtual bool is_open() const { return table != 0; }
virtual int open(JOIN *join __attribute__((unused)));
virtual void fetch(ulong num_rows);
@@ -115,7 +115,7 @@ public:
Materialized_cursor *materialized_cursor;
Select_materialize(select_result *result_arg)
:result(result_arg), materialized_cursor(0) {}
- virtual bool send_fields(List<Item> &list, uint flags);
+ virtual bool send_result_set_metadata(List<Item> &list, uint flags);
};
@@ -169,7 +169,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
thd->lock_id= sensitive_cursor->get_lock_id();
thd->cursor= sensitive_cursor;
}
- MYSQL_QUERY_EXEC_START(thd->query,
+ MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
(char *) (thd->db ? thd->db : ""),
thd->security_ctx->priv_user,
@@ -376,12 +376,12 @@ Sensitive_cursor::open(JOIN *join_arg)
join->change_result(result);
/*
Send fields description to the client; server_status is sent
- in 'EOF' packet, which follows send_fields().
- We don't simply use SEND_EOF flag of send_fields because we also
+ in 'EOF' packet, which follows send_result_set_metadata().
+ We don't simply use SEND_EOF flag of send_result_set_metadata because we also
want to flush the network buffer, which is done only in a standalone
send_eof().
*/
- result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
+ result->send_result_set_metadata(*join->fields, Protocol::SEND_NUM_ROWS);
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
result->send_eof();
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
@@ -566,14 +566,14 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg,
Preserve the original metadata that would be sent to the client.
@param thd Thread identifier.
- @param send_fields List of fields that would be sent.
+ @param send_result_set_metadata List of fields that would be sent.
*/
-int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_fields)
+int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_result_set_metadata)
{
Query_arena backup_arena;
int rc;
- List_iterator_fast<Item> it_org(send_fields);
+ List_iterator_fast<Item> it_org(send_result_set_metadata);
List_iterator_fast<Item> it_dst(item_list);
Item *item_org;
Item *item_dst;
@@ -583,7 +583,7 @@ int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_fields)
if ((rc= table->fill_item_list(&item_list)))
goto end;
- DBUG_ASSERT(send_fields.elements == item_list.elements);
+ DBUG_ASSERT(send_result_set_metadata.elements == item_list.elements);
/*
Unless we preserve the original metadata, it will be lost,
@@ -623,17 +623,17 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
{
/*
Now send the result set metadata to the client. We need to
- do it here, as in Select_materialize::send_fields the items
- for column types are not yet created (send_fields requires
+ do it here, as in Select_materialize::send_result_set_metadata the items
+ for column types are not yet created (send_result_set_metadata requires
a list of items). The new types may differ from the original
ones sent at prepare if some of them were altered by MySQL
HEAP tables mechanism -- used when create_tmp_field_from_item
may alter the original column type.
- We can't simply supply SEND_EOF flag to send_fields, because
- send_fields doesn't flush the network buffer.
+ We can't simply supply SEND_EOF flag to send_result_set_metadata, because
+ send_result_set_metadata doesn't flush the network buffer.
*/
- rc= result->send_fields(item_list, Protocol::SEND_NUM_ROWS);
+ rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS);
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
result->send_eof();
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
@@ -717,7 +717,7 @@ Materialized_cursor::~Materialized_cursor()
Select_materialize
****************************************************************************/
-bool Select_materialize::send_fields(List<Item> &list, uint flags)
+bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
{
DBUG_ASSERT(table == 0);
if (create_result_table(unit->thd, unit->get_unit_column_types(),
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index a6b2eb92667..3198791d5d1 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -105,8 +105,8 @@ static my_bool lock_db_insert(const char *dbname, uint length)
safe_mutex_assert_owner(&LOCK_lock_db);
- if (!(opt= (my_dblock_t*) hash_search(&lock_db_cache,
- (uchar*) dbname, length)))
+ if (!(opt= (my_dblock_t*) my_hash_search(&lock_db_cache,
+ (uchar*) dbname, length)))
{
/* Db is not in the hash, insert it */
char *tmp_name;
@@ -139,9 +139,9 @@ void lock_db_delete(const char *name, uint length)
{
my_dblock_t *opt;
safe_mutex_assert_owner(&LOCK_lock_db);
- if ((opt= (my_dblock_t *)hash_search(&lock_db_cache,
- (const uchar*) name, length)))
- hash_delete(&lock_db_cache, (uchar*) opt);
+ if ((opt= (my_dblock_t *)my_hash_search(&lock_db_cache,
+ (const uchar*) name, length)))
+ my_hash_delete(&lock_db_cache, (uchar*) opt);
}
@@ -221,14 +221,14 @@ bool my_database_names_init(void)
if (!dboptions_init)
{
dboptions_init= 1;
- error= hash_init(&dboptions, lower_case_table_names ?
- &my_charset_bin : system_charset_info,
- 32, 0, 0, (hash_get_key) dboptions_get_key,
- free_dbopt,0) ||
- hash_init(&lock_db_cache, lower_case_table_names ?
- &my_charset_bin : system_charset_info,
- 32, 0, 0, (hash_get_key) lock_db_get_key,
- lock_db_free_element,0);
+ error= my_hash_init(&dboptions, lower_case_table_names ?
+ &my_charset_bin : system_charset_info,
+ 32, 0, 0, (my_hash_get_key) dboptions_get_key,
+ free_dbopt,0) ||
+ my_hash_init(&lock_db_cache, lower_case_table_names ?
+ &my_charset_bin : system_charset_info,
+ 32, 0, 0, (my_hash_get_key) lock_db_get_key,
+ lock_db_free_element,0);
}
return error;
@@ -245,9 +245,9 @@ void my_database_names_free(void)
if (dboptions_init)
{
dboptions_init= 0;
- hash_free(&dboptions);
+ my_hash_free(&dboptions);
(void) rwlock_destroy(&LOCK_dboptions);
- hash_free(&lock_db_cache);
+ my_hash_free(&lock_db_cache);
}
}
@@ -259,11 +259,11 @@ void my_database_names_free(void)
void my_dbopt_cleanup(void)
{
rw_wrlock(&LOCK_dboptions);
- hash_free(&dboptions);
- hash_init(&dboptions, lower_case_table_names ?
- &my_charset_bin : system_charset_info,
- 32, 0, 0, (hash_get_key) dboptions_get_key,
- free_dbopt,0);
+ my_hash_free(&dboptions);
+ my_hash_init(&dboptions, lower_case_table_names ?
+ &my_charset_bin : system_charset_info,
+ 32, 0, 0, (my_hash_get_key) dboptions_get_key,
+ free_dbopt,0);
rw_unlock(&LOCK_dboptions);
}
@@ -289,7 +289,7 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
length= (uint) strlen(dbname);
rw_rdlock(&LOCK_dboptions);
- if ((opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
+ if ((opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname, length)))
{
create->default_table_charset= opt->charset;
error= 0;
@@ -321,7 +321,8 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
length= (uint) strlen(dbname);
rw_wrlock(&LOCK_dboptions);
- if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
+ if (!(opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname,
+ length)))
{
/* Options are not in the hash, insert them */
char *tmp_name;
@@ -361,9 +362,9 @@ void del_dbopt(const char *path)
{
my_dbopt_t *opt;
rw_wrlock(&LOCK_dboptions);
- if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const uchar*) path,
- strlen(path))))
- hash_delete(&dboptions, (uchar*) opt);
+ if ((opt= (my_dbopt_t *)my_hash_search(&dboptions, (const uchar*) path,
+ strlen(path))))
+ my_hash_delete(&dboptions, (uchar*) opt);
rw_unlock(&LOCK_dboptions);
}
@@ -703,7 +704,7 @@ not_silent:
char *query;
uint query_length;
- if (!thd->query) // Only in replication
+ if (!thd->query()) // Only in replication
{
query= tmp_query;
query_length= (uint) (strxmov(tmp_query,"create database `",
@@ -711,8 +712,8 @@ not_silent:
}
else
{
- query= thd->query;
- query_length= thd->query_length;
+ query= thd->query();
+ query_length= thd->query_length();
}
ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB,
@@ -805,13 +806,13 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
}
ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
db, "");
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
+ Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0,
/* suppress_use */ TRUE, errcode);
/*
@@ -948,7 +949,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
const char *query;
ulong query_length;
- if (!thd->query)
+ if (!thd->query())
{
/* The client used the old obsolete mysql_drop_db() call */
query= path;
@@ -957,8 +958,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
else
{
- query =thd->query;
- query_length= thd->query_length;
+ query= thd->query();
+ query_length= thd->query_length();
}
if (mysql_bin_log.is_open())
{
@@ -1719,8 +1720,8 @@ lock_databases(THD *thd, const char *db1, uint length1,
{
pthread_mutex_lock(&LOCK_lock_db);
while (!thd->killed &&
- (hash_search(&lock_db_cache,(uchar*) db1, length1) ||
- hash_search(&lock_db_cache,(uchar*) db2, length2)))
+ (my_hash_search(&lock_db_cache,(uchar*) db1, length1) ||
+ my_hash_search(&lock_db_cache,(uchar*) db2, length2)))
{
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
pthread_mutex_lock(&LOCK_lock_db);
@@ -1964,7 +1965,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
- Query_log_event qinfo(thd, thd->query, thd->query_length,
+ Query_log_event qinfo(thd, thd->query(), thd->query_length(),
0, TRUE, errcode);
thd->clear_error();
mysql_bin_log.write(&qinfo);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index fc8a4c3d787..6b59cbc14c1 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -413,7 +413,7 @@ cleanup:
therefore be treated as a DDL.
*/
int log_result= thd->binlog_query(query_type,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
is_trans, FALSE, errcode);
if (log_result)
@@ -850,7 +850,7 @@ void multi_delete::abort()
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
transactional_tables, FALSE, errcode);
}
thd->transaction.all.modified_non_trans_table= true;
@@ -1024,7 +1024,7 @@ bool multi_delete::send_eof()
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
transactional_tables, FALSE, errcode) &&
!normal_tables)
{
@@ -1181,7 +1181,7 @@ end:
TRUNCATE must always be statement-based binlogged (not row-based) so
we don't test current_stmt_binlog_row_based.
*/
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
my_ok(thd); // This should return record count
}
VOID(pthread_mutex_lock(&LOCK_open));
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 78b30619999..eeefdb99eed 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -673,7 +673,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
- if (thd->protocol->send_fields(&field_list,
+ if (thd->protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 00717640974..ab3f2797405 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -207,21 +207,21 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
DBUG_RETURN(TRUE);
}
- if (! hash_inited(&thd->handler_tables_hash))
+ if (! my_hash_inited(&thd->handler_tables_hash))
{
/*
HASH entries are of type TABLE_LIST.
*/
- if (hash_init(&thd->handler_tables_hash, &my_charset_latin1,
- HANDLER_TABLES_HASH_SIZE, 0, 0,
- (hash_get_key) mysql_ha_hash_get_key,
- (hash_free_key) mysql_ha_hash_free, 0))
+ if (my_hash_init(&thd->handler_tables_hash, &my_charset_latin1,
+ HANDLER_TABLES_HASH_SIZE, 0, 0,
+ (my_hash_get_key) mysql_ha_hash_get_key,
+ (my_hash_free_key) mysql_ha_hash_free, 0))
goto err;
}
else if (! reopen) /* Otherwise we have 'tables' already. */
{
- if (hash_search(&thd->handler_tables_hash, (uchar*) tables->alias,
- strlen(tables->alias) + 1))
+ if (my_hash_search(&thd->handler_tables_hash, (uchar*) tables->alias,
+ strlen(tables->alias) + 1))
{
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
@@ -367,12 +367,12 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
tables->db, tables->table_name, tables->alias));
- if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
- (uchar*) tables->alias,
- strlen(tables->alias) + 1)))
+ if ((hash_tables= (TABLE_LIST*) my_hash_search(&thd->handler_tables_hash,
+ (uchar*) tables->alias,
+ strlen(tables->alias) + 1)))
{
mysql_ha_close_table(thd, hash_tables, FALSE);
- hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
+ my_hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
}
else
{
@@ -436,9 +436,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
it++;
retry:
- if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
- (uchar*) tables->alias,
- strlen(tables->alias) + 1)))
+ if ((hash_tables= (TABLE_LIST*) my_hash_search(&thd->handler_tables_hash,
+ (uchar*) tables->alias,
+ strlen(tables->alias) + 1)))
{
table= hash_tables->table;
DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' table: 0x%lx",
@@ -545,7 +545,7 @@ retry:
tables->db, tables->alias, &it, 0))
goto err;
- protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
+ protocol->send_result_set_metadata(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
/*
In ::external_lock InnoDB resets the fields which tell it that
@@ -667,18 +667,11 @@ retry:
continue;
if (num_rows >= offset_limit_cnt)
{
- Item *item;
protocol->prepare_for_resend();
- it.rewind();
- while ((item=it++))
- {
- if (item->send(thd->protocol, &buffer))
- {
- protocol->free(); // Free used
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- goto err;
- }
- }
+
+ if (protocol->send_result_set_row(&list))
+ goto err;
+
protocol->write();
}
num_rows++;
@@ -716,7 +709,7 @@ static TABLE_LIST *mysql_ha_find(THD *thd, TABLE_LIST *tables)
/* search for all handlers with matching table names */
for (uint i= 0; i < thd->handler_tables_hash.records; i++)
{
- hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
+ hash_tables= (TABLE_LIST*) my_hash_element(&thd->handler_tables_hash, i);
for (tables= first; tables; tables= tables->next_local)
{
if ((! *tables->db ||
@@ -760,7 +753,7 @@ void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables, bool is_locked)
next= hash_tables->next_local;
if (hash_tables->table)
mysql_ha_close_table(thd, hash_tables, is_locked);
- hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
+ my_hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
hash_tables= next;
}
@@ -786,7 +779,7 @@ void mysql_ha_flush(THD *thd)
for (uint i= 0; i < thd->handler_tables_hash.records; i++)
{
- hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
+ hash_tables= (TABLE_LIST*) my_hash_element(&thd->handler_tables_hash, i);
if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
mysql_ha_close_table(thd, hash_tables, TRUE);
}
@@ -810,12 +803,12 @@ void mysql_ha_cleanup(THD *thd)
for (uint i= 0; i < thd->handler_tables_hash.records; i++)
{
- hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
+ hash_tables= (TABLE_LIST*) my_hash_element(&thd->handler_tables_hash, i);
if (hash_tables->table)
mysql_ha_close_table(thd, hash_tables, FALSE);
- }
+ }
- hash_free(&thd->handler_tables_hash);
+ my_hash_free(&thd->handler_tables_hash);
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 2818aa5082c..003741a7ddc 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -431,7 +431,7 @@ int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3)
field_list.push_back(new Item_empty_string("description",1000));
field_list.push_back(new Item_empty_string("example",1000));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(1);
@@ -463,7 +463,7 @@ int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3)
+- -+
RETURN VALUES
- result of protocol->send_fields
+ result of protocol->send_result_set_metadata
*/
int send_header_2(Protocol *protocol, bool for_category)
@@ -474,7 +474,7 @@ int send_header_2(Protocol *protocol, bool for_category)
field_list.push_back(new Item_empty_string("source_category_name",64));
field_list.push_back(new Item_empty_string("name",64));
field_list.push_back(new Item_empty_string("is_it_category",1));
- DBUG_RETURN(protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ DBUG_RETURN(protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF));
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b9c32bfb430..7edd3b496da 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -585,7 +585,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
Name_resolution_context *context;
Name_resolution_context_state ctx_state;
#ifndef EMBEDDED_LIBRARY
- char *query= thd->query;
+ char *query= thd->query();
/*
log_on is about delayed inserts only.
By default, both logs are enabled (this won't cause problems if the server
@@ -819,7 +819,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{
- LEX_STRING const st_query = { query, thd->query_length };
+ LEX_STRING const st_query = { query, thd->query_length() };
error=write_delayed(thd, table, duplic, st_query, ignore, log_on);
query=0;
}
@@ -912,7 +912,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
*/
DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
transactional_table, FALSE,
errcode))
{
@@ -1785,7 +1785,7 @@ public:
pthread_cond_destroy(&cond);
pthread_cond_destroy(&cond_client);
thd.unlink(); // Must be unlinked under lock
- x_free(thd.query);
+ x_free(thd.query());
thd.security_ctx->user= thd.security_ctx->host=0;
thread_count--;
delayed_insert_threads--;
@@ -1931,7 +1931,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
pthread_mutex_unlock(&LOCK_thread_count);
di->thd.set_db(table_list->db, (uint) strlen(table_list->db));
di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0);
- if (di->thd.db == NULL || di->thd.query == NULL)
+ if (di->thd.db == NULL || di->thd.query() == NULL)
{
/* The error is reported */
delete di;
@@ -1940,7 +1940,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
}
di->table_list= *table_list; // Needed to open table
/* Replace volatile strings with local copies */
- di->table_list.alias= di->table_list.table_name= di->thd.query;
+ di->table_list.alias= di->table_list.table_name= di->thd.query();
di->table_list.db= di->thd.db;
di->lock();
pthread_mutex_lock(&di->mutex);
@@ -2308,12 +2308,6 @@ static void handle_delayed_insert_impl(THD *thd, Delayed_insert *di)
goto err;
}
- /*
- Open table requires an initialized lex in case the table is
- partitioned. The .frm file contains a partial SQL string which is
- parsed using a lex, that depends on initialized thd->lex.
- */
- lex_start(thd);
thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock()
/*
Statement-based replication of INSERT DELAYED has problems with RAND()
@@ -2748,6 +2742,12 @@ bool Delayed_insert::handle_inserts(void)
thread_safe_increment(delayed_insert_writes,&LOCK_delayed_status);
pthread_mutex_lock(&mutex);
+ /*
+ Reset the table->auto_increment_field_not_null as it is valid for
+ only one row.
+ */
+ table->auto_increment_field_not_null= FALSE;
+
delete row;
/*
Let READ clients do something once in a while
@@ -3267,7 +3267,7 @@ bool select_insert::send_eof()
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
trans_table, FALSE, errcode);
}
table->file->ha_release_auto_increment();
@@ -3339,7 +3339,8 @@ void select_insert::abort() {
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
- thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length,
+ thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(),
+ thd->query_length(),
transactional_table, FALSE, errcode);
}
if (!thd->current_stmt_binlog_row_based && !can_rollback_data())
@@ -3857,6 +3858,7 @@ void select_create::abort()
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
+ table->auto_increment_field_not_null= FALSE;
if (!create_info->table_existed)
drop_open_table(thd, table, create_table->db, create_table->table_name);
table=0; // Safety
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 88bed97cd35..c443f092d9b 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -33,7 +33,14 @@ static int lex_one_token(void *arg, void *yythd);
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
+/**
+ LEX_STRING constant for null-string to be used in parser and other places.
+*/
+const LEX_STRING null_lex_str= {NULL, 0};
+const LEX_STRING empty_lex_str= { (char*) "", 0 };
+
/* Longest standard keyword name */
+
#define TOCK_NAME_LENGTH 24
/*
@@ -138,6 +145,7 @@ Lex_input_stream::Lex_input_stream(THD *thd,
found_semicolon(NULL),
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
stmt_prepare_mode(FALSE),
+ multi_statements(TRUE),
in_comment(NO_COMMENT),
m_underscore_cs(NULL)
{
@@ -1555,7 +1563,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
keys_onoff(rhs.keys_onoff),
tablespace_op(rhs.tablespace_op),
partition_names(rhs.partition_names, mem_root),
- no_parts(rhs.no_parts),
+ num_parts(rhs.num_parts),
change_level(rhs.change_level),
datetime_field(rhs.datetime_field),
error_if_not_empty(rhs.error_if_not_empty)
@@ -2149,7 +2157,7 @@ void st_select_lex::print_limit(THD *thd,
to implement the clean up.
*/
-void st_lex::cleanup_lex_after_parse_error(THD *thd)
+void LEX::cleanup_lex_after_parse_error(THD *thd)
{
/*
Delete sphead for the side effect of restoring of the original
@@ -2208,7 +2216,7 @@ void Query_tables_list::reset_query_tables_list(bool init)
We delay real initialization of hash (and therefore related
memory allocation) until first insertion into this hash.
*/
- hash_clear(&sroutines);
+ my_hash_clear(&sroutines);
}
else if (sroutines.records)
{
@@ -2231,7 +2239,7 @@ void Query_tables_list::reset_query_tables_list(bool init)
void Query_tables_list::destroy_query_tables_list()
{
- hash_free(&sroutines);
+ my_hash_free(&sroutines);
}
@@ -2239,7 +2247,7 @@ void Query_tables_list::destroy_query_tables_list()
Initialize LEX object.
SYNOPSIS
- st_lex::st_lex()
+ LEX::LEX()
NOTE
LEX object initialized with this constructor can be used as part of
@@ -2249,7 +2257,7 @@ void Query_tables_list::destroy_query_tables_list()
for this.
*/
-st_lex::st_lex()
+LEX::LEX()
:result(0),
sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0)
{
@@ -2266,7 +2274,7 @@ st_lex::st_lex()
Check whether the merging algorithm can be used on this VIEW
SYNOPSIS
- st_lex::can_be_merged()
+ LEX::can_be_merged()
DESCRIPTION
We can apply merge algorithm if it is single SELECT view with
@@ -2280,7 +2288,7 @@ st_lex::st_lex()
TRUE - merge algorithm can be used
*/
-bool st_lex::can_be_merged()
+bool LEX::can_be_merged()
{
// TODO: do not forget implement case when select_lex.table_list.elements==0
@@ -2317,19 +2325,19 @@ bool st_lex::can_be_merged()
check if command can use VIEW with MERGE algorithm (for top VIEWs)
SYNOPSIS
- st_lex::can_use_merged()
+ LEX::can_use_merged()
DESCRIPTION
Only listed here commands can use merge algorithm in top level
SELECT_LEX (for subqueries will be used merge algorithm if
- st_lex::can_not_use_merged() is not TRUE).
+ LEX::can_not_use_merged() is not TRUE).
RETURN
FALSE - command can't use merged VIEWs
TRUE - VIEWs with MERGE algorithms can be used
*/
-bool st_lex::can_use_merged()
+bool LEX::can_use_merged()
{
switch (sql_command)
{
@@ -2354,18 +2362,18 @@ bool st_lex::can_use_merged()
Check if command can't use merged views in any part of command
SYNOPSIS
- st_lex::can_not_use_merged()
+ LEX::can_not_use_merged()
DESCRIPTION
Temporary table algorithm will be used on all SELECT levels for queries
- listed here (see also st_lex::can_use_merged()).
+ listed here (see also LEX::can_use_merged()).
RETURN
FALSE - command can't use merged VIEWs
TRUE - VIEWs with MERGE algorithms can be used
*/
-bool st_lex::can_not_use_merged()
+bool LEX::can_not_use_merged()
{
switch (sql_command)
{
@@ -2394,7 +2402,7 @@ bool st_lex::can_not_use_merged()
FALSE no, we need data
*/
-bool st_lex::only_view_structure()
+bool LEX::only_view_structure()
{
switch (sql_command) {
case SQLCOM_SHOW_CREATE:
@@ -2423,7 +2431,7 @@ bool st_lex::only_view_structure()
*/
-bool st_lex::need_correct_ident()
+bool LEX::need_correct_ident()
{
switch(sql_command)
{
@@ -2453,7 +2461,7 @@ bool st_lex::need_correct_ident()
VIEW_CHECK_CASCADED CHECK OPTION CASCADED
*/
-uint8 st_lex::get_effective_with_check(TABLE_LIST *view)
+uint8 LEX::get_effective_with_check(TABLE_LIST *view)
{
if (view->select_lex->master_unit() == &unit &&
which_check_option_applicable())
@@ -2482,7 +2490,7 @@ uint8 st_lex::get_effective_with_check(TABLE_LIST *view)
*/
bool
-st_lex::copy_db_to(char **p_db, size_t *p_db_length) const
+LEX::copy_db_to(char **p_db, size_t *p_db_length) const
{
if (sphead)
{
@@ -2559,7 +2567,7 @@ void st_select_lex_unit::set_limit(st_select_lex *sl)
clause.
*/
-void st_lex::set_trg_event_type_for_tables()
+void LEX::set_trg_event_type_for_tables()
{
uint8 new_trg_event_map= 0;
@@ -2702,7 +2710,7 @@ void st_lex::set_trg_event_type_for_tables()
In this case link_to_local is set.
*/
-TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
+TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
{
TABLE_LIST *first;
if ((first= query_tables))
@@ -2742,7 +2750,7 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
table list
SYNOPSYS
- st_lex::first_lists_tables_same()
+ LEX::first_lists_tables_same()
NOTES
In many cases (for example, usual INSERT/DELETE/...) the first table of
@@ -2753,7 +2761,7 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
the global list first.
*/
-void st_lex::first_lists_tables_same()
+void LEX::first_lists_tables_same()
{
TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first;
if (query_tables != first_table && first_table != 0)
@@ -2789,7 +2797,7 @@ void st_lex::first_lists_tables_same()
global list
*/
-void st_lex::link_first_table_back(TABLE_LIST *first,
+void LEX::link_first_table_back(TABLE_LIST *first,
bool link_to_local)
{
if (first)
@@ -2816,7 +2824,7 @@ void st_lex::link_first_table_back(TABLE_LIST *first,
cleanup lex for case when we open table by table for processing
SYNOPSIS
- st_lex::cleanup_after_one_table_open()
+ LEX::cleanup_after_one_table_open()
NOTE
This method is mostly responsible for cleaning up of selects lists and
@@ -2824,7 +2832,7 @@ void st_lex::link_first_table_back(TABLE_LIST *first,
to call Query_tables_list::reset_query_tables_list(FALSE).
*/
-void st_lex::cleanup_after_one_table_open()
+void LEX::cleanup_after_one_table_open()
{
/*
thd->lex->derived_tables & additional units may be set if we open
@@ -2859,7 +2867,7 @@ void st_lex::cleanup_after_one_table_open()
backup Pointer to Query_tables_list instance to be used for backup
*/
-void st_lex::reset_n_backup_query_tables_list(Query_tables_list *backup)
+void LEX::reset_n_backup_query_tables_list(Query_tables_list *backup)
{
backup->set_query_tables_list(this);
/*
@@ -2878,7 +2886,7 @@ void st_lex::reset_n_backup_query_tables_list(Query_tables_list *backup)
backup Pointer to Query_tables_list instance used for backup
*/
-void st_lex::restore_backup_query_tables_list(Query_tables_list *backup)
+void LEX::restore_backup_query_tables_list(Query_tables_list *backup)
{
this->destroy_query_tables_list();
this->set_query_tables_list(backup);
@@ -2889,14 +2897,14 @@ void st_lex::restore_backup_query_tables_list(Query_tables_list *backup)
Checks for usage of routines and/or tables in a parsed statement
SYNOPSIS
- st_lex:table_or_sp_used()
+ LEX:table_or_sp_used()
RETURN
FALSE No routines and tables used
TRUE Either or both routines and tables are used.
*/
-bool st_lex::table_or_sp_used()
+bool LEX::table_or_sp_used()
{
DBUG_ENTER("table_or_sp_used");
@@ -3057,7 +3065,7 @@ bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
@retval FALSE No, not a management partition command
*/
-bool st_lex::is_partition_management() const
+bool LEX::is_partition_management() const
{
return (sql_command == SQLCOM_ALTER_TABLE &&
(alter_info.flags == ALTER_ADD_PARTITION ||
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index be7375fa3fa..9daf28653b1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -400,7 +400,7 @@ public:
Base class for st_select_lex (SELECT_LEX) &
st_select_lex_unit (SELECT_LEX_UNIT)
*/
-struct st_lex;
+struct LEX;
class st_select_lex;
class st_select_lex_unit;
class st_select_lex_node {
@@ -470,7 +470,7 @@ public:
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
friend class st_select_lex_unit;
- friend bool mysql_new_select(struct st_lex *lex, bool move_down);
+ friend bool mysql_new_select(LEX *lex, bool move_down);
friend bool mysql_make_view(THD *thd, File_parser *parser,
TABLE_LIST *table, uint flags);
private:
@@ -590,7 +590,7 @@ public:
/* Saved values of the WHERE and HAVING clauses*/
Item::cond_result cond_value, having_value;
/* point on lex in which it was created, used in view subquery detection */
- st_lex *parent_lex;
+ LEX *parent_lex;
enum olap_type olap;
/* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */
SQL_LIST table_list;
@@ -899,7 +899,7 @@ public:
enum enum_enable_or_disable keys_onoff;
enum tablespace_op_type tablespace_op;
List<char> partition_names;
- uint no_parts;
+ uint num_parts;
enum_alter_table_change_level change_level;
Create_field *datetime_field;
bool error_if_not_empty;
@@ -909,7 +909,7 @@ public:
flags(0),
keys_onoff(LEAVE_AS_IS),
tablespace_op(NO_TABLESPACE_OP),
- no_parts(0),
+ num_parts(0),
change_level(ALTER_TABLE_METADATA_ONLY),
datetime_field(NULL),
error_if_not_empty(FALSE)
@@ -924,7 +924,7 @@ public:
flags= 0;
keys_onoff= LEAVE_AS_IS;
tablespace_op= NO_TABLESPACE_OP;
- no_parts= 0;
+ num_parts= 0;
partition_names.empty();
change_level= ALTER_TABLE_METADATA_ONLY;
datetime_field= 0;
@@ -956,6 +956,9 @@ extern sys_var *trg_new_row_fake_var;
enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE,
XA_SUSPEND, XA_FOR_MIGRATE};
+extern const LEX_STRING null_lex_str;
+extern const LEX_STRING empty_lex_str;
+
/*
Class representing list of all tables used by statement.
@@ -964,7 +967,7 @@ enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE,
stored functions/triggers to this list in order to pre-open and lock
them.
- Also used by st_lex::reset_n_backup/restore_backup_query_tables_list()
+ Also used by LEX::reset_n_backup/restore_backup_query_tables_list()
methods to save and restore this information.
*/
@@ -1503,9 +1506,13 @@ public:
/**
TRUE if we're parsing a prepared statement: in this mode
- we should allow placeholders and disallow multi-statements.
+ we should allow placeholders.
*/
bool stmt_prepare_mode;
+ /**
+ TRUE if we should allow multi-statements.
+ */
+ bool multi_statements;
/** State of the lexical analyser for comments. */
enum_comment_state in_comment;
@@ -1564,7 +1571,7 @@ protected:
Constructor.
@param lex the LEX structure that represents parts of this statement.
*/
- Sql_statement(struct st_lex *lex)
+ Sql_statement(LEX *lex)
: m_lex(lex)
{}
@@ -1589,12 +1596,12 @@ protected:
with the minimum set of attributes, instead of a LEX structure that
contains the collection of every possible attribute.
*/
- struct st_lex *m_lex;
+ LEX *m_lex;
};
/* The state of the lex parsing. This is saved in the THD struct */
-typedef struct st_lex : public Query_tables_list
+struct LEX: public Query_tables_list
{
SELECT_LEX_UNIT unit; /* most upper unit */
SELECT_LEX select_lex; /* first SELECT_LEX */
@@ -1844,9 +1851,9 @@ typedef struct st_lex : public Query_tables_list
*/
bool protect_against_global_read_lock;
- st_lex();
+ LEX();
- virtual ~st_lex()
+ virtual ~LEX()
{
destroy_query_tables_list();
plugin_unlock_list(NULL, (plugin_ref *)plugins.buffer, plugins.elements);
@@ -1888,7 +1895,7 @@ typedef struct st_lex : public Query_tables_list
Is this update command where 'WHITH CHECK OPTION' clause is important
SYNOPSIS
- st_lex::which_check_option_applicable()
+ LEX::which_check_option_applicable()
RETURN
TRUE have to take 'WHITH CHECK OPTION' clause into account
@@ -1960,7 +1967,7 @@ typedef struct st_lex : public Query_tables_list
}
return FALSE;
}
-} LEX;
+};
/**
@@ -2051,7 +2058,7 @@ public:
};
-struct st_lex_local: public st_lex
+struct st_lex_local: public LEX
{
static void *operator new(size_t size) throw()
{
diff --git a/sql/sql_list.cc b/sql/sql_list.cc
index 49b649133d0..a256212471d 100644
--- a/sql/sql_list.cc
+++ b/sql/sql_list.cc
@@ -18,7 +18,7 @@
#pragma implementation // gcc: Class implementation
#endif
-#include "mysql_priv.h"
+#include "sql_list.h"
list_node end_of_list;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 22df77afeb3..74f4cc0ec0d 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -15,11 +15,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "my_global.h"
+#include "my_sys.h"
+#include "m_string.h" /* for TRASH */
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
+void *sql_alloc(size_t);
+
/* mysql standard class memory allocator */
class Sql_alloc
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 4e9c94973b9..34e899fc536 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -117,7 +117,7 @@ static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
#ifndef EMBEDDED_LIBRARY
static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
- const char* db_arg,
+ const char* db_arg, /* table's database */
const char* table_name_arg,
enum enum_duplicates duplicates,
bool ignore,
@@ -538,7 +538,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (thd->transaction.stmt.modified_non_trans_table)
write_execute_load_query_log_event(thd, ex,
- tdb, table_list->table_name,
+ table_list->db,
+ table_list->table_name,
handle_duplicates, ignore,
transactional_table,
errcode);
@@ -586,7 +587,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
write_execute_load_query_log_event(thd, ex,
- tdb, table_list->table_name,
+ table_list->db, table_list->table_name,
handle_duplicates, ignore,
transactional_table,
errcode);
@@ -611,7 +612,7 @@ err:
/* Not a very useful function; just to avoid duplication of code */
static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
- const char* db_arg,
+ const char* db_arg, /* table's database */
const char* table_name_arg,
enum enum_duplicates duplicates,
bool ignore,
@@ -628,8 +629,27 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
Item *item, *val;
String pfield, pfields;
int n;
+ const char *tbl= table_name_arg;
+ const char *tdb= (thd->db != NULL ? thd->db : db_arg);
+ String string_buf;
- Load_log_event lle(thd, ex, db_arg, table_name_arg, fv, duplicates,
+ if (!thd->db || strcmp(db_arg, thd->db))
+ {
+ /*
+ If used database differs from table's database,
+ prefix table name with database name so that it
+ becomes a FQ name.
+ */
+ string_buf.set_charset(system_charset_info);
+ string_buf.append(db_arg);
+ string_buf.append("`");
+ string_buf.append(".");
+ string_buf.append("`");
+ string_buf.append(table_name_arg);
+ tbl= string_buf.c_ptr_safe();
+ }
+
+ Load_log_event lle(thd, ex, tdb, tbl, fv, duplicates,
ignore, transactional_table);
/*
@@ -692,13 +712,12 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
strcpy(end, p);
end += pl;
- thd->query_length= end - load_data_query;
- thd->query= load_data_query;
+ thd->set_query_inner(load_data_query, end - load_data_query);
Execute_load_query_log_event
- e(thd, thd->query, thd->query_length,
- (uint) ((char*)fname_start - (char*)thd->query - 1),
- (uint) ((char*)fname_end - (char*)thd->query),
+ e(thd, thd->query(), thd->query_length(),
+ (uint) ((char*) fname_start - (char*) thd->query() - 1),
+ (uint) ((char*) fname_end - (char*) thd->query()),
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
transactional_table, FALSE, errcode);
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index e6b12d0e38b..9b1bb67ca06 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -1506,9 +1506,9 @@ static const char *my_locale_month_names_ro_RO[13] =
static const char *my_locale_ab_month_names_ro_RO[13] =
{"ian","feb","mar","apr","mai","iun","iul","aug","sep","oct","nov","dec", NullS };
static const char *my_locale_day_names_ro_RO[8] =
- {"Luni","Marţi","Miercuri","Joi","Vineri","SîmbĂtĂ","DuminicĂ", NullS };
+ {"Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă","Duminică", NullS };
static const char *my_locale_ab_day_names_ro_RO[8] =
- {"Lu","Ma","Mi","Jo","Vi","Sî","Du", NullS };
+ {"Lu","Ma","Mi","Jo","Vi","Sâ","Du", NullS };
static TYPELIB my_locale_typelib_month_names_ro_RO =
{ array_elements(my_locale_month_names_ro_RO)-1, "", my_locale_month_names_ro_RO, NULL };
static TYPELIB my_locale_typelib_ab_month_names_ro_RO =
@@ -1733,6 +1733,24 @@ static TYPELIB my_locale_typelib_day_names_sr_RS =
{ array_elements(my_locale_day_names_sr_RS)-1, "", my_locale_day_names_sr_RS, NULL };
static TYPELIB my_locale_typelib_ab_day_names_sr_RS =
{ array_elements(my_locale_ab_day_names_sr_RS)-1, "", my_locale_ab_day_names_sr_RS, NULL };
+MY_LOCALE my_locale_sr_YU /* Deprecated, use sr_RS instead */
+(
+ 48,
+ "sr_YU",
+ "Serbian - Yugoslavia",
+ FALSE,
+ &my_locale_typelib_month_names_sr_RS,
+ &my_locale_typelib_ab_month_names_sr_RS,
+ &my_locale_typelib_day_names_sr_RS,
+ &my_locale_typelib_ab_day_names_sr_RS,
+ 9,
+ 10,
+ '.', /* decimal point sr_RS */
+ '\0', /* thousands_sep sr_RS */
+ "\x80", /* grouping sr_RS */
+ &global_errmsgs[sr_RS]
+);
+
MY_LOCALE my_locale_sr_RS
(
48,
@@ -3347,6 +3365,13 @@ MY_LOCALE *my_locales[]=
};
+MY_LOCALE *my_locales_deprecated[]=
+{
+ &my_locale_sr_YU,
+ NULL
+};
+
+
MY_LOCALE *my_locale_by_number(uint number)
{
MY_LOCALE *locale;
@@ -3359,22 +3384,56 @@ MY_LOCALE *my_locale_by_number(uint number)
}
-MY_LOCALE *my_locale_by_name(const char *name)
+static MY_LOCALE*
+my_locale_by_name(MY_LOCALE** locales, const char *name)
{
MY_LOCALE **locale;
- for (locale= my_locales; *locale != NULL; locale++)
+ for (locale= locales; *locale != NULL; locale++)
{
if (!my_strcasecmp(&my_charset_latin1, (*locale)->name, name))
- {
- // Check that locale is on its correct position in the array
- DBUG_ASSERT((*locale) == my_locales[(*locale)->number]);
return *locale;
- }
}
return NULL;
}
+MY_LOCALE *my_locale_by_name(const char *name)
+{
+ MY_LOCALE *locale;
+
+ if ((locale= my_locale_by_name(my_locales, name)))
+ {
+ // Check that locale is on its correct position in the array
+ DBUG_ASSERT(locale == my_locales[locale->number]);
+ return locale;
+ }
+ else if ((locale= my_locale_by_name(my_locales_deprecated, name)))
+ {
+ THD *thd= current_thd;
+ /*
+ Replace the deprecated locale to the corresponding
+ 'fresh' locale with the same ID.
+ */
+ locale= my_locales[locale->number];
+ if (thd)
+ {
+ // Send a warning to the client
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX),
+ name, locale->name);
+ }
+ else
+ {
+ // Send a warning to mysqld error log
+ sql_print_warning("The syntax '%s' is deprecated and will be removed. "
+ "Please use %s instead.",
+ name, locale->name);
+ }
+ }
+ return locale;
+}
+
+
void cleanup_errmsgs()
{
for (MY_LOCALE_ERRMSGS *msgs= global_errmsgs; msgs->language; msgs++)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3b99d0e4c5f..094a715902f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -28,6 +28,7 @@
#include "sp_cache.h"
#include "events.h"
#include "sql_trigger.h"
+#include "sql_prepare.h"
#include "probes_mysql.h"
/**
@@ -46,7 +47,6 @@
"FUNCTION" : "PROCEDURE")
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
-static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
const char *any_db="*any*"; // Special symbol for check_access
@@ -124,6 +124,14 @@ static bool xa_trans_rolled_back(XID_STATE *xid_state)
*/
static bool xa_trans_rollback(THD *thd)
{
+ /*
+ Resource Manager error is meaningless at this point, as we perform
+ explicit rollback request by user. We must reset rm_error before
+ calling ha_rollback(), so thd->transaction.xid structure gets reset
+ by ha_rollback()/THD::transaction::cleanup().
+ */
+ thd->transaction.xid_state.rm_error= 0;
+
bool status= test(ha_rollback(thd));
thd->options&= ~(ulong) OPTION_BEGIN;
@@ -131,7 +139,6 @@ static bool xa_trans_rollback(THD *thd)
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
- thd->transaction.xid_state.rm_error= 0;
return status;
}
@@ -375,7 +382,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var,
Vio* save_vio;
ulong save_client_capabilities;
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.start_new_query();
thd->profiling.set_query_source(init_command_var->value,
init_command_var->value_length);
@@ -403,7 +410,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var,
thd->client_capabilities= save_client_capabilities;
thd->net.vio= save_vio;
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
#endif
}
@@ -453,7 +460,7 @@ static void handle_bootstrap_impl(THD *thd)
/* purecov: begin tested */
if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
{
- net_end_statement(thd);
+ thd->protocol->end_statement();
bootstrap_error= 1;
break;
}
@@ -478,10 +485,10 @@ static void handle_bootstrap_impl(THD *thd)
thd->db_length + 1 +
QUERY_CACHE_FLAGS_SIZE);
thd->set_query(query, length);
- DBUG_PRINT("query",("%-.4096s",thd->query));
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+ DBUG_PRINT("query",("%-.4096s",thd->query()));
+#if defined(ENABLED_PROFILING)
thd->profiling.start_new_query();
- thd->profiling.set_query_source(thd->query, length);
+ thd->profiling.set_query_source(thd->query(), length);
#endif
/*
@@ -490,13 +497,13 @@ static void handle_bootstrap_impl(THD *thd)
*/
thd->query_id=next_query_id();
thd->set_time();
- mysql_parse(thd, thd->query, length, & found_semicolon);
+ mysql_parse(thd, thd->query(), length, & found_semicolon);
close_thread_tables(thd); // Free tables
bootstrap_error= thd->is_error();
- net_end_statement(thd);
+ thd->protocol->end_statement();
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
#endif
@@ -589,7 +596,7 @@ static bool check_merge_table_access(THD *thd, char *db,
tlist->db= db; /* purecov: inspected */
}
error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
- table_list, UINT_MAX, FALSE);
+ table_list, FALSE, UINT_MAX, FALSE);
}
return error;
}
@@ -806,7 +813,7 @@ bool do_command(THD *thd)
net_new_transaction(net);
packet_length= my_net_read(net);
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.start_new_query();
#endif
if (packet_length == packet_error)
@@ -819,7 +826,7 @@ bool do_command(THD *thd)
/* The error must be set. */
DBUG_ASSERT(thd->is_error());
- net_end_statement(thd);
+ thd->protocol->end_statement();
if (net->error != 3)
{
@@ -866,7 +873,7 @@ bool do_command(THD *thd)
return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1));
out:
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
#endif
DBUG_RETURN(return_value);
@@ -1213,30 +1220,30 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
- MYSQL_QUERY_START(thd->query, thd->thread_id,
+ MYSQL_QUERY_START(thd->query(), thd->thread_id,
(char *) (thd->db ? thd->db : ""),
thd->security_ctx->priv_user,
(char *) thd->security_ctx->host_or_ip);
- char *packet_end= thd->query + thd->query_length;
+ char *packet_end= thd->query() + thd->query_length();
/* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
const char* end_of_stmt= NULL;
- general_log_write(thd, command, thd->query, thd->query_length);
- DBUG_PRINT("query",("%-.4096s",thd->query));
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
- thd->profiling.set_query_source(thd->query, thd->query_length);
+ general_log_write(thd, command, thd->query(), thd->query_length());
+ DBUG_PRINT("query",("%-.4096s",thd->query()));
+#if defined(ENABLED_PROFILING)
+ thd->profiling.set_query_source(thd->query(), thd->query_length());
#endif
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
- mysql_parse(thd, thd->query, thd->query_length, &end_of_stmt);
+ mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt);
while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error())
{
char *beginning_of_next_stmt= (char*) end_of_stmt;
- net_end_statement(thd);
+ thd->protocol->end_statement();
query_cache_end_of_result(thd);
/*
Multiple queries exits, execute them individually
@@ -1258,7 +1265,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
MYSQL_QUERY_DONE(thd->is_error());
}
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
thd->profiling.start_new_query("continuing");
thd->profiling.set_query_source(beginning_of_next_stmt, length);
@@ -1334,7 +1341,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
0, 0, test(table_list.schema_table)))
break;
- if (check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
+ if (check_grant(thd, SELECT_ACL, &table_list, TRUE, UINT_MAX, FALSE))
break;
/* init structures for VIEW processing */
table_list.select_lex= &(thd->lex->select_lex);
@@ -1630,7 +1637,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->transaction.stmt.reset();
- net_end_statement(thd);
+ thd->protocol->end_statement();
query_cache_end_of_result(thd);
thd->proc_info= "closing tables";
@@ -1694,7 +1701,8 @@ void log_slow_statement(THD *thd)
{
thd_proc_info(thd, "logging slow query");
thd->status_var.long_query_count++;
- slow_log_print(thd, thd->query, thd->query_length, end_utime_of_query);
+ slow_log_print(thd, thd->query(), thd->query_length(),
+ end_utime_of_query);
}
}
DBUG_VOID_RETURN;
@@ -1799,7 +1807,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
Mark this current profiling record to be discarded. We don't
wish to have SHOW commands show up in profiling.
*/
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.discard_current_query();
#endif
break;
@@ -2214,14 +2222,16 @@ mysql_execute_command(THD *thd)
#endif
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
- if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
+ UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
break;
case SQLCOM_SHOW_STATUS:
{
system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var;
- if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
+ UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
/* Don't log SHOW STATUS commands to slow query log */
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
@@ -2251,18 +2261,22 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STORAGE_ENGINES:
case SQLCOM_SHOW_PROFILE:
case SQLCOM_SELECT:
+ {
thd->status_var.last_query_cost= 0.0;
+
+ /*
+ lex->exchange != NULL implies SELECT .. INTO OUTFILE and this
+ requires FILE_ACL access.
+ */
+ ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL :
+ SELECT_ACL;
+
if (all_tables)
- {
res= check_table_access(thd,
- lex->exchange ? SELECT_ACL | FILE_ACL :
- SELECT_ACL,
- all_tables, UINT_MAX, FALSE);
- }
+ privileges_requested,
+ all_tables, FALSE, UINT_MAX, FALSE);
else
- res= check_access(thd,
- lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
- any_db, 0, 0, 0, 0);
+ res= check_access(thd, privileges_requested, any_db, 0, 0, 0, UINT_MAX);
if (res)
break;
@@ -2273,7 +2287,8 @@ mysql_execute_command(THD *thd)
res= execute_sqlcom_select(thd, all_tables);
break;
- case SQLCOM_PREPARE:
+ }
+case SQLCOM_PREPARE:
{
mysql_sql_stmt_prepare(thd);
break;
@@ -2289,8 +2304,8 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_DO:
- if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
- open_and_lock_tables(thd, all_tables))
+ if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
+ || open_and_lock_tables(thd, all_tables))
goto error;
res= mysql_do(thd, *lex->insert_list);
@@ -2354,7 +2369,7 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_PROFILES:
{
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
thd->profiling.discard_current_query();
res= thd->profiling.show_profiles();
if (res)
@@ -2400,8 +2415,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_BACKUP_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
- check_global_access(thd, FILE_ACL))
+ if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
+ || check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_backup_table(thd, first_table);
@@ -2412,8 +2427,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESTORE_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_table_access(thd, INSERT_ACL, all_tables, UINT_MAX, FALSE) ||
- check_global_access(thd, FILE_ACL))
+ if (check_table_access(thd, INSERT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
+ || check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_restore_table(thd, first_table);
@@ -2512,7 +2527,7 @@ mysql_execute_command(THD *thd)
test(first_table->schema_table)))
goto error; /* purecov: inspected */
/* Check that the first table has CREATE privilege */
- if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
+ if (check_grant(thd, CREATE_ACL, all_tables, FALSE, 1, FALSE))
goto error;
pthread_mutex_lock(&LOCK_active_mi);
@@ -2882,7 +2897,7 @@ end_with_restore_list:
(TABLE_LIST *)
create_info.merge_list.first))
goto error; /* purecov: inspected */
- if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
+ if (check_grant(thd, priv_needed, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
@@ -2891,8 +2906,8 @@ end_with_restore_list:
tmp_table.table_name= lex->name.str;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
- if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
- UINT_MAX, 0))
+ if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, FALSE,
+ UINT_MAX, FALSE))
goto error;
}
@@ -2946,10 +2961,11 @@ end_with_restore_list:
*/
old_list= table[0];
new_list= table->next_local[0];
- if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) ||
+ if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, FALSE, 1, FALSE) ||
(!test_all_bits(table->next_local->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
- check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
+ check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, FALSE, 1,
+ FALSE)))
goto error;
}
@@ -2980,11 +2996,75 @@ end_with_restore_list:
goto error;
#else
{
- /* Ignore temporary tables if this is "SHOW CREATE VIEW" */
+ /*
+ Access check:
+ SHOW CREATE TABLE require any privileges on the table level (ie
+ effecting all columns in the table).
+ SHOW CREATE VIEW require the SHOW_VIEW and SELECT ACLs on the table
+ level.
+ NOTE: SHOW_VIEW ACL is checked when the view is created.
+ */
+
if (lex->only_view)
+ {
+ if (check_table_access(thd, SELECT_ACL, first_table, FALSE, 1, FALSE))
+ {
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ "SHOW", thd->security_ctx->priv_user,
+ thd->security_ctx->host_or_ip, first_table->alias);
+ goto error;
+ }
+
+ /* Ignore temporary tables if this is "SHOW CREATE VIEW" */
first_table->skip_temporary= 1;
- if (check_show_create_table_access(thd, first_table))
- goto error;
+ }
+ else
+ {
+ ulong save_priv;
+
+ /*
+ If it is an INFORMATION_SCHEMA table, SELECT_ACL privilege is the
+ only privilege allowed. For any other privilege check_access()
+ reports an error. That's how internal implementation protects
+ INFORMATION_SCHEMA from updates.
+
+ For ordinary tables any privilege from the SHOW_CREATE_TABLE_ACLS
+ set is sufficient.
+ */
+
+ ulong check_privs= test(first_table->schema_table) ?
+ SELECT_ACL : SHOW_CREATE_TABLE_ACLS;
+
+ if (check_access(thd, check_privs, first_table->db,
+ &save_priv, FALSE, FALSE,
+ test(first_table->schema_table)))
+ goto error;
+
+ /*
+ save_priv contains any privileges actually granted by check_access
+ (i.e. save_priv contains global (user- and database-level)
+ privileges).
+
+ The fact that check_access() returned FALSE does not mean that
+ access is granted. We need to check if save_priv contains any
+ table-specific privilege. If not, we need to check table-level
+ privileges.
+
+ If there are no global privileges and no table-level privileges,
+ access is denied.
+ */
+
+ if (!(save_priv & (SHOW_CREATE_TABLE_ACLS)) &&
+ !has_any_table_level_privileges(thd, SHOW_CREATE_TABLE_ACLS, first_table))
+ {
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ "SHOW", thd->security_ctx->priv_user,
+ thd->security_ctx->host_or_ip, first_table->alias);
+ goto error;
+ }
+ }
+
+ /* Access is granted. Execute the command. */
res= mysqld_show_create(thd, first_table);
break;
}
@@ -2992,8 +3072,8 @@ end_with_restore_list:
case SQLCOM_CHECKSUM:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables,
- UINT_MAX, FALSE))
+ if (check_table_access(thd, SELECT_ACL, all_tables,
+ FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
res = mysql_checksum_table(thd, first_table, &lex->check_opt);
break;
@@ -3002,7 +3082,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
- UINT_MAX, FALSE))
+ FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_repair_table(thd, first_table, &lex->check_opt);
@@ -3012,7 +3092,7 @@ end_with_restore_list:
/*
Presumably, REPAIR and binlog writing doesn't require synchronization
*/
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
select_lex->table_list.first= (uchar*) first_table;
lex->query_tables=all_tables;
@@ -3021,8 +3101,8 @@ end_with_restore_list:
case SQLCOM_CHECK:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables,
- UINT_MAX, FALSE))
+ if (check_table_access(thd, SELECT_ACL, all_tables,
+ TRUE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_check_table(thd, first_table, &lex->check_opt);
@@ -3034,7 +3114,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
- UINT_MAX, FALSE))
+ FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_analyze_table(thd, first_table, &lex->check_opt);
@@ -3044,7 +3124,7 @@ end_with_restore_list:
/*
Presumably, ANALYZE and binlog writing doesn't require synchronization
*/
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
select_lex->table_list.first= (uchar*) first_table;
lex->query_tables=all_tables;
@@ -3055,7 +3135,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables,
- UINT_MAX, FALSE))
+ FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
@@ -3067,7 +3147,7 @@ end_with_restore_list:
/*
Presumably, OPTIMIZE and binlog writing doesn't require synchronization
*/
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
select_lex->table_list.first= (uchar*) first_table;
lex->query_tables=all_tables;
@@ -3084,7 +3164,7 @@ end_with_restore_list:
goto error;
DBUG_ASSERT(select_lex->offset_limit == 0);
unit->set_limit(select_lex);
- MYSQL_UPDATE_START(thd->query);
+ MYSQL_UPDATE_START(thd->query());
res= (up_result= mysql_update(thd, all_tables,
select_lex->item_list,
lex->value_list,
@@ -3158,7 +3238,7 @@ end_with_restore_list:
#endif
{
multi_update *result_obj;
- MYSQL_MULTI_UPDATE_START(thd->query);
+ MYSQL_MULTI_UPDATE_START(thd->query());
res= mysql_multi_update(thd, all_tables,
&select_lex->item_list,
&lex->value_list,
@@ -3226,7 +3306,7 @@ end_with_restore_list:
res= 1;
break;
}
- MYSQL_INSERT_START(thd->query);
+ MYSQL_INSERT_START(thd->query());
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
lex->update_list, lex->value_list,
lex->duplicates, lex->ignore);
@@ -3268,7 +3348,7 @@ end_with_restore_list:
}
if (!(res= open_and_lock_tables(thd, all_tables)))
{
- MYSQL_INSERT_SELECT_START(thd->query);
+ MYSQL_INSERT_SELECT_START(thd->query());
/* Skip first table, which is the table we are inserting in */
TABLE_LIST *second_table= first_table->next_local;
select_lex->table_list.first= (uchar*) second_table;
@@ -3354,7 +3434,7 @@ end_with_restore_list:
res= 1;
break;
}
- MYSQL_DELETE_START(thd->query);
+ MYSQL_DELETE_START(thd->query());
res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list,
unit->select_limit_cnt, select_lex->options,
@@ -3389,7 +3469,7 @@ end_with_restore_list:
if ((res= open_and_lock_tables(thd, all_tables)))
break;
- MYSQL_MULTI_DELETE_START(thd->query);
+ MYSQL_MULTI_DELETE_START(thd->query());
if ((res= mysql_multi_delete_prepare(thd)))
{
MYSQL_MULTI_DELETE_DONE(1, 0);
@@ -3428,7 +3508,7 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (!lex->drop_temporary)
{
- if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE))
+ if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
goto error;
@@ -3533,8 +3613,8 @@ end_with_restore_list:
if (lex->autocommit && end_active_trans(thd))
goto error;
- if ((check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
- open_and_lock_tables(thd, all_tables)))
+ if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
+ || open_and_lock_tables(thd, all_tables)))
goto error;
if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
{
@@ -3588,7 +3668,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
- UINT_MAX, FALSE))
+ FALSE, UINT_MAX, FALSE))
goto error;
if (lex->protect_against_global_read_lock &&
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
@@ -3984,7 +4064,7 @@ end_with_restore_list:
else
{
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
- all_tables, 0, UINT_MAX, 0))
+ all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog */
res= mysql_table_grant(thd, all_tables, lex->users_list,
@@ -4049,7 +4129,7 @@ end_with_restore_list:
*/
if (!lex->no_write_to_binlog && write_to_binlog)
{
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
}
my_ok(thd);
}
@@ -4093,7 +4173,7 @@ end_with_restore_list:
#endif
case SQLCOM_HA_OPEN:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE))
+ if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
res= mysql_ha_open(thd, first_table, 0);
break;
@@ -4379,7 +4459,8 @@ create_sp_error:
This will cache all SP and SF and open and lock all tables
required for execution.
*/
- if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) ||
+ if (check_table_access(thd, SELECT_ACL, all_tables, FALSE,
+ UINT_MAX, FALSE) ||
open_and_lock_tables(thd, all_tables))
goto error;
@@ -4620,7 +4701,7 @@ create_sp_error:
case SP_KEY_NOT_FOUND:
if (lex->drop_if_exists)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
SP_COM_STRING(lex), lex->spname->m_name.str);
@@ -4711,8 +4792,8 @@ create_sp_error:
}
case SQLCOM_DROP_VIEW:
{
- if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE) ||
- end_active_trans(thd))
+ if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)
+ || end_active_trans(thd))
goto error;
/* Conditionally writes to binlog. */
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
@@ -4922,7 +5003,7 @@ create_sp_error:
res= mysql_xa_recover(thd);
break;
case SQLCOM_ALTER_TABLESPACE:
- if (check_access(thd, ALTER_ACL, thd->db, 0, 1, 0, thd->db ? is_schema_db(thd->db) : 0))
+ if (check_global_access(thd, CREATE_TABLESPACE_ACL))
break;
if (!(res= mysql_alter_tablespace(thd, lex->alter_tablespace_info)))
my_ok(thd);
@@ -5159,9 +5240,7 @@ bool check_single_table_access(THD *thd, ulong privilege,
/* Show only 1 table for check_grant */
if (!(all_tables->belong_to_view &&
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
- !(all_tables->view &&
- all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE) &&
- check_grant(thd, privilege, all_tables, 0, 1, no_errors))
+ check_grant(thd, privilege, all_tables, FALSE, 1, no_errors))
goto deny;
thd->security_ctx= backup_ctx;
@@ -5206,7 +5285,8 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
subselects_tables= subselects_tables->next_global;
}
if (subselects_tables &&
- (check_table_access(thd, SELECT_ACL, subselects_tables, UINT_MAX, FALSE)))
+ (check_table_access(thd, SELECT_ACL, subselects_tables, FALSE,
+ UINT_MAX, FALSE)))
return 1;
}
return 0;
@@ -5214,46 +5294,54 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
/**
- Get the user (global) and database privileges for all used tables.
-
- @param save_priv In this we store global and db level grants for the
- table. Note that we don't store db level grants if the
- global grants is enough to satisfy the request and the
- global grants contains a SELECT grant.
-
- @note
- The idea of EXTRA_ACL is that one will be granted access to the table if
- one has the asked privilege on any column combination of the table; For
- example to be able to check a table one needs to have SELECT privilege on
- any column of the table.
-
- @retval
- 0 ok
- @retval
- 1 If we can't get the privileges and we don't use table/column
- grants.
+ @brief Compare requested privileges with the privileges acquired from the
+ User- and Db-tables.
+ @param thd Thread handler
+ @param want_access The requested access privileges.
+ @param db A pointer to the Db name.
+ @param[out] save_priv A pointer to the granted privileges will be stored.
+ @param dont_check_global_grants True if no global grants are checked.
+ @param no_error True if no errors should be sent to the client.
+ @param schema_db True if the db specified belongs to the meta data tables.
+
+ 'save_priv' is used to save the User-table (global) and Db-table grants for
+ the supplied db name. Note that we don't store db level grants if the global
+ grants is enough to satisfy the request AND the global grants contains a
+ SELECT grant.
+
+ A meta data table (from INFORMATION_SCHEMA) can always be accessed with
+ a SELECT_ACL.
+
+ @see check_grant
+
+ @return Status of denial of access by exclusive ACLs.
+ @retval FALSE Access can't exclusively be denied by Db- and User-table
+ access unless Column- and Table-grants are checked too.
+ @retval TRUE Access denied.
*/
+
bool
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool dont_check_global_grants, bool no_errors, bool schema_db)
{
Security_context *sctx= thd->security_ctx;
ulong db_access;
+
/*
GRANT command:
In case of database level grant the database name may be a pattern,
in case of table|column level grant the database name can not be a pattern.
We use 'dont_check_global_grants' as a flag to determine
- if it's database level grant command
+ if it's database level grant command
(see SQLCOM_GRANT case, mysql_execute_command() function) and
set db_is_pattern according to 'dont_check_global_grants' value.
*/
- bool db_is_pattern= (test(want_access & GRANT_ACL) &&
- dont_check_global_grants);
+ bool db_is_pattern= ((want_access & GRANT_ACL) && dont_check_global_grants);
ulong dummy;
DBUG_ENTER("check_access");
DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
db ? db : "", want_access, sctx->master_access));
+
if (save_priv)
*save_priv=0;
else
@@ -5271,8 +5359,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (schema_db)
{
- if ((!(sctx->master_access & FILE_ACL) && (want_access & FILE_ACL)) ||
- (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
+ /*
+ We don't allow any simple privileges but SELECT_ACL or CREATE_VIEW_ACL
+ on the information_schema database.
+ */
+ want_access &= ~SELECT_ACL;
+ if (want_access & DB_ACLS)
{
if (!no_errors)
{
@@ -5280,10 +5372,15 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host, db_name);
}
+ /*
+ Access denied;
+ [out] *save_privileges= 0
+ */
DBUG_RETURN(TRUE);
}
else
{
+ /* Access granted */
*save_priv= SELECT_ACL;
DBUG_RETURN(FALSE);
}
@@ -5291,20 +5388,27 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((sctx->master_access & want_access) == want_access)
{
+ /* get access for current db */
+ db_access= sctx->db_access;
/*
- If we don't have a global SELECT privilege, we have to get the database
- specific access rights to be able to handle queries of type
+ 1. If we don't have a global SELECT privilege, we have to get the
+ database specific access rights to be able to handle queries of type
UPDATE t1 SET a=1 WHERE b > 0
+ 2. Change db access if it isn't current db which is being addressed
*/
- db_access= sctx->db_access;
if (!(sctx->master_access & SELECT_ACL) &&
(db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
db_is_pattern);
+
+ /*
+ The effective privileges are the union of the global privileges
+ and the the intersection of db- and host-privileges.
+ */
*save_priv=sctx->master_access | db_access;
DBUG_RETURN(FALSE);
}
- if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
+ if (((want_access & ~sctx->master_access) & ~DB_ACLS) ||
(! db && dont_check_global_grants))
{ // We can never grant this
DBUG_PRINT("error",("No possible access"));
@@ -5319,33 +5423,66 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
}
if (db == any_db)
- DBUG_RETURN(FALSE); // Allow select on anything
+ {
+ /*
+ Access granted; Allow select on *any* db.
+ [out] *save_privileges= 0
+ */
+ DBUG_RETURN(FALSE);
+ }
if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
db_is_pattern);
else
db_access= sctx->db_access;
- DBUG_PRINT("info",("db_access: %lu", db_access));
- /* Remove SHOW attribute and access rights we already have */
- want_access &= ~(sctx->master_access | EXTRA_ACL);
DBUG_PRINT("info",("db_access: %lu want_access: %lu",
db_access, want_access));
- db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access);
- if (db_access == want_access ||
+ /*
+ Save the union of User-table and the intersection between Db-table and
+ Host-table privileges.
+ */
+ db_access= (db_access | sctx->master_access);
+ *save_priv= db_access;
+
+ /*
+ We need to investigate column- and table access if all requested privileges
+ belongs to the bit set of .
+ */
+ bool need_table_or_column_check=
+ (want_access & (TABLE_ACLS | PROC_ACLS | db_access)) == want_access;
+
+ /*
+ Grant access if the requested access is in the intersection of
+ host- and db-privileges (as retrieved from the acl cache),
+ also grant access if all the requested privileges are in the union of
+ TABLES_ACLS and PROC_ACLS; see check_grant.
+ */
+ if ( (db_access & want_access) == want_access ||
(!dont_check_global_grants &&
- !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
- DBUG_RETURN(FALSE); /* Ok */
+ need_table_or_column_check))
+ {
+ /*
+ Ok; but need to check table- and column privileges.
+ [out] *save_privileges is (User-priv | (Db-priv & Host-priv))
+ */
+ DBUG_RETURN(FALSE);
+ }
+ /*
+ Access is denied;
+ [out] *save_privileges is (User-priv | (Db-priv & Host-priv))
+ */
DBUG_PRINT("error",("Access denied"));
if (!no_errors)
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host,
(db ? db : (thd->db ?
thd->db :
- "unknown"))); /* purecov: tested */
- DBUG_RETURN(TRUE); /* purecov: tested */
+ "unknown")));
+ DBUG_RETURN(TRUE);
+
}
@@ -5391,14 +5528,20 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
DBUG_ASSERT(dst_table);
- if (check_access(thd, SELECT_ACL | EXTRA_ACL,
- dst_table->db,
- &dst_table->grant.privilege,
- FALSE, FALSE,
+ if (check_access(thd, SELECT_ACL, dst_table->db,
+ &dst_table->grant.privilege, FALSE, FALSE,
test(dst_table->schema_table)))
- return FALSE;
+ return TRUE; /* Access denied */
+
+ /*
+ Check_grant will grant access if there is any column privileges on
+ all of the tables thanks to the fourth parameter (bool show_table).
+ */
+ if (check_grant(thd, SELECT_ACL, dst_table, TRUE, UINT_MAX, FALSE))
+ return TRUE; /* Access denied */
- return (check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE));
+ /* Access granted */
+ return FALSE;
}
default:
break;
@@ -5408,30 +5551,46 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
}
-/**
- Check the privilege for all used tables.
- @param thd Thread context
- @param want_access Privileges requested
- @param tables List of tables to be checked
- @param number Check at most this number of tables.
- @param no_errors FALSE/TRUE - report/don't report error to
- the client (using my_error() call).
+/**
+ @brief Check if the requested privileges exists in either User-, Host- or
+ Db-tables.
+ @param thd Thread context
+ @param want_access Privileges requested
+ @param tables List of tables to be compared against
+ @param no_errors Don't report error to the client (using my_error() call).
+ @param any_combination_of_privileges_will_do TRUE if any privileges on any
+ column combination is enough.
+ @param number Only the first 'number' tables in the linked list are
+ relevant.
+
+ The suppled table list contains cached privileges. This functions calls the
+ help functions check_access and check_grant to verify the first three steps
+ in the privileges check queue:
+ 1. Global privileges
+ 2. OR (db privileges AND host privileges)
+ 3. OR table privileges
+ 4. OR column privileges (not checked by this function!)
+ 5. OR routine privileges (not checked by this function!)
+
+ @see check_access
+ @see check_grant
+
+ @note This functions assumes that table list used and
+ thd->lex->query_tables_own_last value correspond to each other
+ (the latter should be either 0 or point to next_global member
+ of one of elements of this table list).
- @note
- Table privileges are cached in the table list for GRANT checking.
- This functions assumes that table list used and
- thd->lex->query_tables_own_last value correspond to each other
- (the latter should be either 0 or point to next_global member
- of one of elements of this table list).
-
- @retval FALSE OK
- @retval TRUE Access denied
+ @return
+ @retval FALSE OK
+ @retval TRUE Access denied; But column or routine privileges might need to
+ be checked also.
*/
bool
-check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
- uint number, bool no_errors)
+check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
+ bool any_combination_of_privileges_will_do,
+ uint number, bool no_errors)
{
TABLE_LIST *org_tables= tables;
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
@@ -5442,22 +5601,31 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
the given table list refers to the list for prelocking (contains tables
of other queries). For simple queries first_not_own_table is 0.
*/
- for (; i < number && tables != first_not_own_table;
+ for (; i < number && tables != first_not_own_table && tables;
tables= tables->next_global, i++)
{
+ ulong want_access= requirements;
if (tables->security_ctx)
sctx= tables->security_ctx;
else
sctx= backup_ctx;
- if (tables->schema_table &&
- (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
+ /*
+ Always allow SELECT on schema tables. This is done by removing the
+ required SELECT_ACL privilege in the want_access parameter.
+ Disallow any other DDL or DML operation on any schema table.
+ */
+ if (tables->schema_table)
{
- if (!no_errors)
- my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- sctx->priv_user, sctx->priv_host,
- INFORMATION_SCHEMA_NAME.str);
- return TRUE;
+ want_access &= ~SELECT_ACL;
+ if (want_access & DB_ACLS)
+ {
+ if (!no_errors)
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ sctx->priv_user, sctx->priv_host,
+ INFORMATION_SCHEMA_NAME.str);
+ goto deny;
+ }
}
/*
Register access for view underlying table.
@@ -5469,33 +5637,34 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
{
if (check_show_access(thd, tables))
goto deny;
-
continue;
}
+ DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0,
+ tables->view != 0));
if (tables->is_anonymous_derived_table() ||
- (tables->table && (int)tables->table->s->tmp_table))
+ (tables->table && tables->table->s &&
+ (int)tables->table->s->tmp_table))
continue;
thd->security_ctx= sctx;
- if ((sctx->master_access & want_access) ==
- (want_access & ~EXTRA_ACL) &&
- thd->db)
+ if ((sctx->master_access & want_access) == want_access &&
+ thd->db)
tables->grant.privilege= want_access;
else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
{
if (check_access(thd, want_access, tables->get_db_name(),
- &tables->grant.privilege, 0, no_errors,
+ &tables->grant.privilege, 0, no_errors,
test(tables->schema_table)))
goto deny; // Access denied
}
else if (check_access(thd, want_access, tables->get_db_name(),
- &tables->grant.privilege, 0, no_errors,
- test(tables->schema_table)))
+ &tables->grant.privilege, 0, no_errors, 0))
goto deny;
}
thd->security_ctx= backup_ctx;
- return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
- test(want_access & EXTRA_ACL), number, no_errors);
+ return check_grant(thd,requirements,org_tables,
+ any_combination_of_privileges_will_do,
+ number, no_errors);
deny:
thd->security_ctx= backup_ctx;
return TRUE;
@@ -5583,7 +5752,7 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
if (!check_access(thd, access, table->db,
&table->grant.privilege, 0, 1,
test(table->schema_table)) &&
- !check_grant(thd, access, table, 0, 1, 1))
+ !check_grant(thd, access, table, FALSE, 1, TRUE))
DBUG_RETURN(0);
}
}
@@ -6021,9 +6190,10 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
PROCESSLIST.
Note that we don't need LOCK_thread_count to modify query_length.
*/
- if (*found_semicolon &&
- (thd->query_length= (ulong)(*found_semicolon - thd->query)))
- thd->query_length--;
+ if (*found_semicolon && (ulong) (*found_semicolon - thd->query()))
+ thd->set_query_inner(thd->query(),
+ (uint32) (*found_semicolon -
+ thd->query() - 1));
/* Actually execute the query */
if (*found_semicolon)
{
@@ -6031,7 +6201,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
}
lex->set_trg_event_type_for_tables();
- MYSQL_QUERY_EXEC_START(thd->query,
+ MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
(char *) (thd->db ? thd->db : ""),
thd->security_ctx->priv_user,
@@ -6049,7 +6219,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
- query_cache_abort(&thd->net);
+ query_cache_abort(&thd->query_cache_tls);
}
if (thd->lex->sphead)
{
@@ -6133,8 +6303,8 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
if (type_modifier & PRI_KEY_FLAG)
{
Key *key;
- lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
- key= new Key(Key::PRIMARY, NullS,
+ lex->col_list.push_back(new Key_part_spec(*field_name, 0));
+ key= new Key(Key::PRIMARY, null_lex_str,
&default_key_create_info,
0, lex->col_list);
lex->alter_info.key_list.push_back(key);
@@ -6143,8 +6313,8 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
Key *key;
- lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
- key= new Key(Key::UNIQUE, NullS,
+ lex->col_list.push_back(new Key_part_spec(*field_name, 0));
+ key= new Key(Key::UNIQUE, null_lex_str,
&default_key_create_info, 0,
lex->col_list);
lex->alter_info.key_list.push_back(key);
@@ -6880,7 +7050,6 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
{
thd->thread_stack= (char*) &tmp_thd;
thd->store_globals();
- lex_start(thd);
}
if (thd)
@@ -7289,11 +7458,11 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
else if ((check_access(thd, UPDATE_ACL, table->db,
&table->grant.privilege, 0, 1,
test(table->schema_table)) ||
- check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
+ check_grant(thd, UPDATE_ACL, table, FALSE, 1, TRUE)) &&
(check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
- check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
+ check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE)))
DBUG_RETURN(TRUE);
table->table_in_first_from_clause= 1;
@@ -7311,7 +7480,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
- check_grant(thd, SELECT_ACL, table, 0, 1, 0))
+ check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
}
}
@@ -7351,7 +7520,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
- if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
+ if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
/*
@@ -7360,7 +7529,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
call check_table_access() safely.
*/
thd->lex->query_tables_own_last= 0;
- if (check_table_access(thd, DELETE_ACL, aux_tables, UINT_MAX, FALSE))
+ if (check_table_access(thd, DELETE_ACL, aux_tables, FALSE, UINT_MAX, FALSE))
{
thd->lex->query_tables_own_last= save_query_tables_own_last;
DBUG_RETURN(TRUE);
@@ -7514,25 +7683,6 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables)
/**
- @brief Check privileges for SHOW CREATE TABLE statement.
-
- @param thd Thread context
- @param table Target table
-
- @retval TRUE Failure
- @retval FALSE Success
-*/
-
-static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
-{
- return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
- &table->grant.privilege, 0, 0,
- test(table->schema_table)) ||
- check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
-}
-
-
-/**
CREATE TABLE query pre-check.
@param thd Thread handler
@@ -7571,7 +7721,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
lex->create_info.merge_list.first))
goto err;
if (want_priv != CREATE_TMP_ACL &&
- check_grant(thd, want_priv, create_table, 0, 1, 0))
+ check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
goto err;
if (select_lex->item_list.elements)
@@ -7599,12 +7749,13 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
}
}
#endif
- if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
+ if (tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
+ UINT_MAX, FALSE))
goto err;
}
else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
{
- if (check_show_create_table_access(thd, tables))
+ if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
goto err;
}
error= FALSE;
@@ -7911,7 +8062,7 @@ bool parse_sql(THD *thd,
bool ret_value;
DBUG_ASSERT(thd->m_parser_state == NULL);
- MYSQL_QUERY_PARSE_START(thd->query);
+ MYSQL_QUERY_PARSE_START(thd->query());
/* Backup creation context. */
Object_creation_ctx *backup_ctx= NULL;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index eb711001ef6..a05e8fbf3ab 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1,4 +1,4 @@
-/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,16 +18,29 @@
to partitioning introduced in MySQL version 5.1. It contains functionality
used by all handlers that support partitioning, such as
the partitioning handler itself and the NDB handler.
+ (Much of the code in this file has been split into partition_info.cc and
+ the header files partition_info.h + partition_element.h + sql_partition.h)
- The first version was written by Mikael Ronstrom.
+ The first version was written by Mikael Ronstrom 2004-2006.
+ Various parts of the optimizer code was written by Sergey Petrunia.
+ Code have been maintained by Mattias Jonsson.
+ The second version was written by Mikael Ronstrom 2006-2007 with some
+ final fixes for partition pruning in 2008-2009 with assistance from Sergey
+ Petrunia and Mattias Jonsson.
- This version supports RANGE partitioning, LIST partitioning, HASH
+ The first version supports RANGE partitioning, LIST partitioning, HASH
partitioning and composite partitioning (hereafter called subpartitioning)
where each RANGE/LIST partitioning is HASH partitioned. The hash function
can either be supplied by the user or by only a list of fields (also
called KEY partitioning), where the MySQL server will use an internal
hash function.
There are quite a few defaults that can be used as well.
+
+ The second version introduces a new variant of RANGE and LIST partitioning
+ which is often referred to as column lists in the code variables. This
+ enables a user to specify a set of columns and their concatenated value
+ as the partition value. By comparing the concatenation of these values
+ the proper partition can be choosen.
*/
/* Some general useful functions */
@@ -54,9 +67,11 @@ const LEX_STRING partition_keywords[]=
{ C_STRING_WITH_LEN("LIST") },
{ C_STRING_WITH_LEN("KEY") },
{ C_STRING_WITH_LEN("MAXVALUE") },
- { C_STRING_WITH_LEN("LINEAR ") }
+ { C_STRING_WITH_LEN("LINEAR ") },
+ { C_STRING_WITH_LEN(" COLUMNS") }
};
static const char *part_str= "PARTITION";
+static const char *subpart_str= "SUBPARTITION";
static const char *sub_str= "SUB";
static const char *by_str= "BY";
static const char *space_str= " ";
@@ -65,26 +80,23 @@ static const char *end_paren_str= ")";
static const char *begin_paren_str= "(";
static const char *comma_str= ",";
-static int get_part_id_charset_func_all(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-static int get_part_id_charset_func_part(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-static int get_part_id_charset_func_subpart(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-static int get_part_part_id_charset_func(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-static int get_subpart_id_charset_func(partition_info *part_info,
- uint32 *part_id);
+int get_partition_id_list_col(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value);
int get_partition_id_list(partition_info *part_info,
uint32 *part_id,
longlong *func_value);
+int get_partition_id_range_col(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value);
int get_partition_id_range(partition_info *part_info,
uint32 *part_id,
longlong *func_value);
+static int get_part_id_charset_func_part(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value);
+static int get_part_id_charset_func_subpart(partition_info *part_info,
+ uint32 *part_id);
int get_partition_id_hash_nosub(partition_info *part_info,
uint32 *part_id,
longlong *func_value);
@@ -97,30 +109,9 @@ int get_partition_id_linear_hash_nosub(partition_info *part_info,
int get_partition_id_linear_key_nosub(partition_info *part_info,
uint32 *part_id,
longlong *func_value);
-int get_partition_id_range_sub_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_range_sub_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_range_sub_linear_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_range_sub_linear_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_list_sub_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_list_sub_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_list_sub_linear_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
-int get_partition_id_list_sub_linear_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value);
+int get_partition_id_with_sub(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value);
int get_partition_id_hash_sub(partition_info *part_info,
uint32 *part_id);
int get_partition_id_key_sub(partition_info *part_info,
@@ -138,17 +129,64 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter);
uint32 get_next_partition_id_list(PARTITION_ITERATOR* part_iter);
int get_part_iter_for_interval_via_mapping(partition_info *part_info,
bool is_subpart,
+ uint32 *store_length_array,
uchar *min_value, uchar *max_value,
+ uint min_len, uint max_len,
uint flags,
PARTITION_ITERATOR *part_iter);
+int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
+ bool is_subpart,
+ uint32 *store_length_array,
+ uchar *min_value, uchar *max_value,
+ uint min_len, uint max_len,
+ uint flags,
+ PARTITION_ITERATOR *part_iter);
int get_part_iter_for_interval_via_walking(partition_info *part_info,
bool is_subpart,
+ uint32 *store_length_array,
uchar *min_value, uchar *max_value,
+ uint min_len, uint max_len,
uint flags,
PARTITION_ITERATOR *part_iter);
+static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec);
+static int cmp_rec_and_tuple_prune(part_column_list_val *val,
+ uint32 n_vals_in_rec,
+ bool tail_is_min);
#ifdef WITH_PARTITION_STORAGE_ENGINE
/*
+ Convert constants in VALUES definition to the character set the
+ corresponding field uses.
+
+ SYNOPSIS
+ convert_charset_partition_constant()
+ item Item to convert
+ cs Character set to convert to
+
+ RETURN VALUE
+ NULL Error
+ item New converted item
+*/
+
+Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs)
+{
+ THD *thd= current_thd;
+ Name_resolution_context *context= &thd->lex->current_select->context;
+ TABLE_LIST *save_list= context->table_list;
+ const char *save_where= thd->where;
+
+ item= item->safe_charset_converter(cs);
+ context->table_list= NULL;
+ thd->where= "convert character set partition constant";
+ if (!item || item->fix_fields(thd, (Item**)NULL))
+ item= NULL;
+ thd->where= save_where;
+ context->table_list= save_list;
+ return item;
+}
+
+
+/*
A support function to check if a name is in a list of strings
SYNOPSIS
@@ -165,7 +203,7 @@ bool is_name_in_list(char *name,
List<char> list_names)
{
List_iterator<char> names_it(list_names);
- uint no_names= list_names.elements;
+ uint num_names= list_names.elements;
uint i= 0;
do
@@ -173,7 +211,7 @@ bool is_name_in_list(char *name,
char *list_name= names_it++;
if (!(my_strcasecmp(system_charset_info, name, list_name)))
return TRUE;
- } while (++i < no_names);
+ } while (++i < num_names);
return FALSE;
}
@@ -200,26 +238,26 @@ bool partition_default_handling(TABLE *table, partition_info *part_info,
{
DBUG_ENTER("partition_default_handling");
- if (part_info->use_default_no_partitions)
+ if (part_info->use_default_num_partitions)
{
if (!is_create_table_ind &&
- table->file->get_no_parts(normalized_path, &part_info->no_parts))
+ table->file->get_no_parts(normalized_path, &part_info->num_parts))
{
DBUG_RETURN(TRUE);
}
}
else if (part_info->is_sub_partitioned() &&
- part_info->use_default_no_subpartitions)
+ part_info->use_default_num_subpartitions)
{
- uint no_parts;
+ uint num_parts;
if (!is_create_table_ind &&
- (table->file->get_no_parts(normalized_path, &no_parts)))
+ (table->file->get_no_parts(normalized_path, &num_parts)))
{
DBUG_RETURN(TRUE);
}
- DBUG_ASSERT(part_info->no_parts > 0);
- part_info->no_subparts= no_parts / part_info->no_parts;
- DBUG_ASSERT((no_parts % part_info->no_parts) == 0);
+ DBUG_ASSERT(part_info->num_parts > 0);
+ part_info->num_subparts= num_parts / part_info->num_parts;
+ DBUG_ASSERT((num_parts % part_info->num_parts) == 0);
}
part_info->set_up_defaults_for_partitioning(table->file,
(ulonglong)0, (uint)0);
@@ -252,8 +290,8 @@ bool check_reorganise_list(partition_info *new_part_info,
List<char> list_part_names)
{
uint new_count, old_count;
- uint no_new_parts= new_part_info->partitions.elements;
- uint no_old_parts= old_part_info->partitions.elements;
+ uint num_new_parts= new_part_info->partitions.elements;
+ uint num_old_parts= old_part_info->partitions.elements;
List_iterator<partition_element> new_parts_it(new_part_info->partitions);
bool same_part_info= (new_part_info == old_part_info);
DBUG_ENTER("check_reorganise_list");
@@ -276,8 +314,8 @@ bool check_reorganise_list(partition_info *new_part_info,
if (!is_name_in_list(old_name, list_part_names))
DBUG_RETURN(TRUE);
}
- } while (old_count < no_old_parts);
- } while (new_count < no_new_parts);
+ } while (old_count < num_old_parts);
+ } while (new_count < num_new_parts);
DBUG_RETURN(FALSE);
}
@@ -452,9 +490,10 @@ static bool set_up_field_array(TABLE *table,
bool is_sub_part)
{
Field **ptr, *field, **field_array;
- uint no_fields= 0;
+ uint num_fields= 0;
uint size_field_array;
uint i= 0;
+ uint inx;
partition_info *part_info= table->part_info;
int result= FALSE;
DBUG_ENTER("set_up_field_array");
@@ -463,9 +502,19 @@ static bool set_up_field_array(TABLE *table,
while ((field= *(ptr++)))
{
if (field->flags & GET_FIXED_FIELDS_FLAG)
- no_fields++;
+ num_fields++;
}
- if (no_fields == 0)
+ if (num_fields > MAX_REF_PARTS)
+ {
+ char *ptr;
+ if (is_sub_part)
+ ptr= (char*)"subpartition function";
+ else
+ ptr= (char*)"partition function";
+ my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0), ptr);
+ DBUG_RETURN(TRUE);
+ }
+ if (num_fields == 0)
{
/*
We are using hidden key as partitioning field
@@ -473,8 +522,8 @@ static bool set_up_field_array(TABLE *table,
DBUG_ASSERT(!is_sub_part);
DBUG_RETURN(result);
}
- size_field_array= (no_fields+1)*sizeof(Field*);
- field_array= (Field**)sql_alloc(size_field_array);
+ size_field_array= (num_fields+1)*sizeof(Field*);
+ field_array= (Field**)sql_calloc(size_field_array);
if (unlikely(!field_array))
{
mem_alloc_error(size_field_array);
@@ -489,7 +538,32 @@ static bool set_up_field_array(TABLE *table,
field->flags|= FIELD_IN_PART_FUNC_FLAG;
if (likely(!result))
{
- field_array[i++]= field;
+ if (!is_sub_part && part_info->column_list)
+ {
+ List_iterator<char> it(part_info->part_field_list);
+ char *field_name;
+
+ DBUG_ASSERT(num_fields == part_info->part_field_list.elements);
+ inx= 0;
+ do
+ {
+ field_name= it++;
+ if (!my_strcasecmp(system_charset_info,
+ field_name,
+ field->field_name))
+ break;
+ } while (++inx < num_fields);
+ if (inx == num_fields)
+ {
+ mem_alloc_error(1);
+ result= TRUE;
+ continue;
+ }
+ }
+ else
+ inx= i;
+ field_array[inx]= field;
+ i++;
/*
We check that the fields are proper. It is required for each
@@ -507,16 +581,16 @@ static bool set_up_field_array(TABLE *table,
}
}
}
- field_array[no_fields]= 0;
+ field_array[num_fields]= 0;
if (!is_sub_part)
{
part_info->part_field_array= field_array;
- part_info->no_part_fields= no_fields;
+ part_info->num_part_fields= num_fields;
}
else
{
part_info->subpart_field_array= field_array;
- part_info->no_subpart_fields= no_fields;
+ part_info->num_subpart_fields= num_fields;
}
DBUG_RETURN(result);
}
@@ -555,36 +629,36 @@ static bool create_full_part_field_array(THD *thd, TABLE *table,
if (!part_info->is_sub_partitioned())
{
part_info->full_part_field_array= part_info->part_field_array;
- part_info->no_full_part_fields= part_info->no_part_fields;
+ part_info->num_full_part_fields= part_info->num_part_fields;
}
else
{
Field *field, **field_array;
- uint no_part_fields=0, size_field_array;
+ uint num_part_fields=0, size_field_array;
ptr= table->field;
while ((field= *(ptr++)))
{
if (field->flags & FIELD_IN_PART_FUNC_FLAG)
- no_part_fields++;
+ num_part_fields++;
}
- size_field_array= (no_part_fields+1)*sizeof(Field*);
- field_array= (Field**)sql_alloc(size_field_array);
+ size_field_array= (num_part_fields+1)*sizeof(Field*);
+ field_array= (Field**)sql_calloc(size_field_array);
if (unlikely(!field_array))
{
mem_alloc_error(size_field_array);
result= TRUE;
goto end;
}
- no_part_fields= 0;
+ num_part_fields= 0;
ptr= table->field;
while ((field= *(ptr++)))
{
if (field->flags & FIELD_IN_PART_FUNC_FLAG)
- field_array[no_part_fields++]= field;
+ field_array[num_part_fields++]= field;
}
- field_array[no_part_fields]=0;
+ field_array[num_part_fields]=0;
part_info->full_part_field_array= field_array;
- part_info->no_full_part_fields= no_part_fields;
+ part_info->num_full_part_fields= num_part_fields;
}
/*
@@ -780,16 +854,16 @@ static bool handle_list_of_fields(List_iterator<char> it,
goto end;
}
}
- if (is_list_empty)
+ if (is_list_empty && part_info->part_type == HASH_PARTITION)
{
uint primary_key= table->s->primary_key;
if (primary_key != MAX_KEY)
{
- uint no_key_parts= table->key_info[primary_key].key_parts, i;
+ uint num_key_parts= table->key_info[primary_key].key_parts, i;
/*
In the case of an empty list we use primary key as partition key.
*/
- for (i= 0; i < no_key_parts; i++)
+ for (i= 0; i < num_key_parts; i++)
{
Field *field= table->key_info[primary_key].key_part[i].field;
field->flags|= GET_FIXED_FIELDS_FLAG;
@@ -853,11 +927,90 @@ int check_signed_flag(partition_info *part_info)
error= ER_PARTITION_CONST_DOMAIN_ERROR;
break;
}
- } while (++i < part_info->no_parts);
+ } while (++i < part_info->num_parts);
}
return error;
}
+/**
+ Initialize lex object for use in fix_fields and parsing.
+
+ SYNOPSIS
+ init_lex_with_single_table()
+ @param thd The thread object
+ @param table The table object
+ @return Operation status
+ @retval TRUE An error occurred, memory allocation error
+ @retval FALSE Ok
+
+ DESCRIPTION
+ This function is used to initialize a lex object on the
+ stack for use by fix_fields and for parsing. In order to
+ work properly it also needs to initialize the
+ Name_resolution_context object of the lexer.
+ Finally it needs to set a couple of variables to ensure
+ proper functioning of fix_fields.
+*/
+
+static int
+init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
+{
+ TABLE_LIST *table_list;
+ Table_ident *table_ident;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ Name_resolution_context *context= &select_lex->context;
+ /*
+ We will call the parser to create a part_info struct based on the
+ partition string stored in the frm file.
+ We will use a local lex object for this purpose. However we also
+ need to set the Name_resolution_object for this lex object. We
+ do this by using add_table_to_list where we add the table that
+ we're working with to the Name_resolution_context.
+ */
+ thd->lex= lex;
+ lex_start(thd);
+ context->init();
+ if ((!(table_ident= new Table_ident(thd,
+ table->s->table_name,
+ table->s->db, TRUE))) ||
+ (!(table_list= select_lex->add_table_to_list(thd,
+ table_ident,
+ NULL,
+ 0))))
+ return TRUE;
+ context->resolve_in_table_list_only(table_list);
+ lex->use_only_table_context= TRUE;
+ select_lex->cur_pos_in_select_list= UNDEF_POS;
+ table->map= 1; //To ensure correct calculation of const item
+ table->get_fields_in_item_tree= TRUE;
+ table_list->table= table;
+ return FALSE;
+}
+
+/**
+ End use of local lex with single table
+
+ SYNOPSIS
+ end_lex_with_single_table()
+ @param thd The thread object
+ @param table The table object
+ @param old_lex The real lex object connected to THD
+
+ DESCRIPTION
+ This function restores the real lex object after calling
+ init_lex_with_single_table and also restores some table
+ variables temporarily set.
+*/
+
+static void
+end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex)
+{
+ LEX *lex= thd->lex;
+ table->map= 0;
+ table->get_fields_in_item_tree= FALSE;
+ lex_end(lex);
+ thd->lex= old_lex;
+}
/*
The function uses a new feature in fix_fields where the flag
@@ -872,7 +1025,6 @@ int check_signed_flag(partition_info *part_info)
table The table object
part_info Reference to partitioning data structure
is_sub_part Is the table subpartitioned as well
- is_field_to_be_setup Flag if we are to set-up field arrays
RETURN VALUE
TRUE An error occurred, something was wrong with the
@@ -895,66 +1047,22 @@ int check_signed_flag(partition_info *part_info)
on the field object.
*/
-bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
- bool is_sub_part, bool is_field_to_be_setup)
+static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
+ bool is_sub_part)
{
partition_info *part_info= table->part_info;
- uint dir_length, home_dir_length;
bool result= TRUE;
- TABLE_LIST tables;
- TABLE_LIST *save_table_list, *save_first_table, *save_last_table;
int error;
- Name_resolution_context *context;
const char *save_where;
- char* db_name;
- char db_name_string[FN_REFLEN];
- bool save_use_only_table_context;
+ LEX *old_lex= thd->lex;
+ LEX lex;
DBUG_ENTER("fix_fields_part_func");
- if (part_info->fixed)
- {
- if (!(is_sub_part || (error= check_signed_flag(part_info))))
- result= FALSE;
+ if (init_lex_with_single_table(thd, table, &lex))
goto end;
- }
- /*
- Set-up the TABLE_LIST object to be a list with a single table
- Set the object to zero to create NULL pointers and set alias
- and real name to table name and get database name from file name.
- TODO: Consider generalizing or refactoring Lex::add_table_to_list() so
- it can be used in all places where we create TABLE_LIST objects.
- Also consider creating appropriate constructors for TABLE_LIST.
- */
-
- bzero((void*)&tables, sizeof(TABLE_LIST));
- tables.alias= tables.table_name= (char*) table->s->table_name.str;
- tables.table= table;
- tables.next_local= 0;
- tables.next_name_resolution_table= 0;
- /*
- Cache the table in Item_fields. All the tables can be cached except
- the trigger pseudo table.
- */
- tables.cacheable_table= TRUE;
- context= thd->lex->current_context();
- tables.select_lex= context->select_lex;
- strmov(db_name_string, table->s->normalized_path.str);
- dir_length= dirname_length(db_name_string);
- db_name_string[dir_length - 1]= 0;
- home_dir_length= dirname_length(db_name_string);
- db_name= &db_name_string[home_dir_length];
- tables.db= db_name;
-
- table->map= 1; //To ensure correct calculation of const item
- table->get_fields_in_item_tree= TRUE;
- save_table_list= context->table_list;
- save_first_table= context->first_name_resolution_table;
- save_last_table= context->last_name_resolution_table;
- context->table_list= &tables;
- context->first_name_resolution_table= &tables;
- context->last_name_resolution_table= NULL;
- func_expr->walk(&Item::change_context_processor, 0, (uchar*) context);
+ func_expr->walk(&Item::change_context_processor, 0,
+ (uchar*) &lex.select_lex.context);
save_where= thd->where;
thd->where= "partition function";
/*
@@ -969,31 +1077,18 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
that does this during val_int must be disallowed as partition
function.
SEE Bug #21658
- */
- /*
+
This is a tricky call to prepare for since it can have a large number
of interesting side effects, both desirable and undesirable.
*/
-
- save_use_only_table_context= thd->lex->use_only_table_context;
- thd->lex->use_only_table_context= TRUE;
- thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
-
error= func_expr->fix_fields(thd, (Item**)&func_expr);
- thd->lex->use_only_table_context= save_use_only_table_context;
-
- context->table_list= save_table_list;
- context->first_name_resolution_table= save_first_table;
- context->last_name_resolution_table= save_last_table;
if (unlikely(error))
{
DBUG_PRINT("info", ("Field in partition function not part of table"));
- if (is_field_to_be_setup)
- clear_field_flag(table);
+ clear_field_flag(table);
goto end;
}
- thd->where= save_where;
if (unlikely(func_expr->const_item()))
{
my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
@@ -1002,14 +1097,13 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
}
if ((!is_sub_part) && (error= check_signed_flag(part_info)))
goto end;
- result= FALSE;
- if (is_field_to_be_setup)
- result= set_up_field_array(table, is_sub_part);
- if (!is_sub_part)
- part_info->fixed= TRUE;
+ result= set_up_field_array(table, is_sub_part);
end:
- table->get_fields_in_item_tree= FALSE;
- table->map= 0; //Restore old value
+ end_lex_with_single_table(thd, table, old_lex);
+#if !defined(DBUG_OFF)
+ func_expr->walk(&Item::change_context_processor, 0,
+ (uchar*) 0);
+#endif
DBUG_RETURN(result);
}
@@ -1185,9 +1279,9 @@ void check_range_capable_PF(TABLE *table)
static bool set_up_partition_bitmap(THD *thd, partition_info *part_info)
{
uint32 *bitmap_buf;
- uint bitmap_bits= part_info->no_subparts?
- (part_info->no_subparts* part_info->no_parts):
- part_info->no_parts;
+ uint bitmap_bits= part_info->num_subparts?
+ (part_info->num_subparts* part_info->num_parts):
+ part_info->num_parts;
uint bitmap_bytes= bitmap_buffer_size(bitmap_bits);
DBUG_ENTER("set_up_partition_bitmap");
@@ -1287,64 +1381,47 @@ static void set_up_partition_func_pointers(partition_info *part_info)
if (part_info->is_sub_partitioned())
{
+ part_info->get_partition_id= get_partition_id_with_sub;
if (part_info->part_type == RANGE_PARTITION)
{
- part_info->get_part_partition_id= get_partition_id_range;
+ if (part_info->column_list)
+ part_info->get_part_partition_id= get_partition_id_range_col;
+ else
+ part_info->get_part_partition_id= get_partition_id_range;
if (part_info->list_of_subpart_fields)
{
if (part_info->linear_hash_ind)
- {
- part_info->get_partition_id= get_partition_id_range_sub_linear_key;
part_info->get_subpartition_id= get_partition_id_linear_key_sub;
- }
else
- {
- part_info->get_partition_id= get_partition_id_range_sub_key;
part_info->get_subpartition_id= get_partition_id_key_sub;
- }
}
else
{
if (part_info->linear_hash_ind)
- {
- part_info->get_partition_id= get_partition_id_range_sub_linear_hash;
part_info->get_subpartition_id= get_partition_id_linear_hash_sub;
- }
else
- {
- part_info->get_partition_id= get_partition_id_range_sub_hash;
part_info->get_subpartition_id= get_partition_id_hash_sub;
- }
}
}
else /* LIST Partitioning */
{
- part_info->get_part_partition_id= get_partition_id_list;
+ if (part_info->column_list)
+ part_info->get_part_partition_id= get_partition_id_list_col;
+ else
+ part_info->get_part_partition_id= get_partition_id_list;
if (part_info->list_of_subpart_fields)
{
if (part_info->linear_hash_ind)
- {
- part_info->get_partition_id= get_partition_id_list_sub_linear_key;
part_info->get_subpartition_id= get_partition_id_linear_key_sub;
- }
else
- {
- part_info->get_partition_id= get_partition_id_list_sub_key;
part_info->get_subpartition_id= get_partition_id_key_sub;
- }
}
else
{
if (part_info->linear_hash_ind)
- {
- part_info->get_partition_id= get_partition_id_list_sub_linear_hash;
part_info->get_subpartition_id= get_partition_id_linear_hash_sub;
- }
else
- {
- part_info->get_partition_id= get_partition_id_list_sub_hash;
part_info->get_subpartition_id= get_partition_id_hash_sub;
- }
}
}
}
@@ -1353,9 +1430,19 @@ static void set_up_partition_func_pointers(partition_info *part_info)
part_info->get_part_partition_id= NULL;
part_info->get_subpartition_id= NULL;
if (part_info->part_type == RANGE_PARTITION)
- part_info->get_partition_id= get_partition_id_range;
+ {
+ if (part_info->column_list)
+ part_info->get_partition_id= get_partition_id_range_col;
+ else
+ part_info->get_partition_id= get_partition_id_range;
+ }
else if (part_info->part_type == LIST_PARTITION)
- part_info->get_partition_id= get_partition_id_list;
+ {
+ if (part_info->column_list)
+ part_info->get_partition_id= get_partition_id_list_col;
+ else
+ part_info->get_partition_id= get_partition_id_list;
+ }
else /* HASH partitioning */
{
if (part_info->list_of_part_fields)
@@ -1374,32 +1461,43 @@ static void set_up_partition_func_pointers(partition_info *part_info)
}
}
}
- if (part_info->full_part_charset_field_array)
- {
- DBUG_ASSERT(part_info->get_partition_id);
- part_info->get_partition_id_charset= part_info->get_partition_id;
- if (part_info->part_charset_field_array &&
- part_info->subpart_charset_field_array)
- part_info->get_partition_id= get_part_id_charset_func_all;
- else if (part_info->part_charset_field_array)
- part_info->get_partition_id= get_part_id_charset_func_part;
- else
- part_info->get_partition_id= get_part_id_charset_func_subpart;
- }
- if (part_info->part_charset_field_array &&
- part_info->is_sub_partitioned())
+ /*
+ We need special functions to handle character sets since they require copy
+ of field pointers and restore afterwards. For subpartitioned tables we do
+ the copy and restore individually on the part and subpart parts. For non-
+ subpartitioned tables we use the same functions as used for the parts part
+ of subpartioning.
+ Thus for subpartitioned tables the get_partition_id is always
+ get_partition_id_with_sub, even when character sets exists.
+ */
+ if (part_info->part_charset_field_array)
{
- DBUG_ASSERT(part_info->get_part_partition_id);
- part_info->get_part_partition_id_charset=
+ if (part_info->is_sub_partitioned())
+ {
+ DBUG_ASSERT(part_info->get_part_partition_id);
+ if (!part_info->column_list)
+ {
+ part_info->get_part_partition_id_charset=
part_info->get_part_partition_id;
- part_info->get_part_partition_id= get_part_part_id_charset_func;
+ part_info->get_part_partition_id= get_part_id_charset_func_part;
+ }
+ }
+ else
+ {
+ DBUG_ASSERT(part_info->get_partition_id);
+ if (!part_info->column_list)
+ {
+ part_info->get_part_partition_id_charset= part_info->get_partition_id;
+ part_info->get_part_partition_id= get_part_id_charset_func_part;
+ }
+ }
}
if (part_info->subpart_charset_field_array)
{
DBUG_ASSERT(part_info->get_subpartition_id);
part_info->get_subpartition_id_charset=
part_info->get_subpartition_id;
- part_info->get_subpartition_id= get_subpart_id_charset_func;
+ part_info->get_subpartition_id= get_part_id_charset_func_subpart;
}
DBUG_VOID_RETURN;
}
@@ -1407,22 +1505,22 @@ static void set_up_partition_func_pointers(partition_info *part_info)
/*
For linear hashing we need a mask which is on the form 2**n - 1 where
- 2**n >= no_parts. Thus if no_parts is 6 then mask is 2**3 - 1 = 8 - 1 = 7.
+ 2**n >= num_parts. Thus if num_parts is 6 then mask is 2**3 - 1 = 8 - 1 = 7.
SYNOPSIS
set_linear_hash_mask()
part_info Reference to partitioning data structure
- no_parts Number of parts in linear hash partitioning
+ num_parts Number of parts in linear hash partitioning
RETURN VALUE
NONE
*/
-void set_linear_hash_mask(partition_info *part_info, uint no_parts)
+void set_linear_hash_mask(partition_info *part_info, uint num_parts)
{
uint mask;
- for (mask= 1; mask < no_parts; mask<<=1)
+ for (mask= 1; mask < num_parts; mask<<=1)
;
part_info->linear_hash_mask= mask - 1;
}
@@ -1436,7 +1534,7 @@ void set_linear_hash_mask(partition_info *part_info, uint no_parts)
get_part_id_from_linear_hash()
hash_value Hash value calculated by HASH function or KEY function
mask Mask calculated previously by set_linear_hash_mask
- no_parts Number of partitions in HASH partitioned part
+ num_parts Number of partitions in HASH partitioned part
RETURN VALUE
part_id The calculated partition identity (starting at 0)
@@ -1449,11 +1547,11 @@ void set_linear_hash_mask(partition_info *part_info, uint no_parts)
*/
static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask,
- uint no_parts)
+ uint num_parts)
{
uint32 part_id= (uint32)(hash_value & mask);
- if (part_id >= no_parts)
+ if (part_id >= num_parts)
{
uint new_mask= ((mask + 1) >> 1) - 1;
part_id= (uint32)(hash_value & new_mask);
@@ -1597,7 +1695,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
function is correct.
*/
if (part_info->linear_hash_ind)
- set_linear_hash_mask(part_info, part_info->no_subparts);
+ set_linear_hash_mask(part_info, part_info->num_subparts);
if (part_info->list_of_subpart_fields)
{
List_iterator<char> it(part_info->subpart_field_list);
@@ -1607,12 +1705,12 @@ bool fix_partition_func(THD *thd, TABLE *table,
else
{
if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr,
- table, TRUE, TRUE)))
+ table, TRUE)))
goto end;
if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT))
{
- my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0),
- "SUBPARTITION");
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0),
+ subpart_str);
goto end;
}
}
@@ -1625,7 +1723,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
if (part_info->part_type == HASH_PARTITION)
{
if (part_info->linear_hash_ind)
- set_linear_hash_mask(part_info, part_info->no_parts);
+ set_linear_hash_mask(part_info, part_info->num_parts);
if (part_info->list_of_part_fields)
{
List_iterator<char> it(part_info->part_field_list);
@@ -1635,32 +1733,43 @@ bool fix_partition_func(THD *thd, TABLE *table,
else
{
if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
- table, FALSE, TRUE)))
+ table, FALSE)))
goto end;
if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
{
- my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), part_str);
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0), part_str);
goto end;
}
part_info->part_result_type= INT_RESULT;
}
+ part_info->fixed= TRUE;
}
else
{
const char *error_str;
- if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
- table, FALSE, TRUE)))
- goto end;
+ if (part_info->column_list)
+ {
+ List_iterator<char> it(part_info->part_field_list);
+ if (unlikely(handle_list_of_fields(it, table, part_info, FALSE)))
+ goto end;
+ }
+ else
+ {
+ if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
+ table, FALSE)))
+ goto end;
+ }
+ part_info->fixed= TRUE;
if (part_info->part_type == RANGE_PARTITION)
{
error_str= partition_keywords[PKW_RANGE].str;
- if (unlikely(part_info->check_range_constants()))
+ if (unlikely(part_info->check_range_constants(thd)))
goto end;
}
else if (part_info->part_type == LIST_PARTITION)
{
error_str= partition_keywords[PKW_LIST].str;
- if (unlikely(part_info->check_list_constants()))
+ if (unlikely(part_info->check_list_constants(thd)))
goto end;
}
else
@@ -1669,12 +1778,13 @@ bool fix_partition_func(THD *thd, TABLE *table,
my_error(ER_INCONSISTENT_PARTITION_INFO_ERROR, MYF(0));
goto end;
}
- if (unlikely(part_info->no_parts < 1))
+ if (unlikely(part_info->num_parts < 1))
{
my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str);
goto end;
}
- if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
+ if (unlikely(!part_info->column_list &&
+ part_info->part_expr->result_type() != INT_RESULT))
{
my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), part_str);
goto end;
@@ -1682,7 +1792,8 @@ bool fix_partition_func(THD *thd, TABLE *table,
}
if (((part_info->part_type != HASH_PARTITION ||
part_info->list_of_part_fields == FALSE) &&
- check_part_func_fields(part_info->part_field_array, TRUE)) ||
+ (!part_info->column_list &&
+ check_part_func_fields(part_info->part_field_array, TRUE))) ||
(part_info->list_of_part_fields == FALSE &&
part_info->is_sub_partitioned() &&
check_part_func_fields(part_info->subpart_field_array, TRUE)))
@@ -1705,6 +1816,11 @@ bool fix_partition_func(THD *thd, TABLE *table,
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
goto end;
}
+ if (unlikely(part_info->check_partition_field_length()))
+ {
+ my_error(ER_PARTITION_FIELDS_TOO_LONG, MYF(0));
+ goto end;
+ }
check_range_capable_PF(table);
set_up_partition_key_maps(table, part_info);
set_up_partition_func_pointers(part_info);
@@ -1727,9 +1843,9 @@ end:
static int add_write(File fptr, const char *buf, uint len)
{
- uint len_written= my_write(fptr, (const uchar*)buf, len, MYF(0));
+ uint ret_code= my_write(fptr, (const uchar*)buf, len, MYF(MY_FNABP));
- if (likely(len == len_written))
+ if (likely(ret_code == 0))
return 0;
else
return 1;
@@ -1778,14 +1894,8 @@ static int add_begin_parenthesis(File fptr)
static int add_part_key_word(File fptr, const char *key_string)
{
int err= add_string(fptr, key_string);
-
err+= add_space(fptr);
- return err + add_begin_parenthesis(fptr);
-}
-
-static int add_hash(File fptr)
-{
- return add_part_key_word(fptr, partition_keywords[PKW_HASH].str);
+ return err;
}
static int add_partition(File fptr)
@@ -1816,16 +1926,16 @@ static int add_subpartition_by(File fptr)
return err + add_partition_by(fptr);
}
-static int add_key_partition(File fptr, List<char> field_list)
+static int add_part_field_list(File fptr, List<char> field_list)
{
- uint i, no_fields;
- int err;
+ uint i, num_fields;
+ int err= 0;
List_iterator<char> part_it(field_list);
- err= add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
- no_fields= field_list.elements;
+ num_fields= field_list.elements;
i= 0;
- while (i < no_fields)
+ err+= add_begin_parenthesis(fptr);
+ while (i < num_fields)
{
const char *field_str= part_it++;
String field_string("", 0, system_charset_info);
@@ -1836,10 +1946,11 @@ static int add_key_partition(File fptr, List<char> field_list)
strlen(field_str));
thd->options= save_options;
err+= add_string_object(fptr, &field_string);
- if (i != (no_fields-1))
+ if (i != (num_fields-1))
err+= add_comma(fptr);
i++;
}
+ err+= add_end_parenthesis(fptr);
return err;
}
@@ -1949,37 +2060,269 @@ static int add_partition_options(File fptr, partition_element *p_elem)
return err + add_engine(fptr,p_elem->engine_type);
}
-static int add_partition_values(File fptr, partition_info *part_info, partition_element *p_elem)
+
+/*
+ Check partition fields for result type and if they need
+ to check the character set.
+
+ SYNOPSIS
+ check_part_field()
+ sql_type Type provided by user
+ field_name Name of field, used for error handling
+ result_type Out value: Result type of field
+ need_cs_check Out value: Do we need character set check
+
+ RETURN VALUES
+ TRUE Error
+ FALSE Ok
+*/
+
+static int check_part_field(enum_field_types sql_type,
+ const char *field_name,
+ Item_result *result_type,
+ bool *need_cs_check)
+{
+ if (sql_type >= MYSQL_TYPE_TINY_BLOB &&
+ sql_type <= MYSQL_TYPE_BLOB)
+ {
+ my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0));
+ return TRUE;
+ }
+ switch (sql_type)
+ {
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_INT24:
+ *result_type= INT_RESULT;
+ *need_cs_check= FALSE;
+ return FALSE;
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ *result_type= STRING_RESULT;
+ *need_cs_check= TRUE;
+ return FALSE;
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ *result_type= STRING_RESULT;
+ *need_cs_check= TRUE;
+ return FALSE;
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:
+ goto error;
+ default:
+ goto error;
+ }
+error:
+ my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
+ field_name);
+ return TRUE;
+}
+
+
+/*
+ Find the given field's Create_field object using name of field
+
+ SYNOPSIS
+ get_sql_field()
+ field_name Field name
+ alter_info Info from ALTER TABLE/CREATE TABLE
+
+ RETURN VALUE
+ sql_field Object filled in by parser about field
+ NULL No field found
+*/
+
+static Create_field* get_sql_field(char *field_name,
+ Alter_info *alter_info)
+{
+ List_iterator<Create_field> it(alter_info->create_list);
+ Create_field *sql_field;
+ DBUG_ENTER("get_sql_field");
+
+ while ((sql_field= it++))
+ {
+ if (!(my_strcasecmp(system_charset_info,
+ sql_field->field_name,
+ field_name)))
+ {
+ DBUG_RETURN(sql_field);
+ }
+ }
+ DBUG_RETURN(NULL);
+}
+
+
+static int add_column_list_values(File fptr, partition_info *part_info,
+ part_elem_value *list_value,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
+{
+ int err= 0;
+ uint i;
+ List_iterator<char> it(part_info->part_field_list);
+ uint num_elements= part_info->part_field_list.elements;
+ bool use_parenthesis= (part_info->part_type == LIST_PARTITION &&
+ part_info->num_columns > 1U);
+
+ if (use_parenthesis)
+ err+= add_begin_parenthesis(fptr);
+ for (i= 0; i < num_elements; i++)
+ {
+ part_column_list_val *col_val= &list_value->col_val_array[i];
+ char *field_name= it++;
+ if (col_val->max_value)
+ err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
+ else if (col_val->null_value)
+ err+= add_string(fptr, "NULL");
+ else
+ {
+ char buffer[MAX_KEY_LENGTH];
+ String str(buffer, sizeof(buffer), &my_charset_bin);
+ Item *item_expr= col_val->item_expression;
+ if (item_expr->null_value)
+ err+= add_string(fptr, "NULL");
+ else
+ {
+ String *res;
+ CHARSET_INFO *field_cs;
+ bool need_cs_check= FALSE;
+ Item_result result_type= STRING_RESULT;
+
+ /*
+ This function is called at a very early stage, even before
+ we have prepared the sql_field objects. Thus we have to
+ find the proper sql_field object and get the character set
+ from that object.
+ */
+ if (create_info)
+ {
+ Create_field *sql_field;
+
+ if (!(sql_field= get_sql_field(field_name,
+ alter_info)))
+ {
+ my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
+ return 1;
+ }
+ if (check_part_field(sql_field->sql_type,
+ sql_field->field_name,
+ &result_type,
+ &need_cs_check))
+ return 1;
+ if (need_cs_check)
+ field_cs= get_sql_field_charset(sql_field, create_info);
+ else
+ field_cs= NULL;
+ }
+ else
+ {
+ Field *field= part_info->part_field_array[i];
+ result_type= field->result_type();
+ if (check_part_field(field->real_type(),
+ field->field_name,
+ &result_type,
+ &need_cs_check))
+ return 1;
+ DBUG_ASSERT(result_type == field->result_type());
+ if (need_cs_check)
+ field_cs= field->charset();
+ else
+ field_cs= NULL;
+ }
+ if (result_type != item_expr->result_type())
+ {
+ my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
+ return 1;
+ }
+ if (field_cs && field_cs != item_expr->collation.collation)
+ {
+ if (!(item_expr= convert_charset_partition_constant(item_expr,
+ field_cs)))
+ {
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ return 1;
+ }
+ }
+ {
+ String val_conv;
+ val_conv.set_charset(system_charset_info);
+ res= item_expr->val_str(&str);
+ if (get_cs_converted_part_value_from_string(current_thd,
+ item_expr, res,
+ &val_conv, field_cs,
+ (bool)(alter_info != NULL)))
+ return 1;
+ err+= add_string_object(fptr, &val_conv);
+ }
+ }
+ }
+ if (i != (num_elements - 1))
+ err+= add_string(fptr, comma_str);
+ }
+ if (use_parenthesis)
+ err+= add_end_parenthesis(fptr);
+ return err;
+}
+
+static int add_partition_values(File fptr, partition_info *part_info,
+ partition_element *p_elem,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
{
int err= 0;
if (part_info->part_type == RANGE_PARTITION)
{
err+= add_string(fptr, " VALUES LESS THAN ");
- if (!p_elem->max_value)
+ if (part_info->column_list)
{
+ List_iterator<part_elem_value> list_val_it(p_elem->list_val_list);
+ part_elem_value *list_value= list_val_it++;
err+= add_begin_parenthesis(fptr);
- if (p_elem->signed_flag)
- err+= add_int(fptr, p_elem->range_value);
- else
- err+= add_uint(fptr, p_elem->range_value);
+ err+= add_column_list_values(fptr, part_info, list_value,
+ create_info, alter_info);
err+= add_end_parenthesis(fptr);
}
else
- err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
+ {
+ if (!p_elem->max_value)
+ {
+ err+= add_begin_parenthesis(fptr);
+ if (p_elem->signed_flag)
+ err+= add_int(fptr, p_elem->range_value);
+ else
+ err+= add_uint(fptr, p_elem->range_value);
+ err+= add_end_parenthesis(fptr);
+ }
+ else
+ err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
+ }
}
else if (part_info->part_type == LIST_PARTITION)
{
uint i;
List_iterator<part_elem_value> list_val_it(p_elem->list_val_list);
err+= add_string(fptr, " VALUES IN ");
- uint no_items= p_elem->list_val_list.elements;
+ uint num_items= p_elem->list_val_list.elements;
err+= add_begin_parenthesis(fptr);
if (p_elem->has_null_value)
{
err+= add_string(fptr, "NULL");
- if (no_items == 0)
+ if (num_items == 0)
{
err+= add_end_parenthesis(fptr);
goto end;
@@ -1991,13 +2334,19 @@ static int add_partition_values(File fptr, partition_info *part_info, partition_
{
part_elem_value *list_value= list_val_it++;
- if (!list_value->unsigned_flag)
- err+= add_int(fptr, list_value->value);
+ if (part_info->column_list)
+ err+= add_column_list_values(fptr, part_info, list_value,
+ create_info, alter_info);
else
- err+= add_uint(fptr, list_value->value);
- if (i != (no_items-1))
+ {
+ if (!list_value->unsigned_flag)
+ err+= add_int(fptr, list_value->value);
+ else
+ err+= add_uint(fptr, list_value->value);
+ }
+ if (i != (num_items-1))
err+= add_comma(fptr);
- } while (++i < no_items);
+ } while (++i < num_items);
err+= add_end_parenthesis(fptr);
}
end:
@@ -2016,6 +2365,8 @@ end:
use_sql_alloc Allocate buffer from sql_alloc if true
otherwise use my_malloc
show_partition_options Should we display partition options
+ create_info Info generated by parser
+ alter_info Info generated by parser
RETURN VALUES
NULL error
@@ -2044,9 +2395,11 @@ end:
char *generate_partition_syntax(partition_info *part_info,
uint *buf_length,
bool use_sql_alloc,
- bool show_partition_options)
+ bool show_partition_options,
+ HA_CREATE_INFO *create_info,
+ Alter_info *alter_info)
{
- uint i,j, tot_no_parts, no_subparts;
+ uint i,j, tot_num_parts, num_subparts;
partition_element *part_elem;
ulonglong buffer_length;
char path[FN_REFLEN];
@@ -2077,9 +2430,12 @@ char *generate_partition_syntax(partition_info *part_info,
if (part_info->linear_hash_ind)
err+= add_string(fptr, partition_keywords[PKW_LINEAR].str);
if (part_info->list_of_part_fields)
- err+= add_key_partition(fptr, part_info->part_field_list);
+ {
+ err+= add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
+ err+= add_part_field_list(fptr, part_info->part_field_list);
+ }
else
- err+= add_hash(fptr);
+ err+= add_part_key_word(fptr, partition_keywords[PKW_HASH].str);
break;
default:
DBUG_ASSERT(0);
@@ -2089,15 +2445,23 @@ char *generate_partition_syntax(partition_info *part_info,
DBUG_RETURN(NULL);
}
if (part_info->part_expr)
+ {
+ err+= add_begin_parenthesis(fptr);
err+= add_string_len(fptr, part_info->part_func_string,
part_info->part_func_len);
- err+= add_end_parenthesis(fptr);
- if ((!part_info->use_default_no_partitions) &&
+ err+= add_end_parenthesis(fptr);
+ }
+ else if (part_info->column_list)
+ {
+ err+= add_string(fptr, partition_keywords[PKW_COLUMNS].str);
+ err+= add_part_field_list(fptr, part_info->part_field_list);
+ }
+ if ((!part_info->use_default_num_partitions) &&
part_info->use_default_partitions)
{
err+= add_string(fptr, "\n");
err+= add_string(fptr, "PARTITIONS ");
- err+= add_int(fptr, part_info->no_parts);
+ err+= add_int(fptr, part_info->num_parts);
}
if (part_info->is_sub_partitioned())
{
@@ -2107,23 +2471,29 @@ char *generate_partition_syntax(partition_info *part_info,
if (part_info->linear_hash_ind)
err+= add_string(fptr, partition_keywords[PKW_LINEAR].str);
if (part_info->list_of_subpart_fields)
- err+= add_key_partition(fptr, part_info->subpart_field_list);
+ {
+ add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
+ add_part_field_list(fptr, part_info->subpart_field_list);
+ }
else
- err+= add_hash(fptr);
+ err+= add_part_key_word(fptr, partition_keywords[PKW_HASH].str);
if (part_info->subpart_expr)
+ {
+ err+= add_begin_parenthesis(fptr);
err+= add_string_len(fptr, part_info->subpart_func_string,
part_info->subpart_func_len);
- err+= add_end_parenthesis(fptr);
- if ((!part_info->use_default_no_subpartitions) &&
+ err+= add_end_parenthesis(fptr);
+ }
+ if ((!part_info->use_default_num_subpartitions) &&
part_info->use_default_subpartitions)
{
err+= add_string(fptr, "\n");
err+= add_string(fptr, "SUBPARTITIONS ");
- err+= add_int(fptr, part_info->no_subparts);
+ err+= add_int(fptr, part_info->num_subparts);
}
}
- tot_no_parts= part_info->partitions.elements;
- no_subparts= part_info->no_subparts;
+ tot_num_parts= part_info->partitions.elements;
+ num_subparts= part_info->num_subparts;
if (!part_info->use_default_partitions)
{
@@ -2146,7 +2516,8 @@ char *generate_partition_syntax(partition_info *part_info,
first= FALSE;
err+= add_partition(fptr);
err+= add_name_string(fptr, part_elem->partition_name);
- err+= add_partition_values(fptr, part_info, part_elem);
+ err+= add_partition_values(fptr, part_info, part_elem,
+ create_info, alter_info);
if (!part_info->is_sub_partitioned() ||
part_info->use_default_subpartitions)
{
@@ -2167,7 +2538,7 @@ char *generate_partition_syntax(partition_info *part_info,
err+= add_name_string(fptr, part_elem->partition_name);
if (show_partition_options)
err+= add_partition_options(fptr, part_elem);
- if (j != (no_subparts-1))
+ if (j != (num_subparts-1))
{
err+= add_comma(fptr);
err+= add_string(fptr, "\n");
@@ -2176,12 +2547,12 @@ char *generate_partition_syntax(partition_info *part_info,
}
else
err+= add_end_parenthesis(fptr);
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
}
- if (i == (tot_no_parts-1))
+ if (i == (tot_num_parts-1))
err+= add_end_parenthesis(fptr);
- } while (++i < tot_no_parts);
+ } while (++i < tot_num_parts);
}
if (err)
goto close_file;
@@ -2328,14 +2699,14 @@ static uint32 calculate_key_value(Field **field_array)
get_part_id_for_sub()
loc_part_id Local partition id
sub_part_id Subpartition id
- no_subparts Number of subparts
+ num_subparts Number of subparts
*/
inline
static uint32 get_part_id_for_sub(uint32 loc_part_id, uint32 sub_part_id,
- uint no_subparts)
+ uint num_subparts)
{
- return (uint32)((loc_part_id * no_subparts) + sub_part_id);
+ return (uint32)((loc_part_id * num_subparts) + sub_part_id);
}
@@ -2344,7 +2715,7 @@ static uint32 get_part_id_for_sub(uint32 loc_part_id, uint32 sub_part_id,
SYNOPSIS
get_part_id_hash()
- no_parts Number of hash partitions
+ num_parts Number of hash partitions
part_expr Item tree of hash function
out:part_id The returned partition id
out:func_value Value of hash function
@@ -2354,7 +2725,7 @@ static uint32 get_part_id_for_sub(uint32 loc_part_id, uint32 sub_part_id,
FALSE Success
*/
-static int get_part_id_hash(uint no_parts,
+static int get_part_id_hash(uint num_parts,
Item *part_expr,
uint32 *part_id,
longlong *func_value)
@@ -2365,7 +2736,7 @@ static int get_part_id_hash(uint no_parts,
if (part_val_int(part_expr, func_value))
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
- int_hash_id= *func_value % no_parts;
+ int_hash_id= *func_value % num_parts;
*part_id= int_hash_id < 0 ? (uint32) -int_hash_id : (uint32) int_hash_id;
DBUG_RETURN(FALSE);
@@ -2379,7 +2750,7 @@ static int get_part_id_hash(uint no_parts,
get_part_id_linear_hash()
part_info A reference to the partition_info struct where all the
desired information is given
- no_parts Number of hash partitions
+ num_parts Number of hash partitions
part_expr Item tree of hash function
out:part_id The returned partition id
out:func_value Value of hash function
@@ -2390,7 +2761,7 @@ static int get_part_id_hash(uint no_parts,
*/
static int get_part_id_linear_hash(partition_info *part_info,
- uint no_parts,
+ uint num_parts,
Item *part_expr,
uint32 *part_id,
longlong *func_value)
@@ -2402,7 +2773,7 @@ static int get_part_id_linear_hash(partition_info *part_info,
*part_id= get_part_id_from_linear_hash(*func_value,
part_info->linear_hash_mask,
- no_parts);
+ num_parts);
DBUG_RETURN(FALSE);
}
@@ -2413,7 +2784,7 @@ static int get_part_id_linear_hash(partition_info *part_info,
SYNOPSIS
get_part_id_key()
field_array Array of fields for PARTTION KEY
- no_parts Number of KEY partitions
+ num_parts Number of KEY partitions
RETURN VALUE
Calculated partition id
@@ -2421,12 +2792,12 @@ static int get_part_id_linear_hash(partition_info *part_info,
inline
static uint32 get_part_id_key(Field **field_array,
- uint no_parts,
+ uint num_parts,
longlong *func_value)
{
DBUG_ENTER("get_part_id_key");
*func_value= calculate_key_value(field_array);
- DBUG_RETURN((uint32) (*func_value % no_parts));
+ DBUG_RETURN((uint32) (*func_value % num_parts));
}
@@ -2438,7 +2809,7 @@ static uint32 get_part_id_key(Field **field_array,
part_info A reference to the partition_info struct where all the
desired information is given
field_array Array of fields for PARTTION KEY
- no_parts Number of KEY partitions
+ num_parts Number of KEY partitions
RETURN VALUE
Calculated partition id
@@ -2447,15 +2818,15 @@ static uint32 get_part_id_key(Field **field_array,
inline
static uint32 get_part_id_linear_key(partition_info *part_info,
Field **field_array,
- uint no_parts,
+ uint num_parts,
longlong *func_value)
{
- DBUG_ENTER("get_partition_id_linear_key");
+ DBUG_ENTER("get_part_id_linear_key");
*func_value= calculate_key_value(field_array);
DBUG_RETURN(get_part_id_from_linear_hash(*func_value,
part_info->linear_hash_mask,
- no_parts));
+ num_parts));
}
/*
@@ -2489,7 +2860,8 @@ static void copy_to_part_field_buffers(Field **ptr,
if (!field->maybe_null() || !field->is_null())
{
CHARSET_INFO *cs= ((Field_str*)field)->charset();
- uint len= field->pack_length();
+ uint max_len= field->pack_length();
+ uint data_len= field->data_length();
uchar *field_buf= *field_bufs;
/*
We only use the field buffer for VARCHAR and CHAR strings
@@ -2501,17 +2873,17 @@ static void copy_to_part_field_buffers(Field **ptr,
if (field->type() == MYSQL_TYPE_VARCHAR)
{
uint len_bytes= ((Field_varstring*)field)->length_bytes;
- my_strnxfrm(cs, field_buf + len_bytes, (len - len_bytes),
- field->ptr + len_bytes, field->field_length);
+ my_strnxfrm(cs, field_buf + len_bytes, max_len,
+ field->ptr + len_bytes, data_len);
if (len_bytes == 1)
- *field_buf= (uchar) field->field_length;
+ *field_buf= (uchar) data_len;
else
- int2store(field_buf, field->field_length);
+ int2store(field_buf, data_len);
}
else
{
- my_strnxfrm(cs, field_buf, len,
- field->ptr, field->field_length);
+ my_strnxfrm(cs, field_buf, max_len,
+ field->ptr, max_len);
}
field->ptr= field_buf;
}
@@ -2541,6 +2913,44 @@ static void restore_part_field_pointers(Field **ptr, uchar **restore_ptr)
return;
}
+/*
+ This function is used to calculate the partition id where all partition
+ fields have been prepared to point to a record where the partition field
+ values are bound.
+
+ SYNOPSIS
+ get_partition_id()
+ part_info A reference to the partition_info struct where all the
+ desired information is given
+ out:part_id The partition id is returned through this pointer
+ out:func_value Value of partition function (longlong)
+
+ RETURN VALUE
+ part_id Partition id of partition that would contain
+ row with given values of PF-fields
+ HA_ERR_NO_PARTITION_FOUND The fields of the partition function didn't
+ fit into any partition and thus the values of
+ the PF-fields are not allowed.
+
+ DESCRIPTION
+ A routine used from write_row, update_row and delete_row from any
+ handler supporting partitioning. It is also a support routine for
+ get_partition_set used to find the set of partitions needed to scan
+ for a certain index scan or full table scan.
+
+ It is actually 9 different variants of this function which are called
+ through a function pointer.
+
+ get_partition_id_list
+ get_partition_id_list_col
+ get_partition_id_range
+ get_partition_id_range_col
+ get_partition_id_hash_nosub
+ get_partition_id_key_nosub
+ get_partition_id_linear_hash_nosub
+ get_partition_id_linear_key_nosub
+ get_partition_id_with_sub
+*/
/*
This function is used to calculate the main partition to use in the case of
@@ -2562,67 +2972,26 @@ static void restore_part_field_pointers(Field **ptr, uchar **restore_ptr)
DESCRIPTION
- It is actually 6 different variants of this function which are called
+ It is actually 8 different variants of this function which are called
through a function pointer.
get_partition_id_list
+ get_partition_id_list_col
get_partition_id_range
+ get_partition_id_range_col
get_partition_id_hash_nosub
get_partition_id_key_nosub
get_partition_id_linear_hash_nosub
get_partition_id_linear_key_nosub
*/
-static int get_part_id_charset_func_subpart(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- int res;
- copy_to_part_field_buffers(part_info->subpart_charset_field_array,
- part_info->subpart_field_buffers,
- part_info->restore_subpart_field_ptrs);
- res= part_info->get_partition_id_charset(part_info, part_id, func_value);
- restore_part_field_pointers(part_info->subpart_charset_field_array,
- part_info->restore_subpart_field_ptrs);
- return res;
-}
-
-
static int get_part_id_charset_func_part(partition_info *part_info,
uint32 *part_id,
longlong *func_value)
{
int res;
- copy_to_part_field_buffers(part_info->part_charset_field_array,
- part_info->part_field_buffers,
- part_info->restore_part_field_ptrs);
- res= part_info->get_partition_id_charset(part_info, part_id, func_value);
- restore_part_field_pointers(part_info->part_charset_field_array,
- part_info->restore_part_field_ptrs);
- return res;
-}
-
-
-static int get_part_id_charset_func_all(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- int res;
- copy_to_part_field_buffers(part_info->full_part_field_array,
- part_info->full_part_field_buffers,
- part_info->restore_full_part_field_ptrs);
- res= part_info->get_partition_id_charset(part_info, part_id, func_value);
- restore_part_field_pointers(part_info->full_part_field_array,
- part_info->restore_full_part_field_ptrs);
- return res;
-}
+ DBUG_ENTER("get_part_id_charset_func_part");
-
-static int get_part_part_id_charset_func(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- int res;
copy_to_part_field_buffers(part_info->part_charset_field_array,
part_info->part_field_buffers,
part_info->restore_part_field_ptrs);
@@ -2630,21 +2999,58 @@ static int get_part_part_id_charset_func(partition_info *part_info,
part_id, func_value);
restore_part_field_pointers(part_info->part_charset_field_array,
part_info->restore_part_field_ptrs);
- return res;
+ DBUG_RETURN(res);
}
-static int get_subpart_id_charset_func(partition_info *part_info,
- uint32 *part_id)
+static int get_part_id_charset_func_subpart(partition_info *part_info,
+ uint32 *part_id)
{
int res;
+ DBUG_ENTER("get_part_id_charset_func_subpart");
+
copy_to_part_field_buffers(part_info->subpart_charset_field_array,
part_info->subpart_field_buffers,
part_info->restore_subpart_field_ptrs);
res= part_info->get_subpartition_id_charset(part_info, part_id);
restore_part_field_pointers(part_info->subpart_charset_field_array,
part_info->restore_subpart_field_ptrs);
- return res;
+ DBUG_RETURN(res);
+}
+
+int get_partition_id_list_col(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value)
+{
+ part_column_list_val *list_col_array= part_info->list_col_array;
+ uint num_columns= part_info->part_field_list.elements;
+ int list_index, cmp;
+ int min_list_index= 0;
+ int max_list_index= part_info->num_list_values - 1;
+ DBUG_ENTER("get_partition_id_list_col");
+
+ while (max_list_index >= min_list_index)
+ {
+ list_index= (max_list_index + min_list_index) >> 1;
+ cmp= cmp_rec_and_tuple(list_col_array + list_index*num_columns,
+ num_columns);
+ if (cmp > 0)
+ min_list_index= list_index + 1;
+ else if (cmp < 0)
+ {
+ if (!list_index)
+ goto notfound;
+ max_list_index= list_index - 1;
+ }
+ else
+ {
+ *part_id= (uint32)list_col_array[list_index].partition_id;
+ DBUG_RETURN(0);
+ }
+ }
+notfound:
+ *part_id= 0;
+ DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
}
@@ -2655,7 +3061,7 @@ int get_partition_id_list(partition_info *part_info,
LIST_PART_ENTRY *list_array= part_info->list_array;
int list_index;
int min_list_index= 0;
- int max_list_index= part_info->no_list_values - 1;
+ int max_list_index= part_info->num_list_values - 1;
longlong part_func_value;
int error= part_val_int(part_info->part_expr, &part_func_value);
longlong list_value;
@@ -2725,7 +3131,7 @@ notfound:
index idx.
The function returns first number idx, such that
list_array[idx].list_value is NOT contained within the passed interval.
- If all array elements are contained, part_info->no_list_values is
+ If all array elements are contained, part_info->num_list_values is
returned.
NOTE
@@ -2739,6 +3145,44 @@ notfound:
The edge of corresponding sub-array of part_info->list_array
*/
+uint32 get_partition_id_cols_list_for_endpoint(partition_info *part_info,
+ bool left_endpoint,
+ bool include_endpoint,
+ uint32 nparts)
+{
+ part_column_list_val *list_col_array= part_info->list_col_array;
+ uint num_columns= part_info->part_field_list.elements;
+ int list_index, cmp;
+ uint min_list_index= 0;
+ uint max_list_index= part_info->num_list_values - 1;
+ bool tailf= !(left_endpoint ^ include_endpoint);
+ DBUG_ENTER("get_partition_id_cols_list_for_endpoint");
+
+ do
+ {
+ list_index= (max_list_index + min_list_index) >> 1;
+ cmp= cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
+ nparts, tailf);
+ if (cmp > 0)
+ min_list_index= list_index + 1;
+ else if (cmp < 0)
+ {
+ if (!list_index)
+ goto notfound;
+ max_list_index= list_index - 1;
+ }
+ else
+ {
+ DBUG_RETURN(list_index + test(!tailf));
+ }
+ } while (max_list_index >= min_list_index);
+ if (cmp > 0)
+ list_index++;
+notfound:
+ DBUG_RETURN(list_index);
+}
+
+
uint32 get_list_array_idx_for_endpoint_charset(partition_info *part_info,
bool left_endpoint,
bool include_endpoint)
@@ -2760,7 +3204,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
{
LIST_PART_ENTRY *list_array= part_info->list_array;
uint list_index;
- uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
+ uint min_list_index= 0, max_list_index= part_info->num_list_values - 1;
longlong list_value;
/* Get the partitioning function value for the endpoint */
longlong part_func_value=
@@ -2790,7 +3234,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
if (unsigned_flag)
part_func_value-= 0x8000000000000000ULL;
- DBUG_ASSERT(part_info->no_list_values);
+ DBUG_ASSERT(part_info->num_list_values);
do
{
list_index= (max_list_index + min_list_index) >> 1;
@@ -2815,12 +3259,49 @@ notfound:
}
+int get_partition_id_range_col(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value)
+{
+ part_column_list_val *range_col_array= part_info->range_col_array;
+ uint num_columns= part_info->part_field_list.elements;
+ uint max_partition= part_info->num_parts - 1;
+ uint min_part_id= 0;
+ uint max_part_id= max_partition;
+ uint loc_part_id;
+ DBUG_ENTER("get_partition_id_range_col");
+
+ while (max_part_id > min_part_id)
+ {
+ loc_part_id= (max_part_id + min_part_id + 1) >> 1;
+ if (cmp_rec_and_tuple(range_col_array + loc_part_id*num_columns,
+ num_columns) >= 0)
+ min_part_id= loc_part_id + 1;
+ else
+ max_part_id= loc_part_id - 1;
+ }
+ loc_part_id= max_part_id;
+ if (loc_part_id != max_partition)
+ if (cmp_rec_and_tuple(range_col_array + loc_part_id*num_columns,
+ num_columns) >= 0)
+ loc_part_id++;
+ *part_id= (uint32)loc_part_id;
+ if (loc_part_id == max_partition &&
+ (cmp_rec_and_tuple(range_col_array + loc_part_id*num_columns,
+ num_columns) >= 0))
+ DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
+
+ DBUG_PRINT("exit",("partition: %d", *part_id));
+ DBUG_RETURN(0);
+}
+
+
int get_partition_id_range(partition_info *part_info,
uint32 *part_id,
longlong *func_value)
{
longlong *range_array= part_info->range_int_array;
- uint max_partition= part_info->no_parts - 1;
+ uint max_partition= part_info->num_parts - 1;
uint min_part_id= 0;
uint max_part_id= max_partition;
uint loc_part_id;
@@ -2897,7 +3378,7 @@ int get_partition_id_range(partition_info *part_info,
represented by range_int_array[idx] has EMPTY intersection with the
passed interval.
If the interval represented by the last array element has non-empty
- intersection with the passed interval, part_info->no_parts is
+ intersection with the passed interval, part_info->num_parts is
returned.
RETURN
@@ -2925,7 +3406,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
bool include_endpoint)
{
longlong *range_array= part_info->range_int_array;
- uint max_partition= part_info->no_parts - 1;
+ uint max_partition= part_info->num_parts - 1;
uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
/* Get the partitioning function value for the endpoint */
longlong part_func_value=
@@ -3008,7 +3489,7 @@ int get_partition_id_hash_nosub(partition_info *part_info,
uint32 *part_id,
longlong *func_value)
{
- return get_part_id_hash(part_info->no_parts, part_info->part_expr,
+ return get_part_id_hash(part_info->num_parts, part_info->part_expr,
part_id, func_value);
}
@@ -3017,7 +3498,7 @@ int get_partition_id_linear_hash_nosub(partition_info *part_info,
uint32 *part_id,
longlong *func_value)
{
- return get_part_id_linear_hash(part_info, part_info->no_parts,
+ return get_part_id_linear_hash(part_info, part_info->num_parts,
part_info->part_expr, part_id, func_value);
}
@@ -3027,232 +3508,44 @@ int get_partition_id_key_nosub(partition_info *part_info,
longlong *func_value)
{
*part_id= get_part_id_key(part_info->part_field_array,
- part_info->no_parts, func_value);
+ part_info->num_parts, func_value);
return 0;
}
int get_partition_id_linear_key_nosub(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
+ uint32 *part_id,
+ longlong *func_value)
{
*part_id= get_part_id_linear_key(part_info,
part_info->part_field_array,
- part_info->no_parts, func_value);
+ part_info->num_parts, func_value);
return 0;
}
-int get_partition_id_range_sub_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_range_sub_hash");
- LINT_INIT(loc_part_id);
- LINT_INIT(sub_part_id);
-
- if (unlikely((error= get_partition_id_range(part_info, &loc_part_id,
- func_value))))
- {
- DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- if (unlikely((error= get_part_id_hash(no_subparts, part_info->subpart_expr,
- &sub_part_id, &local_func_value))))
- {
- DBUG_RETURN(error);
- }
-
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_range_sub_linear_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_range_sub_linear_hash");
- LINT_INIT(loc_part_id);
- LINT_INIT(sub_part_id);
-
- if (unlikely((error= get_partition_id_range(part_info, &loc_part_id,
- func_value))))
- {
- DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- if (unlikely((error= get_part_id_linear_hash(part_info, no_subparts,
- part_info->subpart_expr,
- &sub_part_id,
- &local_func_value))))
- {
- DBUG_RETURN(error);
- }
-
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_range_sub_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_range_sub_key");
- LINT_INIT(loc_part_id);
-
- if (unlikely((error= get_partition_id_range(part_info, &loc_part_id,
- func_value))))
- {
- DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- sub_part_id= get_part_id_key(part_info->subpart_field_array,
- no_subparts, &local_func_value);
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_range_sub_linear_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_range_sub_linear_key");
- LINT_INIT(loc_part_id);
-
- if (unlikely((error= get_partition_id_range(part_info, &loc_part_id,
- func_value))))
- {
- DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- sub_part_id= get_part_id_linear_key(part_info,
- part_info->subpart_field_array,
- no_subparts, &local_func_value);
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_list_sub_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_list_sub_hash");
- LINT_INIT(sub_part_id);
-
- if (unlikely((error= get_partition_id_list(part_info, &loc_part_id,
- func_value))))
- {
- DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- if (unlikely((error= get_part_id_hash(no_subparts, part_info->subpart_expr,
- &sub_part_id, &local_func_value))))
- {
- DBUG_RETURN(error);
- }
-
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_list_sub_linear_hash(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_list_sub_linear_hash");
- LINT_INIT(sub_part_id);
-
- if (unlikely((error= get_partition_id_list(part_info, &loc_part_id,
- func_value))))
- {
- DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- if (unlikely((error= get_part_id_linear_hash(part_info, no_subparts,
- part_info->subpart_expr,
- &sub_part_id,
- &local_func_value))))
- {
- DBUG_RETURN(error);
- }
-
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_list_sub_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
+int get_partition_id_with_sub(partition_info *part_info,
+ uint32 *part_id,
+ longlong *func_value)
{
uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
+ uint num_subparts;
int error;
- DBUG_ENTER("get_partition_id_range_sub_key");
+ DBUG_ENTER("get_partition_id_with_sub");
- if (unlikely((error= get_partition_id_list(part_info, &loc_part_id,
- func_value))))
+ if (unlikely((error= part_info->get_part_partition_id(part_info,
+ &loc_part_id,
+ func_value))))
{
DBUG_RETURN(error);
}
- no_subparts= part_info->no_subparts;
- sub_part_id= get_part_id_key(part_info->subpart_field_array,
- no_subparts, &local_func_value);
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
- DBUG_RETURN(0);
-}
-
-
-int get_partition_id_list_sub_linear_key(partition_info *part_info,
- uint32 *part_id,
- longlong *func_value)
-{
- uint32 loc_part_id, sub_part_id;
- uint no_subparts;
- longlong local_func_value;
- int error;
- DBUG_ENTER("get_partition_id_list_sub_linear_key");
-
- if (unlikely((error= get_partition_id_list(part_info, &loc_part_id,
- func_value))))
+ num_subparts= part_info->num_subparts;
+ if (unlikely((error= part_info->get_subpartition_id(part_info,
+ &sub_part_id))))
{
DBUG_RETURN(error);
- }
- no_subparts= part_info->no_subparts;
- sub_part_id= get_part_id_linear_key(part_info,
- part_info->subpart_field_array,
- no_subparts, &local_func_value);
- *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts);
+ }
+ *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, num_subparts);
DBUG_RETURN(0);
}
@@ -3285,7 +3578,7 @@ int get_partition_id_hash_sub(partition_info *part_info,
uint32 *part_id)
{
longlong func_value;
- return get_part_id_hash(part_info->no_subparts, part_info->subpart_expr,
+ return get_part_id_hash(part_info->num_subparts, part_info->subpart_expr,
part_id, &func_value);
}
@@ -3294,7 +3587,7 @@ int get_partition_id_linear_hash_sub(partition_info *part_info,
uint32 *part_id)
{
longlong func_value;
- return get_part_id_linear_hash(part_info, part_info->no_subparts,
+ return get_part_id_linear_hash(part_info, part_info->num_subparts,
part_info->subpart_expr, part_id,
&func_value);
}
@@ -3305,7 +3598,7 @@ int get_partition_id_key_sub(partition_info *part_info,
{
longlong func_value;
*part_id= get_part_id_key(part_info->subpart_field_array,
- part_info->no_subparts, &func_value);
+ part_info->num_subparts, &func_value);
return FALSE;
}
@@ -3316,7 +3609,7 @@ int get_partition_id_linear_key_sub(partition_info *part_info,
longlong func_value;
*part_id= get_part_id_linear_key(part_info,
part_info->subpart_field_array,
- part_info->no_subparts, &func_value);
+ part_info->num_subparts, &func_value);
return FALSE;
}
@@ -3615,16 +3908,16 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
const key_range *key_spec, part_id_range *part_spec)
{
partition_info *part_info= table->part_info;
- uint no_parts= part_info->get_tot_partitions();
+ uint num_parts= part_info->get_tot_partitions();
uint i, part_id;
- uint sub_part= no_parts;
- uint32 part_part= no_parts;
+ uint sub_part= num_parts;
+ uint32 part_part= num_parts;
KEY *key_info= NULL;
bool found_part_field= FALSE;
DBUG_ENTER("get_partition_set");
part_spec->start_part= 0;
- part_spec->end_part= no_parts - 1;
+ part_spec->end_part= num_parts - 1;
if ((index < MAX_KEY) &&
key_spec->flag == (uint)HA_READ_KEY_EXACT &&
part_info->some_fields_in_PF.is_set(index))
@@ -3661,7 +3954,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
{
if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part))
{
- part_spec->start_part= no_parts;
+ part_spec->start_part= num_parts;
DBUG_VOID_RETURN;
}
}
@@ -3675,7 +3968,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
allowed values. Thus it is certain that the result of this
scan will be empty.
*/
- part_spec->start_part= no_parts;
+ part_spec->start_part= num_parts;
DBUG_VOID_RETURN;
}
}
@@ -3713,7 +4006,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
{
if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part))
{
- part_spec->start_part= no_parts;
+ part_spec->start_part= num_parts;
clear_indicator_in_key_fields(key_info);
DBUG_VOID_RETURN;
}
@@ -3722,7 +4015,7 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
{
if (get_part_id_from_key(table,buf,key_info,key_spec,&part_part))
{
- part_spec->start_part= no_parts;
+ part_spec->start_part= num_parts;
clear_indicator_in_key_fields(key_info);
DBUG_VOID_RETURN;
}
@@ -3743,29 +4036,29 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
nothing or we have discovered a range of partitions with possible holes
in it. We need a bitvector to further the work here.
*/
- if (!(part_part == no_parts && sub_part == no_parts))
+ if (!(part_part == num_parts && sub_part == num_parts))
{
/*
We can only arrive here if we are using subpartitioning.
*/
- if (part_part != no_parts)
+ if (part_part != num_parts)
{
/*
We know the top partition and need to scan all underlying
subpartitions. This is a range without holes.
*/
- DBUG_ASSERT(sub_part == no_parts);
- part_spec->start_part= part_part * part_info->no_subparts;
- part_spec->end_part= part_spec->start_part+part_info->no_subparts - 1;
+ DBUG_ASSERT(sub_part == num_parts);
+ part_spec->start_part= part_part * part_info->num_subparts;
+ part_spec->end_part= part_spec->start_part+part_info->num_subparts - 1;
}
else
{
- DBUG_ASSERT(sub_part != no_parts);
+ DBUG_ASSERT(sub_part != num_parts);
part_spec->start_part= sub_part;
part_spec->end_part=sub_part+
- (part_info->no_subparts*(part_info->no_parts-1));
- for (i= 0, part_id= sub_part; i < part_info->no_parts;
- i++, part_id+= part_info->no_subparts)
+ (part_info->num_subparts*(part_info->num_parts-1));
+ for (i= 0, part_id= sub_part; i < part_info->num_parts;
+ i++, part_id+= part_info->num_subparts)
; //Set bit part_id in bit array
}
}
@@ -3849,26 +4142,13 @@ bool mysql_unpack_partition(THD *thd,
LEX lex;
DBUG_ENTER("mysql_unpack_partition");
- thd->lex= &lex;
thd->variables.character_set_client= system_charset_info;
Parser_state parser_state(thd, part_buf, part_info_len);
- lex_start(thd);
- *work_part_info_used= false;
- /*
- We need to use the current SELECT_LEX since I need to keep the
- Name_resolution_context object which is referenced from the
- Item_field objects.
- This is not a nice solution since if the parser uses current_select
- for anything else it will corrupt the current LEX object.
- Also, we need to make sure there even is a select -- if the statement
- was a "USE ...", current_select will be NULL, but we may still end up
- here if we try to log to a partitioned table. This is currently
- unsupported, but should still fail rather than crash!
- */
- if (!(thd->lex->current_select= old_lex->current_select))
+ if (init_lex_with_single_table(thd, table, &lex))
goto end;
+
/*
All Items created is put into a free list on the THD object. This list
is used to free all Item objects after completing a query. We don't
@@ -3878,16 +4158,19 @@ bool mysql_unpack_partition(THD *thd,
Thus we move away the current list temporarily and start a new list that
we then save in the partition info structure.
*/
+ *work_part_info_used= FALSE;
lex.part_info= new partition_info();/* Indicates MYSQLparse from this place */
if (!lex.part_info)
{
mem_alloc_error(sizeof(partition_info));
goto end;
}
- lex.part_info->part_state= part_state;
- lex.part_info->part_state_len= part_state_len;
+ part_info= lex.part_info;
+ part_info->part_state= part_state;
+ part_info->part_state_len= part_state_len;
DBUG_PRINT("info", ("Parse: %s", part_buf));
- if (parse_sql(thd, & parser_state, NULL))
+ if (parse_sql(thd, & parser_state, NULL) ||
+ part_info->fix_parser_data(thd))
{
thd->free_items();
goto end;
@@ -3908,7 +4191,6 @@ bool mysql_unpack_partition(THD *thd,
*/
DBUG_PRINT("info", ("Successful parse"));
- part_info= lex.part_info;
DBUG_PRINT("info", ("default engine = %s, default_db_type = %s",
ha_resolve_storage_engine_name(part_info->default_engine_type),
ha_resolve_storage_engine_name(default_db_type)));
@@ -3990,8 +4272,7 @@ bool mysql_unpack_partition(THD *thd,
result= FALSE;
end:
- lex_end(thd->lex);
- thd->lex= old_lex;
+ end_lex_with_single_table(thd, table, old_lex);
thd->variables.character_set_client= old_character_set_client;
DBUG_RETURN(result);
}
@@ -4029,9 +4310,9 @@ set_engine_all_partitions(partition_info *part_info,
partition_element *sub_elem= sub_it++;
sub_elem->engine_type= engine_type;
- } while (++j < part_info->no_subparts);
+ } while (++j < part_info->num_subparts);
}
- } while (++i < part_info->no_parts);
+ } while (++i < part_info->num_parts);
}
/*
SYNOPSIS
@@ -4081,7 +4362,7 @@ static int fast_end_partition(THD *thd, ulonglong copied,
if ((!is_empty) && (!written_bin_log) &&
(!thd->lex->no_write_to_binlog))
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) (copied + deleted),
@@ -4176,7 +4457,7 @@ uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
enum partition_state part_state)
{
uint part_count= 0;
- uint no_parts_found= 0;
+ uint num_parts_found= 0;
List_iterator<partition_element> part_it(tab_part_info->partitions);
do
@@ -4191,15 +4472,15 @@ uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
I.e mark the partition as a partition to be "changed" by
analyzing/optimizing/rebuilding/checking/repairing/...
*/
- no_parts_found++;
+ num_parts_found++;
part_elem->part_state= part_state;
DBUG_PRINT("info", ("Setting part_state to %u for partition %s",
part_state, part_elem->partition_name));
}
else
part_elem->part_state= PART_NORMAL;
- } while (++part_count < tab_part_info->no_parts);
- return no_parts_found;
+ } while (++part_count < tab_part_info->num_parts);
+ return num_parts_found;
}
@@ -4266,6 +4547,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
partition_info *tab_part_info= table->part_info;
partition_info *alt_part_info= thd->work_part_info;
uint flags= 0;
+ bool is_last_partition_reorged;
+ part_elem_value *tab_max_elem_val= NULL;
+ part_elem_value *alt_max_elem_val= NULL;
+ longlong tab_max_range= 0, alt_max_range= 0;
+
if (!tab_part_info)
{
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
@@ -4275,13 +4561,13 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
{
uint new_part_no, curr_part_no;
if (tab_part_info->part_type != HASH_PARTITION ||
- tab_part_info->use_default_no_partitions)
+ tab_part_info->use_default_num_partitions)
{
my_error(ER_REORG_NO_PARAM_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
new_part_no= table->file->get_default_no_partitions(create_info);
- curr_part_no= tab_part_info->no_parts;
+ curr_part_no= tab_part_info->num_parts;
if (new_part_no == curr_part_no)
{
/*
@@ -4299,7 +4585,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
setting the flag for no default number of partitions
*/
alter_info->flags|= ALTER_ADD_PARTITION;
- thd->work_part_info->no_parts= new_part_no - curr_part_no;
+ thd->work_part_info->num_parts= new_part_no - curr_part_no;
}
else
{
@@ -4308,7 +4594,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
without setting the flag for no default number of partitions
*/
alter_info->flags|= ALTER_COALESCE_PARTITION;
- alter_info->no_parts= curr_part_no - new_part_no;
+ alter_info->num_parts= curr_part_no - new_part_no;
}
}
if (!(flags= table->file->alter_table_flags(alter_info->flags)))
@@ -4320,34 +4606,73 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
((flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE)) != 0);
DBUG_PRINT("info", ("*fast_alter_partition: %d flags: 0x%x",
*fast_alter_partition, flags));
- if (((alter_info->flags & ALTER_ADD_PARTITION) ||
- (alter_info->flags & ALTER_REORGANIZE_PARTITION)) &&
- (thd->work_part_info->part_type != tab_part_info->part_type) &&
- (thd->work_part_info->part_type != NOT_A_PARTITION))
+ if ((alter_info->flags & ALTER_ADD_PARTITION) ||
+ (alter_info->flags & ALTER_REORGANIZE_PARTITION))
{
- if (thd->work_part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- }
- else if (thd->work_part_info->part_type == LIST_PARTITION)
+ if (thd->work_part_info->part_type != tab_part_info->part_type)
{
- DBUG_ASSERT(thd->work_part_info->part_type == LIST_PARTITION);
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN");
+ if (thd->work_part_info->part_type == NOT_A_PARTITION)
+ {
+ if (tab_part_info->part_type == RANGE_PARTITION)
+ {
+ my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), "RANGE");
+ DBUG_RETURN(TRUE);
+ }
+ else if (tab_part_info->part_type == LIST_PARTITION)
+ {
+ my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), "LIST");
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ Hash partitions can be altered without parser finds out about
+ that it is HASH partitioned. So no error here.
+ */
+ }
+ else
+ {
+ if (thd->work_part_info->part_type == RANGE_PARTITION)
+ {
+ my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN");
+ }
+ else if (thd->work_part_info->part_type == LIST_PARTITION)
+ {
+ DBUG_ASSERT(thd->work_part_info->part_type == LIST_PARTITION);
+ my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN");
+ }
+ else if (tab_part_info->part_type == RANGE_PARTITION)
+ {
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN");
+ }
+ else
+ {
+ DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION);
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "LIST", "IN");
+ }
+ DBUG_RETURN(TRUE);
+ }
}
- else if (tab_part_info->part_type == RANGE_PARTITION)
+ if ((tab_part_info->column_list &&
+ alt_part_info->num_columns != tab_part_info->num_columns) ||
+ (!tab_part_info->column_list &&
+ (tab_part_info->part_type == RANGE_PARTITION ||
+ tab_part_info->part_type == LIST_PARTITION) &&
+ alt_part_info->num_columns != 1U) ||
+ (!tab_part_info->column_list &&
+ tab_part_info->part_type == HASH_PARTITION &&
+ alt_part_info->num_columns != 0))
{
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
+ my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
}
- else
+ alt_part_info->column_list= tab_part_info->column_list;
+ if (alt_part_info->fix_parser_data(thd))
{
- DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION);
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(TRUE);
}
if (alter_info->flags & ALTER_ADD_PARTITION)
{
@@ -4357,9 +4682,9 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
partitioning scheme as currently set-up.
Partitions are always added at the end in ADD PARTITION.
*/
- uint no_new_partitions= alt_part_info->no_parts;
- uint no_orig_partitions= tab_part_info->no_parts;
- uint check_total_partitions= no_new_partitions + no_orig_partitions;
+ uint num_new_partitions= alt_part_info->num_parts;
+ uint num_orig_partitions= tab_part_info->num_parts;
+ uint check_total_partitions= num_new_partitions + num_orig_partitions;
uint new_total_partitions= check_total_partitions;
/*
We allow quite a lot of values to be supplied by defaults, however we
@@ -4376,22 +4701,22 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
- if (no_new_partitions == 0)
+ if (num_new_partitions == 0)
{
my_error(ER_ADD_PARTITION_NO_NEW_PARTITION, MYF(0));
DBUG_RETURN(TRUE);
}
if (tab_part_info->is_sub_partitioned())
{
- if (alt_part_info->no_subparts == 0)
- alt_part_info->no_subparts= tab_part_info->no_subparts;
- else if (alt_part_info->no_subparts != tab_part_info->no_subparts)
+ if (alt_part_info->num_subparts == 0)
+ alt_part_info->num_subparts= tab_part_info->num_subparts;
+ else if (alt_part_info->num_subparts != tab_part_info->num_subparts)
{
my_error(ER_ADD_PARTITION_SUBPART_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
check_total_partitions= new_total_partitions*
- alt_part_info->no_subparts;
+ alt_part_info->num_subparts;
}
if (check_total_partitions > MAX_PARTITIONS)
{
@@ -4401,8 +4726,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
alt_part_info->part_type= tab_part_info->part_type;
alt_part_info->subpart_type= tab_part_info->subpart_type;
if (alt_part_info->set_up_defaults_for_partitioning(table->file,
- ULL(0),
- tab_part_info->no_parts))
+ ULL(0),
+ tab_part_info->num_parts))
{
DBUG_RETURN(TRUE);
}
@@ -4477,7 +4802,7 @@ that are reorganised.
uint lower_2n= upper_2n >> 1;
bool all_parts= TRUE;
if (tab_part_info->linear_hash_ind &&
- no_new_partitions < upper_2n)
+ num_new_partitions < upper_2n)
{
/*
An analysis of which parts needs reorganisation shows that it is
@@ -4486,7 +4811,7 @@ that are reorganised.
onwards it starts again from partition 0 and goes on until
it reaches p(upper_2n - 1). If the last new partition reaches
beyond upper_2n - 1 then the first interval will end with
- p(lower_2n - 1) and start with p(no_orig_partitions - lower_2n).
+ p(lower_2n - 1) and start with p(num_orig_partitions - lower_2n).
If lower_2n partitions are added then p0 to p(lower_2n - 1) will
be reorganised which means that the two interval becomes one
interval at this point. Thus only when adding less than
@@ -4514,7 +4839,7 @@ that are reorganised.
to TRUE. In this case we don't get into this if-part at all.
*/
all_parts= FALSE;
- if (no_new_partitions >= lower_2n)
+ if (num_new_partitions >= lower_2n)
{
/*
In this case there is only one interval since the two intervals
@@ -4530,8 +4855,8 @@ that are reorganised.
Also in this case there is only one interval since we are not
going over a 2**n boundary
*/
- start_part= no_orig_partitions - lower_2n;
- end_part= start_part + (no_new_partitions - 1);
+ start_part= num_orig_partitions - lower_2n;
+ end_part= start_part + (num_new_partitions - 1);
}
else
{
@@ -4540,7 +4865,7 @@ that are reorganised.
new parts that would ensure that the intervals become
overlapping.
*/
- start_part= no_orig_partitions - lower_2n;
+ start_part= num_orig_partitions - lower_2n;
end_part= upper_2n - 1;
start_sec_part= 0;
end_sec_part= new_total_partitions - (upper_2n + 1);
@@ -4557,7 +4882,7 @@ that are reorganised.
{
p_elem->part_state= PART_CHANGED;
}
- } while (++part_no < no_orig_partitions);
+ } while (++part_no < num_orig_partitions);
}
/*
Need to concatenate the lists here to make it possible to check the
@@ -4580,8 +4905,8 @@ that are reorganised.
mem_alloc_error(1);
DBUG_RETURN(TRUE);
}
- } while (++part_count < no_new_partitions);
- tab_part_info->no_parts+= no_new_partitions;
+ } while (++part_count < num_new_partitions);
+ tab_part_info->num_parts+= num_new_partitions;
}
/*
If we specify partitions explicitly we don't use defaults anymore.
@@ -4596,7 +4921,7 @@ that are reorganised.
DBUG_PRINT("info", ("part_info: 0x%lx", (long) tab_part_info));
tab_part_info->use_default_partitions= FALSE;
}
- tab_part_info->use_default_no_partitions= FALSE;
+ tab_part_info->use_default_num_partitions= FALSE;
tab_part_info->is_auto_partitioned= FALSE;
}
}
@@ -4610,8 +4935,8 @@ that are reorganised.
command to drop the partition failed in the middle.
*/
uint part_count= 0;
- uint no_parts_dropped= alter_info->partition_names.elements;
- uint no_parts_found= 0;
+ uint num_parts_dropped= alter_info->partition_names.elements;
+ uint num_parts_found= 0;
List_iterator<partition_element> part_it(tab_part_info->partitions);
tab_part_info->is_auto_partitioned= FALSE;
@@ -4621,7 +4946,7 @@ that are reorganised.
my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP");
DBUG_RETURN(TRUE);
}
- if (no_parts_dropped >= tab_part_info->no_parts)
+ if (num_parts_dropped >= tab_part_info->num_parts)
{
my_error(ER_DROP_LAST_PARTITION, MYF(0));
DBUG_RETURN(TRUE);
@@ -4635,11 +4960,11 @@ that are reorganised.
/*
Set state to indicate that the partition is to be dropped.
*/
- no_parts_found++;
+ num_parts_found++;
part_elem->part_state= PART_TO_BE_DROPPED;
}
- } while (++part_count < tab_part_info->no_parts);
- if (no_parts_found != no_parts_dropped)
+ } while (++part_count < tab_part_info->num_parts);
+ if (num_parts_found != num_parts_dropped)
{
my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "DROP");
DBUG_RETURN(TRUE);
@@ -4649,14 +4974,14 @@ that are reorganised.
my_error(ER_ROW_IS_REFERENCED, MYF(0));
DBUG_RETURN(TRUE);
}
- tab_part_info->no_parts-= no_parts_dropped;
+ tab_part_info->num_parts-= num_parts_dropped;
}
else if (alter_info->flags & ALTER_REBUILD_PARTITION)
{
- uint no_parts_found;
- uint no_parts_opt= alter_info->partition_names.elements;
- no_parts_found= set_part_state(alter_info, tab_part_info, PART_CHANGED);
- if (no_parts_found != no_parts_opt &&
+ uint num_parts_found;
+ uint num_parts_opt= alter_info->partition_names.elements;
+ num_parts_found= set_part_state(alter_info, tab_part_info, PART_CHANGED);
+ if (num_parts_found != num_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REBUILD");
@@ -4670,20 +4995,20 @@ that are reorganised.
}
else if (alter_info->flags & ALTER_COALESCE_PARTITION)
{
- uint no_parts_coalesced= alter_info->no_parts;
- uint no_parts_remain= tab_part_info->no_parts - no_parts_coalesced;
+ uint num_parts_coalesced= alter_info->num_parts;
+ uint num_parts_remain= tab_part_info->num_parts - num_parts_coalesced;
List_iterator<partition_element> part_it(tab_part_info->partitions);
if (tab_part_info->part_type != HASH_PARTITION)
{
my_error(ER_COALESCE_ONLY_ON_HASH_PARTITION, MYF(0));
DBUG_RETURN(TRUE);
}
- if (no_parts_coalesced == 0)
+ if (num_parts_coalesced == 0)
{
my_error(ER_COALESCE_PARTITION_NO_PARTITION, MYF(0));
DBUG_RETURN(TRUE);
}
- if (no_parts_coalesced >= tab_part_info->no_parts)
+ if (num_parts_coalesced >= tab_part_info->num_parts)
{
my_error(ER_DROP_LAST_PARTITION, MYF(0));
DBUG_RETURN(TRUE);
@@ -4731,21 +5056,21 @@ state of p1.
uint upper_2n= tab_part_info->linear_hash_mask + 1;
uint lower_2n= upper_2n >> 1;
all_parts= FALSE;
- if (no_parts_coalesced >= lower_2n)
+ if (num_parts_coalesced >= lower_2n)
{
all_parts= TRUE;
}
- else if (no_parts_remain >= lower_2n)
+ else if (num_parts_remain >= lower_2n)
{
- end_part= tab_part_info->no_parts - (lower_2n + 1);
- start_part= no_parts_remain - lower_2n;
+ end_part= tab_part_info->num_parts - (lower_2n + 1);
+ start_part= num_parts_remain - lower_2n;
}
else
{
start_part= 0;
- end_part= tab_part_info->no_parts - (lower_2n + 1);
+ end_part= tab_part_info->num_parts - (lower_2n + 1);
end_sec_part= (lower_2n >> 1) - 1;
- start_sec_part= end_sec_part - (lower_2n - (no_parts_remain + 1));
+ start_sec_part= end_sec_part - (lower_2n - (num_parts_remain + 1));
}
}
do
@@ -4756,19 +5081,19 @@ state of p1.
(part_count >= start_part && part_count <= end_part) ||
(part_count >= start_sec_part && part_count <= end_sec_part)))
p_elem->part_state= PART_CHANGED;
- if (++part_count > no_parts_remain)
+ if (++part_count > num_parts_remain)
{
if (*fast_alter_partition)
p_elem->part_state= PART_REORGED_DROPPED;
else
part_it.remove();
}
- } while (part_count < tab_part_info->no_parts);
- tab_part_info->no_parts= no_parts_remain;
+ } while (part_count < tab_part_info->num_parts);
+ tab_part_info->num_parts= num_parts_remain;
}
if (!(alter_info->flags & ALTER_TABLE_REORG))
{
- tab_part_info->use_default_no_partitions= FALSE;
+ tab_part_info->use_default_num_partitions= FALSE;
tab_part_info->is_auto_partitioned= FALSE;
}
}
@@ -4785,33 +5110,32 @@ state of p1.
range as those changed from.
This command can be used on RANGE and LIST partitions.
*/
- uint no_parts_reorged= alter_info->partition_names.elements;
- uint no_parts_new= thd->work_part_info->partitions.elements;
- partition_info *alt_part_info= thd->work_part_info;
+ uint num_parts_reorged= alter_info->partition_names.elements;
+ uint num_parts_new= thd->work_part_info->partitions.elements;
uint check_total_partitions;
tab_part_info->is_auto_partitioned= FALSE;
- if (no_parts_reorged > tab_part_info->no_parts)
+ if (num_parts_reorged > tab_part_info->num_parts)
{
my_error(ER_REORG_PARTITION_NOT_EXIST, MYF(0));
DBUG_RETURN(TRUE);
}
if (!(tab_part_info->part_type == RANGE_PARTITION ||
tab_part_info->part_type == LIST_PARTITION) &&
- (no_parts_new != no_parts_reorged))
+ (num_parts_new != num_parts_reorged))
{
my_error(ER_REORG_HASH_ONLY_ON_SAME_NO, MYF(0));
DBUG_RETURN(TRUE);
}
if (tab_part_info->is_sub_partitioned() &&
- alt_part_info->no_subparts &&
- alt_part_info->no_subparts != tab_part_info->no_subparts)
+ alt_part_info->num_subparts &&
+ alt_part_info->num_subparts != tab_part_info->num_subparts)
{
my_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
- check_total_partitions= tab_part_info->no_parts + no_parts_new;
- check_total_partitions-= no_parts_reorged;
+ check_total_partitions= tab_part_info->num_parts + num_parts_new;
+ check_total_partitions-= num_parts_reorged;
if (check_total_partitions > MAX_PARTITIONS)
{
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
@@ -4819,7 +5143,7 @@ state of p1.
}
alt_part_info->part_type= tab_part_info->part_type;
alt_part_info->subpart_type= tab_part_info->subpart_type;
- alt_part_info->no_subparts= tab_part_info->no_subparts;
+ alt_part_info->num_subparts= tab_part_info->num_subparts;
DBUG_ASSERT(!alt_part_info->use_default_partitions);
if (alt_part_info->set_up_defaults_for_partitioning(table->file,
ULL(0),
@@ -4867,9 +5191,7 @@ the generated partition syntax in a correct manner.
uint part_count= 0;
bool found_first= FALSE;
bool found_last= FALSE;
- bool is_last_partition_reorged;
uint drop_count= 0;
- longlong tab_max_range= 0, alt_max_range= 0;
do
{
partition_element *part_elem= tab_it++;
@@ -4879,7 +5201,13 @@ the generated partition syntax in a correct manner.
{
is_last_partition_reorged= TRUE;
drop_count++;
- tab_max_range= part_elem->range_value;
+ if (tab_part_info->column_list)
+ {
+ List_iterator<part_elem_value> p(part_elem->list_val_list);
+ tab_max_elem_val= p++;
+ }
+ else
+ tab_max_range= part_elem->range_value;
if (*fast_alter_partition &&
tab_part_info->temp_partitions.push_back(part_elem))
{
@@ -4891,20 +5219,28 @@ the generated partition syntax in a correct manner.
if (!found_first)
{
uint alt_part_count= 0;
- found_first= TRUE;
+ partition_element *alt_part_elem;
List_iterator<partition_element>
alt_it(alt_part_info->partitions);
+ found_first= TRUE;
do
{
- partition_element *alt_part_elem= alt_it++;
- alt_max_range= alt_part_elem->range_value;
+ alt_part_elem= alt_it++;
+ if (tab_part_info->column_list)
+ {
+ List_iterator<part_elem_value> p(alt_part_elem->list_val_list);
+ alt_max_elem_val= p++;
+ }
+ else
+ alt_max_range= alt_part_elem->range_value;
+
if (*fast_alter_partition)
alt_part_elem->part_state= PART_TO_BE_ADDED;
if (alt_part_count == 0)
tab_it.replace(alt_part_elem);
else
tab_it.after(alt_part_elem);
- } while (++alt_part_count < no_parts_new);
+ } while (++alt_part_count < num_parts_new);
}
else if (found_last)
{
@@ -4919,32 +5255,13 @@ the generated partition syntax in a correct manner.
if (found_first)
found_last= TRUE;
}
- } while (++part_count < tab_part_info->no_parts);
- if (drop_count != no_parts_reorged)
+ } while (++part_count < tab_part_info->num_parts);
+ if (drop_count != num_parts_reorged)
{
my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REORGANIZE");
DBUG_RETURN(TRUE);
}
- if (tab_part_info->part_type == RANGE_PARTITION &&
- ((is_last_partition_reorged &&
- alt_max_range < tab_max_range) ||
- (!is_last_partition_reorged &&
- alt_max_range != tab_max_range)))
- {
- /*
- For range partitioning the total resulting range before and
- after the change must be the same except in one case. This is
- when the last partition is reorganised, in this case it is
- acceptable to increase the total range.
- The reason is that it is not allowed to have "holes" in the
- middle of the ranges and thus we should not allow to reorganise
- to create "holes". Also we should not allow using REORGANIZE
- to drop data.
- */
- my_error(ER_REORG_OUTSIDE_RANGE, MYF(0));
- DBUG_RETURN(TRUE);
- }
- tab_part_info->no_parts= check_total_partitions;
+ tab_part_info->num_parts= check_total_partitions;
}
}
else
@@ -4960,13 +5277,45 @@ the generated partition syntax in a correct manner.
!alt_part_info->use_default_subpartitions)
{
tab_part_info->use_default_subpartitions= FALSE;
- tab_part_info->use_default_no_subpartitions= FALSE;
+ tab_part_info->use_default_num_subpartitions= FALSE;
}
if (tab_part_info->check_partition_info(thd, (handlerton**)NULL,
- table->file, ULL(0), FALSE))
+ table->file, ULL(0), TRUE))
{
DBUG_RETURN(TRUE);
}
+ /*
+ The check below needs to be performed after check_partition_info
+ since this function "fixes" the item trees of the new partitions
+ to reorganize into
+ */
+ if (alter_info->flags == ALTER_REORGANIZE_PARTITION &&
+ tab_part_info->part_type == RANGE_PARTITION &&
+ ((is_last_partition_reorged &&
+ (tab_part_info->column_list ?
+ (tab_part_info->compare_column_values(
+ alt_max_elem_val->col_val_array,
+ tab_max_elem_val->col_val_array) < 0) :
+ alt_max_range < tab_max_range)) ||
+ (!is_last_partition_reorged &&
+ (tab_part_info->column_list ?
+ (tab_part_info->compare_column_values(
+ alt_max_elem_val->col_val_array,
+ tab_max_elem_val->col_val_array) != 0) :
+ alt_max_range != tab_max_range))))
+ {
+ /*
+ For range partitioning the total resulting range before and
+ after the change must be the same except in one case. This is
+ when the last partition is reorganised, in this case it is
+ acceptable to increase the total range.
+ The reason is that it is not allowed to have "holes" in the
+ middle of the ranges and thus we should not allow to reorganise
+ to create "holes".
+ */
+ my_error(ER_REORG_OUTSIDE_RANGE, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
}
}
else
@@ -5080,6 +5429,10 @@ the generated partition syntax in a correct manner.
{
DBUG_PRINT("info", ("partition changed"));
*partition_changed= TRUE;
+ if (thd->work_part_info->fix_parser_data(thd))
+ {
+ DBUG_RETURN(TRUE);
+ }
}
/*
Set up partition default_engine_type either from the create_info
@@ -5240,8 +5593,8 @@ static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
part_it.remove();
remove_count++;
}
- } while (++i < part_info->no_parts);
- part_info->no_parts-= remove_count;
+ } while (++i < part_info->num_parts);
+ part_info->num_parts-= remove_count;
DBUG_RETURN(FALSE);
}
@@ -5363,7 +5716,7 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
char normal_path[FN_REFLEN];
List_iterator<partition_element> part_it(part_info->partitions);
uint temp_partitions= part_info->temp_partitions.elements;
- uint no_elements= part_info->partitions.elements;
+ uint num_elements= part_info->partitions.elements;
uint i= 0;
DBUG_ENTER("write_log_changed_partitions");
@@ -5376,7 +5729,7 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
if (part_info->is_sub_partitioned())
{
List_iterator<partition_element> sub_it(part_elem->subpartitions);
- uint no_subparts= part_info->no_subparts;
+ uint num_subparts= part_info->num_subparts;
uint j= 0;
do
{
@@ -5405,7 +5758,7 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
*next_entry= log_entry->entry_pos;
sub_elem->log_entry= log_entry;
insert_part_info_log_entry_list(part_info, log_entry);
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -5433,7 +5786,7 @@ static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
insert_part_info_log_entry_list(part_info, log_entry);
}
}
- } while (++i < no_elements);
+ } while (++i < num_elements);
DBUG_RETURN(FALSE);
}
@@ -5459,14 +5812,14 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
char tmp_path[FN_LEN];
List_iterator<partition_element> part_it(part_info->partitions);
List_iterator<partition_element> temp_it(part_info->temp_partitions);
- uint no_temp_partitions= part_info->temp_partitions.elements;
- uint no_elements= part_info->partitions.elements;
+ uint num_temp_partitions= part_info->temp_partitions.elements;
+ uint num_elements= part_info->partitions.elements;
DBUG_ENTER("write_log_dropped_partitions");
ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
if (temp_list)
- no_elements= no_temp_partitions;
- while (no_elements--)
+ num_elements= num_temp_partitions;
+ while (num_elements--)
{
partition_element *part_elem;
if (temp_list)
@@ -5480,14 +5833,14 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
uint name_variant;
if (part_elem->part_state == PART_CHANGED ||
(part_elem->part_state == PART_TO_BE_ADDED &&
- no_temp_partitions))
+ num_temp_partitions))
name_variant= TEMP_PART_NAME;
else
name_variant= NORMAL_PART_NAME;
if (part_info->is_sub_partitioned())
{
List_iterator<partition_element> sub_it(part_elem->subpartitions);
- uint no_subparts= part_info->no_subparts;
+ uint num_subparts= part_info->num_subparts;
uint j= 0;
do
{
@@ -5507,7 +5860,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
*next_entry= log_entry->entry_pos;
sub_elem->log_entry= log_entry;
insert_part_info_log_entry_list(part_info, log_entry);
- } while (++j < no_subparts);
+ } while (++j < num_subparts);
}
else
{
@@ -6241,7 +6594,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT_CRASH("crash_drop_partition_5") ||
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
- thd->query, thd->query_length), FALSE)) ||
+ thd->query(), thd->query_length()), FALSE)) ||
ERROR_INJECT_CRASH("crash_drop_partition_6") ||
((frm_install= TRUE), FALSE) ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
@@ -6308,7 +6661,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT_CRASH("crash_add_partition_5") ||
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
- thd->query, thd->query_length), FALSE)) ||
+ thd->query(), thd->query_length()), FALSE)) ||
ERROR_INJECT_CRASH("crash_add_partition_6") ||
write_log_rename_frm(lpt) ||
(not_completed= FALSE) ||
@@ -6398,7 +6751,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
ERROR_INJECT_CRASH("crash_change_partition_6") ||
((!thd->lex->no_write_to_binlog) &&
(write_bin_log(thd, FALSE,
- thd->query, thd->query_length), FALSE)) ||
+ thd->query(), thd->query_length()), FALSE)) ||
ERROR_INJECT_CRASH("crash_change_partition_7") ||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
ERROR_INJECT_CRASH("crash_change_partition_8") ||
@@ -6605,16 +6958,19 @@ void make_used_partitions_str(partition_info *part_info, String *parts_str)
IMPLEMENTATION
There are two available interval analyzer functions:
(1) get_part_iter_for_interval_via_mapping
- (2) get_part_iter_for_interval_via_walking
+ (2) get_part_iter_for_interval_cols_via_map
+ (3) get_part_iter_for_interval_via_walking
They both have limited applicability:
(1) is applicable for "PARTITION BY <RANGE|LIST>(func(t.field))", where
func is a monotonic function.
-
- (2) is applicable for
+
+ (2) is applicable for "PARTITION BY <RANGE|LIST> COLUMNS (field_list)
+
+ (3) is applicable for
"[SUB]PARTITION BY <any-partitioning-type>(any_func(t.integer_field))"
- If both are applicable, (1) is preferred over (2).
+ If both (1) and (3) are applicable, (1) is preferred over (3).
This function sets part_info::get_part_iter_for_interval according to
this criteria, and also sets some auxilary fields that the function
@@ -6634,10 +6990,19 @@ static void set_up_range_analysis_info(partition_info *part_info)
switch (part_info->part_type) {
case RANGE_PARTITION:
case LIST_PARTITION:
- if (part_info->part_expr->get_monotonicity_info() != NON_MONOTONIC)
+ if (!part_info->column_list)
+ {
+ if (part_info->part_expr->get_monotonicity_info() != NON_MONOTONIC)
+ {
+ part_info->get_part_iter_for_interval=
+ get_part_iter_for_interval_via_mapping;
+ goto setup_subparts;
+ }
+ }
+ else
{
part_info->get_part_iter_for_interval=
- get_part_iter_for_interval_via_mapping;
+ get_part_iter_for_interval_cols_via_map;
goto setup_subparts;
}
default:
@@ -6648,7 +7013,7 @@ static void set_up_range_analysis_info(partition_info *part_info)
Check if get_part_iter_for_interval_via_walking() can be used for
partitioning
*/
- if (part_info->no_part_fields == 1)
+ if (part_info->num_part_fields == 1)
{
Field *field= part_info->part_field_array[0];
switch (field->type()) {
@@ -6670,7 +7035,7 @@ setup_subparts:
Check if get_part_iter_for_interval_via_walking() can be used for
subpartitioning
*/
- if (part_info->no_subpart_fields == 1)
+ if (part_info->num_subpart_fields == 1)
{
Field *field= part_info->subpart_field_array[0];
switch (field->type()) {
@@ -6688,9 +7053,118 @@ setup_subparts:
}
+/*
+ This function takes a memory of packed fields in opt-range format
+ and stores it in record format. To avoid having to worry about how
+ the length of fields are calculated in opt-range format we send
+ an array of lengths used for each field in store_length_array.
+
+ SYNOPSIS
+ store_tuple_to_record()
+ pfield Field array
+ store_length_array Array of field lengths
+ value Memory where fields are stored
+ value_end End of memory
+
+ RETURN VALUE
+ nparts Number of fields assigned
+*/
+uint32 store_tuple_to_record(Field **pfield,
+ uint32 *store_length_array,
+ uchar *value,
+ uchar *value_end)
+{
+ /* This function is inspired by store_key_image_rec. */
+ uint32 nparts= 0;
+ uchar *loc_value;
+ while (value < value_end)
+ {
+ loc_value= value;
+ if ((*pfield)->real_maybe_null())
+ {
+ if (*loc_value)
+ (*pfield)->set_null();
+ else
+ (*pfield)->set_notnull();
+ loc_value++;
+ }
+ uint len= (*pfield)->pack_length();
+ (*pfield)->set_key_image(loc_value, len);
+ value+= *store_length_array;
+ store_length_array++;
+ nparts++;
+ pfield++;
+ }
+ return nparts;
+}
+
+/*
+ RANGE(columns) partitioning: compare value bound and probe tuple.
+
+ The value bound always is a full tuple (but may include the MAXVALUE
+ special value).
+
+ The probe tuple may be a prefix of partitioning tuple. The tail_is_min
+ parameter specifies whether the suffix components should be assumed to
+ hold MAXVALUE
+*/
+
+static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec)
+{
+ partition_info *part_info= val->part_info;
+ Field **field= part_info->part_field_array;
+ Field **fields_end= field + nvals_in_rec;
+ int res;
+
+ for (; field != fields_end; field++, val++)
+ {
+ if (val->max_value)
+ return -1;
+ if ((*field)->is_null())
+ {
+ if (val->null_value)
+ continue;
+ return -1;
+ }
+ if (val->null_value)
+ return +1;
+ res= (*field)->cmp((const uchar*)val->column_value);
+ if (res)
+ return res;
+ }
+ return 0;
+}
+
+
+static int cmp_rec_and_tuple_prune(part_column_list_val *val,
+ uint32 n_vals_in_rec,
+ bool tail_is_min)
+{
+ int cmp;
+ Field **field;
+ partition_info *part_info;
+ if ((cmp= cmp_rec_and_tuple(val, n_vals_in_rec)))
+ return cmp;
+ part_info= val->part_info;
+ field= part_info->part_field_array + n_vals_in_rec;
+ for (; *field; field++, val++)
+ {
+ if (tail_is_min)
+ return -1;
+ if (!tail_is_min && !val->max_value)
+ return +1;
+ }
+ return 0;
+}
+
+
typedef uint32 (*get_endpoint_func)(partition_info*, bool left_endpoint,
bool include_endpoint);
+typedef uint32 (*get_col_endpoint_func)(partition_info*, bool left_endpoint,
+ bool include_endpoint,
+ uint32 num_parts);
+
/*
Partitioning Interval Analysis: Initialize the iterator for "mapping" case
@@ -6726,18 +7200,145 @@ typedef uint32 (*get_endpoint_func)(partition_info*, bool left_endpoint,
-1 - All partitions would match (iterator not initialized)
*/
+uint32 get_partition_id_cols_range_for_endpoint(partition_info *part_info,
+ bool left_endpoint,
+ bool include_endpoint,
+ uint32 nparts)
+{
+ uint max_partition= part_info->num_parts - 1;
+ uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
+ part_column_list_val *range_col_array= part_info->range_col_array;
+ uint num_columns= part_info->part_field_list.elements;
+ bool tailf= !(left_endpoint ^ include_endpoint);
+ DBUG_ENTER("get_partition_id_cols_range_for_endpoint");
+
+ /* Get the partitioning function value for the endpoint */
+ while (max_part_id > min_part_id)
+ {
+ loc_part_id= (max_part_id + min_part_id + 1) >> 1;
+ if (cmp_rec_and_tuple_prune(range_col_array + loc_part_id*num_columns,
+ nparts, tailf) >= 0)
+ min_part_id= loc_part_id + 1;
+ else
+ max_part_id= loc_part_id - 1;
+ }
+ loc_part_id= max_part_id;
+ if (loc_part_id < max_partition &&
+ cmp_rec_and_tuple_prune(range_col_array + (loc_part_id+1)*num_columns,
+ nparts, tailf) >= 0
+ )
+ {
+ loc_part_id++;
+ }
+ if (left_endpoint)
+ {
+ if (cmp_rec_and_tuple_prune(range_col_array + loc_part_id*num_columns,
+ nparts, tailf) >= 0)
+ loc_part_id++;
+ }
+ else
+ {
+ if (loc_part_id < max_partition)
+ {
+ int res= cmp_rec_and_tuple_prune(range_col_array +
+ loc_part_id * num_columns,
+ nparts, tailf);
+ if (!res)
+ loc_part_id += test(include_endpoint);
+ else if (res > 0)
+ loc_part_id++;
+ }
+ loc_part_id++;
+ }
+ DBUG_RETURN(loc_part_id);
+}
+
+
+int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
+ bool is_subpart,
+ uint32 *store_length_array,
+ uchar *min_value, uchar *max_value,
+ uint min_len, uint max_len,
+ uint flags,
+ PARTITION_ITERATOR *part_iter)
+{
+ uint32 nparts;
+ get_col_endpoint_func get_col_endpoint;
+ DBUG_ENTER("get_part_iter_for_interval_cols_via_map");
+
+ if (part_info->part_type == RANGE_PARTITION)
+ {
+ get_col_endpoint= get_partition_id_cols_range_for_endpoint;
+ part_iter->get_next= get_next_partition_id_range;
+ }
+ else if (part_info->part_type == LIST_PARTITION)
+ {
+ get_col_endpoint= get_partition_id_cols_list_for_endpoint;
+ part_iter->get_next= get_next_partition_id_list;
+ part_iter->part_info= part_info;
+ DBUG_ASSERT(part_info->num_list_values);
+ }
+ else
+ assert(0);
+
+ if (flags & NO_MIN_RANGE)
+ part_iter->part_nums.start= part_iter->part_nums.cur= 0;
+ else
+ {
+ // Copy from min_value to record
+ nparts= store_tuple_to_record(part_info->part_field_array,
+ store_length_array,
+ min_value,
+ min_value + min_len);
+ part_iter->part_nums.start= part_iter->part_nums.cur=
+ get_col_endpoint(part_info, TRUE, !(flags & NEAR_MIN),
+ nparts);
+ }
+ if (flags & NO_MAX_RANGE)
+ {
+ if (part_info->part_type == RANGE_PARTITION)
+ part_iter->part_nums.end= part_info->num_parts;
+ else /* LIST_PARTITION */
+ {
+ DBUG_ASSERT(part_info->part_type == LIST_PARTITION);
+ part_iter->part_nums.end= part_info->num_list_values;
+ }
+ }
+ else
+ {
+ // Copy from max_value to record
+ nparts= store_tuple_to_record(part_info->part_field_array,
+ store_length_array,
+ max_value,
+ max_value + max_len);
+ part_iter->part_nums.end= get_col_endpoint(part_info, FALSE,
+ !(flags & NEAR_MAX),
+ nparts);
+ }
+ if (part_iter->part_nums.start == part_iter->part_nums.end)
+ DBUG_RETURN(0);
+ DBUG_RETURN(1);
+}
+
+
int get_part_iter_for_interval_via_mapping(partition_info *part_info,
bool is_subpart,
+ uint32 *store_length_array, /* ignored */
uchar *min_value, uchar *max_value,
+ uint min_len, uint max_len, /* ignored */
uint flags,
PARTITION_ITERATOR *part_iter)
{
- DBUG_ASSERT(!is_subpart);
Field *field= part_info->part_field_array[0];
uint32 max_endpoint_val;
get_endpoint_func get_endpoint;
bool can_match_multiple_values; /* is not '=' */
uint field_len= field->pack_length_in_rec();
+ DBUG_ENTER("get_part_iter_for_interval_via_mapping");
+ DBUG_ASSERT(!is_subpart);
+ (void) store_length_array;
+ (void)min_len;
+ (void)max_len;
part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
if (part_info->part_type == RANGE_PARTITION)
@@ -6746,7 +7347,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
get_endpoint= get_partition_id_range_for_endpoint_charset;
else
get_endpoint= get_partition_id_range_for_endpoint;
- max_endpoint_val= part_info->no_parts;
+ max_endpoint_val= part_info->num_parts;
part_iter->get_next= get_next_partition_id_range;
}
else if (part_info->part_type == LIST_PARTITION)
@@ -6756,7 +7357,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
get_endpoint= get_list_array_idx_for_endpoint_charset;
else
get_endpoint= get_list_array_idx_for_endpoint;
- max_endpoint_val= part_info->no_list_values;
+ max_endpoint_val= part_info->num_list_values;
part_iter->get_next= get_next_partition_id_list;
part_iter->part_info= part_info;
if (max_endpoint_val == 0)
@@ -6769,7 +7370,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
part_iter->part_nums.start= part_iter->part_nums.end= 0;
part_iter->part_nums.cur= 0;
part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
- return -1;
+ DBUG_RETURN(-1);
}
}
else
@@ -6801,11 +7402,11 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
{
part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
part_iter->part_nums.start= part_iter->part_nums.cur= 0;
- if (*max_value && !(flags & NO_MAX_RANGE))
+ if (!(flags & NO_MAX_RANGE) && *max_value)
{
/* The right bound is X <= NULL, i.e. it is a "X IS NULL" interval */
part_iter->part_nums.end= 0;
- return 1;
+ DBUG_RETURN(1);
}
}
else
@@ -6829,11 +7430,11 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
part_iter->part_nums.cur= part_iter->part_nums.start= 0;
part_iter->part_nums.end= 0;
part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
- return 1;
+ DBUG_RETURN(1);
}
part_iter->part_nums.cur= part_iter->part_nums.start;
if (part_iter->part_nums.start == max_endpoint_val)
- return 0; /* No partitions */
+ DBUG_RETURN(0); /* No partitions */
}
}
@@ -6847,9 +7448,9 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
part_iter->part_nums.end= get_endpoint(part_info, 0, include_endp);
if (part_iter->part_nums.start >= part_iter->part_nums.end &&
!part_iter->ret_null_part)
- return 0; /* No partitions */
+ DBUG_RETURN(0); /* No partitions */
}
- return 1; /* Ok, iterator initialized */
+ DBUG_RETURN(1); /* Ok, iterator initialized */
}
@@ -6897,25 +7498,32 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
*/
int get_part_iter_for_interval_via_walking(partition_info *part_info,
- bool is_subpart,
- uchar *min_value, uchar *max_value,
- uint flags,
- PARTITION_ITERATOR *part_iter)
+ bool is_subpart,
+ uint32 *store_length_array, /* ignored */
+ uchar *min_value, uchar *max_value,
+ uint min_len, uint max_len, /* ignored */
+ uint flags,
+ PARTITION_ITERATOR *part_iter)
{
Field *field;
uint total_parts;
partition_iter_func get_next_func;
+ DBUG_ENTER("get_part_iter_for_interval_via_walking");
+ (void)store_length_array;
+ (void)min_len;
+ (void)max_len;
+
part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
if (is_subpart)
{
field= part_info->subpart_field_array[0];
- total_parts= part_info->no_subparts;
+ total_parts= part_info->num_subparts;
get_next_func= get_next_subpartition_via_walking;
}
else
{
field= part_info->part_field_array[0];
- total_parts= part_info->no_parts;
+ total_parts= part_info->num_parts;
get_next_func= get_next_partition_via_walking;
}
@@ -6935,7 +7543,7 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
if (!part_info->get_subpartition_id(part_info, &part_id))
{
init_single_partition_iterator(part_id, part_iter);
- return 1; /* Ok, iterator initialized */
+ DBUG_RETURN(1); /* Ok, iterator initialized */
}
}
else
@@ -6948,10 +7556,10 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
if (!res)
{
init_single_partition_iterator(part_id, part_iter);
- return 1; /* Ok, iterator initialized */
+ DBUG_RETURN(1); /* Ok, iterator initialized */
}
}
- return 0; /* No partitions match */
+ DBUG_RETURN(0); /* No partitions match */
}
if ((field->real_maybe_null() &&
@@ -6959,7 +7567,7 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
(!(flags & NO_MAX_RANGE) && *max_value))) || // X <? NULL
(flags & (NO_MIN_RANGE | NO_MAX_RANGE))) // -inf at any bound
{
- return -1; /* Can't handle this interval, have to use all partitions */
+ DBUG_RETURN(-1); /* Can't handle this interval, have to use all partitions */
}
/* Get integers for left and right interval bound */
@@ -6978,7 +7586,7 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
an empty interval by "wrapping around" a + 4G-1 + 1 = a.
*/
if ((ulonglong)b - (ulonglong)a == ~0ULL)
- return -1;
+ DBUG_RETURN(-1);
a += test(flags & NEAR_MIN);
b += test(!(flags & NEAR_MAX));
@@ -7001,13 +7609,13 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
- there are not many values to enumerate.
*/
if ((n_values > 2*total_parts) && n_values > MAX_RANGE_TO_WALK)
- return -1;
+ DBUG_RETURN(-1);
part_iter->field_vals.start= part_iter->field_vals.cur= a;
part_iter->field_vals.end= b;
part_iter->part_info= part_info;
part_iter->get_next= get_next_func;
- return 1;
+ DBUG_RETURN(1);
}
@@ -7055,8 +7663,9 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
DESCRIPTION
This implementation of PARTITION_ITERATOR::get_next() is special for
- LIST partitioning: it enumerates partition ids in
- part_info->list_array[i] where i runs over [min_idx, max_idx] interval.
+ LIST partitioning: it enumerates partition ids in
+ part_info->list_array[i] (list_col_array[i] for COLUMNS LIST
+ partitioning) where i runs over [min_idx, max_idx] interval.
The function conforms to partition_iter_func type.
RETURN
@@ -7078,8 +7687,13 @@ uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter)
return NOT_A_PARTITION_ID;
}
else
- return part_iter->part_info->list_array[part_iter->
- part_nums.cur++].partition_id;
+ {
+ partition_info *part_info= part_iter->part_info;
+ uint32 num_part= part_iter->part_nums.cur++;
+ return part_info->column_list ?
+ part_info->list_col_array[num_part].partition_id :
+ part_info->list_array[num_part].partition_id;
+ }
}
@@ -7220,5 +7834,17 @@ void create_subpartition_name(char *out, const char *in1,
strxmov(out, in1, "#P#", transl_part_name,
"#SP#", transl_subpart_name, "#REN#", NullS);
}
+
+uint get_partition_field_store_length(Field *field)
+{
+ uint store_length;
+
+ store_length= field->key_length();
+ if (field->real_maybe_null())
+ store_length+= HA_KEY_NULL_LENGTH;
+ if (field->real_type() == MYSQL_TYPE_VARCHAR)
+ store_length+= HA_KEY_BLOB_LENGTH;
+ return store_length;
+}
#endif
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index 0c47340016c..6e1bf8b5728 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -1,7 +1,7 @@
#ifndef SQL_PARTITION_INCLUDED
#define SQL_PARTITION_INCLUDED
-/* Copyright (C) 2006 MySQL AB
+/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -68,15 +68,19 @@ int get_part_for_delete(const uchar *buf, const uchar *rec0,
void prune_partition_set(const TABLE *table, part_id_range *part_spec);
bool check_partition_info(partition_info *part_info,handlerton **eng_type,
TABLE *table, handler *file, HA_CREATE_INFO *info);
-void set_linear_hash_mask(partition_info *part_info, uint no_parts);
+void set_linear_hash_mask(partition_info *part_info, uint num_parts);
bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind);
-char *generate_partition_syntax(partition_info *part_info,
- uint *buf_length, bool use_sql_alloc,
- bool show_partition_options);
bool partition_key_modified(TABLE *table, const MY_BITMAP *fields);
void get_partition_set(const TABLE *table, uchar *buf, const uint index,
const key_range *key_spec,
part_id_range *part_spec);
+uint get_partition_field_store_length(Field *field);
+int get_cs_converted_part_value_from_string(THD *thd,
+ Item *item,
+ String *input_str,
+ String *output_str,
+ CHARSET_INFO *cs,
+ bool use_hex);
void get_full_part_id_from_key(const TABLE *table, uchar *buf,
KEY *key_info,
const key_range *key_spec,
@@ -99,6 +103,7 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
bool check_part_func_fields(Field **ptr, bool ok_with_charsets);
bool field_is_partition_charset(Field *field);
+Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs);
/*
A "Get next" function for partition iterator.
@@ -175,13 +180,16 @@ typedef struct st_partition_iter
SYNOPSIS
get_partitions_in_range_iter()
- part_info Partitioning info
- is_subpart
- min_val Left edge, field value in opt_range_key format.
- max_val Right edge, field value in opt_range_key format.
- flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
- NO_MAX_RANGE.
- part_iter Iterator structure to be initialized
+ part_info Partitioning info
+ is_subpart
+ store_length_array Length of fields packed in opt_range_key format
+ min_val Left edge, field value in opt_range_key format
+ max_val Right edge, field value in opt_range_key format
+ min_len Length of minimum value
+ max_len Length of maximum value
+ flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
+ NO_MAX_RANGE
+ part_iter Iterator structure to be initialized
DESCRIPTION
Functions with this signature are used to perform "Partitioning Interval
@@ -194,8 +202,9 @@ typedef struct st_partition_iter
The set of partitions is returned by initializing an iterator in *part_iter
NOTES
- There are currently two functions of this type:
+ There are currently three functions of this type:
- get_part_iter_for_interval_via_walking
+ - get_part_iter_for_interval_cols_via_map
- get_part_iter_for_interval_via_mapping
RETURN
@@ -206,7 +215,9 @@ typedef struct st_partition_iter
typedef int (*get_partitions_in_range_iter)(partition_info *part_info,
bool is_subpart,
+ uint32 *store_length_array,
uchar *min_val, uchar *max_val,
+ uint min_len, uint max_len,
uint flags,
PARTITION_ITERATOR *part_iter);
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 515224703ba..d15c97de912 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 MySQL AB
+/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -99,7 +99,9 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_REPLICATION_INTERFACE_VERSION,
};
-static bool initialized= 0;
+/* support for Services */
+
+#include "sql_plugin_services.h"
/*
A mutex LOCK_plugin must be acquired before accessing the
@@ -113,6 +115,8 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
static bool reap_needed= false;
static int plugin_array_version=0;
+static bool initialized= 0;
+
/*
write-lock on LOCK_system_variables_hash is required before modifying
the following variables/structures
@@ -225,6 +229,22 @@ extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
#endif /* EMBEDDED_LIBRARY */
+static void report_error(int where_to, uint error, ...)
+{
+ va_list args;
+ if (where_to & REPORT_TO_USER)
+ {
+ va_start(args, error);
+ my_printv_error(error, ER(error), MYF(0), args);
+ va_end(args);
+ }
+ if (where_to & REPORT_TO_LOG)
+ {
+ va_start(args, error);
+ error_log_print(ERROR_LEVEL, ER_DEFAULT(error), args);
+ va_end(args);
+ }
+}
/****************************************************************************
Value type thunks, allows the C world to play in the C++ world
@@ -345,7 +365,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
{
#ifdef HAVE_DLOPEN
char dlpath[FN_REFLEN];
- uint plugin_dir_len, dummy_errors, dlpathlen;
+ uint plugin_dir_len, dummy_errors, dlpathlen, i;
struct st_plugin_dl *tmp, plugin_dl;
void *sym;
DBUG_ENTER("plugin_dl_add");
@@ -360,10 +380,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
system_charset_info, 1) ||
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
{
- if (report & REPORT_TO_USER)
- my_error(ER_UDF_NO_PATHS, MYF(0));
- if (report & REPORT_TO_LOG)
- sql_print_error("%s", ER_DEFAULT(ER_UDF_NO_PATHS));
+ report_error(report, ER_UDF_NO_PATHS);
DBUG_RETURN(0);
}
/* If this dll is already loaded just increase ref_count. */
@@ -388,21 +405,14 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (*errmsg == ':') errmsg++;
if (*errmsg == ' ') errmsg++;
}
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
DBUG_RETURN(0);
}
/* Determine interface version */
if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
{
free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_interface_version_sym);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY),
- plugin_interface_version_sym);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
DBUG_RETURN(0);
}
plugin_dl.version= *(int *)sym;
@@ -411,29 +421,42 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
(plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
{
free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0,
- "plugin interface version mismatch");
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dlpath, 0,
- "plugin interface version mismatch");
+ report_error(report, ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0,
+ "plugin interface version mismatch");
DBUG_RETURN(0);
}
+
+ /* link the services in */
+ for (i= 0; i < array_elements(list_of_services); i++)
+ {
+ if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
+ {
+ uint ver= (uint)(intptr)*(void**)sym;
+ if (ver > list_of_services[i].version ||
+ (ver >> 8) < (list_of_services[i].version >> 8))
+ {
+ char buf[MYSQL_ERRMSG_SIZE];
+ my_snprintf(buf, sizeof(buf),
+ "service '%s' interface version mismatch",
+ list_of_services[i].name);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
+ DBUG_RETURN(0);
+ }
+ *(void**)sym= list_of_services[i].service;
+ }
+ }
+
/* Find plugin declarations */
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
{
free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY),
- plugin_declarations_sym);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, MYF(0),
+ plugin_declarations_sym);
DBUG_RETURN(0);
}
if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
{
- int i;
uint sizeof_st_plugin;
struct st_mysql_plugin *old, *cur;
char *ptr= (char *)sym;
@@ -443,11 +466,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
else
{
#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
- free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), sizeof_st_plugin_sym);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
DBUG_RETURN(0);
#else
/*
@@ -469,10 +488,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (!cur)
{
free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), plugin_dl.dl.length);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
DBUG_RETURN(0);
}
/*
@@ -494,10 +510,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
{
free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), plugin_dl.dl.length);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
DBUG_RETURN(0);
}
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
@@ -508,19 +521,13 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
{
free_plugin_mem(&plugin_dl);
- if (report & REPORT_TO_USER)
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
+ report_error(report, ER_OUTOFMEMORY, sizeof(struct st_plugin_dl));
DBUG_RETURN(0);
}
DBUG_RETURN(tmp);
#else
DBUG_ENTER("plugin_dl_add");
- if (report & REPORT_TO_USER)
- my_error(ER_FEATURE_DISABLED, MYF(0), "plugin", "HAVE_DLOPEN");
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_FEATURE_DISABLED), "plugin", "HAVE_DLOPEN");
+ report_error(report, ER_FEATURE_DISABLED, "plugin", "HAVE_DLOPEN");
DBUG_RETURN(0);
#endif
}
@@ -571,14 +578,15 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty
for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
{
struct st_plugin_int *plugin= (st_plugin_int *)
- hash_search(&plugin_hash[i], (const uchar *)name->str, name->length);
+ my_hash_search(&plugin_hash[i], (const uchar *)name->str, name->length);
if (plugin)
DBUG_RETURN(plugin);
}
}
else
DBUG_RETURN((st_plugin_int *)
- hash_search(&plugin_hash[type], (const uchar *)name->str, name->length));
+ my_hash_search(&plugin_hash[type], (const uchar *)name->str,
+ name->length));
DBUG_RETURN(0);
}
@@ -636,7 +644,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
/*
For debugging, we do an additional malloc which allows the
memory manager and/or valgrind to track locked references and
- double unlocks to aid resolving reference counting.problems.
+ double unlocks to aid resolving reference counting problems.
*/
if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
DBUG_RETURN(NULL);
@@ -719,10 +727,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
DBUG_ENTER("plugin_add");
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
{
- if (report & REPORT_TO_USER)
- my_error(ER_UDF_EXISTS, MYF(0), name->str);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_UDF_EXISTS), name->str);
+ report_error(report, ER_UDF_EXISTS, name->str);
DBUG_RETURN(TRUE);
}
/* Clear the whole struct to catch future extensions. */
@@ -749,10 +754,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
strxnmov(buf, sizeof(buf) - 1, "API version for ",
plugin_type_names[plugin->type].str,
" plugin is too different", NullS);
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dl->str, 0, buf);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dl->str, 0, buf);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
goto err;
}
tmp.plugin= plugin;
@@ -781,10 +783,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
DBUG_RETURN(FALSE);
}
}
- if (report & REPORT_TO_USER)
- my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
- if (report & REPORT_TO_LOG)
- sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), name->str);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, name->str);
err:
plugin_dl_del(dl);
DBUG_RETURN(TRUE);
@@ -855,7 +854,7 @@ static void plugin_del(struct st_plugin_int *plugin)
safe_mutex_assert_owner(&LOCK_plugin);
/* Free allocated strings before deleting the plugin. */
plugin_vars_free_values(plugin->system_vars);
- hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
+ my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
if (plugin->plugin_dl)
plugin_dl_del(&plugin->plugin_dl->dl);
plugin->state= PLUGIN_IS_FREED;
@@ -1130,8 +1129,8 @@ int plugin_init(int *argc, char **argv, int flags)
init_alloc_root(&plugin_mem_root, 4096, 4096);
init_alloc_root(&tmp_root, 4096, 4096);
- if (hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
- get_bookmark_hash_key, NULL, HASH_UNIQUE))
+ if (my_hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
+ get_bookmark_hash_key, NULL, HASH_UNIQUE))
goto err;
@@ -1145,8 +1144,8 @@ int plugin_init(int *argc, char **argv, int flags)
for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
{
- if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
- get_plugin_hash_key, NULL, HASH_UNIQUE))
+ if (my_hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
+ get_plugin_hash_key, NULL, HASH_UNIQUE))
goto err;
}
@@ -1360,7 +1359,6 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
}
new_thd->thread_stack= (char*) &tables;
new_thd->store_globals();
- lex_start(new_thd);
new_thd->db= my_strdup("mysql", MYF(0));
new_thd->db_length= 5;
bzero((uchar*)&tables, sizeof(tables));
@@ -1624,7 +1622,7 @@ void plugin_shutdown(void)
/* Dispose of the memory */
for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
- hash_free(&plugin_hash[i]);
+ my_hash_free(&plugin_hash[i]);
delete_dynamic(&plugin_array);
count= plugin_dl_array.elements;
@@ -1636,7 +1634,7 @@ void plugin_shutdown(void)
my_afree(dl);
delete_dynamic(&plugin_dl_array);
- hash_free(&bookmark_hash);
+ my_hash_free(&bookmark_hash);
free_root(&plugin_mem_root, MYF(0));
global_variables_dynamic_size= 0;
@@ -1657,7 +1655,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
bzero(&tables, sizeof(tables));
tables.db= (char *)"mysql";
tables.table_name= tables.alias= (char *)"plugin";
- if (check_table_access(thd, INSERT_ACL, &tables, 1, FALSE))
+ if (check_table_access(thd, INSERT_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
/* need to open before acquiring LOCK_plugin or it will deadlock */
@@ -1825,7 +1823,7 @@ bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
HASH *hash= plugin_hash + type;
for (idx= 0; idx < total; idx++)
{
- plugin= (struct st_plugin_int *) hash_element(hash, idx);
+ plugin= (struct st_plugin_int *) my_hash_element(hash, idx);
plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
}
}
@@ -2064,7 +2062,7 @@ static int check_func_set(THD *thd, struct st_mysql_sys_var *var,
const char *strvalue= "NULL", *str;
TYPELIB *typelib;
ulonglong result;
- uint error_len;
+ uint error_len= 0; // init as only set on error
bool not_used;
int length;
@@ -2224,8 +2222,8 @@ static st_bookmark *find_bookmark(const char *plugin, const char *name,
varname[0]= flags & PLUGIN_VAR_TYPEMASK;
- result= (st_bookmark*) hash_search(&bookmark_hash,
- (const uchar*) varname, length - 1);
+ result= (st_bookmark*) my_hash_search(&bookmark_hash,
+ (const uchar*) varname, length - 1);
my_afree(varname);
return result;
@@ -2385,7 +2383,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
{
sys_var_pluginvar *pi;
sys_var *var;
- st_bookmark *v= (st_bookmark*) hash_element(&bookmark_hash,idx);
+ st_bookmark *v= (st_bookmark*) my_hash_element(&bookmark_hash,idx);
if (v->version <= thd->variables.dynamic_variables_version ||
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
@@ -2479,7 +2477,7 @@ static void cleanup_variables(THD *thd, struct system_variables *vars)
rw_rdlock(&LOCK_system_variables_hash);
for (idx= 0; idx < bookmark_hash.records; idx++)
{
- v= (st_bookmark*) hash_element(&bookmark_hash, idx);
+ v= (st_bookmark*) my_hash_element(&bookmark_hash, idx);
if (v->version > vars->dynamic_variables_version ||
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) ||
!(pivar= var->cast_pluginvar()) ||
@@ -2663,7 +2661,9 @@ uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type,
{
if (!(value & mask))
continue;
- str.append(typelib->type_names[i], typelib->type_lengths[i]);
+ str.append(typelib->type_names[i], typelib->type_lengths
+ ? typelib->type_lengths[i]
+ : strlen(typelib->type_names[i]));
str.append(',');
}
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index c6ad846943c..23ce85c994b 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -35,16 +35,6 @@ class sys_var;
#define INITIAL_LEX_PLUGIN_LIST_SIZE 16
-/*
- the following #define adds server-only members to enum_mysql_show_type,
- that is defined in plugin.h
-*/
-#define SHOW_FUNC SHOW_FUNC, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_LONGLONG, \
- SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_HAVE, \
- SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH, \
- SHOW_LONGLONG_STATUS
-#include <mysql/plugin.h>
-#undef SHOW_FUNC
typedef enum enum_mysql_show_type SHOW_TYPE;
typedef struct st_mysql_show_var SHOW_VAR;
diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h
new file mode 100644
index 00000000000..7491ddab79d
--- /dev/null
+++ b/sql/sql_plugin_services.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* support for Services */
+#include <service_versions.h>
+
+struct st_service_ref {
+ const char *name;
+ uint version;
+ void *service;
+};
+
+static struct my_snprintf_service_st my_snprintf_handler = {
+ my_snprintf,
+ my_vsnprintf
+};
+
+static struct thd_alloc_service_st thd_alloc_handler= {
+ thd_alloc,
+ thd_calloc,
+ thd_strdup,
+ thd_strmake,
+ thd_memdup,
+ thd_make_lex_string
+};
+
+static struct st_service_ref list_of_services[]=
+{
+ { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
+ { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }
+};
+
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 27b67132c9d..168934206e5 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -84,6 +84,7 @@ When one supplies long data for a placeholder:
*/
#include "mysql_priv.h"
+#include "sql_prepare.h"
#include "sql_select.h" // for JOIN
#include "sql_cursor.h"
#include "sp_head.h"
@@ -106,7 +107,7 @@ class Select_fetch_protocol_binary: public select_send
Protocol_binary protocol;
public:
Select_fetch_protocol_binary(THD *thd);
- virtual bool send_fields(List<Item> &list, uint flags);
+ virtual bool send_result_set_metadata(List<Item> &list, uint flags);
virtual bool send_data(List<Item> &items);
virtual bool send_eof();
#ifdef EMBEDDED_LIBRARY
@@ -163,6 +164,7 @@ public:
bool execute_loop(String *expanded_query,
bool open_cursor,
uchar *packet_arg, uchar *packet_end_arg);
+ bool execute_server_runnable(Server_runnable *server_runnable);
/* Destroy this statement */
void deallocate();
private:
@@ -183,6 +185,78 @@ private:
void swap_prepared_statement(Prepared_statement *copy);
};
+/**
+ Execute one SQL statement in an isolated context.
+*/
+
+class Execute_sql_statement: public Server_runnable
+{
+public:
+ Execute_sql_statement(LEX_STRING sql_text);
+ virtual bool execute_server_code(THD *thd);
+private:
+ LEX_STRING m_sql_text;
+};
+
+
+class Ed_connection;
+
+/**
+ Protocol_local: a helper class to intercept the result
+ of the data written to the network.
+*/
+
+class Protocol_local :public Protocol
+{
+public:
+ Protocol_local(THD *thd, Ed_connection *ed_connection);
+ ~Protocol_local() { free_root(&m_rset_root, MYF(0)); }
+protected:
+ virtual void prepare_for_resend();
+ virtual bool write();
+ virtual bool store_null();
+ virtual bool store_tiny(longlong from);
+ virtual bool store_short(longlong from);
+ virtual bool store_long(longlong from);
+ virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store_decimal(const my_decimal *);
+ virtual bool store(const char *from, size_t length, CHARSET_INFO *cs);
+ virtual bool store(const char *from, size_t length,
+ CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
+ virtual bool store(MYSQL_TIME *time);
+ virtual bool store_date(MYSQL_TIME *time);
+ virtual bool store_time(MYSQL_TIME *time);
+ virtual bool store(float value, uint32 decimals, String *buffer);
+ virtual bool store(double value, uint32 decimals, String *buffer);
+ virtual bool store(Field *field);
+
+ virtual bool send_result_set_metadata(List<Item> *list, uint flags);
+ virtual bool send_out_parameters(List<Item_param> *sp_params);
+#ifdef EMBEDDED_LIBRARY
+ void remove_last_row();
+#endif
+ virtual enum enum_protocol_type type() { return PROTOCOL_LOCAL; };
+
+ virtual bool send_ok(uint server_status, uint statement_warn_count,
+ ulonglong affected_rows, ulonglong last_insert_id,
+ const char *message);
+
+ virtual bool send_eof(uint server_status, uint statement_warn_count);
+ virtual bool send_error(uint sql_errno, const char *err_msg, const char* sqlstate);
+private:
+ bool store_string(const char *str, size_t length,
+ CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs);
+
+ bool store_column(const void *data, size_t length);
+ void opt_add_row_to_rset();
+private:
+ Ed_connection *m_connection;
+ MEM_ROOT m_rset_root;
+ List<Ed_row> *m_rset;
+ size_t m_column_count;
+ Ed_column *m_current_row;
+ Ed_column *m_current_column;
+};
/******************************************************************************
Implementation
@@ -260,7 +334,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
error= my_net_write(net, buff, sizeof(buff));
if (stmt->param_count && ! error)
{
- error= thd->protocol_text.send_fields((List<Item> *)
+ error= thd->protocol_text.send_result_set_metadata((List<Item> *)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
@@ -753,7 +827,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
const String *res;
DBUG_ENTER("insert_params_with_log");
- if (query->copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query(), stmt->query_length(), default_charset_info))
DBUG_RETURN(1);
for (Item_param **it= begin; it < end; ++it)
@@ -915,7 +989,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt,
DBUG_ENTER("emb_insert_params_with_log");
- if (query->copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query(), stmt->query_length(), default_charset_info))
DBUG_RETURN(1);
for (; it < end; ++it, ++client_param)
@@ -1027,9 +1101,9 @@ static bool insert_params_from_vars(Prepared_statement *stmt,
{
Item_param *param= *it;
varname= var_it++;
- entry= (user_var_entry*)hash_search(&stmt->thd->user_vars,
- (uchar*) varname->str,
- varname->length);
+ entry= (user_var_entry*)my_hash_search(&stmt->thd->user_vars,
+ (uchar*) varname->str,
+ varname->length);
if (param->set_from_user_var(stmt->thd, entry) ||
param->convert_str_value(stmt->thd))
DBUG_RETURN(1);
@@ -1066,7 +1140,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
DBUG_ENTER("insert_params_from_vars");
- if (query->copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query(), stmt->query_length(), default_charset_info))
DBUG_RETURN(1);
for (Item_param **it= begin; it < end; ++it)
@@ -1074,8 +1148,8 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
Item_param *param= *it;
varname= var_it++;
- entry= (user_var_entry *) hash_search(&thd->user_vars, (uchar*) varname->str,
- varname->length);
+ entry= (user_var_entry *) my_hash_search(&thd->user_vars, (uchar*)
+ varname->str, varname->length);
/*
We have to call the setup_one_conversion_function() here to set
the parameter's members that might be needed further
@@ -1336,7 +1410,7 @@ static int mysql_test_select(Prepared_statement *stmt,
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
if (tables)
{
- if (check_table_access(thd, privilege, tables, UINT_MAX, FALSE))
+ if (check_table_access(thd, privilege, tables, FALSE, UINT_MAX, FALSE))
goto error;
}
else if (check_access(thd, privilege, any_db,0,0,0,0))
@@ -1374,7 +1448,7 @@ static int mysql_test_select(Prepared_statement *stmt,
unit->prepare call above.
*/
if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
- lex->result->send_fields(fields, Protocol::SEND_EOF) ||
+ lex->result->send_result_set_metadata(fields, Protocol::SEND_EOF) ||
thd->protocol->flush())
goto error;
DBUG_RETURN(2);
@@ -1405,7 +1479,8 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
THD *thd= stmt->thd;
DBUG_ENTER("mysql_test_do_fields");
- if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
+ if (tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
+ UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
if (open_normal_and_derived_tables(thd, tables, 0))
@@ -1436,8 +1511,9 @@ static bool mysql_test_set_fields(Prepared_statement *stmt,
THD *thd= stmt->thd;
set_var_base *var;
- if ((tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
- || open_normal_and_derived_tables(thd, tables, 0))
+ if ((tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
+ UINT_MAX, FALSE)) ||
+ open_normal_and_derived_tables(thd, tables, 0))
goto error;
while ((var= it++))
@@ -1472,7 +1548,8 @@ static bool mysql_test_call_fields(Prepared_statement *stmt,
THD *thd= stmt->thd;
Item *item;
- if ((tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) ||
+ if ((tables && check_table_access(thd, SELECT_ACL, tables, FALSE,
+ UINT_MAX, FALSE)) ||
open_normal_and_derived_tables(thd, tables, 0))
goto err;
@@ -1920,29 +1997,6 @@ static bool check_prepared_statement(Prepared_statement *stmt)
Note that we don't need to have cases in this list if they are
marked with CF_STATUS_COMMAND in sql_command_flags
*/
- case SQLCOM_SHOW_PROCESSLIST:
- case SQLCOM_SHOW_STORAGE_ENGINES:
- case SQLCOM_SHOW_PRIVILEGES:
- case SQLCOM_SHOW_ENGINE_LOGS:
- case SQLCOM_SHOW_ENGINE_STATUS:
- case SQLCOM_SHOW_ENGINE_MUTEX:
- case SQLCOM_SHOW_CREATE_DB:
- case SQLCOM_SHOW_GRANTS:
- case SQLCOM_SHOW_BINLOG_EVENTS:
- case SQLCOM_SHOW_MASTER_STAT:
- case SQLCOM_SHOW_SLAVE_STAT:
- case SQLCOM_SHOW_CREATE_PROC:
- case SQLCOM_SHOW_CREATE_FUNC:
- case SQLCOM_SHOW_CREATE_EVENT:
- case SQLCOM_SHOW_CREATE_TRIGGER:
- case SQLCOM_SHOW_CREATE:
- case SQLCOM_SHOW_PROC_CODE:
- case SQLCOM_SHOW_FUNC_CODE:
- case SQLCOM_SHOW_AUTHORS:
- case SQLCOM_SHOW_CONTRIBUTORS:
- case SQLCOM_SHOW_WARNS:
- case SQLCOM_SHOW_ERRORS:
- case SQLCOM_SHOW_BINLOGS:
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
case SQLCOM_ALTER_TABLE:
@@ -2065,7 +2119,6 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
{
Protocol *save_protocol= thd->protocol;
Prepared_statement *stmt;
- bool error;
DBUG_ENTER("mysqld_stmt_prepare");
DBUG_PRINT("prep_query", ("%s", packet));
@@ -2090,15 +2143,7 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
thd->protocol= &thd->protocol_binary;
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),QUERY_PRIOR);
-
- error= stmt->prepare(packet, packet_length);
-
- if (!(specialflag & SPECIAL_NO_PRIOR))
- my_pthread_setprio(pthread_self(),WAIT_PRIOR);
-
- if (error)
+ if (stmt->prepare(packet, packet_length))
{
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
@@ -2148,9 +2193,9 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len)
convert it for error messages to be uniform.
*/
if ((entry=
- (user_var_entry*)hash_search(&thd->user_vars,
- (uchar*)lex->prepared_stmt_code.str,
- lex->prepared_stmt_code.length))
+ (user_var_entry*)my_hash_search(&thd->user_vars,
+ (uchar*)lex->prepared_stmt_code.str,
+ lex->prepared_stmt_code.length))
&& entry->value)
{
my_bool is_var_null;
@@ -2344,6 +2389,9 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
/* Fix ORDER list */
for (order= (ORDER *)sl->order_list.first; order; order= order->next)
order->item= &order->item_ptr;
+
+ /* clear the no_error flag for INSERT/UPDATE IGNORE */
+ sl->no_error= FALSE;
}
{
SELECT_LEX_UNIT *unit= sl->master_unit();
@@ -2458,10 +2506,10 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
DBUG_VOID_RETURN;
}
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
- thd->profiling.set_query_source(stmt->query, stmt->query_length);
+#if defined(ENABLED_PROFILING)
+ thd->profiling.set_query_source(stmt->query(), stmt->query_length());
#endif
- DBUG_PRINT("exec_query", ("%s", stmt->query));
+ DBUG_PRINT("exec_query", ("%s", stmt->query()));
DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt));
sp_cache_flush_obsolete(&thd->sp_proc_cache);
@@ -2477,7 +2525,6 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_close(thd->net.vio););
DBUG_VOID_RETURN;
-
}
@@ -2786,19 +2833,19 @@ Select_fetch_protocol_binary::Select_fetch_protocol_binary(THD *thd_arg)
:protocol(thd_arg)
{}
-bool Select_fetch_protocol_binary::send_fields(List<Item> &list, uint flags)
+bool Select_fetch_protocol_binary::send_result_set_metadata(List<Item> &list, uint flags)
{
bool rc;
Protocol *save_protocol= thd->protocol;
/*
- Protocol::send_fields caches the information about column types:
+ Protocol::send_result_set_metadata caches the information about column types:
this information is later used to send data. Therefore, the same
dedicated Protocol object must be used for all operations with
a cursor.
*/
thd->protocol= &protocol;
- rc= select_send::send_fields(list, flags);
+ rc= select_send::send_result_set_metadata(list, flags);
thd->protocol= save_protocol;
return rc;
@@ -2847,6 +2894,70 @@ Reprepare_observer::report_error(THD *thd)
}
+/*******************************************************************
+* Server_runnable
+*******************************************************************/
+
+Server_runnable::~Server_runnable()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+Execute_sql_statement::
+Execute_sql_statement(LEX_STRING sql_text)
+ :m_sql_text(sql_text)
+{}
+
+
+/**
+ Parse and execute a statement. Does not prepare the query.
+
+ Allows to execute a statement from within another statement.
+ The main property of the implementation is that it does not
+ affect the environment -- i.e. you can run many
+ executions without having to cleanup/reset THD in between.
+*/
+
+bool
+Execute_sql_statement::execute_server_code(THD *thd)
+{
+ bool error;
+
+ if (alloc_query(thd, m_sql_text.str, m_sql_text.length))
+ return TRUE;
+
+ Parser_state parser_state(thd, thd->query(), thd->query_length());
+
+ parser_state.m_lip.multi_statements= FALSE;
+ lex_start(thd);
+
+ error= parse_sql(thd, &parser_state, NULL) || thd->is_error();
+
+ if (error)
+ goto end;
+
+ thd->lex->set_trg_event_type_for_tables();
+
+ error= mysql_execute_command(thd);
+
+ if (thd->killed_errno())
+ {
+ if (! thd->stmt_da->is_set())
+ thd->send_kill_message();
+ }
+
+ /* report error issued during command execution */
+ if (error == 0 && thd->spcont == NULL)
+ general_log_write(thd, COM_STMT_EXECUTE,
+ thd->query(), thd->query_length());
+
+end:
+ lex_end(thd->lex);
+
+ return error;
+}
+
/***************************************************************************
Prepared_statement
****************************************************************************/
@@ -2944,7 +3055,8 @@ void Prepared_statement::cleanup_stmt()
DBUG_ENTER("Prepared_statement::cleanup_stmt");
DBUG_PRINT("enter",("stmt: 0x%lx", (long) this));
- DBUG_ASSERT(lex->sphead == 0);
+ delete lex->sphead;
+ lex->sphead= 0;
/* The order is important */
lex->unit.cleanup();
cleanup_items(free_list);
@@ -3055,8 +3167,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
old_stmt_arena= thd->stmt_arena;
thd->stmt_arena= this;
- Parser_state parser_state(thd, thd->query, thd->query_length);
+ Parser_state parser_state(thd, thd->query(), thd->query_length());
parser_state.m_lip.stmt_prepare_mode= TRUE;
+ parser_state.m_lip.multi_statements= FALSE;
lex_start(thd);
error= parse_sql(thd, & parser_state, NULL) ||
@@ -3144,7 +3257,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
the general log.
*/
if (thd->spcont == NULL)
- general_log_write(thd, COM_STMT_PREPARE, query, query_length);
+ general_log_write(thd, COM_STMT_PREPARE, query(), query_length());
}
DBUG_RETURN(error);
}
@@ -3301,6 +3414,45 @@ reexecute:
}
+bool
+Prepared_statement::execute_server_runnable(Server_runnable *server_runnable)
+{
+ Statement stmt_backup;
+ bool error;
+ Query_arena *save_stmt_arena= thd->stmt_arena;
+ Item_change_list save_change_list;
+ thd->change_list= save_change_list;
+
+ state= CONVENTIONAL_EXECUTION;
+
+ if (!(lex= new (mem_root) st_lex_local))
+ return TRUE;
+
+ thd->set_n_backup_statement(this, &stmt_backup);
+ thd->set_n_backup_active_arena(this, &stmt_backup);
+ thd->stmt_arena= this;
+
+ error= server_runnable->execute_server_code(thd);
+
+ delete lex->sphead;
+ lex->sphead= 0;
+ /* The order is important */
+ lex->unit.cleanup();
+ close_thread_tables(thd);
+ thd->cleanup_after_query();
+
+ thd->restore_active_arena(this, &stmt_backup);
+ thd->restore_backup_statement(this, &stmt_backup);
+ thd->stmt_arena= save_stmt_arena;
+
+ save_change_list= thd->change_list;
+
+ /* Items and memory will freed in destructor */
+
+ return error;
+}
+
+
/**
Reprepare this prepared statement.
@@ -3335,7 +3487,7 @@ Prepared_statement::reprepare()
return TRUE;
error= ((name.str && copy.set_name(&name)) ||
- copy.prepare(query, query_length) ||
+ copy.prepare(query(), query_length()) ||
validate_metadata(&copy));
if (cur_db_changed)
@@ -3573,8 +3725,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
to point at it even after we restore from backup. This is ok, as
expanded query was allocated in thd->mem_root.
*/
- stmt_backup.query= thd->query;
- stmt_backup.query_length= thd->query_length;
+ stmt_backup.set_query_inner(thd->query(), thd->query_length());
/*
At first execution of prepared statement we may perform logical
@@ -3599,10 +3750,10 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Note that multi-statements cannot exist here (they are not supported in
prepared statements).
*/
- if (query_cache_send_result_to_client(thd, thd->query,
- thd->query_length) <= 0)
+ if (query_cache_send_result_to_client(thd, thd->query(),
+ thd->query_length()) <= 0)
{
- MYSQL_QUERY_EXEC_START(thd->query,
+ MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
(char *) (thd->db ? thd->db : ""),
thd->security_ctx->priv_user,
@@ -3636,6 +3787,15 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
if (state == Query_arena::PREPARED)
state= Query_arena::EXECUTED;
+ if (this->lex->sql_command == SQLCOM_CALL)
+ {
+ if (is_sql_prepare())
+ thd->protocol_text.send_out_parameters(&this->lex->param_list);
+ else
+ thd->protocol->send_out_parameters(&this->lex->param_list);
+ }
+
+
/*
Log COM_EXECUTE to the general log. Note, that in case of SQL
prepared statements this causes two records to be output:
@@ -3652,7 +3812,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
the general log.
*/
if (error == 0 && thd->spcont == NULL)
- general_log_write(thd, COM_STMT_EXECUTE, thd->query, thd->query_length);
+ general_log_write(thd, COM_STMT_EXECUTE, thd->query(), thd->query_length());
error:
flags&= ~ (uint) IS_IN_USE;
@@ -3669,3 +3829,573 @@ void Prepared_statement::deallocate()
/* Statement map calls delete stmt on erase */
thd->stmt_map.erase(this);
}
+
+
+/***************************************************************************
+* Ed_result_set
+***************************************************************************/
+/**
+ Use operator delete to free memory of Ed_result_set.
+ Accessing members of a class after the class has been destroyed
+ is a violation of the C++ standard but is commonly used in the
+ server code.
+*/
+
+void Ed_result_set::operator delete(void *ptr, size_t size) throw ()
+{
+ if (ptr)
+ {
+ /*
+ Make a stack copy, otherwise free_root() will attempt to
+ write to freed memory.
+ */
+ MEM_ROOT own_root= ((Ed_result_set*) ptr)->m_mem_root;
+ free_root(&own_root, MYF(0));
+ }
+}
+
+
+/**
+ Initialize an instance of Ed_result_set.
+
+ Instances of the class, as well as all result set rows, are
+ always allocated in the memory root passed over as the second
+ argument. In the constructor, we take over ownership of the
+ memory root. It will be freed when the class is destroyed.
+
+ sic: Ed_result_est is not designed to be allocated on stack.
+*/
+
+Ed_result_set::Ed_result_set(List<Ed_row> *rows_arg,
+ size_t column_count_arg,
+ MEM_ROOT *mem_root_arg)
+ :m_mem_root(*mem_root_arg),
+ m_column_count(column_count_arg),
+ m_rows(rows_arg),
+ m_next_rset(NULL)
+{
+ /* Take over responsibility for the memory */
+ clear_alloc_root(mem_root_arg);
+}
+
+/***************************************************************************
+* Ed_result_set
+***************************************************************************/
+
+/**
+ Create a new "execute direct" connection.
+*/
+
+Ed_connection::Ed_connection(THD *thd)
+ :m_warning_info(thd->query_id),
+ m_thd(thd),
+ m_rsets(0),
+ m_current_rset(0)
+{
+}
+
+
+/**
+ Free all result sets of the previous statement, if any,
+ and reset warnings and errors.
+
+ Called before execution of the next query.
+*/
+
+void
+Ed_connection::free_old_result()
+{
+ while (m_rsets)
+ {
+ Ed_result_set *rset= m_rsets->m_next_rset;
+ delete m_rsets;
+ m_rsets= rset;
+ }
+ m_current_rset= m_rsets;
+ m_diagnostics_area.reset_diagnostics_area();
+ m_warning_info.clear_warning_info(m_thd->query_id);
+}
+
+
+/**
+ A simple wrapper that uses a helper class to execute SQL statements.
+*/
+
+bool
+Ed_connection::execute_direct(LEX_STRING sql_text)
+{
+ Execute_sql_statement execute_sql_statement(sql_text);
+ DBUG_PRINT("ed_query", ("%s", sql_text.str));
+
+ return execute_direct(&execute_sql_statement);
+}
+
+
+/**
+ Execute a fragment of server functionality without an effect on
+ thd, and store results in memory.
+
+ Conventions:
+ - the code fragment must finish with OK, EOF or ERROR.
+ - the code fragment doesn't have to close thread tables,
+ free memory, commit statement transaction or do any other
+ cleanup that is normally done in the end of dispatch_command().
+
+ @param server_runnable A code fragment to execute.
+*/
+
+bool Ed_connection::execute_direct(Server_runnable *server_runnable)
+{
+ bool rc= FALSE;
+ Protocol_local protocol_local(m_thd, this);
+ Prepared_statement stmt(m_thd);
+ Protocol *save_protocol= m_thd->protocol;
+ Diagnostics_area *save_diagnostics_area= m_thd->stmt_da;
+ Warning_info *save_warning_info= m_thd->warning_info;
+
+ DBUG_ENTER("Ed_connection::execute_direct");
+
+ free_old_result(); /* Delete all data from previous execution, if any */
+
+ m_thd->protocol= &protocol_local;
+ m_thd->stmt_da= &m_diagnostics_area;
+ m_thd->warning_info= &m_warning_info;
+
+ rc= stmt.execute_server_runnable(server_runnable);
+ m_thd->protocol->end_statement();
+
+ m_thd->protocol= save_protocol;
+ m_thd->stmt_da= save_diagnostics_area;
+ m_thd->warning_info= save_warning_info;
+ /*
+ Protocol_local makes use of m_current_rset to keep
+ track of the last result set, while adding result sets to the end.
+ Reset it to point to the first result set instead.
+ */
+ m_current_rset= m_rsets;
+
+ DBUG_RETURN(rc);
+}
+
+
+/**
+ A helper method that is called only during execution.
+
+ Although Ed_connection doesn't support multi-statements,
+ a statement may generate many result sets. All subsequent
+ result sets are appended to the end.
+
+ @pre This is called only by Protocol_local.
+*/
+
+void
+Ed_connection::add_result_set(Ed_result_set *ed_result_set)
+{
+ if (m_rsets)
+ {
+ m_current_rset->m_next_rset= ed_result_set;
+ /* While appending, use m_current_rset as a pointer to the tail. */
+ m_current_rset= ed_result_set;
+ }
+ else
+ m_current_rset= m_rsets= ed_result_set;
+}
+
+
+/**
+ Release ownership of the current result set to the client.
+
+ Since we use a simple linked list for result sets,
+ this method uses a linear search of the previous result
+ set to exclude the released instance from the list.
+
+ @todo Use double-linked list, when this is really used.
+
+ XXX: This has never been tested with more than one result set!
+
+ @pre There must be a result set.
+*/
+
+Ed_result_set *
+Ed_connection::store_result_set()
+{
+ Ed_result_set *ed_result_set;
+
+ DBUG_ASSERT(m_current_rset);
+
+ if (m_current_rset == m_rsets)
+ {
+ /* Assign the return value */
+ ed_result_set= m_current_rset;
+ /* Exclude the return value from the list. */
+ m_current_rset= m_rsets= m_rsets->m_next_rset;
+ }
+ else
+ {
+ Ed_result_set *prev_rset= m_rsets;
+ /* Assign the return value. */
+ ed_result_set= m_current_rset;
+
+ /* Exclude the return value from the list */
+ while (prev_rset->m_next_rset != m_current_rset)
+ prev_rset= ed_result_set->m_next_rset;
+ m_current_rset= prev_rset->m_next_rset= m_current_rset->m_next_rset;
+ }
+ ed_result_set->m_next_rset= NULL; /* safety */
+
+ return ed_result_set;
+}
+
+/*************************************************************************
+* Protocol_local
+**************************************************************************/
+
+Protocol_local::Protocol_local(THD *thd, Ed_connection *ed_connection)
+ :Protocol(thd),
+ m_connection(ed_connection),
+ m_rset(NULL),
+ m_column_count(0),
+ m_current_row(NULL),
+ m_current_column(NULL)
+{
+ clear_alloc_root(&m_rset_root);
+}
+
+/**
+ Called between two result set rows.
+
+ Prepare structures to fill result set rows.
+ Unfortunately, we can't return an error here. If memory allocation
+ fails, we'll have to return an error later. And so is done
+ in methods such as @sa store_column().
+*/
+
+void Protocol_local::prepare_for_resend()
+{
+ DBUG_ASSERT(alloc_root_inited(&m_rset_root));
+
+ opt_add_row_to_rset();
+ /* Start a new row. */
+ m_current_row= (Ed_column *) alloc_root(&m_rset_root,
+ sizeof(Ed_column) * m_column_count);
+ m_current_column= m_current_row;
+}
+
+
+/**
+ In "real" protocols this is called to finish a result set row.
+ Unused in the local implementation.
+*/
+
+bool Protocol_local::write()
+{
+ return FALSE;
+}
+
+/**
+ A helper function to add the current row to the current result
+ set. Called in @sa prepare_for_resend(), when a new row is started,
+ and in send_eof(), when the result set is finished.
+*/
+
+void Protocol_local::opt_add_row_to_rset()
+{
+ if (m_current_row)
+ {
+ /* Add the old row to the result set */
+ Ed_row *ed_row= new (&m_rset_root) Ed_row(m_current_row, m_column_count);
+ if (ed_row)
+ m_rset->push_back(ed_row, &m_rset_root);
+ }
+}
+
+
+/**
+ Add a NULL column to the current row.
+*/
+
+bool Protocol_local::store_null()
+{
+ if (m_current_column == NULL)
+ return TRUE; /* prepare_for_resend() failed to allocate memory. */
+
+ bzero(m_current_column, sizeof(*m_current_column));
+ ++m_current_column;
+ return FALSE;
+}
+
+
+/**
+ A helper method to add any column to the current row
+ in its binary form.
+
+ Allocates memory for the data in the result set memory root.
+*/
+
+bool Protocol_local::store_column(const void *data, size_t length)
+{
+ if (m_current_column == NULL)
+ return TRUE; /* prepare_for_resend() failed to allocate memory. */
+ /*
+ alloc_root() automatically aligns memory, so we don't need to
+ do any extra alignment if we're pointing to, say, an integer.
+ */
+ m_current_column->str= (char*) memdup_root(&m_rset_root,
+ data,
+ length + 1 /* Safety */);
+ if (! m_current_column->str)
+ return TRUE;
+ m_current_column->str[length]= '\0'; /* Safety */
+ m_current_column->length= length;
+ ++m_current_column;
+ return FALSE;
+}
+
+
+/**
+ Store a string value in a result set column, optionally
+ having converted it to character_set_results.
+*/
+
+bool
+Protocol_local::store_string(const char *str, size_t length,
+ CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs)
+{
+ /* Store with conversion */
+ uint error_unused;
+
+ if (dst_cs && !my_charset_same(src_cs, dst_cs) &&
+ src_cs != &my_charset_bin &&
+ dst_cs != &my_charset_bin)
+ {
+ if (convert->copy(str, length, src_cs, dst_cs, &error_unused))
+ return TRUE;
+ str= convert->ptr();
+ length= convert->length();
+ }
+ return store_column(str, length);
+}
+
+
+/** Store a tiny int as is (1 byte) in a result set column. */
+
+bool Protocol_local::store_tiny(longlong value)
+{
+ char v= (char) value;
+ return store_column(&v, 1);
+}
+
+
+/** Store a short as is (2 bytes, host order) in a result set column. */
+
+bool Protocol_local::store_short(longlong value)
+{
+ int16 v= (int16) value;
+ return store_column(&v, 2);
+}
+
+
+/** Store a "long" as is (4 bytes, host order) in a result set column. */
+
+bool Protocol_local::store_long(longlong value)
+{
+ int32 v= (int32) value;
+ return store_column(&v, 4);
+}
+
+
+/** Store a "longlong" as is (8 bytes, host order) in a result set column. */
+
+bool Protocol_local::store_longlong(longlong value, bool unsigned_flag)
+{
+ int64 v= (int64) value;
+ return store_column(&v, 8);
+}
+
+
+/** Store a decimal in string format in a result set column */
+
+bool Protocol_local::store_decimal(const my_decimal *value)
+{
+ char buf[DECIMAL_MAX_STR_LENGTH];
+ String str(buf, sizeof (buf), &my_charset_bin);
+ int rc;
+
+ rc= my_decimal2string(E_DEC_FATAL_ERROR, value, 0, 0, 0, &str);
+
+ if (rc)
+ return TRUE;
+
+ return store_column(str.ptr(), str.length());
+}
+
+
+/** Convert to cs_results and store a string. */
+
+bool Protocol_local::store(const char *str, size_t length,
+ CHARSET_INFO *src_cs)
+{
+ CHARSET_INFO *dst_cs;
+
+ dst_cs= m_connection->m_thd->variables.character_set_results;
+ return store_string(str, length, src_cs, dst_cs);
+}
+
+
+/** Store a string. */
+
+bool Protocol_local::store(const char *str, size_t length,
+ CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs)
+{
+ return store_string(str, length, src_cs, dst_cs);
+}
+
+
+/* Store MYSQL_TIME (in binary format) */
+
+bool Protocol_local::store(MYSQL_TIME *time)
+{
+ return store_column(time, sizeof(MYSQL_TIME));
+}
+
+
+/** Store MYSQL_TIME (in binary format) */
+
+bool Protocol_local::store_date(MYSQL_TIME *time)
+{
+ return store_column(time, sizeof(MYSQL_TIME));
+}
+
+
+/** Store MYSQL_TIME (in binary format) */
+
+bool Protocol_local::store_time(MYSQL_TIME *time)
+{
+ return store_column(time, sizeof(MYSQL_TIME));
+}
+
+
+/* Store a floating point number, as is. */
+
+bool Protocol_local::store(float value, uint32 decimals, String *buffer)
+{
+ return store_column(&value, sizeof(float));
+}
+
+
+/* Store a double precision number, as is. */
+
+bool Protocol_local::store(double value, uint32 decimals, String *buffer)
+{
+ return store_column(&value, sizeof (double));
+}
+
+
+/* Store a Field. */
+
+bool Protocol_local::store(Field *field)
+{
+ if (field->is_null())
+ return store_null();
+ return field->send_binary(this);
+}
+
+
+/** Called to start a new result set. */
+
+bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint)
+{
+ DBUG_ASSERT(m_rset == 0 && !alloc_root_inited(&m_rset_root));
+
+ init_sql_alloc(&m_rset_root, MEM_ROOT_BLOCK_SIZE, 0);
+
+ if (! (m_rset= new (&m_rset_root) List<Ed_row>))
+ return TRUE;
+
+ m_column_count= columns->elements;
+
+ return FALSE;
+}
+
+
+/**
+ Normally this is a separate result set with OUT parameters
+ of stored procedures. Currently unsupported for the local
+ version.
+*/
+
+bool Protocol_local::send_out_parameters(List<Item_param> *sp_params)
+{
+ return FALSE;
+}
+
+
+/** Called for statements that don't have a result set, at statement end. */
+
+bool
+Protocol_local::send_ok(uint server_status, uint statement_warn_count,
+ ulonglong affected_rows, ulonglong last_insert_id,
+ const char *message)
+{
+ /*
+ Just make sure nothing is sent to the client, we have grabbed
+ the status information in the connection diagnostics area.
+ */
+ return FALSE;
+}
+
+
+/**
+ Called at the end of a result set. Append a complete
+ result set to the list in Ed_connection.
+
+ Don't send anything to the client, but instead finish
+ building of the result set at hand.
+*/
+
+bool Protocol_local::send_eof(uint server_status, uint statement_warn_count)
+{
+ Ed_result_set *ed_result_set;
+
+ DBUG_ASSERT(m_rset);
+
+ opt_add_row_to_rset();
+ m_current_row= 0;
+
+ ed_result_set= new (&m_rset_root) Ed_result_set(m_rset, m_column_count,
+ &m_rset_root);
+
+ m_rset= NULL;
+
+ if (! ed_result_set)
+ return TRUE;
+
+ /* In case of successful allocation memory ownership was transferred. */
+ DBUG_ASSERT(!alloc_root_inited(&m_rset_root));
+
+ /*
+ Link the created Ed_result_set instance into the list of connection
+ result sets. Never fails.
+ */
+ m_connection->add_result_set(ed_result_set);
+ return FALSE;
+}
+
+
+/** Called to send an error to the client at the end of a statement. */
+
+bool
+Protocol_local::send_error(uint sql_errno, const char *err_msg, const char*)
+{
+ /*
+ Just make sure that nothing is sent to the client (default
+ implementation).
+ */
+ return FALSE;
+}
+
+
+#ifdef EMBEDDED_LIBRARY
+void Protocol_local::remove_last_row()
+{ }
+#endif
diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h
new file mode 100644
index 00000000000..11017b127b1
--- /dev/null
+++ b/sql/sql_prepare.h
@@ -0,0 +1,367 @@
+#ifndef SQL_PREPARE_H
+#define SQL_PREPARE_H
+/* Copyright (C) 1995-2008 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "sql_error.h"
+
+class THD;
+struct LEX;
+
+/**
+ An interface that is used to take an action when
+ the locking module notices that a table version has changed
+ since the last execution. "Table" here may refer to any kind of
+ table -- a base table, a temporary table, a view or an
+ information schema table.
+
+ When we open and lock tables for execution of a prepared
+ statement, we must verify that they did not change
+ since statement prepare. If some table did change, the statement
+ parse tree *may* be no longer valid, e.g. in case it contains
+ optimizations that depend on table metadata.
+
+ This class provides an interface (a method) that is
+ invoked when such a situation takes place.
+ The implementation of the method simply reports an error, but
+ the exact details depend on the nature of the SQL statement.
+
+ At most 1 instance of this class is active at a time, in which
+ case THD::m_reprepare_observer is not NULL.
+
+ @sa check_and_update_table_version() for details of the
+ version tracking algorithm
+
+ @sa Open_tables_state::m_reprepare_observer for the life cycle
+ of metadata observers.
+*/
+
+class Reprepare_observer
+{
+public:
+ /**
+ Check if a change of metadata is OK. In future
+ the signature of this method may be extended to accept the old
+ and the new versions, but since currently the check is very
+ simple, we only need the THD to report an error.
+ */
+ bool report_error(THD *thd);
+ bool is_invalidated() const { return m_invalidated; }
+ void reset_reprepare_observer() { m_invalidated= FALSE; }
+private:
+ bool m_invalidated;
+};
+
+
+void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length);
+void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length);
+void mysqld_stmt_close(THD *thd, char *packet);
+void mysql_sql_stmt_prepare(THD *thd);
+void mysql_sql_stmt_execute(THD *thd);
+void mysql_sql_stmt_close(THD *thd);
+void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length);
+void mysqld_stmt_reset(THD *thd, char *packet);
+void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
+void reinit_stmt_before_use(THD *thd, LEX *lex);
+
+/**
+ Execute a fragment of server code in an isolated context, so that
+ it doesn't leave any effect on THD. THD must have no open tables.
+ The code must not leave any open tables around.
+ The result of execution (if any) is stored in Ed_result.
+*/
+
+class Server_runnable
+{
+public:
+ virtual bool execute_server_code(THD *thd)= 0;
+ virtual ~Server_runnable();
+};
+
+
+/**
+ Execute direct interface.
+
+ @todo Implement support for prelocked mode.
+*/
+
+class Ed_row;
+
+/**
+ Ed_result_set -- a container with result set rows.
+ @todo Implement support for result set metadata and
+ automatic type conversion.
+*/
+
+class Ed_result_set: public Sql_alloc
+{
+public:
+ operator List<Ed_row>&() { return *m_rows; }
+ unsigned int size() const { return m_rows->elements; }
+
+ Ed_result_set(List<Ed_row> *rows_arg, size_t column_count,
+ MEM_ROOT *mem_root_arg);
+
+ /** We don't call member destructors, they all are POD types. */
+ ~Ed_result_set() {}
+
+ size_t get_field_count() const { return m_column_count; }
+
+ static void operator delete(void *ptr, size_t size) throw ();
+private:
+ Ed_result_set(const Ed_result_set &); /* not implemented */
+ Ed_result_set &operator=(Ed_result_set &); /* not implemented */
+private:
+ MEM_ROOT m_mem_root;
+ size_t m_column_count;
+ List<Ed_row> *m_rows;
+ Ed_result_set *m_next_rset;
+ friend class Ed_connection;
+};
+
+
+class Ed_connection
+{
+public:
+ /**
+ Construct a new "execute direct" connection.
+
+ The connection can be used to execute SQL statements.
+ If the connection failed to initialize, the error
+ will be returned on the attempt to execute a statement.
+
+ @pre thd must have no open tables
+ while the connection is used. However,
+ Ed_connection works okay in LOCK TABLES mode.
+ Other properties of THD, such as the current warning
+ information, errors, etc. do not matter and are
+ preserved by Ed_connection. One thread may have many
+ Ed_connections created for it.
+ */
+ Ed_connection(THD *thd);
+
+ /**
+ Execute one SQL statement.
+
+ Until this method is executed, no other methods of
+ Ed_connection can be used. Life cycle of Ed_connection is:
+
+ Initialized -> a statement has been executed ->
+ look at result, move to next result ->
+ look at result, move to next result ->
+ ...
+ moved beyond the last result == Initialized.
+
+ This method can be called repeatedly. Once it's invoked,
+ results of the previous execution are lost.
+
+ A result of execute_direct() can be either:
+
+ - success, no result set rows. In this case get_field_count()
+ returns 0. This happens after execution of INSERT, UPDATE,
+ DELETE, DROP and similar statements. Some other methods, such
+ as get_affected_rows() can be used to retrieve additional
+ result information.
+
+ - success, there are some result set rows (maybe 0). E.g.
+ happens after SELECT. In this case get_field_count() returns
+ the number of columns in a result set and store_result()
+ can be used to retrieve a result set..
+
+ - an error, methods to retrieve error information can
+ be used.
+
+ @return execution status
+ @retval FALSE success, use get_field_count()
+ to determine what to do next.
+ @retval TRUE error, use get_last_error()
+ to see the error number.
+ */
+ bool execute_direct(LEX_STRING sql_text);
+
+ /**
+ Same as the previous, but takes an instance of Server_runnable
+ instead of SQL statement text.
+
+ @return execution status
+
+ @retval FALSE success, use get_field_count()
+ if your code fragment is supposed to
+ return a result set
+ @retval TRUE failure
+ */
+ bool execute_direct(Server_runnable *server_runnable);
+
+ /**
+ Get the number of result set fields.
+
+ This method is valid only if we have a result:
+ execute_direct() has been called. Otherwise
+ the returned value is undefined.
+
+ @sa Documentation for C API function
+ mysql_field_count()
+ */
+ ulong get_field_count() const
+ {
+ return m_current_rset ? m_current_rset->get_field_count() : 0;
+ }
+
+ /**
+ Get the number of affected (deleted, updated)
+ rows for the current statement. Can be
+ used for statements with get_field_count() == 0.
+
+ @sa Documentation for C API function
+ mysql_affected_rows().
+ */
+ ulonglong get_affected_rows() const
+ {
+ return m_diagnostics_area.affected_rows();
+ }
+
+ /**
+ Get the last insert id, if any.
+
+ @sa Documentation for mysql_insert_id().
+ */
+ ulonglong get_last_insert_id() const
+ {
+ return m_diagnostics_area.last_insert_id();
+ }
+
+ /**
+ Get the total number of warnings for the last executed
+ statement. Note, that there is only one warning list even
+ if a statement returns multiple results.
+
+ @sa Documentation for C API function
+ mysql_num_warnings().
+ */
+ ulong get_warn_count() const
+ {
+ return m_warning_info.warn_count();
+ }
+ /**
+ Get the server warnings as a result set.
+ The result set has fixed metadata:
+ The first column is the level.
+ The second is a numeric code.
+ The third is warning text.
+ */
+ List<MYSQL_ERROR> *get_warn_list() { return &m_warning_info.warn_list(); }
+ /**
+ The following members are only valid if execute_direct()
+ or move_to_next_result() returned an error.
+ They never fail, but if they are called when there is no
+ result, or no error, the result is not defined.
+ */
+ const char *get_last_error() const { return m_diagnostics_area.message(); }
+ unsigned int get_last_errno() const { return m_diagnostics_area.sql_errno(); }
+ const char *get_last_sqlstate() const { return m_diagnostics_area.get_sqlstate(); }
+
+ /**
+ Provided get_field_count() is not 0, this never fails. You don't
+ need to free the result set, this is done automatically when
+ you advance to the next result set or destroy the connection.
+ Not returning const because of List iterator not accepting
+ Should be used when you would like Ed_connection to manage
+ result set memory for you.
+ */
+ Ed_result_set *use_result_set() { return m_current_rset; }
+ /**
+ Provided get_field_count() is not 0, this never fails. You
+ must free the returned result set. This can be called only
+ once after execute_direct().
+ Should be used when you would like to get the results
+ and destroy the connection.
+ */
+ Ed_result_set *store_result_set();
+
+ /**
+ If the query returns multiple results, this method
+ can be checked if there is another result beyond the next
+ one.
+ Never fails.
+ */
+ bool has_next_result() const { return test(m_current_rset->m_next_rset); }
+ /**
+ Only valid to call if has_next_result() returned true.
+ Otherwise the result is undefined.
+ */
+ bool move_to_next_result()
+ {
+ m_current_rset= m_current_rset->m_next_rset;
+ return test(m_current_rset);
+ }
+
+ ~Ed_connection() { free_old_result(); }
+private:
+ Diagnostics_area m_diagnostics_area;
+ Warning_info m_warning_info;
+ /**
+ Execute direct interface does not support multi-statements, only
+ multi-results. So we never have a situation when we have
+ a mix of result sets and OK or error packets. We either
+ have a single result set, a single error, or a single OK,
+ or we have a series of result sets, followed by an OK or error.
+ */
+ THD *m_thd;
+ Ed_result_set *m_rsets;
+ Ed_result_set *m_current_rset;
+ friend class Protocol_local;
+private:
+ void free_old_result();
+ void add_result_set(Ed_result_set *ed_result_set);
+private:
+ Ed_connection(const Ed_connection &); /* not implemented */
+ Ed_connection &operator=(Ed_connection &); /* not implemented */
+};
+
+
+/** One result set column. */
+
+struct Ed_column: public LEX_STRING
+{
+ /** Implementation note: destructor for this class is never called. */
+};
+
+
+/** One result set record. */
+
+class Ed_row: public Sql_alloc
+{
+public:
+ const Ed_column &operator[](const unsigned int column_index) const
+ {
+ return *get_column(column_index);
+ }
+ const Ed_column *get_column(const unsigned int column_index) const
+ {
+ DBUG_ASSERT(column_index < size());
+ return m_column_array + column_index;
+ }
+ size_t size() const { return m_column_count; }
+
+ Ed_row(Ed_column *column_array_arg, size_t column_count_arg)
+ :m_column_array(column_array_arg),
+ m_column_count(column_count_arg)
+ {}
+private:
+ Ed_column *m_column_array;
+ size_t m_column_count; /* TODO: change to point to metadata */
+};
+
+#endif // SQL_PREPARE_H
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 8c9b147089f..69e5bc3cbb4 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -47,7 +47,7 @@ const char * const _unknown_func_ = "<unknown>";
int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables,
Item *cond)
{
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
return(thd->profiling.fill_statistics_info(thd, tables, cond));
#else
my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILE", "enable-profiling");
@@ -129,7 +129,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table)
}
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
#define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec)
#define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2)))
@@ -415,7 +415,7 @@ bool PROFILING::show_profiles()
MYSQL_TYPE_DOUBLE));
field_list.push_back(new Item_empty_string("Query", 40));
- if (thd->protocol->send_fields(&field_list,
+ if (thd->protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_profile.h b/sql/sql_profile.h
index 245959e0953..bffe1cb576b 100644
--- a/sql/sql_profile.h
+++ b/sql/sql_profile.h
@@ -41,7 +41,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table);
#define PROFILE_ALL (uint)(~0)
-#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+#if defined(ENABLED_PROFILING)
#include "mysql_priv.h"
#ifdef HAVE_SYS_RESOURCE_H
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 0e0b8eb60b9..dac96f2e9c4 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -177,7 +177,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
/* Lets hope this doesn't fail as the result will be messy */
if (!silent && !error)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
my_ok(thd);
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 3481092fe35..4e5ce08ab5d 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -377,7 +377,7 @@ static ulonglong get_heartbeat_period(THD * thd)
my_bool null_value;
LEX_STRING name= { C_STRING_WITH_LEN("master_heartbeat_period")};
user_var_entry *entry=
- (user_var_entry*) hash_search(&thd->user_vars, (uchar*) name.str,
+ (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name.str,
name.length);
return entry? entry->val_int(&null_value) : 0;
}
@@ -1674,7 +1674,7 @@ bool mysql_show_binlog_events(THD* thd)
DBUG_ENTER("mysql_show_binlog_events");
Log_event::init_show_field_list(&field_list);
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -1849,7 +1849,7 @@ bool show_binlog_info(THD* thd)
field_list.push_back(new Item_empty_string("Binlog_Do_DB",255));
field_list.push_back(new Item_empty_string("Binlog_Ignore_DB",255));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
@@ -1901,7 +1901,7 @@ bool show_binlogs(THD* thd)
field_list.push_back(new Item_empty_string("Log_name", 255));
field_list.push_back(new Item_return_int("File_size", 20,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1d19ba7e96e..13197d44ce2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -150,6 +150,7 @@ static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
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 void join_read_key_unlock_row(st_join_table *tab);
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);
@@ -242,7 +243,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
bool res;
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
- MYSQL_SELECT_START(thd->query);
+ MYSQL_SELECT_START(thd->query());
if (select_lex->master_unit()->is_union() ||
select_lex->master_unit()->fake_select_lex)
@@ -637,6 +638,18 @@ JOIN::prepare(Item ***rref_pointer_array,
MYF(0)); /* purecov: inspected */
goto err; /* purecov: inspected */
}
+ if (thd->lex->derived_tables)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE",
+ thd->lex->derived_tables & DERIVED_VIEW ?
+ "view" : "subquery");
+ goto err;
+ }
+ if (thd->lex->sql_command != SQLCOM_SELECT)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "non-SELECT");
+ goto err;
+ }
}
if (!procedure && result && result->prepare(fields_list, unit_arg))
@@ -973,6 +986,12 @@ JOIN::optimize()
DBUG_RETURN(1);
}
+ if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields())
+ {
+ DBUG_PRINT("error", ("Error: rollup_process_fields() failed"));
+ DBUG_RETURN(1);
+ }
+
/* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables);
thd_proc_info(thd, "preparing");
@@ -1002,13 +1021,13 @@ JOIN::optimize()
}
if (const_tables && !thd->locked_tables &&
!(select_options & SELECT_NO_UNLOCK))
- mysql_unlock_some_tables(thd, table, const_tables);
+ mysql_unlock_some_tables(thd, all_tables, const_tables);
if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true
}
- select= make_select(*table, const_table_map,
+ select= make_select(*all_tables, const_table_map,
const_table_map, conds, 1, &error);
if (error)
{ /* purecov: inspected */
@@ -1103,7 +1122,7 @@ JOIN::optimize()
join_tab[const_tables].select->quick->get_type() !=
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
{
- if (group_list &&
+ if (group_list && rollup.state == ROLLUP::STATE_NONE &&
list_contains_unique_index(join_tab[const_tables].table,
find_field_in_order_list,
(void *) group_list))
@@ -1147,7 +1166,8 @@ JOIN::optimize()
if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE)
select_distinct=0;
}
- else if (select_distinct && tables - const_tables == 1)
+ else if (select_distinct && tables - const_tables == 1 &&
+ rollup.state == ROLLUP::STATE_NONE)
{
/*
We are only using one table. In this case we change DISTINCT to a
@@ -1700,8 +1720,8 @@ JOIN::exec()
(zero_result_cause?zero_result_cause:"No tables used"));
else
{
- if (result->send_fields(*columns_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ if (result->send_result_set_metadata(*columns_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
DBUG_VOID_RETURN;
}
@@ -2104,7 +2124,7 @@ JOIN::exec()
}
if (curr_join->group_list || curr_join->order)
{
- DBUG_PRINT("info",("Sorting for send_fields"));
+ DBUG_PRINT("info",("Sorting for send_result_set_metadata"));
thd_proc_info(thd, "Sorting result");
/* If we have already done the group, add HAVING to sorted table */
if (curr_join->tmp_having && ! curr_join->group_list &&
@@ -2244,7 +2264,7 @@ JOIN::exec()
{
thd_proc_info(thd, "Sending data");
DBUG_PRINT("info", ("%s", thd->proc_info));
- result->send_fields((procedure ? curr_join->procedure_fields_list :
+ result->send_result_set_metadata((procedure ? curr_join->procedure_fields_list :
*curr_fields_list),
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
error= do_select(curr_join, curr_fields_list, NULL, procedure);
@@ -2931,7 +2951,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
join->join_tab=stat;
join->map2table=stat_ref;
- join->table= join->all_tables=table_vector;
+ join->all_tables= table_vector;
join->const_tables=const_count;
join->found_const_table_map=found_const_table_map;
@@ -3587,7 +3607,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
{
if (!(form->keys_in_use_for_query.is_set(key)))
continue;
- if (form->key_info[key].flags & HA_FULLTEXT)
+ if (form->key_info[key].flags & (HA_FULLTEXT | HA_SPATIAL))
continue; // ToDo: ft-keys in non-ft queries. SerG
uint key_parts= (uint) form->key_info[key].key_parts;
@@ -5085,8 +5105,8 @@ greedy_search(JOIN *join,
the interleaving state to the one of the non-extended partial plan
on exit.
*/
- IF_DBUG(bool is_interleave_error= )
- check_interleaving_with_nj (best_table);
+ bool is_interleave_error __attribute__((unused))=
+ check_interleaving_with_nj (best_table);
/* This has been already checked by best_extension_by_limited_search */
DBUG_ASSERT(!is_interleave_error);
@@ -5622,7 +5642,7 @@ get_best_combination(JOIN *join)
{
TABLE *form;
*j= *join->best_positions[tablenr].table;
- form=join->table[tablenr]=j->table;
+ form=join->all_tables[tablenr]=j->table;
used_tables|= form->map;
form->reginfo.join_tab=j;
if (!*j->on_expr_ref)
@@ -5717,7 +5737,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
}
j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
j->ref.key_err=1;
+ j->ref.has_record= FALSE;
j->ref.null_rejecting= 0;
+ j->ref.use_count= 0;
keyuse=org_keyuse;
store_key **ref_key= j->ref.key_copy;
@@ -5894,7 +5916,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
DBUG_RETURN(TRUE); /* purecov: inspected */
join_tab= parent->join_tab_reexec;
- table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table;
+ parent->table_reexec[0]= tmp_table;
tables= 1;
const_tables= 0;
const_table_map= 0;
@@ -6550,6 +6572,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
DBUG_RETURN(0);
}
+
+/**
+ The default implementation of unlock-row method of READ_RECORD,
+ used in all access methods.
+*/
+
+void rr_unlock_row(st_join_table *tab)
+{
+ READ_RECORD *info= &tab->read_record;
+ info->file->unlock_row();
+}
+
+
+
static void
make_join_readinfo(JOIN *join, ulonglong options)
{
@@ -6565,6 +6601,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
TABLE *table=tab->table;
tab->read_record.table= table;
tab->read_record.file=table->file;
+ tab->read_record.unlock_row= rr_unlock_row;
tab->next_select=sub_select; /* normal select */
/*
@@ -6610,6 +6647,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
delete tab->quick;
tab->quick=0;
tab->read_first_record= join_read_key;
+ tab->read_record.unlock_row= join_read_key_unlock_row;
tab->read_record.read_record= join_no_more_records;
if (table->covering_keys.is_set(tab->ref.key) &&
!table->no_keyread)
@@ -6926,24 +6964,23 @@ void JOIN::cleanup(bool full)
{
DBUG_ENTER("JOIN::cleanup");
- if (table)
+ if (all_tables)
{
JOIN_TAB *tab,*end;
/*
Only a sorted table may be cached. This sorted table is always the
- first non const table in join->table
+ first non const table in join->all_tables
*/
if (tables > const_tables) // Test for not-const tables
{
- free_io_cache(table[const_tables]);
- filesort_free_buffers(table[const_tables],full);
+ free_io_cache(all_tables[const_tables]);
+ filesort_free_buffers(all_tables[const_tables],full);
}
if (full)
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup();
- table= 0;
}
else
{
@@ -7242,7 +7279,7 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
if (having && having->val_int() == 0)
send_row=0;
}
- if (!(result->send_fields(fields,
+ if (!(result->send_result_set_metadata(fields,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
{
bool send_error= FALSE;
@@ -7272,7 +7309,7 @@ static void clear_tables(JOIN *join)
are not re-calculated.
*/
for (uint i=join->const_tables ; i < join->tables ; i++)
- mark_as_null_row(join->table[i]); // All fields are NULL
+ mark_as_null_row(join->all_tables[i]); // All fields are NULL
}
/*****************************************************************************
@@ -9072,7 +9109,10 @@ static void restore_prev_nj_state(JOIN_TAB *last)
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
else if (last_emb->nested_join->join_list.elements-1 ==
last_emb->nested_join->counter)
+ {
join->cur_embedding_map|= last_emb->nested_join->nj_map;
+ break;
+ }
else
break;
last_emb= last_emb->embedding;
@@ -9302,7 +9342,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
thd->substitute_null_with_insert_id))
{
#ifdef HAVE_QUERY_CACHE
- query_cache_abort(&thd->net);
+ query_cache_abort(&thd->query_cache_tls);
#endif
COND *new_cond;
if ((new_cond= new Item_func_eq(args[0],
@@ -9571,8 +9611,47 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
new_field->set_derivation(item->collation.derivation);
break;
case DECIMAL_RESULT:
- new_field= Field_new_decimal::new_decimal_field(item);
+ {
+ uint8 dec= item->decimals;
+ uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec;
+ uint32 len= item->max_length;
+
+ /*
+ Trying to put too many digits overall in a DECIMAL(prec,dec)
+ will always throw a warning. We must limit dec to
+ DECIMAL_MAX_SCALE however to prevent an assert() later.
+ */
+
+ if (dec > 0)
+ {
+ signed int overflow;
+
+ dec= min(dec, DECIMAL_MAX_SCALE);
+
+ /*
+ If the value still overflows the field with the corrected dec,
+ we'll throw out decimals rather than integers. This is still
+ bad and of course throws a truncation warning.
+ +1: for decimal point
+ */
+
+ const int required_length=
+ my_decimal_precision_to_length(intg + dec, dec,
+ item->unsigned_flag);
+
+ overflow= required_length - len;
+
+ if (overflow > 0)
+ dec= max(0, dec - overflow); // too long, discard fract
+ else
+ /* Corrected value fits. */
+ len= required_length;
+ }
+
+ new_field= new Field_new_decimal(len, maybe_null, item->name,
+ dec, item->unsigned_flag);
break;
+ }
case ROW_RESULT:
default:
// This case should never be choosen
@@ -9816,7 +9895,7 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
Create a temp table according to a field list.
Given field pointers are changed to point at tmp_table for
- send_fields. The table object is self contained: it's
+ send_result_set_metadata. The table object is self contained: it's
allocated in its own memory root, as well as Field objects
created for table columns.
This function will replace Item_sum items in 'fields' list with
@@ -10374,6 +10453,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
for (; cur_group ; cur_group= cur_group->next, key_part_info++)
{
Field *field=(*cur_group->item)->get_tmp_table_field();
+ DBUG_ASSERT(field->table == table);
bool maybe_null=(*cur_group->item)->maybe_null;
key_part_info->null_bit=0;
key_part_info->field= field;
@@ -11082,26 +11162,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (error == NESTED_LOOP_NO_MORE_ROWS)
error= NESTED_LOOP_OK;
- if (error == NESTED_LOOP_OK)
- {
- /*
- Sic: this branch works even if rc != 0, e.g. when
- send_data above returns an error.
- */
- if (!table) // If sending data to client
- {
- /*
- The following will unlock all cursors if the command wasn't an
- update command
- */
- join->join_free(); // Unlock all cursors
- if (join->result->send_eof())
- rc= 1; // Don't send error
- }
- DBUG_PRINT("info",("%ld records output", (long) join->send_records));
- }
- else
- rc= -1;
+
if (table)
{
int tmp, new_errno= 0;
@@ -11118,6 +11179,29 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (new_errno)
table->file->print_error(new_errno,MYF(0));
}
+ else
+ {
+ /*
+ The following will unlock all cursors if the command wasn't an
+ update command
+ */
+ join->join_free(); // Unlock all cursors
+ }
+ if (error == NESTED_LOOP_OK)
+ {
+ /*
+ Sic: this branch works even if rc != 0, e.g. when
+ send_data above returns an error.
+ */
+ if (!table) // If sending data to client
+ {
+ if (join->result->send_eof())
+ rc= 1; // Don't send error
+ }
+ DBUG_PRINT("info",("%ld records output", (long) join->send_records));
+ }
+ else
+ rc= -1;
#ifndef DBUG_OFF
if (rc)
{
@@ -11351,6 +11435,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
bool not_used_in_distinct=join_tab->not_used_in_distinct;
ha_rows found_records=join->found_records;
COND *select_cond= join_tab->select_cond;
+ bool select_cond_result= TRUE;
if (error > 0 || (join->thd->is_error())) // Fatal error
return NESTED_LOOP_ERROR;
@@ -11362,7 +11447,17 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
return NESTED_LOOP_KILLED; /* purecov: inspected */
}
DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
- if (!select_cond || select_cond->val_int())
+
+ if (select_cond)
+ {
+ select_cond_result= test(select_cond->val_int());
+
+ /* check for errors evaluating the condition */
+ if (join->thd->is_error())
+ return NESTED_LOOP_ERROR;
+ }
+
+ if (!select_cond || select_cond_result)
{
/*
There is no select condition or the attached pushed down
@@ -11448,7 +11543,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
else
{
join->thd->warning_info->inc_current_row_for_warning();
- join_tab->read_record.file->unlock_row();
+ join_tab->read_record.unlock_row(join_tab);
}
}
else
@@ -11459,7 +11554,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
*/
join->examined_rows++;
join->thd->warning_info->inc_current_row_for_warning();
- join_tab->read_record.file->unlock_row();
+ join_tab->read_record.unlock_row(join_tab);
}
return NESTED_LOOP_OK;
}
@@ -11819,18 +11914,55 @@ join_read_key(JOIN_TAB *tab)
table->status=STATUS_NOT_FOUND;
return -1;
}
+ /*
+ Moving away from the current record. Unlock the row
+ in the handler if it did not match the partial WHERE.
+ */
+ if (tab->ref.has_record && tab->ref.use_count == 0)
+ {
+ tab->read_record.file->unlock_row();
+ tab->ref.has_record= FALSE;
+ }
error=table->file->index_read_map(table->record[0],
tab->ref.key_buff,
make_prev_keypart_map(tab->ref.key_parts),
HA_READ_KEY_EXACT);
if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
+
+ if (! error)
+ {
+ tab->ref.has_record= TRUE;
+ tab->ref.use_count= 1;
+ }
+ }
+ else if (table->status == 0)
+ {
+ DBUG_ASSERT(tab->ref.has_record);
+ tab->ref.use_count++;
}
table->null_row=0;
return table->status ? -1 : 0;
}
+/**
+ Since join_read_key may buffer a record, do not unlock
+ it if it was not used in this invocation of join_read_key().
+ Only count locks, thus remembering if the record was left unused,
+ and unlock already when pruning the current value of
+ TABLE_REF buffer.
+ @sa join_read_key()
+*/
+
+static void
+join_read_key_unlock_row(st_join_table *tab)
+{
+ DBUG_ASSERT(tab->ref.use_count);
+ if (tab->ref.use_count)
+ tab->ref.use_count--;
+}
+
/*
ref access method implementation: "read_first" function
@@ -11965,10 +12097,8 @@ join_init_quick_read_record(JOIN_TAB *tab)
}
-int rr_sequential(READ_RECORD *info);
-int init_read_record_seq(JOIN_TAB *tab)
+int read_first_record_seq(JOIN_TAB *tab)
{
- tab->read_record.read_record= rr_sequential;
if (tab->read_record.file->ha_rnd_init(1))
return 1;
return (*tab->read_record.read_record)(&tab->read_record);
@@ -13978,8 +14108,8 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
extra_length= ALIGN_SIZE(key_length)-key_length;
}
- if (hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0,
- key_length, (hash_get_key) 0, 0, 0))
+ if (my_hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0,
+ key_length, (my_hash_get_key) 0, 0, 0))
{
my_free((char*) key_buffer,MYF(0));
DBUG_RETURN(1);
@@ -14020,7 +14150,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
key_pos+= *field_length++;
}
/* Check if it exists before */
- if (hash_search(&hash, org_key_pos, key_length))
+ if (my_hash_search(&hash, org_key_pos, key_length))
{
/* Duplicated found ; Remove the row */
if ((error=file->ha_delete_row(record)))
@@ -14031,14 +14161,14 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
key_pos+=extra_length;
}
my_free((char*) key_buffer,MYF(0));
- hash_free(&hash);
+ my_hash_free(&hash);
file->extra(HA_EXTRA_NO_CACHE);
(void) file->ha_rnd_end();
DBUG_RETURN(0);
err:
my_free((char*) key_buffer,MYF(0));
- hash_free(&hash);
+ my_hash_free(&hash);
file->extra(HA_EXTRA_NO_CACHE);
(void) file->ha_rnd_end();
if (error)
@@ -15074,7 +15204,7 @@ test_if_group_changed(List<Cached_item> &list)
Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
Change old item_field to use a new field with points at saved fieldvalue
- This function is only called before use of send_fields.
+ This function is only called before use of send_result_set_metadata.
@param thd THD pointer
@param param temporary table parameters
@@ -15105,7 +15235,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
Item *pos;
List_iterator_fast<Item> li(all_fields);
Copy_field *copy= NULL;
- IF_DBUG(Copy_field *copy_start);
+ Copy_field *copy_start __attribute__((unused));
res_selected_fields.empty();
res_all_fields.empty();
List_iterator_fast<Item> itr(res_all_fields);
@@ -15118,7 +15248,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
goto err2;
param->copy_funcs.empty();
- IF_DBUG(copy_start= copy);
+ copy_start= copy;
for (i= 0; (pos= li++); i++)
{
Field *field;
@@ -15314,7 +15444,7 @@ bool JOIN::alloc_func_list()
Initialize 'sum_funcs' array with all Item_sum objects.
@param field_list All items
- @param send_fields Items in select list
+ @param send_result_set_metadata Items in select list
@param before_group_by Set to 1 if this is called before GROUP BY handling
@param recompute Set to TRUE if sum_funcs must be recomputed
@@ -15324,7 +15454,7 @@ bool JOIN::alloc_func_list()
1 error
*/
-bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
+bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_result_set_metadata,
bool before_group_by, bool recompute)
{
List_iterator_fast<Item> it(field_list);
@@ -15346,7 +15476,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
{
rollup.state= ROLLUP::STATE_READY;
- if (rollup_make_fields(field_list, send_fields, &func))
+ if (rollup_make_fields(field_list, send_result_set_metadata, &func))
DBUG_RETURN(TRUE); // Should never happen
}
else if (rollup.state == ROLLUP::STATE_NONE)
@@ -15817,32 +15947,7 @@ bool JOIN::rollup_init()
{
item->maybe_null= 1;
found_in_group= 1;
- if (item->const_item())
- {
- /*
- For ROLLUP queries each constant item referenced in GROUP BY list
- is wrapped up into an Item_func object yielding the same value
- as the constant item. The objects of the wrapper class are never
- considered as constant items and besides they inherit all
- properties of the Item_result_field class.
- This wrapping allows us to ensure writing constant items
- into temporary tables whenever the result of the ROLLUP
- operation has to be written into a temporary table, e.g. when
- ROLLUP is used together with DISTINCT in the SELECT list.
- Usually when creating temporary tables for a intermidiate
- result we do not include fields for constant expressions.
- */
- Item* new_item= new Item_func_rollup_const(item);
- if (!new_item)
- return 1;
- new_item->fix_fields(thd, (Item **) 0);
- thd->change_item_tree(it.ref(), new_item);
- for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
- {
- if (*tmp->item == item)
- thd->change_item_tree(tmp->item, new_item);
- }
- }
+ break;
}
}
if (item->type() == Item::FUNC_ITEM && !found_in_group)
@@ -15861,6 +15966,59 @@ bool JOIN::rollup_init()
}
return 0;
}
+
+/**
+ Wrap all constant Items in GROUP BY list.
+
+ For ROLLUP queries each constant item referenced in GROUP BY list
+ is wrapped up into an Item_func object yielding the same value
+ as the constant item. The objects of the wrapper class are never
+ considered as constant items and besides they inherit all
+ properties of the Item_result_field class.
+ This wrapping allows us to ensure writing constant items
+ into temporary tables whenever the result of the ROLLUP
+ operation has to be written into a temporary table, e.g. when
+ ROLLUP is used together with DISTINCT in the SELECT list.
+ Usually when creating temporary tables for a intermidiate
+ result we do not include fields for constant expressions.
+
+ @retval
+ 0 if ok
+ @retval
+ 1 on error
+*/
+
+bool JOIN::rollup_process_const_fields()
+{
+ ORDER *group_tmp;
+ Item *item;
+ List_iterator<Item> it(all_fields);
+
+ for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
+ {
+ if (!(*group_tmp->item)->const_item())
+ continue;
+ while ((item= it++))
+ {
+ if (*group_tmp->item == item)
+ {
+ Item* new_item= new Item_func_rollup_const(item);
+ if (!new_item)
+ return 1;
+ new_item->fix_fields(thd, (Item **) 0);
+ thd->change_item_tree(it.ref(), new_item);
+ for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
+ {
+ if (*tmp->item == item)
+ thd->change_item_tree(tmp->item, new_item);
+ }
+ break;
+ }
+ }
+ it.rewind();
+ }
+ return 0;
+}
/**
diff --git a/sql/sql_select.h b/sql/sql_select.h
index f7dc09ddc62..e049e4ed765 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -61,6 +61,8 @@ class store_key;
typedef struct st_table_ref
{
bool key_err;
+ /** True if something was read into buffer in join_read_key. */
+ bool has_record;
uint key_parts; ///< num of ...
uint key_length; ///< length of key_buff
int key; ///< key no
@@ -88,6 +90,11 @@ typedef struct st_table_ref
table_map depend_map; ///< Table depends on these tables.
/* null byte position in the key_buf. Used for REF_OR_NULL optimization */
uchar *null_ref_key;
+ /*
+ The number of times the record associated with this key was used
+ in the join.
+ */
+ ha_rows use_count;
} TABLE_REF;
@@ -137,7 +144,6 @@ enum enum_nested_loop_state
typedef enum_nested_loop_state
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
-typedef int (*Read_record_func)(struct st_join_table *tab);
Next_select_func setup_end_select_func(JOIN *join);
@@ -165,7 +171,7 @@ typedef struct st_join_table {
*/
uint packed_info;
- Read_record_func read_first_record;
+ READ_RECORD::Setup_func read_first_record;
Next_select_func next_select;
READ_RECORD read_record;
/*
@@ -173,8 +179,8 @@ typedef struct st_join_table {
if it is executed by an alternative full table scan when the left operand of
the subquery predicate is evaluated to NULL.
*/
- Read_record_func save_read_first_record;/* to save read_first_record */
- int (*save_read_record) (READ_RECORD *);/* to save read_record.read_record */
+ READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */
+ READ_RECORD::Read_func save_read_record;/* to save read_record.read_record */
double worst_seeks;
key_map const_keys; /**< Keys with constant part */
key_map checked_keys; /**< Keys checked in find_best */
@@ -283,7 +289,7 @@ public:
JOIN_TAB *join_tab,**best_ref;
JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs
JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
- TABLE **table,**all_tables,*sort_by_table;
+ TABLE **all_tables,*sort_by_table;
uint tables,const_tables;
uint send_group_parts;
/**
@@ -439,7 +445,7 @@ public:
select_result *result_arg)
{
join_tab= join_tab_save= 0;
- table= 0;
+ all_tables= 0;
tables= 0;
const_tables= 0;
join_list= 0;
@@ -520,6 +526,7 @@ public:
}
bool rollup_init();
+ bool rollup_process_const_fields();
bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
Item_sum ***func);
int rollup_send_data(uint idx);
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 33058887952..8432b68a1d1 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -120,8 +120,8 @@ bool servers_init(bool dont_read_servers_table)
DBUG_RETURN(TRUE);
/* initialise our servers cache */
- if (hash_init(&servers_cache, system_charset_info, 32, 0, 0,
- (hash_get_key) servers_cache_get_key, 0, 0))
+ if (my_hash_init(&servers_cache, system_charset_info, 32, 0, 0,
+ (my_hash_get_key) servers_cache_get_key, 0, 0))
{
return_val= TRUE; /* we failed, out of memory? */
goto end;
@@ -140,7 +140,6 @@ bool servers_init(bool dont_read_servers_table)
DBUG_RETURN(TRUE);
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/*
It is safe to call servers_reload() since servers_* arrays and hashes which
will be freed there are global static objects and thus are initialized
@@ -646,9 +645,10 @@ delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options)
server_options->server_name_length));
- if (!(server= (FOREIGN_SERVER *) hash_search(&servers_cache,
- (uchar*) server_options->server_name,
- server_options->server_name_length)))
+ if (!(server= (FOREIGN_SERVER *)
+ my_hash_search(&servers_cache,
+ (uchar*) server_options->server_name,
+ server_options->server_name_length)))
{
DBUG_PRINT("info", ("server_name %s length %d not found!",
server_options->server_name,
@@ -663,7 +663,7 @@ delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options)
server->server_name,
server->server_name_length));
- VOID(hash_delete(&servers_cache, (uchar*) server));
+ VOID(my_hash_delete(&servers_cache, (uchar*) server));
error= 0;
@@ -770,7 +770,7 @@ int update_server_record_in_cache(FOREIGN_SERVER *existing,
/*
delete the existing server struct from the server cache
*/
- VOID(hash_delete(&servers_cache, (uchar*)existing));
+ VOID(my_hash_delete(&servers_cache, (uchar*)existing));
/*
Insert the altered server struct into the server cache
@@ -965,8 +965,8 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
rw_wrlock(&THR_LOCK_servers);
/* hit the memory first */
- if (hash_search(&servers_cache, (uchar*) server_options->server_name,
- server_options->server_name_length))
+ if (my_hash_search(&servers_cache, (uchar*) server_options->server_name,
+ server_options->server_name_length))
goto end;
@@ -1014,9 +1014,9 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
rw_wrlock(&THR_LOCK_servers);
- if (!(existing= (FOREIGN_SERVER *) hash_search(&servers_cache,
- (uchar*) name.str,
- name.length)))
+ if (!(existing= (FOREIGN_SERVER *) my_hash_search(&servers_cache,
+ (uchar*) name.str,
+ name.length)))
goto end;
altered= (FOREIGN_SERVER *)alloc_root(&mem,
@@ -1195,7 +1195,7 @@ prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
void servers_free(bool end)
{
DBUG_ENTER("servers_free");
- if (!hash_inited(&servers_cache))
+ if (!my_hash_inited(&servers_cache))
DBUG_VOID_RETURN;
if (!end)
{
@@ -1205,7 +1205,7 @@ void servers_free(bool end)
}
rwlock_destroy(&THR_LOCK_servers);
free_root(&mem,MYF(0));
- hash_free(&servers_cache);
+ my_hash_free(&servers_cache);
DBUG_VOID_RETURN;
}
@@ -1286,9 +1286,9 @@ FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name,
DBUG_PRINT("info", ("locking servers_cache"));
rw_rdlock(&THR_LOCK_servers);
- if (!(server= (FOREIGN_SERVER *) hash_search(&servers_cache,
- (uchar*) server_name,
- server_name_length)))
+ if (!(server= (FOREIGN_SERVER *) my_hash_search(&servers_cache,
+ (uchar*) server_name,
+ server_name_length)))
{
DBUG_PRINT("info", ("server_name %s length %u not found!",
server_name, (unsigned) server_name_length));
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 96f166160c6..b9f5015f8f0 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -25,6 +25,7 @@
#include "sql_trigger.h"
#include "authors.h"
#include "contributors.h"
+#include "sql_partition.h"
#ifdef HAVE_EVENT_SCHEDULER
#include "events.h"
#include "event_data_objects.h"
@@ -77,6 +78,12 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
static void store_key_options(THD *thd, String *packet, TABLE *table,
KEY *key_info);
+static void get_cs_converted_string_value(THD *thd,
+ String *input_str,
+ String *output_str,
+ CHARSET_INFO *cs,
+ bool use_hex);
+
static void
append_algorithm(TABLE_LIST *table, String *buff);
@@ -216,7 +223,7 @@ bool mysqld_show_authors(THD *thd)
field_list.push_back(new Item_empty_string("Location",40));
field_list.push_back(new Item_empty_string("Comment",80));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -250,7 +257,7 @@ bool mysqld_show_contributors(THD *thd)
field_list.push_back(new Item_empty_string("Location",40));
field_list.push_back(new Item_empty_string("Comment",80));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -310,6 +317,7 @@ static struct show_privileges_st sys_privileges[]=
{"Shutdown","Server Admin", "To shut down the server"},
{"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
{"Trigger","Tables", "To use triggers"},
+ {"Create tablespace", "Server Admin", "To create/alter/drop tablespaces"},
{"Update", "Tables", "To update existing rows"},
{"Usage","Server Admin","No privileges - allow connect only"},
{NullS, NullS, NullS}
@@ -325,7 +333,7 @@ bool mysqld_show_privileges(THD *thd)
field_list.push_back(new Item_empty_string("Context",15));
field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -472,7 +480,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
table_list.table_name= uname;
table_list.table_name_length= file_name_len;
table_list.grant.privilege=col_access;
- if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1))
+ if (check_grant(thd, TABLE_ACLS, &table_list, TRUE, 1, TRUE))
continue;
}
#endif
@@ -675,7 +683,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
max(buffer.length(),1024)));
}
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
@@ -760,7 +768,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -828,7 +836,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
}
restore_record(table, s->default_values); // Get empty record
table->use_all_columns();
- if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
+ if (thd->protocol->send_result_set_metadata(&field_list, Protocol::SEND_DEFAULTS))
DBUG_VOID_RETURN;
my_eof(thd);
DBUG_VOID_RETURN;
@@ -1486,7 +1494,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
((part_syntax= generate_partition_syntax(table->part_info,
&part_syntax_len,
FALSE,
- show_table_options))))
+ show_table_options,
+ NULL, NULL))))
{
packet->append(STRING_WITH_LEN("\n/*!50100"));
packet->append(part_syntax, part_syntax_len);
@@ -1718,7 +1727,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
field->maybe_null=1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_VOID_RETURN;
@@ -1778,10 +1787,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thd_info->query=0;
/* Lock THD mutex that protects its data when looking at it. */
pthread_mutex_lock(&tmp->LOCK_thd_data);
- if (tmp->query)
+ if (tmp->query())
{
- uint length= min(max_query_length, tmp->query_length);
- thd_info->query=(char*) thd->strmake(tmp->query,length);
+ uint length= min(max_query_length, tmp->query_length());
+ thd_info->query= (char*) thd->strmake(tmp->query(),length);
}
pthread_mutex_unlock(&tmp->LOCK_thd_data);
thread_infos.append(thd_info);
@@ -1906,11 +1915,11 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
pthread_mutex_unlock(&mysys_var->mutex);
/* INFO */
- if (tmp->query)
+ if (tmp->query())
{
- table->field[7]->store(tmp->query,
+ table->field[7]->store(tmp->query(),
min(PROCESS_LIST_INFO_WIDTH,
- tmp->query_length), cs);
+ tmp->query_length()), cs);
table->field[7]->set_notnull();
}
@@ -3099,12 +3108,31 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table,
int error;
char key[MAX_DBKEY_LENGTH];
uint key_length;
+ char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1];
bzero((char*) &table_list, sizeof(TABLE_LIST));
bzero((char*) &tbl, sizeof(TABLE));
- table_list.table_name= table_name->str;
- table_list.db= db_name->str;
+ if (lower_case_table_names)
+ {
+ /*
+ In lower_case_table_names > 0 metadata locking and table definition
+ cache subsystems require normalized (lowercased) database and table
+ names as input.
+ */
+ strmov(db_name_buff, db_name->str);
+ strmov(table_name_buff, table_name->str);
+ my_casedn_str(files_charset_info, db_name_buff);
+ my_casedn_str(files_charset_info, table_name_buff);
+ table_list.db= db_name_buff;
+ table_list.table_name= table_name_buff;
+ }
+ else
+ {
+ table_list.table_name= table_name->str;
+ table_list.db= db_name->str;
+ }
+
key_length= create_table_def_key(thd, key, &table_list, 0);
pthread_mutex_lock(&LOCK_open);
share= get_table_share(thd, &table_list, key,
@@ -3142,7 +3170,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table,
{
tbl.s= share;
table_list.table= &tbl;
- table_list.view= (st_lex*) share->is_view;
+ table_list.view= (LEX*) share->is_view;
res= schema_table->process_table(thd, &table_list, table,
res, db_name, table_name);
closefrm(&tbl, true);
@@ -3771,8 +3799,9 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access;
- check_access(thd,SELECT_ACL | EXTRA_ACL, db_name->str,
- &tables->grant.privilege, 0, 0, test(tables->schema_table));
+ check_access(thd,SELECT_ACL, db_name->str,
+ &tables->grant.privilege, FALSE, FALSE,
+ test(tables->schema_table));
col_access= get_column_grant(thd, &tables->grant,
db_name->str, table_name->str,
field->field_name) & COL_ACLS;
@@ -4213,7 +4242,8 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
proc_tables.table_name= proc_tables.alias= (char*) "proc";
proc_tables.table_name_length= 4;
proc_tables.lock_type= TL_READ;
- full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1, TRUE);
+ full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE,
+ 1, TRUE);
if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
{
DBUG_RETURN(1);
@@ -4627,7 +4657,7 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
Table_triggers_list *triggers= tables->table->triggers;
int event, timing;
- if (check_table_access(thd, TRIGGER_ACL, tables, 1, TRUE))
+ if (check_table_access(thd, TRIGGER_ACL, tables, FALSE, 1, TRUE))
goto ret;
for (event= 0; event < (int)TRG_EVENT_MAX; event++)
@@ -4793,6 +4823,57 @@ static void collect_partition_expr(List<char> &field_list, String *str)
}
return;
}
+
+
+/*
+ Convert a string in a given character set to a string which can be
+ used for FRM file storage in which case use_hex is TRUE and we store
+ the character constants as hex strings in the character set encoding
+ their field have. In the case of SHOW CREATE TABLE and the
+ PARTITIONS information schema table we instead provide utf8 strings
+ to the user and convert to the utf8 character set.
+
+ SYNOPSIS
+ get_cs_converted_part_value_from_string()
+ item Item from which constant comes
+ input_str String as provided by val_str after
+ conversion to character set
+ output_str Out value: The string created
+ cs Character set string is encoded in
+ NULL for INT_RESULT's here
+ use_hex TRUE => hex string created
+ FALSE => utf8 constant string created
+
+ RETURN VALUES
+ TRUE Error
+ FALSE Ok
+*/
+
+int get_cs_converted_part_value_from_string(THD *thd,
+ Item *item,
+ String *input_str,
+ String *output_str,
+ CHARSET_INFO *cs,
+ bool use_hex)
+{
+ if (item->result_type() == INT_RESULT)
+ {
+ longlong value= item->val_int();
+ output_str->set(value, system_charset_info);
+ return FALSE;
+ }
+ if (!input_str)
+ {
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ return TRUE;
+ }
+ get_cs_converted_string_value(thd,
+ input_str,
+ output_str,
+ cs,
+ use_hex);
+ return FALSE;
+}
#endif
@@ -4874,6 +4955,51 @@ static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
return;
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+static int
+get_partition_column_description(THD *thd,
+ partition_info *part_info,
+ part_elem_value *list_value,
+ String &tmp_str)
+{
+ uint num_elements= part_info->part_field_list.elements;
+ uint i;
+ DBUG_ENTER("get_partition_column_description");
+
+ for (i= 0; i < num_elements; i++)
+ {
+ part_column_list_val *col_val= &list_value->col_val_array[i];
+ if (col_val->max_value)
+ tmp_str.append(partition_keywords[PKW_MAXVALUE].str);
+ else if (col_val->null_value)
+ tmp_str.append("NULL");
+ else
+ {
+ char buffer[MAX_KEY_LENGTH];
+ String str(buffer, sizeof(buffer), &my_charset_bin);
+ String val_conv;
+ Item *item= col_val->item_expression;
+
+ if (!(item= part_info->get_column_item(item,
+ part_info->part_field_array[i])))
+ {
+ DBUG_RETURN(1);
+ }
+ String *res= item->val_str(&str);
+ if (get_cs_converted_part_value_from_string(thd, item, res, &val_conv,
+ part_info->part_field_array[i]->charset(),
+ FALSE))
+ {
+ DBUG_RETURN(1);
+ }
+ tmp_str.append(val_conv);
+ }
+ if (i != num_elements - 1)
+ tmp_str.append(",");
+ }
+ DBUG_RETURN(0);
+}
+#endif /* WITH_PARTITION_STORAGE_ENGINE */
static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
@@ -4917,12 +5043,18 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
/* Partition method*/
switch (part_info->part_type) {
case RANGE_PARTITION:
- table->field[7]->store(partition_keywords[PKW_RANGE].str,
- partition_keywords[PKW_RANGE].length, cs);
- break;
case LIST_PARTITION:
- table->field[7]->store(partition_keywords[PKW_LIST].str,
- partition_keywords[PKW_LIST].length, cs);
+ tmp_res.length(0);
+ if (part_info->part_type == RANGE_PARTITION)
+ tmp_res.append(partition_keywords[PKW_RANGE].str,
+ partition_keywords[PKW_RANGE].length);
+ else
+ tmp_res.append(partition_keywords[PKW_LIST].str,
+ partition_keywords[PKW_LIST].length);
+ if (part_info->column_list)
+ tmp_res.append(partition_keywords[PKW_COLUMNS].str,
+ partition_keywords[PKW_COLUMNS].length);
+ table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
break;
case HASH_PARTITION:
tmp_res.length(0);
@@ -5000,36 +5132,70 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
/* Partition description */
if (part_info->part_type == RANGE_PARTITION)
{
- if (part_elem->range_value != LONGLONG_MAX)
- table->field[11]->store((longlong) part_elem->range_value, FALSE);
+ if (part_info->column_list)
+ {
+ List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
+ part_elem_value *list_value= list_val_it++;
+ tmp_str.length(0);
+ if (get_partition_column_description(thd,
+ part_info,
+ list_value,
+ tmp_str))
+ {
+ DBUG_RETURN(1);
+ }
+ table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
+ }
else
- table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
+ {
+ if (part_elem->range_value != LONGLONG_MAX)
+ table->field[11]->store((longlong) part_elem->range_value, FALSE);
+ else
+ table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
partition_keywords[PKW_MAXVALUE].length, cs);
+ }
table->field[11]->set_notnull();
}
else if (part_info->part_type == LIST_PARTITION)
{
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
part_elem_value *list_value;
- uint no_items= part_elem->list_val_list.elements;
+ uint num_items= part_elem->list_val_list.elements;
tmp_str.length(0);
tmp_res.length(0);
if (part_elem->has_null_value)
{
tmp_str.append("NULL");
- if (no_items > 0)
+ if (num_items > 0)
tmp_str.append(",");
}
while ((list_value= list_val_it++))
{
- if (!list_value->unsigned_flag)
- tmp_res.set(list_value->value, cs);
+ if (part_info->column_list)
+ {
+ if (part_info->part_field_list.elements > 1U)
+ tmp_str.append("(");
+ if (get_partition_column_description(thd,
+ part_info,
+ list_value,
+ tmp_str))
+ {
+ DBUG_RETURN(1);
+ }
+ if (part_info->part_field_list.elements > 1U)
+ tmp_str.append(")");
+ }
else
- tmp_res.set((ulonglong)list_value->value, cs);
- tmp_str.append(tmp_res);
- if (--no_items != 0)
+ {
+ if (!list_value->unsigned_flag)
+ tmp_res.set(list_value->value, cs);
+ else
+ tmp_res.set((ulonglong)list_value->value, cs);
+ tmp_str.append(tmp_res);
+ }
+ if (--num_items != 0)
tmp_str.append(",");
- };
+ }
table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
table->field[11]->set_notnull();
}
@@ -6320,7 +6486,7 @@ ST_FIELD_INFO proc_fields_info[]=
{"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Created", SKIP_OPEN_TABLE},
{"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Modified", SKIP_OPEN_TABLE},
{"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
- {"ROUTINE_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment",
+ {"ROUTINE_COMMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Comment",
SKIP_OPEN_TABLE},
{"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
{"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
@@ -6533,7 +6699,7 @@ ST_FIELD_INFO partitions_fields_info[]=
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
{"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
- {"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
+ {"PARTITION_METHOD", 18, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0,
@@ -6936,7 +7102,7 @@ static bool show_create_trigger_impl(THD *thd,
fields.push_back(new Item_empty_string("Database Collation",
MY_CS_NAME_SIZE));
- if (p->send_fields(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ if (p->send_result_set_metadata(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
return TRUE;
/* Send data. */
@@ -7095,7 +7261,7 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name)
if (!lst)
return TRUE;
- if (check_table_access(thd, TRIGGER_ACL, lst, 1, TRUE))
+ if (check_table_access(thd, TRIGGER_ACL, lst, FALSE, 1, TRUE))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "TRIGGER");
return TRUE;
@@ -7149,3 +7315,95 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name)
status and client connection will be closed.
*/
}
+
+/*
+ Convert a string in character set in column character set format
+ to utf8 character set if possible, the utf8 character set string
+ will later possibly be converted to character set used by client.
+ Thus we attempt conversion from column character set to both
+ utf8 and to character set client.
+
+ Examples of strings that should fail conversion to utf8 are unassigned
+ characters as e.g. 0x81 in cp1250 (Windows character set for for countries
+ like Czech and Poland). Example of string that should fail conversion to
+ character set on client (e.g. if this is latin1) is 0x2020 (daggger) in
+ ucs2.
+
+ If the conversion fails we will as a fall back convert the string to
+ hex encoded format. The caller of the function can also ask for hex
+ encoded format of output string unconditionally.
+
+ SYNOPSIS
+ get_cs_converted_string_value()
+ thd Thread object
+ input_str Input string in cs character set
+ output_str Output string to be produced in utf8
+ cs Character set of input string
+ use_hex Use hex string unconditionally
+
+
+ RETURN VALUES
+ No return value
+*/
+
+static void get_cs_converted_string_value(THD *thd,
+ String *input_str,
+ String *output_str,
+ CHARSET_INFO *cs,
+ bool use_hex)
+{
+
+ output_str->length(0);
+ if (input_str->length() == 0)
+ {
+ output_str->append("''");
+ return;
+ }
+ if (!use_hex)
+ {
+ String try_val;
+ uint try_conv_error= 0;
+
+ try_val.copy(input_str->ptr(), input_str->length(), cs,
+ thd->variables.character_set_client, &try_conv_error);
+ if (!try_conv_error)
+ {
+ String val;
+ uint conv_error= 0;
+
+ val.copy(input_str->ptr(), input_str->length(), cs,
+ system_charset_info, &conv_error);
+ if (!conv_error)
+ {
+ append_unescaped(output_str, val.ptr(), val.length());
+ return;
+ }
+ }
+ /* We had a conversion error, use hex encoded string for safety */
+ }
+ {
+ const uchar *ptr;
+ uint i, len;
+ char buf[3];
+
+ output_str->append("_");
+ output_str->append(cs->csname);
+ output_str->append(" ");
+ output_str->append("0x");
+ len= input_str->length();
+ ptr= (uchar*)input_str->ptr();
+ for (i= 0; i < len; i++)
+ {
+ uint high, low;
+
+ high= (*ptr) >> 4;
+ low= (*ptr) & 0x0F;
+ buf[0]= _dig_vec_upper[high];
+ buf[1]= _dig_vec_upper[low];
+ buf[2]= 0;
+ output_str->append((const char*)buf);
+ ptr++;
+ }
+ }
+ return;
+}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 7b10aafbff1..75dc1163eec 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -123,6 +123,11 @@ public:
(void) realloc(str_length);
return Ptr;
}
+ LEX_STRING lex_string() const
+ {
+ LEX_STRING lex_string = { (char*) ptr(), length() };
+ return lex_string;
+ }
void set(String &str,uint32 offset,uint32 arg_length)
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 91106fcabac..cc46dc1ae7a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1585,7 +1585,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
{
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ lpt->create_info,
+ lpt->alter_info)))
{
DBUG_RETURN(TRUE);
}
@@ -1677,7 +1679,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
char *tmp_part_syntax_str;
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ lpt->create_info,
+ lpt->alter_info)))
{
error= 1;
goto err;
@@ -2056,6 +2060,12 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
DBUG_PRINT("table", ("table: 0x%lx s: 0x%lx", (long) table->table,
table->table ? (long) table->table->s : (long) -1));
+
+ DBUG_EXECUTE_IF("bug43138",
+ my_printf_error(ER_BAD_TABLE_ERROR,
+ ER(ER_BAD_TABLE_ERROR), MYF(0),
+ table->table_name););
+
}
/*
It's safe to unlock LOCK_open: we have an exclusive lock
@@ -2089,7 +2099,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
tables). In this case, we can write the original query into
the binary log.
*/
- write_bin_log(thd, !error, thd->query, thd->query_length);
+ write_bin_log(thd, !error, thd->query(), thd->query_length());
}
else if (thd->current_stmt_binlog_row_based &&
tmp_table_deleted)
@@ -2498,6 +2508,39 @@ int prepare_create_field(Create_field *sql_field,
DBUG_RETURN(0);
}
+
+/*
+ Get character set from field object generated by parser using
+ default values when not set.
+
+ SYNOPSIS
+ get_sql_field_charset()
+ sql_field The sql_field object
+ create_info Info generated by parser
+
+ RETURN VALUES
+ cs Character set
+*/
+
+CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+ HA_CREATE_INFO *create_info)
+{
+ CHARSET_INFO *cs= sql_field->charset;
+
+ if (!cs)
+ cs= create_info->default_table_charset;
+ /*
+ table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
+ if we want change character set for all varchar/char columns.
+ But the table charset must not affect the BLOB fields, so don't
+ allow to change my_charset_bin to somethig else.
+ */
+ if (create_info->table_charset && cs != &my_charset_bin)
+ cs= create_info->table_charset;
+ return cs;
+}
+
+
/*
Preparation for table creation
@@ -2561,18 +2604,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
executing a prepared statement for the second time.
*/
sql_field->length= sql_field->char_length;
- if (!sql_field->charset)
- sql_field->charset= create_info->default_table_charset;
- /*
- table_charset is set in ALTER TABLE if we want change character set
- for all varchar/char columns.
- But the table charset must not affect the BLOB fields, so don't
- allow to change my_charset_bin to somethig else.
- */
- if (create_info->table_charset && sql_field->charset != &my_charset_bin)
- sql_field->charset= create_info->table_charset;
-
- save_cs= sql_field->charset;
+ save_cs= sql_field->charset= get_sql_field_charset(sql_field,
+ create_info);
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
@@ -2882,9 +2915,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
while ((key=key_iterator++))
{
- DBUG_PRINT("info", ("key name: '%s' type: %d", key->name ? key->name :
+ DBUG_PRINT("info", ("key name: '%s' type: %d", key->name.str ? key->name.str :
"(none)" , key->type));
- LEX_STRING key_name_str;
if (key->type == Key::FOREIGN_KEY)
{
fk_key_count++;
@@ -2893,7 +2925,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
fk_key->ref_columns.elements != fk_key->columns.elements)
{
my_error(ER_WRONG_FK_DEF, MYF(0),
- (fk_key->name ? fk_key->name : "foreign key without name"),
+ (fk_key->name.str ? fk_key->name.str :
+ "foreign key without name"),
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(TRUE);
}
@@ -2906,12 +2939,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
DBUG_RETURN(TRUE);
}
- key_name_str.str= (char*) key->name;
- key_name_str.length= key->name ? strlen(key->name) : 0;
- if (check_string_char_length(&key_name_str, "", NAME_CHAR_LEN,
+ if (check_string_char_length(&key->name, "", NAME_CHAR_LEN,
system_charset_info, 1))
{
- my_error(ER_TOO_LONG_IDENT, MYF(0), key->name);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), key->name.str);
DBUG_RETURN(TRUE);
}
key_iterator2.rewind ();
@@ -2925,7 +2956,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
Then we do not need the generated shorter key.
*/
if ((key2->type != Key::FOREIGN_KEY &&
- key2->name != ignore_key &&
+ key2->name.str != ignore_key &&
!foreign_key_prefix(key, key2)))
{
/* TODO: issue warning message */
@@ -2933,10 +2964,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (!key2->generated ||
(key->generated && key->columns.elements <
key2->columns.elements))
- key->name= ignore_key;
+ key->name.str= ignore_key;
else
{
- key2->name= ignore_key;
+ key2->name.str= ignore_key;
key_parts-= key2->columns.elements;
(*key_count)--;
}
@@ -2944,14 +2975,14 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
}
- if (key->name != ignore_key)
+ if (key->name.str != ignore_key)
key_parts+=key->columns.elements;
else
(*key_count)--;
- if (key->name && !tmp_table && (key->type != Key::PRIMARY) &&
- !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
+ !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
{
- my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
DBUG_RETURN(TRUE);
}
}
@@ -2974,12 +3005,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
uint key_length=0;
Key_part_spec *column;
- if (key->name == ignore_key)
+ if (key->name.str == ignore_key)
{
/* ignore redundant keys */
do
key=key_iterator++;
- while (key && key->name == ignore_key);
+ while (key && key->name.str == ignore_key);
if (!key)
break;
}
@@ -3092,22 +3123,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
field=0;
while ((sql_field=it++) &&
my_strcasecmp(system_charset_info,
- column->field_name,
+ column->field_name.str,
sql_field->field_name))
field++;
if (!sql_field)
{
- my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
while ((dup_column= cols2++) != column)
{
if (!my_strcasecmp(system_charset_info,
- column->field_name, dup_column->field_name))
+ column->field_name.str, dup_column->field_name.str))
{
my_printf_error(ER_DUP_FIELDNAME,
ER(ER_DUP_FIELDNAME),MYF(0),
- column->field_name);
+ column->field_name.str);
DBUG_RETURN(TRUE);
}
}
@@ -3121,7 +3152,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
(ft_key_charset && sql_field->charset != ft_key_charset))
{
- my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(-1);
}
ft_key_charset=sql_field->charset;
@@ -3149,7 +3180,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
{
- my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
+ my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
@@ -3157,7 +3188,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
column->length= 25;
if (!column->length)
{
- my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
+ my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
}
@@ -3188,7 +3219,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags|= HA_NULL_PART_KEY;
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
{
- my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
+ my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (key->type == Key::SPATIAL)
@@ -3238,13 +3269,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
else if (!f_is_geom(sql_field->pack_flag) &&
- (column->length > length ||
- !Field::type_can_have_key_part (sql_field->sql_type) ||
- ((f_is_packed(sql_field->pack_flag) ||
- ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
- (key_info->flags & HA_NOSAME))) &&
- column->length != length)))
- {
+ ((column->length > length &&
+ !Field::type_can_have_key_part (sql_field->sql_type)) ||
+ ((f_is_packed(sql_field->pack_flag) ||
+ ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
+ (key_info->flags & HA_NOSAME))) &&
+ column->length != length)))
+ {
+ /* Catch invalid uses of partial keys.
+ A key is identified as 'partial' if column->length != length.
+ A partial key is invalid if they data type does
+ not allow it, or the field is packed (as in MyISAM),
+ or the storage engine doesn't allow prefixed search and
+ the key is primary key.
+ */
+
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
DBUG_RETURN(TRUE);
}
@@ -3253,7 +3292,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
else if (length == 0)
{
- my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
+ my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
@@ -3311,7 +3350,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_name=primary_key_name;
primary_key=1;
}
- else if (!(key_name = key->name))
+ else if (!(key_name= key->name.str))
key_name=make_unique_key_name(sql_field->field_name,
*key_info_buffer, key_info);
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
@@ -3557,7 +3596,7 @@ static inline void write_create_table_bin_log(THD *thd,
(!thd->current_stmt_binlog_row_based ||
(thd->current_stmt_binlog_row_based &&
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
@@ -3622,6 +3661,9 @@ bool mysql_create_table_no_lock(THD *thd,
}
if (check_engine(thd, table_name, create_info))
DBUG_RETURN(TRUE);
+
+ set_table_default_charset(thd, create_info, (char*) db);
+
db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
@@ -3715,7 +3757,7 @@ bool mysql_create_table_no_lock(THD *thd,
ha_resolve_storage_engine_name(part_info->default_engine_type),
ha_resolve_storage_engine_name(create_info->db_type)));
if (part_info->check_partition_info(thd, &engine_type, file,
- create_info, TRUE))
+ create_info, FALSE))
goto err;
part_info->default_engine_type= engine_type;
@@ -3725,7 +3767,9 @@ bool mysql_create_table_no_lock(THD *thd,
*/
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
- TRUE, TRUE)))
+ TRUE, TRUE,
+ create_info,
+ alter_info)))
goto err;
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
@@ -3751,9 +3795,9 @@ bool mysql_create_table_no_lock(THD *thd,
creates a proper .par file. The current part_info object is
only used to create the frm-file and .par-file.
*/
- if (part_info->use_default_no_partitions &&
- part_info->no_parts &&
- (int)part_info->no_parts !=
+ if (part_info->use_default_num_partitions &&
+ part_info->num_parts &&
+ (int)part_info->num_parts !=
file->get_default_no_partitions(create_info))
{
uint i;
@@ -3764,13 +3808,13 @@ bool mysql_create_table_no_lock(THD *thd,
(part_it++)->part_state= PART_TO_BE_DROPPED;
}
else if (part_info->is_sub_partitioned() &&
- part_info->use_default_no_subpartitions &&
- part_info->no_subparts &&
- (int)part_info->no_subparts !=
+ part_info->use_default_num_subpartitions &&
+ part_info->num_subparts &&
+ (int)part_info->num_subparts !=
file->get_default_no_partitions(create_info))
{
DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
- part_info->no_subparts= file->get_default_no_partitions(create_info);
+ part_info->num_subparts= file->get_default_no_partitions(create_info);
}
}
else if (create_info->db_type != engine_type)
@@ -3792,8 +3836,6 @@ bool mysql_create_table_no_lock(THD *thd,
}
#endif
- set_table_default_charset(thd, create_info, (char*) db);
-
if (mysql_prepare_create_table(thd, create_info, alter_info,
internal_tmp_table,
&db_options, file,
@@ -3849,7 +3891,7 @@ bool mysql_create_table_no_lock(THD *thd,
Then she could create the table. This case is pretty obscure and
therefore we don't introduce a new error message only for it.
*/
- if (get_cached_table_share(db, alias))
+ if (get_cached_table_share(db, table_name))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto unlock_and_end;
@@ -3983,7 +4025,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
/* Wait for any database locks */
pthread_mutex_lock(&LOCK_lock_db);
while (!thd->killed &&
- hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
+ my_hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
{
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
pthread_mutex_lock(&LOCK_lock_db);
@@ -4523,7 +4565,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -4583,11 +4625,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(TRUE);
}
- uint no_parts_found;
- uint no_parts_opt= alter_info->partition_names.elements;
- no_parts_found= set_part_state(alter_info, table->table->part_info,
- PART_ADMIN);
- if (no_parts_found != no_parts_opt &&
+ uint num_parts_found;
+ uint num_parts_opt= alter_info->partition_names.elements;
+ num_parts_found= set_part_state(alter_info, table->table->part_info,
+ PART_ADMIN);
+ if (num_parts_found != num_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
@@ -5423,7 +5465,7 @@ binlog:
}
VOID(pthread_mutex_unlock(&LOCK_open));
- IF_DBUG(int result=)
+ int result __attribute__((unused))=
store_create_info(thd, table, &query,
create_info, FALSE /* show_database */);
@@ -5431,14 +5473,14 @@ binlog:
write_bin_log(thd, TRUE, query.ptr(), query.length());
}
else // Case 1
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
/*
Case 3 and 4 does nothing under RBR
*/
}
else
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
res= FALSE;
@@ -5526,7 +5568,7 @@ mysql_discard_or_import_tablespace(THD *thd,
error=1;
if (error)
goto err;
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
err:
ha_autocommit_or_rollback(thd, error);
@@ -6281,6 +6323,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
key_part_length /= key_part->field->charset()->mbmaxlen;
key_parts.push_back(new Key_part_spec(cfield->field_name,
+ strlen(cfield->field_name),
key_part_length));
}
if (key_parts.elements)
@@ -6310,7 +6353,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
else
key_type= Key::MULTIPLE;
- key= new Key(key_type, key_name,
+ key= new Key(key_type, key_name, strlen(key_name),
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
key_parts);
@@ -6323,10 +6366,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{
if (key->type != Key::FOREIGN_KEY)
new_key_list.push_back(key);
- if (key->name &&
- !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ if (key->name.str &&
+ !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
{
- my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
goto err;
}
}
@@ -6575,7 +6618,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
+ Query_log_event qinfo(thd, thd->query(), thd->query_length(),
0, FALSE, 0);
mysql_bin_log.write(&qinfo);
}
@@ -6829,7 +6872,7 @@ view_err:
if (!error)
{
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
my_ok(thd);
}
else if (error > 0)
@@ -7319,7 +7362,7 @@ view_err:
goto err1;
/* We don't replicate alter table statement on temporary tables */
if (!thd->current_stmt_binlog_row_based)
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
goto end_temporary;
}
@@ -7476,13 +7519,13 @@ view_err:
DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
db, table_name);
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
thd->current_stmt_binlog_row_based &&
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
{
@@ -7525,7 +7568,7 @@ view_err:
end_temporary:
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) (copied + deleted), (ulong) deleted,
- (ulong) thd->cuted_fields);
+ (ulong) thd->warning_info->statement_warn_count());
my_ok(thd, copied + deleted, 0L, tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
@@ -7867,7 +7910,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
MY_INT64_NUM_DECIMAL_DIGITS));
item->maybe_null= 1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc
index 3549a44807e..ef81c7d847e 100644
--- a/sql/sql_tablespace.cc
+++ b/sql/sql_tablespace.cc
@@ -66,6 +66,6 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info)
ha_resolve_storage_engine_name(hton),
"TABLESPACE or LOGFILE GROUP");
}
- write_bin_log(thd, FALSE, thd->query, thd->query_length);
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length());
DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index eeb9a21b6f5..6c0cb08cc79 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -85,7 +85,7 @@ void print_cached_tables(void)
for (idx=unused=0 ; idx < open_cache.records ; idx++)
{
- TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
+ TABLE *entry=(TABLE*) my_hash_element(&open_cache,idx);
printf("%-14.14s %-32s%6ld%8ld%6d %s\n",
entry->s->db.str, entry->s->table_name.str, entry->s->version,
entry->in_use ? entry->in_use->thread_id : 0L,
@@ -113,7 +113,7 @@ void print_cached_tables(void)
if (count != unused)
printf("Unused_links (%d) doesn't match open_cache: %d\n", count,unused);
printf("\nCurrent refresh version: %ld\n",refresh_version);
- if (hash_check(&open_cache))
+ if (my_hash_check(&open_cache))
printf("Error: File hash table is corrupted\n");
fflush(stdout);
VOID(pthread_mutex_unlock(&LOCK_open));
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index c055268ecca..61da4617610 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -409,7 +409,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
*/
result= FALSE;
/* Still, we need to log the query ... */
- stmt_query.append(thd->query, thd->query_length);
+ stmt_query.append(thd->query(), thd->query_length());
goto end;
}
}
@@ -422,7 +422,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
thd->lex->query_tables_own_last= 0;
- err_status= check_table_access(thd, TRIGGER_ACL, tables, 1, FALSE);
+ err_status= check_table_access(thd, TRIGGER_ACL, tables, FALSE, 1, FALSE);
thd->lex->query_tables_own_last= save_query_tables_own_last;
@@ -918,7 +918,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
List_iterator<LEX_STRING> it_connection_cl_name(connection_cl_names);
List_iterator<LEX_STRING> it_db_cl_name(db_cl_names);
- stmt_query->append(thd->query, thd->query_length);
+ stmt_query->append(thd->query(), thd->query_length());
while ((name= it_name++))
{
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index c60dac42fb8..f38d8921181 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -124,10 +124,10 @@ void udf_init()
init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0);
THD *new_thd = new THD;
if (!new_thd ||
- hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0))
+ my_hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0))
{
sql_print_error("Can't allocate memory for udf structures");
- hash_free(&udf_hash);
+ my_hash_free(&udf_hash);
free_root(&mem,MYF(0));
delete new_thd;
DBUG_VOID_RETURN;
@@ -135,7 +135,6 @@ void udf_init()
initialized = 1;
new_thd->thread_stack= (char*) &new_thd;
new_thd->store_globals();
- lex_start(new_thd);
new_thd->set_db(db, sizeof(db)-1);
bzero((uchar*) &tables,sizeof(tables));
@@ -239,20 +238,20 @@ void udf_free()
DBUG_ENTER("udf_free");
for (uint idx=0 ; idx < udf_hash.records ; idx++)
{
- udf_func *udf=(udf_func*) hash_element(&udf_hash,idx);
+ udf_func *udf=(udf_func*) my_hash_element(&udf_hash,idx);
if (udf->dlhandle) // Not closed before
{
/* Mark all versions using the same handler as closed */
for (uint j=idx+1 ; j < udf_hash.records ; j++)
{
- udf_func *tmp=(udf_func*) hash_element(&udf_hash,j);
+ udf_func *tmp=(udf_func*) my_hash_element(&udf_hash,j);
if (udf->dlhandle == tmp->dlhandle)
tmp->dlhandle=0; // Already closed
}
dlclose(udf->dlhandle);
}
}
- hash_free(&udf_hash);
+ my_hash_free(&udf_hash);
free_root(&mem,MYF(0));
if (initialized)
{
@@ -268,7 +267,7 @@ static void del_udf(udf_func *udf)
DBUG_ENTER("del_udf");
if (!--udf->usage_count)
{
- hash_delete(&udf_hash,(uchar*) udf);
+ my_hash_delete(&udf_hash,(uchar*) udf);
using_udf_functions=udf_hash.records != 0;
}
else
@@ -282,7 +281,7 @@ static void del_udf(udf_func *udf)
uint name_length=udf->name.length;
udf->name.str=(char*) "*";
udf->name.length=1;
- hash_update(&udf_hash,(uchar*) udf,(uchar*) name,name_length);
+ my_hash_update(&udf_hash,(uchar*) udf,(uchar*) name,name_length);
}
DBUG_VOID_RETURN;
}
@@ -302,7 +301,7 @@ void free_udf(udf_func *udf)
We come here when someone has deleted the udf function
while another thread still was using the udf
*/
- hash_delete(&udf_hash,(uchar*) udf);
+ my_hash_delete(&udf_hash,(uchar*) udf);
using_udf_functions=udf_hash.records != 0;
if (!find_udf_dl(udf->dl))
dlclose(udf->dlhandle);
@@ -328,8 +327,8 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
else
rw_rdlock(&THR_LOCK_udf); /* Called during parsing */
- if ((udf=(udf_func*) hash_search(&udf_hash,(uchar*) name,
- length ? length : (uint) strlen(name))))
+ if ((udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) name,
+ length ? length : (uint) strlen(name))))
{
if (!udf->dlhandle)
udf=0; // Could not be opened
@@ -351,7 +350,7 @@ static void *find_udf_dl(const char *dl)
*/
for (uint idx=0 ; idx < udf_hash.records ; idx++)
{
- udf_func *udf=(udf_func*) hash_element(&udf_hash,idx);
+ udf_func *udf=(udf_func*) my_hash_element(&udf_hash,idx);
if (!strcmp(dl, udf->dl) && udf->dlhandle != NULL)
DBUG_RETURN(udf->dlhandle);
}
@@ -441,7 +440,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
thd->clear_current_stmt_binlog_row_based();
rw_wrlock(&THR_LOCK_udf);
- if ((hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length)))
+ if ((my_hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length)))
{
my_error(ER_UDF_EXISTS, MYF(0), udf->name.str);
goto err;
@@ -506,7 +505,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
rw_unlock(&THR_LOCK_udf);
/* Binlog the create function. */
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
DBUG_RETURN(0);
@@ -544,8 +543,8 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
thd->clear_current_stmt_binlog_row_based();
rw_wrlock(&THR_LOCK_udf);
- if (!(udf=(udf_func*) hash_search(&udf_hash,(uchar*) udf_name->str,
- (uint) udf_name->length)))
+ if (!(udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) udf_name->str,
+ (uint) udf_name->length)))
{
my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
goto err;
@@ -581,7 +580,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
rw_unlock(&THR_LOCK_udf);
/* Binlog the drop function. */
- write_bin_log(thd, TRUE, thd->query, thd->query_length);
+ write_bin_log(thd, TRUE, thd->query(), thd->query_length());
DBUG_RETURN(0);
err:
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index f5c4b85e904..e7b4eb22e78 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -812,7 +812,7 @@ int mysql_update(THD *thd,
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
transactional_table, FALSE, errcode))
{
error=1; // Rollback update
@@ -833,7 +833,7 @@ int mysql_update(THD *thd,
char buff[STRING_BUFFER_USUAL_SIZE];
my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found,
(ulong) updated,
- (ulong) thd->warning_info->statement_warn_count());
+ (ulong) thd->warning_info->statement_warn_count());
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
my_ok(thd, (ulong) thd->row_count_func, id, buff);
@@ -922,7 +922,6 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
{
update_non_unique_table_error(table_list, "UPDATE", duplicate);
- my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
DBUG_RETURN(TRUE);
}
}
@@ -1077,7 +1076,7 @@ reopen_tables:
if (check_access(thd, want_privilege,
tl->db, &tl->grant.privilege, 0, 0,
test(tl->schema_table)) ||
- check_grant(thd, want_privilege, tl, 0, 1, 0))
+ check_grant(thd, want_privilege, tl, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
}
}
@@ -1704,6 +1703,11 @@ bool multi_update::send_data(List<Item> &not_used_values)
TRG_EVENT_UPDATE))
DBUG_RETURN(1);
+ /*
+ Reset the table->auto_increment_field_not_null as it is valid for
+ only one row.
+ */
+ table->auto_increment_field_not_null= FALSE;
found++;
if (!can_compare_record || compare_record(table))
{
@@ -1868,7 +1872,7 @@ void multi_update::abort()
*/
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
transactional_tables, FALSE, errcode);
}
thd->transaction.all.modified_non_trans_table= TRUE;
@@ -2101,7 +2105,7 @@ bool multi_update::send_eof()
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
- thd->query, thd->query_length,
+ thd->query(), thd->query_length(),
transactional_tables, FALSE, errcode))
{
local_error= 1; // Rollback update
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 43d0b9fade0..9abbadb8c6b 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -269,11 +269,11 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
*/
if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege,
0, 0, is_schema_db(view->db)) ||
- check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) ||
+ check_grant(thd, CREATE_VIEW_ACL, view, FALSE, 1, FALSE)) ||
(mode != VIEW_CREATE_NEW &&
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
0, 0, is_schema_db(view->db)) ||
- check_grant(thd, DROP_ACL, view, 0, 1, 0))))
+ check_grant(thd, DROP_ACL, view, FALSE, 1, FALSE))))
goto err;
for (sl= select_lex; sl; sl= sl->next_select())
@@ -323,7 +323,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
{
if (check_access(thd, SELECT_ACL, tbl->db,
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
- check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
+ check_grant(thd, SELECT_ACL, tbl, FALSE, 1, FALSE))
goto err;
}
}
@@ -1233,8 +1233,9 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
if (!table->prelocking_placeholder &&
(old_lex->sql_command == SQLCOM_SELECT && old_lex->describe))
{
- if (check_table_access(thd, SELECT_ACL, view_tables, UINT_MAX, TRUE) &&
- check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, TRUE))
+ if (check_table_access(thd, SELECT_ACL, view_tables, FALSE,
+ UINT_MAX, TRUE) &&
+ check_table_access(thd, SHOW_VIEW_ACL, table, FALSE, UINT_MAX, TRUE))
{
my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));
goto err;
@@ -1244,7 +1245,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
(old_lex->sql_command == SQLCOM_SHOW_CREATE) &&
!table->belong_to_view)
{
- if (check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, FALSE))
+ if (check_table_access(thd, SHOW_VIEW_ACL, table, FALSE, UINT_MAX, FALSE))
goto err;
}
@@ -1652,7 +1653,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
/* if something goes wrong, bin-log with possible error code,
otherwise bin-log with error code cleared.
*/
- write_bin_log(thd, !something_wrong, thd->query, thd->query_length);
+ write_bin_log(thd, !something_wrong, thd->query(), thd->query_length());
}
VOID(pthread_mutex_unlock(&LOCK_open));
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 43f5c73f5e7..6ff70bf8a8a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -56,8 +56,6 @@
int yylex(void *yylval, void *yythd);
-const LEX_STRING null_lex_str= {0,0};
-
#define yyoverflow(A,B,C,D,E,F) \
{ \
ulong val= *(F); \
@@ -591,7 +589,7 @@ bool setup_select_in_parentheses(LEX *lex)
struct sp_cond_type *spcondtype;
struct { int vars, conds, hndlrs, curs; } spblock;
sp_name *spname;
- struct st_lex *lex;
+ LEX *lex;
sp_head *sphead;
struct p_elem_val *p_elem_value;
enum index_hint_type index_hint;
@@ -1241,6 +1239,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
+ opt_constraint constraint opt_ident
%type <lex_str_ptr>
opt_table_alias
@@ -1249,8 +1248,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_ident table_ident_nodb references xid
%type <simple_string>
- remember_name remember_end opt_ident opt_db text_or_password
- opt_constraint constraint
+ remember_name remember_end opt_db text_or_password
%type <string>
text_string opt_gconcat_separator
@@ -1273,9 +1271,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number
-%type <p_elem_value>
- part_bit_expr
-
%type <lock_type>
replace_lock_option opt_low_priority insert_lock_option load_data_lock
@@ -1413,6 +1408,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
view_check_option trigger_tail sp_tail sf_tail udf_tail event_tail
install uninstall partition_entry binlog_base64_event
init_key_options key_options key_opts key_opt key_using_alg
+ part_column_list
server_def server_options_list server_option
definer_opt no_definer definer
END_OF_INPUT
@@ -1484,7 +1480,7 @@ query:
Lex_input_stream *lip = YYLIP;
if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) &&
- ! lip->stmt_prepare_mode &&
+ lip->multi_statements &&
! lip->eof())
{
/*
@@ -1899,7 +1895,7 @@ create:
my_parse_error(ER(ER_SYNTAX_ERROR));
MYSQL_YYABORT;
}
- key= new Key($2, $4.str, &lex->key_create_info, 0,
+ key= new Key($2, $4, &lex->key_create_info, 0,
lex->col_list);
if (key == NULL)
MYSQL_YYABORT;
@@ -4150,25 +4146,28 @@ partition_entry:
;
partition:
- BY part_type_def opt_no_parts opt_sub_part part_defs
+ BY part_type_def opt_num_parts opt_sub_part part_defs
;
part_type_def:
opt_linear KEY_SYM '(' part_field_list ')'
{
- LEX *lex= Lex;
- lex->part_info->list_of_part_fields= TRUE;
- lex->part_info->part_type= HASH_PARTITION;
+ partition_info *part_info= Lex->part_info;
+ part_info->list_of_part_fields= TRUE;
+ part_info->column_list= FALSE;
+ part_info->part_type= HASH_PARTITION;
}
| opt_linear HASH_SYM
{ Lex->part_info->part_type= HASH_PARTITION; }
part_func {}
- | RANGE_SYM
+ | RANGE_SYM part_func
{ Lex->part_info->part_type= RANGE_PARTITION; }
- part_func {}
- | LIST_SYM
+ | RANGE_SYM part_column_list
+ { Lex->part_info->part_type= RANGE_PARTITION; }
+ | LIST_SYM part_func
+ { Lex->part_info->part_type= LIST_PARTITION; }
+ | LIST_SYM part_column_list
{ Lex->part_info->part_type= LIST_PARTITION; }
- part_func {}
;
opt_linear:
@@ -4190,59 +4189,66 @@ part_field_item_list:
part_field_item:
ident
{
- if (Lex->part_info->part_field_list.push_back($1.str))
+ partition_info *part_info= Lex->part_info;
+ part_info->num_columns++;
+ if (part_info->part_field_list.push_back($1.str))
{
mem_alloc_error(1);
MYSQL_YYABORT;
}
+ if (part_info->num_columns > MAX_REF_PARTS)
+ {
+ my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of partition fields");
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+part_column_list:
+ COLUMNS '(' part_field_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->column_list= TRUE;
+ part_info->list_of_part_fields= TRUE;
}
;
+
part_func:
'(' remember_name part_func_expr remember_end ')'
{
- LEX *lex= Lex;
- uint expr_len= (uint)($4 - $2) - 1;
- lex->part_info->list_of_part_fields= FALSE;
- lex->part_info->part_expr= $3;
- char *func_string= (char*) sql_memdup($2+1, expr_len);
- if (func_string == NULL)
- MYSQL_YYABORT;
- lex->part_info->part_func_string= func_string;
- lex->part_info->part_func_len= expr_len;
+ partition_info *part_info= Lex->part_info;
+ if (part_info->set_part_expr($2+1, $3, $4, FALSE))
+ { MYSQL_YYABORT; }
+ part_info->num_columns= 1;
+ part_info->column_list= FALSE;
}
;
sub_part_func:
'(' remember_name part_func_expr remember_end ')'
{
- LEX *lex= Lex;
- uint expr_len= (uint)($4 - $2) - 1;
- lex->part_info->list_of_subpart_fields= FALSE;
- lex->part_info->subpart_expr= $3;
- char *func_string= (char*) sql_memdup($2+1, expr_len);
- if (func_string == NULL)
- MYSQL_YYABORT;
- lex->part_info->subpart_func_string= func_string;
- lex->part_info->subpart_func_len= expr_len;
+ if (Lex->part_info->set_part_expr($2+1, $3, $4, TRUE))
+ { MYSQL_YYABORT; }
}
;
-opt_no_parts:
+opt_num_parts:
/* empty */ {}
| PARTITIONS_SYM real_ulong_num
{
- uint no_parts= $2;
- LEX *lex= Lex;
- if (no_parts == 0)
+ uint num_parts= $2;
+ partition_info *part_info= Lex->part_info;
+ if (num_parts == 0)
{
my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions");
MYSQL_YYABORT;
}
- lex->part_info->no_parts= no_parts;
- lex->part_info->use_default_no_partitions= FALSE;
+ part_info->num_parts= num_parts;
+ part_info->use_default_num_partitions= FALSE;
}
;
@@ -4250,15 +4256,15 @@ opt_sub_part:
/* empty */ {}
| SUBPARTITION_SYM BY opt_linear HASH_SYM sub_part_func
{ Lex->part_info->subpart_type= HASH_PARTITION; }
- opt_no_subparts {}
+ opt_num_subparts {}
| SUBPARTITION_SYM BY opt_linear KEY_SYM
'(' sub_part_field_list ')'
{
- LEX *lex= Lex;
- lex->part_info->subpart_type= HASH_PARTITION;
- lex->part_info->list_of_subpart_fields= TRUE;
+ partition_info *part_info= Lex->part_info;
+ part_info->subpart_type= HASH_PARTITION;
+ part_info->list_of_subpart_fields= TRUE;
}
- opt_no_subparts {}
+ opt_num_subparts {}
;
sub_part_field_list:
@@ -4269,11 +4275,18 @@ sub_part_field_list:
sub_part_field_item:
ident
{
- if (Lex->part_info->subpart_field_list.push_back($1.str))
+ partition_info *part_info= Lex->part_info;
+ if (part_info->subpart_field_list.push_back($1.str))
{
mem_alloc_error(1);
MYSQL_YYABORT;
}
+ if (part_info->subpart_field_list.elements > MAX_REF_PARTS)
+ {
+ my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of subpartition fields");
+ MYSQL_YYABORT;
+ }
}
;
@@ -4293,33 +4306,46 @@ part_func_expr:
}
;
-opt_no_subparts:
+opt_num_subparts:
/* empty */ {}
| SUBPARTITIONS_SYM real_ulong_num
{
- uint no_parts= $2;
+ uint num_parts= $2;
LEX *lex= Lex;
- if (no_parts == 0)
+ if (num_parts == 0)
{
my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions");
MYSQL_YYABORT;
}
- lex->part_info->no_subparts= no_parts;
- lex->part_info->use_default_no_subpartitions= FALSE;
+ lex->part_info->num_subparts= num_parts;
+ lex->part_info->use_default_num_subpartitions= FALSE;
}
;
part_defs:
/* empty */
- {}
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->part_type == RANGE_PARTITION)
+ {
+ my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "RANGE");
+ MYSQL_YYABORT;
+ }
+ else if (part_info->part_type == LIST_PARTITION)
+ {
+ my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "LIST");
+ MYSQL_YYABORT;
+ }
+ }
| '(' part_def_list ')'
{
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
+ partition_info *part_info= Lex->part_info;
uint count_curr_parts= part_info->partitions.elements;
- if (part_info->no_parts != 0)
+ if (part_info->num_parts != 0)
{
- if (part_info->no_parts !=
+ if (part_info->num_parts !=
count_curr_parts)
{
my_parse_error(ER(ER_PARTITION_WRONG_NO_PART_ERROR));
@@ -4328,7 +4354,7 @@ part_defs:
}
else if (count_curr_parts > 0)
{
- part_info->no_parts= count_curr_parts;
+ part_info->num_parts= count_curr_parts;
}
part_info->count_curr_subparts= 0;
}
@@ -4342,8 +4368,7 @@ part_def_list:
part_definition:
PARTITION_SYM
{
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
+ partition_info *part_info= Lex->part_info;
partition_element *p_elem= new partition_element();
if (!p_elem || part_info->partitions.push_back(p_elem))
@@ -4355,7 +4380,7 @@ part_definition:
part_info->curr_part_elem= p_elem;
part_info->current_partition= p_elem;
part_info->use_default_partitions= FALSE;
- part_info->use_default_no_partitions= FALSE;
+ part_info->use_default_num_partitions= FALSE;
}
part_name
opt_part_values
@@ -4367,8 +4392,7 @@ part_definition:
part_name:
ident
{
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
+ partition_info *part_info= Lex->part_info;
partition_element *p_elem= part_info->curr_part_elem;
p_elem->partition_name= $1.str;
}
@@ -4378,15 +4402,16 @@ opt_part_values:
/* empty */
{
LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
- if (lex->part_info->part_type == RANGE_PARTITION)
+ if (part_info->part_type == RANGE_PARTITION)
{
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"RANGE", "LESS THAN");
MYSQL_YYABORT;
}
- if (lex->part_info->part_type == LIST_PARTITION)
+ if (part_info->part_type == LIST_PARTITION)
{
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"LIST", "IN");
@@ -4394,14 +4419,15 @@ opt_part_values:
}
}
else
- lex->part_info->part_type= HASH_PARTITION;
+ part_info->part_type= HASH_PARTITION;
}
- | VALUES LESS_SYM THAN_SYM part_func_max
+ | VALUES LESS_SYM THAN_SYM
{
LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
- if (Lex->part_info->part_type != RANGE_PARTITION)
+ if (part_info->part_type != RANGE_PARTITION)
{
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
"RANGE", "LESS THAN");
@@ -4409,153 +4435,183 @@ opt_part_values:
}
}
else
- lex->part_info->part_type= RANGE_PARTITION;
+ part_info->part_type= RANGE_PARTITION;
}
- | VALUES IN_SYM '(' part_list_func ')'
+ part_func_max {}
+ | VALUES IN_SYM
{
LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
- if (Lex->part_info->part_type != LIST_PARTITION)
+ if (part_info->part_type != LIST_PARTITION)
{
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN");
+ "LIST", "IN");
MYSQL_YYABORT;
}
}
else
- lex->part_info->part_type= LIST_PARTITION;
+ part_info->part_type= LIST_PARTITION;
}
+ part_values_in {}
;
part_func_max:
- max_value_sym
+ MAX_VALUE_SYM
{
- LEX *lex= Lex;
- if (lex->part_info->defined_max_value)
+ partition_info *part_info= Lex->part_info;
+
+ if (part_info->num_columns &&
+ part_info->num_columns != 1U)
{
- my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
+ part_info->print_debug("Kilroy II", NULL);
+ my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
- lex->part_info->defined_max_value= TRUE;
- lex->part_info->curr_part_elem->max_value= TRUE;
- lex->part_info->curr_part_elem->range_value= LONGLONG_MAX;
- }
- | part_range_func
- {
- if (Lex->part_info->defined_max_value)
+ else
+ part_info->num_columns= 1U;
+ if (part_info->init_column_part())
{
- my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
MYSQL_YYABORT;
}
- if (Lex->part_info->curr_part_elem->has_null_value)
+ if (part_info->add_max_value())
{
- my_parse_error(ER(ER_NULL_IN_VALUES_LESS_THAN));
MYSQL_YYABORT;
}
}
+ | part_value_item {}
;
-max_value_sym:
- MAX_VALUE_SYM
- | '(' MAX_VALUE_SYM ')'
- ;
-
-part_range_func:
- '(' part_bit_expr ')'
+part_values_in:
+ part_value_item
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ part_info->print_debug("part_values_in: part_value_item", NULL);
+
+ if (part_info->num_columns != 1U)
+ {
+ if (!lex->is_partition_management() ||
+ part_info->num_columns == 0 ||
+ part_info->num_columns > MAX_REF_PARTS)
+ {
+ part_info->print_debug("Kilroy III", NULL);
+ my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
+ MYSQL_YYABORT;
+ }
+ /*
+ Reorganize the current large array into a list of small
+ arrays with one entry in each array. This can happen
+ in the first partition of an ALTER TABLE statement where
+ we ADD or REORGANIZE partitions. Also can only happen
+ for LIST partitions.
+ */
+ if (part_info->reorganize_into_single_field_col_val())
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ }
+ | '(' part_value_list ')'
{
partition_info *part_info= Lex->part_info;
- if (!($2->unsigned_flag))
- part_info->curr_part_elem->signed_flag= TRUE;
- part_info->curr_part_elem->range_value= $2->value;
+ if (part_info->num_columns < 2U)
+ {
+ my_parse_error(ER(ER_ROW_SINGLE_PARTITION_FIELD_ERROR));
+ MYSQL_YYABORT;
+ }
}
;
-part_list_func:
- part_list_item {}
- | part_list_func ',' part_list_item {}
+part_value_list:
+ part_value_item {}
+ | part_value_list ',' part_value_item {}
;
-part_list_item:
- part_bit_expr
+part_value_item:
+ '('
{
- part_elem_value *value_ptr= $1;
partition_info *part_info= Lex->part_info;
- if (!value_ptr->unsigned_flag)
- part_info->curr_part_elem->signed_flag= TRUE;
- if (!value_ptr->null_value &&
- part_info->curr_part_elem->
- list_val_list.push_back(value_ptr))
+ part_info->print_debug("( part_value_item", NULL);
+ /* Initialisation code needed for each list of value expressions */
+ if (!(part_info->part_type == LIST_PARTITION &&
+ part_info->num_columns == 1U) &&
+ part_info->init_column_part())
{
- mem_alloc_error(sizeof(part_elem_value));
MYSQL_YYABORT;
}
}
- ;
-
-part_bit_expr:
- bit_expr
+ part_value_item_list {}
+ ')'
{
- Item *part_expr= $1;
- THD *thd= YYTHD;
- LEX *lex= thd->lex;
- Name_resolution_context *context= &lex->current_select->context;
- TABLE_LIST *save_list= context->table_list;
- const char *save_where= thd->where;
-
- context->table_list= 0;
- thd->where= "partition function";
-
- part_elem_value *value_ptr=
- (part_elem_value*)sql_alloc(sizeof(part_elem_value));
- if (!value_ptr)
+ LEX *lex= Lex;
+ partition_info *part_info= Lex->part_info;
+ part_info->print_debug(") part_value_item", NULL);
+ if (part_info->num_columns == 0)
+ part_info->num_columns= part_info->curr_list_object;
+ if (part_info->num_columns != part_info->curr_list_object)
{
- mem_alloc_error(sizeof(part_elem_value));
+ /*
+ All value items lists must be of equal length, in some cases
+ which is covered by the above if-statement we don't know yet
+ how many columns is in the partition so the assignment above
+ ensures that we only report errors when we know we have an
+ error.
+ */
+ part_info->print_debug("Kilroy I", NULL);
+ my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
- if (part_expr->walk(&Item::check_partition_func_processor, 0,
- NULL))
+ part_info->curr_list_object= 0;
+ }
+ ;
+
+part_value_item_list:
+ part_value_expr_item {}
+ | part_value_item_list ',' part_value_expr_item {}
+ ;
+
+part_value_expr_item:
+ MAX_VALUE_SYM
+ {
+ partition_info *part_info= Lex->part_info;
+ part_column_list_val *col_val;
+ if (part_info->part_type == LIST_PARTITION)
{
- my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ my_parse_error(ER(ER_MAXVALUE_IN_VALUES_IN));
MYSQL_YYABORT;
}
- if (part_expr->fix_fields(YYTHD, (Item**)0) ||
- ((context->table_list= save_list), FALSE) ||
- (!part_expr->const_item()) ||
- (!lex->safe_to_cache_query))
+ if (part_info->add_max_value())
{
- my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
MYSQL_YYABORT;
}
- thd->where= save_where;
- value_ptr->value= part_expr->val_int();
- value_ptr->unsigned_flag= TRUE;
- if (!part_expr->unsigned_flag &&
- value_ptr->value < 0)
- value_ptr->unsigned_flag= FALSE;
- if ((value_ptr->null_value= part_expr->null_value))
+ }
+ | bit_expr
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ Item *part_expr= $1;
+
+ if (!lex->safe_to_cache_query)
{
- if (Lex->part_info->curr_part_elem->has_null_value)
- {
- my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
- MYSQL_YYABORT;
- }
- Lex->part_info->curr_part_elem->has_null_value= TRUE;
+ my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
+ MYSQL_YYABORT;
}
- else if (part_expr->result_type() != INT_RESULT)
+ if (part_info->add_column_list_value(YYTHD, part_expr))
{
- my_parse_error(ER(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR));
MYSQL_YYABORT;
}
- $$= value_ptr;
}
;
+
opt_sub_partition:
/* empty */
{
- if (Lex->part_info->no_subparts != 0 &&
- !Lex->part_info->use_default_subpartitions)
+ partition_info *part_info= Lex->part_info;
+ if (part_info->num_subparts != 0 &&
+ !part_info->use_default_subpartitions)
{
/*
We come here when we have defined subpartitions on the first
@@ -4567,11 +4623,10 @@ opt_sub_partition:
}
| '(' sub_part_list ')'
{
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
- if (part_info->no_subparts != 0)
+ partition_info *part_info= Lex->part_info;
+ if (part_info->num_subparts != 0)
{
- if (part_info->no_subparts !=
+ if (part_info->num_subparts !=
part_info->count_curr_subparts)
{
my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
@@ -4585,7 +4640,7 @@ opt_sub_partition:
my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
MYSQL_YYABORT;
}
- part_info->no_subparts= part_info->count_curr_subparts;
+ part_info->num_subparts= part_info->count_curr_subparts;
}
part_info->count_curr_subparts= 0;
}
@@ -4599,8 +4654,7 @@ sub_part_list:
sub_part_definition:
SUBPARTITION_SYM
{
- LEX *lex= Lex;
- partition_info *part_info= lex->part_info;
+ partition_info *part_info= Lex->part_info;
partition_element *curr_part= part_info->current_partition;
partition_element *sub_p_elem= new partition_element(curr_part);
if (part_info->use_default_subpartitions &&
@@ -4628,7 +4682,7 @@ sub_part_definition:
}
part_info->curr_part_elem= sub_p_elem;
part_info->use_default_subpartitions= FALSE;
- part_info->use_default_no_subpartitions= FALSE;
+ part_info->use_default_num_subpartitions= FALSE;
part_info->count_curr_subparts++;
}
sub_name opt_part_options {}
@@ -4654,9 +4708,9 @@ opt_part_option:
{ Lex->part_info->curr_part_elem->tablespace_name= $3.str; }
| opt_storage ENGINE_SYM opt_equal storage_engines
{
- LEX *lex= Lex;
- lex->part_info->curr_part_elem->engine_type= $4;
- lex->part_info->default_engine_type= $4;
+ partition_info *part_info= Lex->part_info;
+ part_info->curr_part_elem->engine_type= $4;
+ part_info->default_engine_type= $4;
}
| NODEGROUP_SYM opt_equal real_ulong_num
{ Lex->part_info->curr_part_elem->nodegroup_id= (uint16) $3; }
@@ -5034,8 +5088,7 @@ key_def:
'(' key_list ')' key_options
{
LEX *lex=Lex;
- const char *key_name= $3 ? $3 : $1;
- Key *key= new Key($2, key_name, &lex->key_create_info, 0,
+ Key *key= new Key($2, $3.str ? $3 : $1, &lex->key_create_info, 0,
lex->col_list);
if (key == NULL)
MYSQL_YYABORT;
@@ -5045,9 +5098,7 @@ key_def:
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
{
LEX *lex=Lex;
- const char *key_name= $1 ? $1 : $4;
- const char *fkey_name = $4 ? $4 : key_name;
- Key *key= new Foreign_key(fkey_name, lex->col_list,
+ Key *key= new Foreign_key($4.str ? $4 : $1, lex->col_list,
$8,
lex->ref_list,
lex->fk_delete_opt,
@@ -5056,7 +5107,7 @@ key_def:
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
- key= new Key(Key::MULTIPLE, key_name,
+ key= new Key(Key::MULTIPLE, $1.str ? $1 : $4,
&default_key_create_info, 1,
lex->col_list);
if (key == NULL)
@@ -5086,7 +5137,7 @@ check_constraint:
;
opt_constraint:
- /* empty */ { $$=(char*) 0; }
+ /* empty */ { $$= null_lex_str; }
| constraint { $$= $1; }
;
@@ -5641,14 +5692,14 @@ opt_ref_list:
ref_list:
ref_list ',' ident
{
- Key_part_spec *key= new Key_part_spec($3.str);
+ Key_part_spec *key= new Key_part_spec($3, 0);
if (key == NULL)
MYSQL_YYABORT;
Lex->ref_list.push_back(key);
}
| ident
{
- Key_part_spec *key= new Key_part_spec($1.str);
+ Key_part_spec *key= new Key_part_spec($1, 0);
if (key == NULL)
MYSQL_YYABORT;
Lex->ref_list.push_back(key);
@@ -5795,7 +5846,7 @@ key_list:
key_part:
ident
{
- $$= new Key_part_spec($1.str);
+ $$= new Key_part_spec($1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -5806,15 +5857,15 @@ key_part:
{
my_error(ER_KEY_PART_0, MYF(0), $1.str);
}
- $$= new Key_part_spec($1.str,(uint) key_part_len);
+ $$= new Key_part_spec($1, (uint) key_part_len);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
opt_ident:
- /* empty */ { $$=(char*) 0; /* Default length */ }
- | field_ident { $$=$1.str; }
+ /* empty */ { $$= null_lex_str; }
+ | field_ident { $$= $1; }
;
opt_component:
@@ -6113,7 +6164,7 @@ alter_commands:
LEX *lex= Lex;
lex->alter_info.flags|= ALTER_COALESCE_PARTITION;
lex->no_write_to_binlog= $3;
- lex->alter_info.no_parts= $4;
+ lex->alter_info.num_parts= $4;
}
| TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
{
@@ -6162,12 +6213,11 @@ add_part_extra:
| '(' part_def_list ')'
{
LEX *lex= Lex;
- lex->part_info->no_parts= lex->part_info->partitions.elements;
+ lex->part_info->num_parts= lex->part_info->partitions.elements;
}
| PARTITIONS_SYM real_ulong_num
{
- LEX *lex= Lex;
- lex->part_info->no_parts= $2;
+ Lex->part_info->num_parts= $2;
}
;
@@ -6197,8 +6247,8 @@ reorg_parts_rule:
}
INTO '(' part_def_list ')'
{
- LEX *lex= Lex;
- lex->part_info->no_parts= lex->part_info->partitions.elements;
+ partition_info *part_info= Lex->part_info;
+ part_info->num_parts= part_info->partitions.elements;
}
;
@@ -9616,8 +9666,7 @@ procedure_clause:
MYSQL_YYABORT;
}
- if (&lex->select_lex != lex->current_select ||
- lex->select_lex.get_table_list()->derived)
+ if (&lex->select_lex != lex->current_select)
{
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
MYSQL_YYABORT;
@@ -11269,7 +11318,7 @@ param_marker:
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
MYSQL_YYABORT;
}
- item= new (thd->mem_root) Item_param((uint) (lip->get_tok_start() - thd->query));
+ item= new (thd->mem_root) Item_param((uint) (lip->get_tok_start() - thd->query()));
if (!($$= item) || lex->param_list.push_back(item))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@@ -12084,7 +12133,6 @@ keyword_sp:
| MAX_SIZE_SYM {}
| MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {}
- | MAX_VALUE_SYM {}
| MEDIUM_SYM {}
| MEMORY_SYM {}
| MERGE_SYM {}
@@ -13026,6 +13074,7 @@ object_privilege:
| CREATE USER { Lex->grant |= CREATE_USER_ACL; }
| EVENT_SYM { Lex->grant |= EVENT_ACL;}
| TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; }
+ | CREATE TABLESPACE { Lex->grant |= CREATE_TABLESPACE_ACL; }
;
opt_and:
diff --git a/sql/structs.h b/sql/structs.h
index bcda7b1e787..33b7148c4b3 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -19,8 +19,9 @@
/* The old structures from unireg */
-struct st_table;
+struct TABLE;
class Field;
+class THD;
typedef struct st_date_time_format {
uchar positions[8];
@@ -100,7 +101,7 @@ typedef struct st_key {
union {
int bdb_return_if_eq;
} handler;
- struct st_table *table;
+ TABLE *table;
} KEY;
@@ -118,30 +119,6 @@ typedef struct st_reginfo { /* Extra info about reg */
} REGINFO;
-struct st_read_record; /* For referense later */
-class SQL_SELECT;
-class THD;
-class handler;
-
-typedef struct st_read_record { /* Parameter to read_record */
- struct st_table *table; /* Head-form */
- handler *file;
- struct st_table **forms; /* head and ref forms */
- int (*read_record)(struct st_read_record *);
- THD *thd;
- SQL_SELECT *select;
- uint cache_records;
- uint ref_length,struct_length,reclength,rec_cache_size,error_offset;
- uint index;
- uchar *ref_pos; /* pointer to form->refpos */
- uchar *record;
- uchar *rec_buf; /* to read field values after filesort */
- uchar *cache,*cache_pos,*cache_end,*read_positions;
- IO_CACHE *io_cache;
- bool print_error, ignore_not_found_rows;
-} READ_RECORD;
-
-
/*
Originally MySQL used MYSQL_TIME structure inside server only, but since
4.1 it's exported to user in the new client API. Define aliases for
diff --git a/sql/table.cc b/sql/table.cc
index b3e0079b001..39a7e163c37 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -423,7 +423,7 @@ void free_table_share(TABLE_SHARE *share)
pthread_mutex_destroy(&share->mutex);
pthread_cond_destroy(&share->cond);
}
- hash_free(&share->name_hash);
+ my_hash_free(&share->name_hash);
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= NULL;
@@ -1148,10 +1148,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
if (use_hash)
- use_hash= !hash_init(&share->name_hash,
- system_charset_info,
- share->fields,0,0,
- (hash_get_key) get_field_name,0,0);
+ use_hash= !my_hash_init(&share->name_hash,
+ system_charset_info,
+ share->fields,0,0,
+ (my_hash_get_key) get_field_name,0,0);
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
@@ -1591,7 +1591,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
delete handler_file;
#ifndef DBUG_OFF
if (use_hash)
- (void) hash_check(&share->name_hash);
+ (void) my_hash_check(&share->name_hash);
#endif
DBUG_RETURN (0);
@@ -1602,7 +1602,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
x_free((uchar*) disk_buff);
delete crypted;
delete handler_file;
- hash_free(&share->name_hash);
+ my_hash_free(&share->name_hash);
+ if (share->ha_data_destroy)
+ share->ha_data_destroy(share->ha_data);
open_table_error(share, error, share->open_errno, errarg);
DBUG_RETURN(error);
@@ -1647,9 +1649,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
share->table_name.str, (long) outparam));
- /* Parsing of partitioning information from .frm needs thd->lex set up. */
- DBUG_ASSERT(thd->lex->is_lex_started);
-
error= 1;
bzero((char*) outparam, sizeof(*outparam));
outparam->in_use= thd;
@@ -2933,7 +2932,7 @@ table_check_intact(TABLE *table, const uint table_f_count,
Create Item_field for each column in the table.
SYNPOSIS
- st_table::fill_item_list()
+ TABLE::fill_item_list()
item_list a pointer to an empty list used to store items
DESCRIPTION
@@ -2946,7 +2945,7 @@ table_check_intact(TABLE *table, const uint table_f_count,
1 out of memory
*/
-bool st_table::fill_item_list(List<Item> *item_list) const
+bool TABLE::fill_item_list(List<Item> *item_list) const
{
/*
All Item_field's created using a direct pointer to a field
@@ -2966,7 +2965,7 @@ bool st_table::fill_item_list(List<Item> *item_list) const
Fields of this table.
SYNPOSIS
- st_table::fill_item_list()
+ TABLE::fill_item_list()
item_list a non-empty list with Item_fields
DESCRIPTION
@@ -2976,7 +2975,7 @@ bool st_table::fill_item_list(List<Item> *item_list) const
is the same as the number of columns in the table.
*/
-void st_table::reset_item_list(List<Item> *item_list) const
+void TABLE::reset_item_list(List<Item> *item_list) const
{
List_iterator_fast<Item> it(*item_list);
for (Field **ptr= field; *ptr; ptr++)
@@ -3918,7 +3917,7 @@ const char *Natural_join_column::db_name()
return table_ref->view_db.str;
/*
- Test that TABLE_LIST::db is the same as st_table_share::db to
+ Test that TABLE_LIST::db is the same as TABLE_SHARE::db to
ensure consistency. An exception are I_S schema tables, which
are inconsistent in this respect.
*/
@@ -4137,7 +4136,7 @@ const char *Field_iterator_table_ref::get_db_name()
return natural_join_it.column_ref()->db_name();
/*
- Test that TABLE_LIST::db is the same as st_table_share::db to
+ Test that TABLE_LIST::db is the same as TABLE_SHARE::db to
ensure consistency. An exception are I_S schema tables, which
are inconsistent in this respect.
*/
@@ -4313,7 +4312,7 @@ Field_iterator_table_ref::get_natural_column_ref()
/* Reset all columns bitmaps */
-void st_table::clear_column_bitmaps()
+void TABLE::clear_column_bitmaps()
{
/*
Reset column read/write usage. It's identical to:
@@ -4334,9 +4333,9 @@ void st_table::clear_column_bitmaps()
key fields.
*/
-void st_table::prepare_for_position()
+void TABLE::prepare_for_position()
{
- DBUG_ENTER("st_table::prepare_for_position");
+ DBUG_ENTER("TABLE::prepare_for_position");
if ((file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
s->primary_key < MAX_KEY)
@@ -4355,14 +4354,14 @@ void st_table::prepare_for_position()
NOTE:
This changes the bitmap to use the tmp bitmap
After this, you can't access any other columns in the table until
- bitmaps are reset, for example with st_table::clear_column_bitmaps()
- or st_table::restore_column_maps_after_mark_index()
+ bitmaps are reset, for example with TABLE::clear_column_bitmaps()
+ or TABLE::restore_column_maps_after_mark_index()
*/
-void st_table::mark_columns_used_by_index(uint index)
+void TABLE::mark_columns_used_by_index(uint index)
{
MY_BITMAP *bitmap= &tmp_set;
- DBUG_ENTER("st_table::mark_columns_used_by_index");
+ DBUG_ENTER("TABLE::mark_columns_used_by_index");
(void) file->extra(HA_EXTRA_KEYREAD);
bitmap_clear_all(bitmap);
@@ -4383,9 +4382,9 @@ void st_table::mark_columns_used_by_index(uint index)
when calling mark_columns_used_by_index
*/
-void st_table::restore_column_maps_after_mark_index()
+void TABLE::restore_column_maps_after_mark_index()
{
- DBUG_ENTER("st_table::restore_column_maps_after_mark_index");
+ DBUG_ENTER("TABLE::restore_column_maps_after_mark_index");
key_read= 0;
(void) file->extra(HA_EXTRA_NO_KEYREAD);
@@ -4399,7 +4398,7 @@ void st_table::restore_column_maps_after_mark_index()
mark columns used by key, but don't reset other fields
*/
-void st_table::mark_columns_used_by_index_no_reset(uint index,
+void TABLE::mark_columns_used_by_index_no_reset(uint index,
MY_BITMAP *bitmap)
{
KEY_PART_INFO *key_part= key_info[index].key_part;
@@ -4418,7 +4417,7 @@ void st_table::mark_columns_used_by_index_no_reset(uint index,
always set and sometimes read.
*/
-void st_table::mark_auto_increment_column()
+void TABLE::mark_auto_increment_column()
{
DBUG_ASSERT(found_next_number_field);
/*
@@ -4451,7 +4450,7 @@ void st_table::mark_auto_increment_column()
retrieve the row again.
*/
-void st_table::mark_columns_needed_for_delete()
+void TABLE::mark_columns_needed_for_delete()
{
if (triggers)
triggers->mark_fields_used(TRG_EVENT_DELETE);
@@ -4501,7 +4500,7 @@ void st_table::mark_columns_needed_for_delete()
retrieve the row again.
*/
-void st_table::mark_columns_needed_for_update()
+void TABLE::mark_columns_needed_for_update()
{
DBUG_ENTER("mark_columns_needed_for_update");
if (triggers)
@@ -4544,7 +4543,7 @@ void st_table::mark_columns_needed_for_update()
as changed.
*/
-void st_table::mark_columns_needed_for_insert()
+void TABLE::mark_columns_needed_for_insert()
{
if (triggers)
{
@@ -4574,7 +4573,7 @@ void st_table::mark_columns_needed_for_insert()
TABLEs. Each of these TABLEs is called a part of a MERGE table.
*/
-bool st_table::is_children_attached(void)
+bool TABLE::is_children_attached(void)
{
return((child_l && children_attached) ||
(parent && parent->children_attached));
@@ -4638,9 +4637,9 @@ Item_subselect *TABLE_LIST::containing_subselect()
DESCRIPTION
The parser collects the index hints for each table in a "tagged list"
(TABLE_LIST::index_hints). Using the information in this tagged list
- this function sets the members st_table::keys_in_use_for_query,
+ this function sets the members st_table::keys_in_use_for_query,
st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
- st_table::force_index, st_table::force_index_order,
+ st_table::force_index, st_table::force_index_order,
st_table::force_index_group and st_table::covering_keys.
Current implementation of the runtime does not allow mixing FORCE INDEX
diff --git a/sql/table.h b/sql/table.h
index 69322eab6f4..49a97958807 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -293,9 +293,9 @@ TABLE_CATEGORY get_table_category(const LEX_STRING *db,
instance of table share per one table in the database.
*/
-typedef struct st_table_share
+struct TABLE_SHARE
{
- st_table_share() {} /* Remove gcc warning */
+ TABLE_SHARE() {} /* Remove gcc warning */
/** Category of this table. */
TABLE_CATEGORY table_category;
@@ -308,11 +308,7 @@ typedef struct st_table_share
TYPELIB *intervals; /* pointer to interval info */
pthread_mutex_t mutex; /* For locking the share */
pthread_cond_t cond; /* To signal that share is ready */
- struct st_table_share *next, /* Link to unused shares */
- **prev;
-#ifdef NOT_YET
- struct st_table *open_tables; /* link to open tables */
-#endif
+ TABLE_SHARE *next, **prev; /* Link to unused shares */
/* The following is copied to each TABLE on OPEN */
Field **field;
@@ -426,6 +422,7 @@ typedef struct st_table_share
/** place to store storage engine specific data */
void *ha_data;
+ void (*ha_data_destroy)(void *); /* An optional destructor for ha_data */
/*
@@ -595,7 +592,7 @@ typedef struct st_table_share
return (tmp_table == SYSTEM_TMP_TABLE || is_view) ? 0 : table_map_id;
}
-} TABLE_SHARE;
+};
extern ulong refresh_version;
@@ -608,19 +605,16 @@ enum index_hint_type
INDEX_HINT_FORCE
};
-struct st_table {
- st_table() {} /* Remove gcc warning */
+struct TABLE
+{
+ TABLE() {} /* Remove gcc warning */
TABLE_SHARE *s;
handler *file;
-#ifdef NOT_YET
- struct st_table *used_next, **used_prev; /* Link to used tables */
- struct st_table *open_next, **open_prev; /* Link to open tables */
-#endif
- struct st_table *next, *prev;
+ TABLE *next, *prev;
/* For the below MERGE related members see top comment in ha_myisammrg.cc */
- struct st_table *parent; /* Set in MERGE child. Ptr to parent */
+ TABLE *parent; /* Set in MERGE child. Ptr to parent */
TABLE_LIST *child_l; /* Set in MERGE parent. List of children */
TABLE_LIST **child_last_l; /* Set in MERGE parent. End of list */
@@ -1014,7 +1008,6 @@ typedef struct st_schema_table
/** The threshold size a blob field buffer before it is freed */
#define MAX_TDC_BLOB_SIZE 65536
-struct st_lex;
class select_union;
class TMP_TABLE_PARAM;
@@ -1092,6 +1085,7 @@ public:
(TABLE_LIST::join_using_fields != NULL)
*/
+struct LEX;
class Index_hint;
struct TABLE_LIST
{
@@ -1212,7 +1206,7 @@ struct TABLE_LIST
TMP_TABLE_PARAM *schema_table_param;
/* link to select_lex where this table was used */
st_select_lex *select_lex;
- st_lex *view; /* link on VIEW lex for merging */
+ LEX *view; /* link on VIEW lex for merging */
Field_translator *field_translation; /* array of VIEW fields */
/* pointer to element after last one in translation table above */
Field_translator *field_translation_end;
@@ -1429,9 +1423,9 @@ struct TABLE_LIST
Item_subselect *containing_subselect();
/*
- Compiles the tagged hints list and fills up st_table::keys_in_use_for_query,
- st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
- st_table::force_index and st_table::covering_keys.
+ Compiles the tagged hints list and fills up TABLE::keys_in_use_for_query,
+ TABLE::keys_in_use_for_group_by, TABLE::keys_in_use_for_order_by,
+ TABLE::force_index and TABLE::covering_keys.
*/
bool process_index_hints(TABLE *table);
diff --git a/sql/time.cc b/sql/time.cc
index 810d6426a01..5f804072eb0 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -965,20 +965,22 @@ calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, longlong *s
0 - a == b
1 - a > b
- NOTES
- TIME.second_part is not considered during comparison
*/
-int
-my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
+int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
{
- my_ulonglong a_t= TIME_to_ulonglong_datetime(a);
- my_ulonglong b_t= TIME_to_ulonglong_datetime(b);
+ ulonglong a_t= TIME_to_ulonglong_datetime(a);
+ ulonglong b_t= TIME_to_ulonglong_datetime(b);
+ if (a_t < b_t)
+ return -1;
if (a_t > b_t)
return 1;
- else if (a_t < b_t)
+
+ if (a->second_part < b->second_part)
return -1;
+ if (a->second_part > b->second_part)
+ return 1;
return 0;
}
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 6757798ad32..d4b7ae4b73a 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1578,20 +1578,19 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
DBUG_RETURN(1);
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/* Init all memory structures that require explicit destruction */
- if (hash_init(&tz_names, &my_charset_latin1, 20,
- 0, 0, (hash_get_key) my_tz_names_get_key, 0, 0))
+ if (my_hash_init(&tz_names, &my_charset_latin1, 20,
+ 0, 0, (my_hash_get_key) my_tz_names_get_key, 0, 0))
{
sql_print_error("Fatal error: OOM while initializing time zones");
goto end;
}
- if (hash_init(&offset_tzs, &my_charset_latin1, 26, 0, 0,
- (hash_get_key)my_offset_tzs_get_key, 0, 0))
+ if (my_hash_init(&offset_tzs, &my_charset_latin1, 26, 0, 0,
+ (my_hash_get_key)my_offset_tzs_get_key, 0, 0))
{
sql_print_error("Fatal error: OOM while initializing time zones");
- hash_free(&tz_names);
+ my_hash_free(&tz_names);
goto end;
}
init_alloc_root(&tz_storage, 32 * 1024, 0);
@@ -1774,8 +1773,8 @@ void my_tz_free()
{
tz_inited= 0;
VOID(pthread_mutex_destroy(&tz_LOCK));
- hash_free(&offset_tzs);
- hash_free(&tz_names);
+ my_hash_free(&offset_tzs);
+ my_hash_free(&tz_names);
free_root(&tz_storage, MYF(0));
}
}
@@ -2267,9 +2266,9 @@ my_tz_find(THD *thd, const String *name)
if (!str_to_offset(name->ptr(), name->length(), &offset))
{
- if (!(result_tz= (Time_zone_offset *)hash_search(&offset_tzs,
- (const uchar *)&offset,
- sizeof(long))))
+ if (!(result_tz= (Time_zone_offset *)my_hash_search(&offset_tzs,
+ (const uchar *)&offset,
+ sizeof(long))))
{
DBUG_PRINT("info", ("Creating new Time_zone_offset object"));
@@ -2285,9 +2284,10 @@ my_tz_find(THD *thd, const String *name)
else
{
result_tz= 0;
- if ((tmp_tzname= (Tz_names_entry *)hash_search(&tz_names,
- (const uchar *)name->ptr(),
- name->length())))
+ if ((tmp_tzname= (Tz_names_entry *)my_hash_search(&tz_names,
+ (const uchar *)
+ name->ptr(),
+ name->length())))
result_tz= tmp_tzname->tz;
else if (time_zone_tables_exist)
{
diff --git a/storage/archive/archive_reader.c b/storage/archive/archive_reader.c
index 84d4e318b49..0d641de3e15 100644
--- a/storage/archive/archive_reader.c
+++ b/storage/archive/archive_reader.c
@@ -390,7 +390,8 @@ static void print_version(void)
static void get_options(int *argc, char ***argv)
{
- load_defaults("my", load_default_groups, argc, argv);
+ if (load_defaults("my", load_default_groups, argc, argv))
+ exit(1);
default_argv= *argv;
handle_options(argc, argv, my_long_options, get_one_option);
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index bdad3e42e44..1cb9b8bba80 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -172,8 +172,8 @@ int archive_db_init(void *p)
if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
goto error;
- if (hash_init(&archive_open_tables, table_alias_charset, 32, 0, 0,
- (hash_get_key) archive_get_key, 0, 0))
+ if (my_hash_init(&archive_open_tables, table_alias_charset, 32, 0, 0,
+ (my_hash_get_key) archive_get_key, 0, 0))
{
VOID(pthread_mutex_destroy(&archive_mutex));
}
@@ -198,7 +198,7 @@ error:
int archive_db_done(void *p)
{
- hash_free(&archive_open_tables);
+ my_hash_free(&archive_open_tables);
VOID(pthread_mutex_destroy(&archive_mutex));
return 0;
@@ -316,9 +316,9 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
pthread_mutex_lock(&archive_mutex);
length=(uint) strlen(table_name);
- if (!(share=(ARCHIVE_SHARE*) hash_search(&archive_open_tables,
- (uchar*) table_name,
- length)))
+ if (!(share=(ARCHIVE_SHARE*) my_hash_search(&archive_open_tables,
+ (uchar*) table_name,
+ length)))
{
char *tmp_name;
azio_stream archive_tmp;
@@ -394,7 +394,7 @@ int ha_archive::free_share()
pthread_mutex_lock(&archive_mutex);
if (!--share->use_count)
{
- hash_delete(&archive_open_tables, (uchar*) share);
+ my_hash_delete(&archive_open_tables, (uchar*) share);
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->mutex));
/*
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 03ed57f38e8..27e4c919911 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -106,7 +106,7 @@ int ha_blackhole::update_row(const uchar *old_data, uchar *new_data)
{
DBUG_ENTER("ha_blackhole::update_row");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -115,7 +115,7 @@ int ha_blackhole::delete_row(const uchar *buf)
{
DBUG_ENTER("ha_blackhole::delete_row");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -134,7 +134,7 @@ int ha_blackhole::rnd_next(uchar *buf)
MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
TRUE);
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -224,7 +224,7 @@ int ha_blackhole::index_read_map(uchar * buf, const uchar * key,
DBUG_ENTER("ha_blackhole::index_read");
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -241,7 +241,7 @@ int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key,
DBUG_ENTER("ha_blackhole::index_read_idx");
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -257,7 +257,7 @@ int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key,
DBUG_ENTER("ha_blackhole::index_read_last");
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -319,8 +319,9 @@ static st_blackhole_share *get_share(const char *table_name)
length= (uint) strlen(table_name);
pthread_mutex_lock(&blackhole_mutex);
- if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables,
- (uchar*) table_name, length)))
+ if (!(share= (st_blackhole_share*)
+ my_hash_search(&blackhole_open_tables,
+ (uchar*) table_name, length)))
{
if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) +
length,
@@ -350,7 +351,7 @@ static void free_share(st_blackhole_share *share)
{
pthread_mutex_lock(&blackhole_mutex);
if (!--share->use_count)
- hash_delete(&blackhole_open_tables, (uchar*) share);
+ my_hash_delete(&blackhole_open_tables, (uchar*) share);
pthread_mutex_unlock(&blackhole_mutex);
}
@@ -377,16 +378,16 @@ static int blackhole_init(void *p)
blackhole_hton->flags= HTON_CAN_RECREATE;
VOID(pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST));
- (void) hash_init(&blackhole_open_tables, system_charset_info,32,0,0,
- (hash_get_key) blackhole_get_key,
- (hash_free_key) blackhole_free_key, 0);
+ (void) my_hash_init(&blackhole_open_tables, system_charset_info,32,0,0,
+ (my_hash_get_key) blackhole_get_key,
+ (my_hash_free_key) blackhole_free_key, 0);
return 0;
}
static int blackhole_fini(void *p)
{
- hash_free(&blackhole_open_tables);
+ my_hash_free(&blackhole_open_tables);
pthread_mutex_destroy(&blackhole_mutex);
return 0;
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 07c4785ab90..9cc0f1e607b 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -111,8 +111,8 @@ static int tina_init_func(void *p)
tina_hton= (handlerton *)p;
VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
- (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
- (hash_get_key) tina_get_key,0,0);
+ (void) my_hash_init(&tina_open_tables,system_charset_info,32,0,0,
+ (my_hash_get_key) tina_get_key,0,0);
tina_hton->state= SHOW_OPTION_YES;
tina_hton->db_type= DB_TYPE_CSV_DB;
tina_hton->create= tina_create_handler;
@@ -123,7 +123,7 @@ static int tina_init_func(void *p)
static int tina_done_func(void *p)
{
- hash_free(&tina_open_tables);
+ my_hash_free(&tina_open_tables);
pthread_mutex_destroy(&tina_mutex);
return 0;
@@ -148,9 +148,9 @@ static TINA_SHARE *get_share(const char *table_name, TABLE *table)
If share is not present in the hash, create a new share and
initialize its members.
*/
- if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
- (uchar*) table_name,
- length)))
+ if (!(share=(TINA_SHARE*) my_hash_search(&tina_open_tables,
+ (uchar*) table_name,
+ length)))
{
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
&share, sizeof(*share),
@@ -377,7 +377,7 @@ static int free_share(TINA_SHARE *share)
share->tina_write_opened= FALSE;
}
- hash_delete(&tina_open_tables, (uchar*) share);
+ my_hash_delete(&tina_open_tables, (uchar*) share);
thr_lock_delete(&share->lock);
pthread_mutex_destroy(&share->mutex);
my_free((uchar*) share, MYF(0));
@@ -448,6 +448,7 @@ ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin);
chain= chain_buffer;
file_buff= new Transparent_file();
+ init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);;
}
@@ -594,7 +595,7 @@ int ha_tina::find_current_row(uchar *buf)
bool read_all;
DBUG_ENTER("ha_tina::find_current_row");
- free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
+ free_root(&blobroot, MYF(0));
/*
We do not read further then local_saved_data_file_length in order
@@ -1073,8 +1074,6 @@ int ha_tina::rnd_init(bool scan)
records_is_known= 0;
chain_ptr= chain;
- init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
-
DBUG_RETURN(0);
}
@@ -1192,6 +1191,7 @@ int ha_tina::extra(enum ha_extra_function operation)
DBUG_RETURN(0);
}
+
/*
Set end_pos to the last valid byte of continuous area, closest
to the given "hole", stored in the buffer. "Valid" here means,
@@ -1394,8 +1394,6 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
/* set current position to the beginning of the file */
current_position= next_position= 0;
- init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
-
/* Read the file row-by-row. If everything is ok, repair is not needed. */
while (!(rc= find_current_row(buf)))
{
@@ -1595,8 +1593,6 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
/* set current position to the beginning of the file */
current_position= next_position= 0;
- init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
-
/* Read the file row-by-row. If everything is ok, repair is not needed. */
while (!(rc= find_current_row(buf)))
{
@@ -1604,7 +1600,7 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
count--;
current_position= next_position;
}
-
+
free_root(&blobroot, MYF(0));
my_free((char*)buf, MYF(0));
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index 02e0700a825..a246d1858e5 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -98,6 +98,7 @@ public:
my_free(chain, 0);
if (file_buff)
delete file_buff;
+ free_root(&blobroot, MYF(0));
}
const char *table_type() const { return "CSV"; }
const char *index_type(uint inx) { return "NONE"; }
diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am
index 5071c217ef3..1179a338ee2 100644
--- a/storage/example/Makefile.am
+++ b/storage/example/Makefile.am
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2006 MySQL AB, 2009 Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright (C) 2005-2006 MySQL AB
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
@@ -34,7 +34,7 @@ noinst_HEADERS = ha_example.h
EXTRA_LTLIBRARIES = ha_example.la
pkgplugin_LTLIBRARIES = @plugin_example_shared_target@
-ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir)
+ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
ha_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
ha_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
ha_example_la_SOURCES = ha_example.cc
@@ -50,18 +50,11 @@ libexample_a_SOURCES= ha_example.cc
EXTRA_DIST = CMakeLists.txt plug.in
if HAVE_DTRACE_DASH_G
-# The object for static and dynamic linking of example differ
-# For static linkage of example to mysqld
-# That's actually not needed as example is only dynamic loadable, but for completion
libexample_a_LIBADD = probes_mysql.o
-libexample_a_DEPENDENCIES = probes_mysql.o dtrace_files dtrace_providers
-# For example as shared library
-ha_example_la_LIBADD = probes_sh_mysql.o
-ha_example_la_DEPENDENCIES = probes_sh_mysql.o $(DTRACESHAREDFILES) dtrace_providers
-
-CLEANFILES = $(DTRACEPROVIDER) dtrace_files dtrace_providers $(DTRACESHAREDFILES)
+libexample_a_DEPENDENCIES = probes_mysql.o
+CLEANFILES =
+BUILT_SOURCES =
DTRACEFILES = libexample_a-ha_example.o
-DTRACESHAREDFILES = .libs/ha_example_la-ha_example.o
DTRACEPROVIDER = probes_mysql.d
dtrace_files:
@@ -73,12 +66,8 @@ probes_mysql.d:
$(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
echo timestamp > dtrace_sources
-probes_sh_mysql.o: $(DTRACEPROVIDER) $(DTRACESHAREDFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACESHAREDFILES) -o $@
-
probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
$(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-
endif
# Don't update the files from bitkeeper
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index 30fc82c82d2..9bc666663c3 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003 MySQL AB, 2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -133,8 +133,8 @@ static int example_init_func(void *p)
example_hton= (handlerton *)p;
VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST));
- (void) hash_init(&example_open_tables,system_charset_info,32,0,0,
- (hash_get_key) example_get_key,0,0);
+ (void) my_hash_init(&example_open_tables,system_charset_info,32,0,0,
+ (my_hash_get_key) example_get_key,0,0);
example_hton->state= SHOW_OPTION_YES;
example_hton->create= example_create_handler;
@@ -151,7 +151,7 @@ static int example_done_func(void *p)
if (example_open_tables.records)
error= 1;
- hash_free(&example_open_tables);
+ my_hash_free(&example_open_tables);
pthread_mutex_destroy(&example_mutex);
DBUG_RETURN(0);
@@ -175,9 +175,9 @@ static EXAMPLE_SHARE *get_share(const char *table_name, TABLE *table)
pthread_mutex_lock(&example_mutex);
length=(uint) strlen(table_name);
- if (!(share=(EXAMPLE_SHARE*) hash_search(&example_open_tables,
- (uchar*) table_name,
- length)))
+ if (!(share=(EXAMPLE_SHARE*) my_hash_search(&example_open_tables,
+ (uchar*) table_name,
+ length)))
{
if (!(share=(EXAMPLE_SHARE *)
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
@@ -222,7 +222,7 @@ static int free_share(EXAMPLE_SHARE *share)
pthread_mutex_lock(&example_mutex);
if (!--share->use_count)
{
- hash_delete(&example_open_tables, (uchar*) share);
+ my_hash_delete(&example_open_tables, (uchar*) share);
thr_lock_delete(&share->lock);
pthread_mutex_destroy(&share->mutex);
my_free(share, MYF(0));
@@ -921,6 +921,24 @@ static struct st_mysql_sys_var* example_system_variables[]= {
NULL
};
+// this is an example of SHOW_FUNC and of my_snprintf() service
+static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var,
+ char *buf)
+{
+ var->type= SHOW_CHAR;
+ var->value= buf; // it's of SHOW_VAR_FUNC_BUFF_SIZE bytes
+ my_snprintf(buf, SHOW_VAR_FUNC_BUFF_SIZE,
+ "enum_var is %u, ulong_var is %lu, %.6b", // %b is MySQL extension
+ srv_enum_var, srv_ulong_var, "really");
+ return 0;
+}
+
+static struct st_mysql_show_var func_status[]=
+{
+ {"example_func_example", (char *)show_func_example, SHOW_FUNC},
+ {0,0,SHOW_UNDEF}
+};
+
mysql_declare_plugin(example)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
@@ -932,7 +950,7 @@ mysql_declare_plugin(example)
example_init_func, /* Plugin Init */
example_done_func, /* Plugin Deinit */
0x0001 /* 0.1 */,
- NULL, /* status variables */
+ func_status, /* status variables */
example_system_variables, /* system variables */
NULL /* config options */
}
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index a3fa42d7d05..05be8b27a8b 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -459,8 +459,8 @@ int federated_db_init(void *p)
if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST))
goto error;
- if (!hash_init(&federated_open_tables, &my_charset_bin, 32, 0, 0,
- (hash_get_key) federated_get_key, 0, 0))
+ if (!my_hash_init(&federated_open_tables, &my_charset_bin, 32, 0, 0,
+ (my_hash_get_key) federated_get_key, 0, 0))
{
DBUG_RETURN(FALSE);
}
@@ -483,7 +483,7 @@ error:
int federated_done(void *p)
{
- hash_free(&federated_open_tables);
+ my_hash_free(&federated_open_tables);
VOID(pthread_mutex_destroy(&federated_mutex));
return 0;
@@ -1495,10 +1495,10 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
goto error;
/* TODO: change tmp_share.scheme to LEX_STRING object */
- if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables,
- (uchar*) tmp_share.share_key,
- tmp_share.
- share_key_length)))
+ if (!(share= (FEDERATED_SHARE *) my_hash_search(&federated_open_tables,
+ (uchar*) tmp_share.share_key,
+ tmp_share.
+ share_key_length)))
{
query.set_charset(system_charset_info);
query.append(STRING_WITH_LEN("SELECT "));
@@ -1560,7 +1560,7 @@ static int free_share(FEDERATED_SHARE *share)
pthread_mutex_lock(&federated_mutex);
if (!--share->use_count)
{
- hash_delete(&federated_open_tables, (uchar*) share);
+ my_hash_delete(&federated_open_tables, (uchar*) share);
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->mutex));
free_root(&mem_root, MYF(0));
@@ -2892,7 +2892,7 @@ int ha_federated::info(uint flag)
}
if (flag & HA_STATUS_AUTO)
- stats.auto_increment_value= mysql->last_used_con->insert_id;
+ stats.auto_increment_value= mysql->insert_id;
mysql_free_result(result);
diff --git a/storage/innobase/ChangeLog b/storage/innobase/ChangeLog
index 0f8f4c4d071..70225ffd9d9 100644
--- a/storage/innobase/ChangeLog
+++ b/storage/innobase/ChangeLog
@@ -1,9 +1,89 @@
+2009-10-29 The InnoDB Team
+
+ * handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
+ mysql-test/innodb-autoinc.test:
+ Fix Bug#47125 auto_increment start value is ignored if an index is
+ created and engine=innodb
+
+2009-10-29 The InnoDB Team
+
+ * handler/ha_innodb.cc, mysql-test/innodb_bug47777.result,
+ mysql-test/innodb_bug47777.test:
+ Fix Bug#47777 innodb dies with spatial pk: Failing assertion: buf <=
+ original_buf + buf_len
+
+2009-10-29 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#38996 Race condition in ANALYZE TABLE
+
+2009-10-29 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix bug#42383: Can't create table 'test.bug39438'
+
+2009-10-29 The InnoDB Team
+
+ * os/os0proc.c:
+ Fix Bug#48237 Error handling in os_mem_alloc_large appears to
+ be incorrect
+
+2009-10-29 The InnoDB Team
+
+ * buf/buf0buf.c, buf/buf0lru.c, include/buf0buf.h, include/buf0buf.ic:
+ Fix corruption of the buf_pool->LRU_old list and improve debug
+ assertions.
+
+2009-10-28 The InnoDB Team
+
+ * srv/srv0start.c:
+ Fix Bug#41490 After enlargement of InnoDB page size, the error message
+ become inaccurate
+
+2009-10-26 The InnoDB Team
+
+ * row/row0ins.c:
+ When allocating a data tuple, zero out the system fields in order
+ to avoid Valgrind warnings about uninitialized fields in
+ dtuple_validate().
+
+2009-10-22 The InnoDB Team
+
+ * handler/ha_innodb.cc, mysql-test/innodb-zip.result,
+ mysql-test/innodb-zip.test, mysql-test/innodb_bug44369.result,
+ mysql-test/innodb_bug44369.test:
+ Fix Bug#47233 Innodb calls push_warning(MYSQL_ERROR::WARN_LEVEL_ERROR)
+
+2009-10-19 The InnoDB Team
+
+ * mysql-test/innodb_information_schema.test:
+ Fix Bug#47808 innodb_information_schema.test fails when run under
+ valgrind
+
+2009-10-15 The InnoDB Team
+
+ * include/page0page.ic:
+ Fix Bug#47058 Failure to compile innodb_plugin on solaris 10u7 + spro
+ cc/CC 5.10
+
+2009-10-05 The InnoDB Team
+
+ * buf/buf0buf.c:
+ Do not invalidate buffer pool while an LRU batch is active. Added code
+ to buf_pool_invalidate() to wait for the running batches to finish.
+
+2009-10-01 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#47763 typo in error message: Failed to open table %s after %lu
+ attemtps.
+
2009-10-01 The InnoDB Team
* fsp/fsp0fsp.c, row/row0merge.c:
- Clean up after a crash during DROP INDEX. When InnoDB crashes
+ Clean up after a crash during DROP INDEX. When InnoDB crashes
while dropping an index, ensure that the index will be completely
- dropped during crash recovery. The MySQL .frm file may still
+ dropped during crash recovery. The MySQL .frm file may still
contain the dropped index, but there is little that we can do
about it.
@@ -20,15 +100,15 @@
include/page0zip.h, page/page0cur.c, page/page0page.c,
page/page0zip.c:
Do not write to PAGE_INDEX_ID when restoring an uncompressed page
- after a compression failure. The field should only be written
- when creating a B-tree page. This fix addresses a race condition
+ after a compression failure. The field should only be written
+ when creating a B-tree page. This fix addresses a race condition
in a debug assertion.
2009-09-28 The InnoDB Team
* fil/fil0fil.c:
Try to prevent the reuse of tablespace identifiers after InnoDB
- has crashed during table creation. Also, refuse to start if files
+ has crashed during table creation. Also, refuse to start if files
with duplicate tablespace identifiers are encountered.
2009-09-25 The InnoDB Team
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index d87abbd0ed9..ff31457d200 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -1163,10 +1163,15 @@ buf_relocate(
#ifdef UNIV_LRU_DEBUG
/* buf_pool->LRU_old must be the first item in the LRU list
whose "old" flag is set. */
+ ut_a(buf_pool->LRU_old->old);
ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
|| !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
|| UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
+ } else {
+ /* Check that the "old" flag is consistent in
+ the block and its neighbours. */
+ buf_page_set_old(dpage, buf_page_is_old(dpage));
#endif /* UNIV_LRU_DEBUG */
}
diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c
index 74dd0c07ca6..8b614ce90e5 100644
--- a/storage/innobase/buf/buf0flu.c
+++ b/storage/innobase/buf/buf0flu.c
@@ -304,6 +304,28 @@ buf_flush_write_complete(
}
/********************************************************************//**
+Flush a batch of writes to the datafiles that have already been
+written by the OS. */
+static
+void
+buf_flush_sync_datafiles(void)
+/*==========================*/
+{
+ /* Wake possible simulated aio thread to actually post the
+ writes to the operating system */
+ os_aio_simulated_wake_handler_threads();
+
+ /* Wait that all async writes to tablespaces have been posted to
+ the OS */
+ os_aio_wait_until_no_pending_writes();
+
+ /* Now we flush the data to disk (for example, with fsync) */
+ fil_flush_file_spaces(FIL_TABLESPACE);
+
+ return;
+}
+
+/********************************************************************//**
Flushes possible buffered writes from the doublewrite memory buffer to disk,
and also wakes up the aio thread if simulated aio is used. It is very
important to call this function after a batch of writes has been posted,
@@ -320,8 +342,8 @@ buf_flush_buffered_writes(void)
ulint i;
if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) {
- os_aio_simulated_wake_handler_threads();
-
+ /* Sync the writes to the disk. */
+ buf_flush_sync_datafiles();
return;
}
@@ -529,22 +551,10 @@ flush:
buf_LRU_stat_inc_io();
}
- /* Wake possible simulated aio thread to actually post the
- writes to the operating system */
-
- os_aio_simulated_wake_handler_threads();
-
- /* Wait that all async writes to tablespaces have been posted to
- the OS */
-
- os_aio_wait_until_no_pending_writes();
-
- /* Now we flush the data to disk (for example, with fsync) */
-
- fil_flush_file_spaces(FIL_TABLESPACE);
+ /* Sync the writes to the disk. */
+ buf_flush_sync_datafiles();
/* We can now reuse the doublewrite memory buffer: */
-
trx_doublewrite->first_free = 0;
mutex_exit(&(trx_doublewrite->mutex));
diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
index d3a79d62d3f..4f19fd13fa5 100644
--- a/storage/innobase/buf/buf0lru.c
+++ b/storage/innobase/buf/buf0lru.c
@@ -978,14 +978,14 @@ buf_LRU_old_adjust_len(void)
#ifdef UNIV_LRU_DEBUG
ut_a(!LRU_old->old);
#endif /* UNIV_LRU_DEBUG */
- buf_page_set_old(LRU_old, TRUE);
old_len = ++buf_pool->LRU_old_len;
+ buf_page_set_old(LRU_old, TRUE);
} else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) {
- buf_page_set_old(LRU_old, FALSE);
buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old);
old_len = --buf_pool->LRU_old_len;
+ buf_page_set_old(LRU_old, FALSE);
} else {
return;
}
@@ -1009,13 +1009,13 @@ buf_LRU_old_init(void)
the adjust function to move the LRU_old pointer to the right
position */
- bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
-
- while (bpage != NULL) {
+ for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage != NULL;
+ bpage = UT_LIST_GET_PREV(LRU, bpage)) {
ut_ad(bpage->in_LRU_list);
ut_ad(buf_page_in_file(bpage));
- buf_page_set_old(bpage, TRUE);
- bpage = UT_LIST_GET_NEXT(LRU, bpage);
+ /* This loop temporarily violates the
+ assertions of buf_page_set_old(). */
+ bpage->old = TRUE;
}
buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
@@ -1091,10 +1091,19 @@ buf_LRU_remove_block(
buf_unzip_LRU_remove_block_if_needed(bpage);
- /* If the LRU list is so short that LRU_old not defined, return */
+ /* If the LRU list is so short that LRU_old is not defined,
+ clear the "old" flags and return */
if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
+ for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU); bpage != NULL;
+ bpage = UT_LIST_GET_NEXT(LRU, bpage)) {
+ /* This loop temporarily violates the
+ assertions of buf_page_set_old(). */
+ bpage->old = FALSE;
+ }
+
buf_pool->LRU_old = NULL;
+ buf_pool->LRU_old_len = 0;
return;
}
@@ -1155,14 +1164,13 @@ buf_LRU_add_block_to_end_low(
UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage);
ut_d(bpage->in_LRU_list = TRUE);
- buf_page_set_old(bpage, TRUE);
-
if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
ut_ad(buf_pool->LRU_old);
/* Adjust the length of the old block list if necessary */
+ buf_page_set_old(bpage, TRUE);
buf_pool->LRU_old_len++;
buf_LRU_old_adjust_len();
@@ -1171,8 +1179,9 @@ buf_LRU_add_block_to_end_low(
/* The LRU list is now long enough for LRU_old to become
defined: init it */
- buf_pool->LRU_old_len++;
buf_LRU_old_init();
+ } else {
+ buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
}
/* If this is a zipped block with decompressed frame as well
@@ -1223,14 +1232,13 @@ buf_LRU_add_block_low(
ut_d(bpage->in_LRU_list = TRUE);
- buf_page_set_old(bpage, old);
-
if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
ut_ad(buf_pool->LRU_old);
/* Adjust the length of the old block list if necessary */
+ buf_page_set_old(bpage, old);
buf_LRU_old_adjust_len();
} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
@@ -1239,6 +1247,8 @@ buf_LRU_add_block_low(
defined: init it */
buf_LRU_old_init();
+ } else {
+ buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
}
/* If this is a zipped block with decompressed frame as well
@@ -1436,15 +1446,6 @@ alloc:
buf_pool->LRU_old = b;
}
-#ifdef UNIV_LRU_DEBUG
- ut_a(prev_b->old
- || !UT_LIST_GET_NEXT(LRU, b)
- || UT_LIST_GET_NEXT(LRU, b)->old);
- } else {
- ut_a(!prev_b->old
- || !UT_LIST_GET_NEXT(LRU, b)
- || !UT_LIST_GET_NEXT(LRU, b)->old);
-#endif /* UNIV_LRU_DEBUG */
}
lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
@@ -1460,6 +1461,11 @@ alloc:
defined: init it */
buf_LRU_old_init();
}
+#ifdef UNIV_LRU_DEBUG
+ /* Check that the "old" flag is consistent
+ in the block and its neighbours. */
+ buf_page_set_old(b, buf_page_is_old(b));
+#endif /* UNIV_LRU_DEBUG */
} else {
ut_d(b->in_LRU_list = FALSE);
buf_LRU_add_block_low(b, buf_page_is_old(b));
@@ -1966,19 +1972,24 @@ buf_LRU_validate(void)
}
if (buf_page_is_old(bpage)) {
- old_len++;
- }
+ const buf_page_t* prev
+ = UT_LIST_GET_PREV(LRU, bpage);
+ const buf_page_t* next
+ = UT_LIST_GET_NEXT(LRU, bpage);
+
+ if (!old_len++) {
+ ut_a(buf_pool->LRU_old == bpage);
+ } else {
+ ut_a(!prev || buf_page_is_old(prev));
+ }
- if (buf_pool->LRU_old && (old_len == 1)) {
- ut_a(buf_pool->LRU_old == bpage);
+ ut_a(!next || buf_page_is_old(next));
}
bpage = UT_LIST_GET_NEXT(LRU, bpage);
}
- if (buf_pool->LRU_old) {
- ut_a(buf_pool->LRU_old_len == old_len);
- }
+ ut_a(buf_pool->LRU_old_len == old_len);
UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free,
ut_ad(ut_list_node_313->in_free_list));
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index df6dad86990..ba6f2f8666f 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -659,6 +659,7 @@ fil_node_open_file(
#ifdef UNIV_HOTBACKUP
if (space->id == 0) {
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
+ os_file_close(node->handle);
goto add_size;
}
#endif /* UNIV_HOTBACKUP */
@@ -3244,7 +3245,7 @@ fil_load_single_table_tablespace(
fprintf(stderr,
"InnoDB: Renaming tablespace %s of id %lu,\n"
"InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
- "InnoDB: because its size %lld is too small"
+ "InnoDB: because its size %" PRId64 " is too small"
" (< 4 pages 16 kB each),\n"
"InnoDB: or the space id in the file header"
" is not sensible.\n"
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index b15212f74a7..851957e53a5 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -110,7 +110,7 @@ extern "C" {
# ifndef MYSQL_PLUGIN_IMPORT
# define MYSQL_PLUGIN_IMPORT /* nothing */
# endif /* MYSQL_PLUGIN_IMPORT */
-/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
+/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count;
@@ -129,6 +129,7 @@ static ulong commit_threads = 0;
static pthread_mutex_t commit_threads_m;
static pthread_cond_t commit_cond;
static pthread_mutex_t commit_cond_m;
+static pthread_mutex_t analyze_mutex;
static bool innodb_inited = 0;
#define INSIDE_HA_INNOBASE_CC
@@ -229,21 +230,6 @@ static handler *innobase_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root);
-/***********************************************************************
-This function checks each index name for a table against reserved
-system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
-this function pushes an error message to the client, and returns true. */
-static
-bool
-innobase_index_name_is_reserved(
-/*============================*/
- /* out: true if index name matches a
- reserved name */
- const trx_t* trx, /* in: InnoDB transaction handle */
- const TABLE* form, /* in: information on table
- columns and indexes */
- const char* norm_name); /* in: table name */
-
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
system primary index. */
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
@@ -2288,6 +2274,7 @@ innobase_change_buffering_inited_ok:
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&commit_cond, NULL);
innodb_inited= 1;
#ifdef MYSQL_DYNAMIC_PLUGIN
@@ -2342,6 +2329,7 @@ innobase_end(
pthread_mutex_destroy(&prepare_commit_mutex);
pthread_mutex_destroy(&commit_threads_m);
pthread_mutex_destroy(&commit_cond_m);
+ pthread_mutex_destroy(&analyze_mutex);
pthread_cond_destroy(&commit_cond);
}
@@ -2620,6 +2608,8 @@ innobase_rollback(
innobase_release_stat_resources(trx);
+ trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
+
/* If we had reserved the auto-inc lock for some table (if
we come here to roll back the latest SQL statement) we
release it now before a possibly lengthy rollback */
@@ -3780,7 +3770,10 @@ ha_innobase::store_key_val_for_row(
} else if (mysql_type == MYSQL_TYPE_TINY_BLOB
|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
|| mysql_type == MYSQL_TYPE_BLOB
- || mysql_type == MYSQL_TYPE_LONG_BLOB) {
+ || mysql_type == MYSQL_TYPE_LONG_BLOB
+ /* MYSQL_TYPE_GEOMETRY data is treated
+ as BLOB data in innodb. */
+ || mysql_type == MYSQL_TYPE_GEOMETRY) {
CHARSET_INFO* cs;
ulint key_len;
@@ -4551,7 +4544,7 @@ calc_row_difference(
upd_t* uvect, /*!< in/out: update vector */
uchar* old_row, /*!< in: old row in MySQL format */
uchar* new_row, /*!< in: new row in MySQL format */
- struct st_table* table, /*!< in: table in MySQL data
+ TABLE* table, /*!< in: table in MySQL data
dictionary */
uchar* upd_buff, /*!< in: buffer to use */
ulint buff_len, /*!< in: buffer length */
@@ -5710,7 +5703,7 @@ create_table_def(
number fits in one byte in prtype */
push_warning_printf(
(THD*) trx->mysql_thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CANT_CREATE_TABLE,
"In InnoDB, charset-collation codes"
" must be below 256."
@@ -5744,7 +5737,7 @@ create_table_def(
if (dict_col_name_is_reserved(field->field_name)){
push_warning_printf(
(THD*) trx->mysql_thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CANT_CREATE_TABLE,
"Error creating table '%s' with "
"column name '%s'. '%s' is a "
@@ -5978,7 +5971,7 @@ create_options_are_valid(
/* Valid value. */
break;
default:
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid"
" KEY_BLOCK_SIZE = %lu."
@@ -5992,7 +5985,7 @@ create_options_are_valid(
/* If KEY_BLOCK_SIZE was specified, check for its
dependencies. */
if (kbs_specified && !srv_file_per_table) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_per_table.");
@@ -6000,7 +5993,7 @@ create_options_are_valid(
}
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_format >"
@@ -6024,7 +6017,7 @@ create_options_are_valid(
if (!srv_file_per_table) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_per_table.",
@@ -6036,7 +6029,7 @@ create_options_are_valid(
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_format >"
@@ -6053,7 +6046,7 @@ create_options_are_valid(
&& form->s->row_type == ROW_TYPE_DYNAMIC) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = DYNAMIC with"
@@ -6077,7 +6070,7 @@ create_options_are_valid(
if (kbs_specified) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = %s with"
@@ -6090,7 +6083,7 @@ create_options_are_valid(
default:
push_warning(thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid ROW_FORMAT specifier.");
ret = FALSE;
@@ -6154,13 +6147,15 @@ ha_innobase::create(
1. <database_name>/<table_name>: for normal table creation
2. full path: for temp table creation, or sym link
- When srv_file_per_table is on, check for full path pattern, i.e.
+ When srv_file_per_table is on and mysqld_embedded is off,
+ check for full path pattern, i.e.
X:\dir\..., X is a driver letter, or
\\dir1\dir2\..., UNC path
returns error if it is in full path format, but not creating a temp.
table. Currently InnoDB does not support symbolic link on Windows. */
if (srv_file_per_table
+ && !mysqld_embedded
&& (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
if ((name[1] == ':')
@@ -6364,7 +6359,8 @@ ha_innobase::create(
/* Check for name conflicts (with reserved name) for
any user indices to be created. */
- if (innobase_index_name_is_reserved(trx, form, norm_name)) {
+ if (innobase_index_name_is_reserved(trx, form->key_info,
+ form->s->keys)) {
error = -1;
goto cleanup;
}
@@ -6451,18 +6447,22 @@ ha_innobase::create(
setup at this stage and so we use thd. */
/* We need to copy the AUTOINC value from the old table if
- this is an ALTER TABLE. */
+ this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
+ does a table copy too. */
if (((create_info->used_fields & HA_CREATE_USED_AUTO)
- || thd_sql_command(thd) == SQLCOM_ALTER_TABLE)
- && create_info->auto_increment_value != 0) {
-
- /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
- CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
- definition from the dictionary and get the current value
- of the auto increment field. Set a new value to the
- auto increment field if the value is greater than the
- maximum value in the column. */
+ || thd_sql_command(thd) == SQLCOM_ALTER_TABLE
+ || thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
+ && create_info->auto_increment_value > 0) {
+
+ /* Query was one of :
+ CREATE TABLE ...AUTO_INCREMENT = x; or
+ ALTER TABLE...AUTO_INCREMENT = x; or
+ CREATE INDEX x on t(...);
+ Find out a table definition from the dictionary and get
+ the current value of the auto increment field. Set a new
+ value to the auto increment field if the value is greater
+ than the maximum value in the column. */
auto_inc_value = create_info->auto_increment_value;
@@ -7316,9 +7316,15 @@ ha_innobase::analyze(
THD* thd, /*!< in: connection thread handle */
HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
{
+ /* Serialize ANALYZE TABLE inside InnoDB, see
+ Bug#38996 Race condition in ANALYZE TABLE */
+ pthread_mutex_lock(&analyze_mutex);
+
/* Simply call ::info() with all the flags */
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ pthread_mutex_unlock(&analyze_mutex);
+
return(0);
}
@@ -7913,8 +7919,9 @@ ha_innobase::external_lock(
{
ulong const binlog_format= thd_binlog_format(thd);
ulong const tx_isolation = thd_tx_isolation(ha_thd());
- if (tx_isolation <= ISO_READ_COMMITTED &&
- binlog_format == BINLOG_FORMAT_STMT)
+ if (tx_isolation <= ISO_READ_COMMITTED
+ && binlog_format == BINLOG_FORMAT_STMT
+ && thd_binlog_filter_ok(thd))
{
char buf[256];
my_snprintf(buf, sizeof(buf),
@@ -8794,6 +8801,7 @@ ha_innobase::get_auto_increment(
AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
ulonglong need;
+ ulonglong current;
ulonglong next_value;
ulonglong col_max_value;
@@ -8802,11 +8810,12 @@ ha_innobase::get_auto_increment(
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
+ current = *first_value > col_max_value ? autoinc : *first_value;
need = *nb_reserved_values * increment;
/* Compute the last value in the interval */
next_value = innobase_next_autoinc(
- *first_value, need, offset, col_max_value);
+ current, need, offset, col_max_value);
prebuilt->autoinc_last_value = next_value;
@@ -9825,36 +9834,39 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
/***********************************************************************
This function checks each index name for a table against reserved
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
-this function pushes an error message to the client, and returns true. */
-static
+this function pushes an warning message to the client, and returns true. */
+extern "C" UNIV_INTERN
bool
innobase_index_name_is_reserved(
/*============================*/
/* out: true if an index name
matches the reserved name */
const trx_t* trx, /* in: InnoDB transaction handle */
- const TABLE* form, /* in: information on table
- columns and indexes */
- const char* norm_name) /* in: table name */
+ const KEY* key_info, /* in: Indexes to be created */
+ ulint num_of_keys) /* in: Number of indexes to
+ be created. */
{
- KEY* key;
+ const KEY* key;
uint key_num; /* index number */
- for (key_num = 0; key_num < form->s->keys; key_num++) {
- key = form->key_info + key_num;
+ for (key_num = 0; key_num < num_of_keys; key_num++) {
+ key = &key_info[key_num];
if (innobase_strcasecmp(key->name,
innobase_index_reserve_name) == 0) {
/* Push warning to mysql */
push_warning_printf((THD*) trx->mysql_thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_CANT_CREATE_TABLE,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WRONG_NAME_FOR_INDEX,
"Cannot Create Index with name "
"'%s'. The name is reserved "
"for the system default primary "
"index.",
innobase_index_reserve_name);
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
+ innobase_index_reserve_name);
+
return(true);
}
}
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index cc98003f8ff..4779651ee27 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -257,6 +257,13 @@ int thd_binlog_format(const MYSQL_THD thd);
@param all TRUE <=> rollback main transaction.
*/
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
+
+/**
+ Check if binary logging is filtered for thread's current db.
+ @param thd Thread handle
+ @retval 1 the query is not filtered, 0 otherwise.
+*/
+bool thd_binlog_filter_ok(const MYSQL_THD thd);
}
typedef struct trx_struct trx_t;
@@ -282,3 +289,21 @@ trx_t*
innobase_trx_allocate(
/*==================*/
MYSQL_THD thd); /*!< in: user thread handle */
+
+
+/*********************************************************************//**
+This function checks each index name for a table against reserved
+system default primary index name 'GEN_CLUST_INDEX'. If a name
+matches, this function pushes an warning message to the client,
+and returns true. */
+extern "C"
+bool
+innobase_index_name_is_reserved(
+/*============================*/
+ /* out: true if the index name
+ matches the reserved name */
+ const trx_t* trx, /* in: InnoDB transaction handle */
+ const KEY* key_info, /* in: Indexes to be created */
+ ulint num_of_keys); /* in: Number of indexes to
+ be created. */
+
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 1aa0e6b126c..37aed06b28a 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -628,7 +628,7 @@ ha_innobase::add_index(
ulint num_created = 0;
ibool dict_locked = FALSE;
ulint new_primary;
- ulint error;
+ int error;
DBUG_ENTER("ha_innobase::add_index");
ut_a(table);
@@ -656,9 +656,13 @@ ha_innobase::add_index(
innodb_table = indexed_table
= dict_table_get(prebuilt->table->name, FALSE);
- /* Check that index keys are sensible */
-
- error = innobase_check_index_keys(key_info, num_of_keys);
+ /* Check if the index name is reserved. */
+ if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
+ error = -1;
+ } else {
+ /* Check that index keys are sensible */
+ error = innobase_check_index_keys(key_info, num_of_keys);
+ }
if (UNIV_UNLIKELY(error)) {
err_exit:
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index e9d95a14f1b..927ff893e39 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1129,7 +1129,7 @@ struct buf_page_struct{
debugging */
#endif /* UNIV_DEBUG */
unsigned old:1; /*!< TRUE if the block is in the old
- blocks in the LRU list */
+ blocks in buf_pool->LRU_old */
unsigned freed_page_clock:31;/*!< the value of
buf_pool->freed_page_clock
when this block was the last
@@ -1393,8 +1393,7 @@ struct buf_pool_struct{
the block to which LRU_old points
onward, including that block;
see buf0lru.c for the restrictions
- on this value; not defined if
- LRU_old == NULL;
+ on this value; 0 if LRU_old == NULL;
NOTE: LRU_old_len must be adjusted
whenever LRU_old shrinks or grows! */
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 8b1f904a090..0f92a59a1c7 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -466,10 +466,19 @@ buf_page_set_old(
ut_ad(bpage->in_LRU_list);
#ifdef UNIV_LRU_DEBUG
- if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)
- && UT_LIST_GET_PREV(LRU, bpage)->old
- == UT_LIST_GET_NEXT(LRU, bpage)->old) {
- ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old);
+ ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL));
+ /* If a block is flagged "old", the LRU_old list must exist. */
+ ut_a(!old || buf_pool->LRU_old);
+
+ if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) {
+ const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage);
+ const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage);
+ if (prev->old == next->old) {
+ ut_a(prev->old == old);
+ } else {
+ ut_a(!prev->old);
+ ut_a(buf_pool->LRU_old == (old ? bpage : next));
+ }
}
#endif /* UNIV_LRU_DEBUG */
diff --git a/storage/innobase/include/handler0alter.h b/storage/innobase/include/handler0alter.h
index 985b76f4f50..7f5af6d2e76 100644
--- a/storage/innobase/include/handler0alter.h
+++ b/storage/innobase/include/handler0alter.h
@@ -27,7 +27,7 @@ UNIV_INTERN
void
innobase_rec_to_mysql(
/*==================*/
- TABLE* table, /*!< in/out: MySQL table */
+ struct TABLE* table, /*!< in/out: MySQL table */
const rec_t* rec, /*!< in: record */
const dict_index_t* index, /*!< in: index */
const ulint* offsets); /*!< in: rec_get_offsets(
@@ -39,4 +39,4 @@ UNIV_INTERN
void
innobase_rec_reset(
/*===============*/
- TABLE* table); /*!< in/out: MySQL table */
+ struct TABLE* table); /*!< in/out: MySQL table */
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index 318ec1cc1f2..8f794410f20 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -907,7 +907,7 @@ page_get_data_size(
/************************************************************//**
Allocates a block of memory from the free list of an index page. */
-UNIV_INTERN
+UNIV_INLINE
void
page_mem_alloc_free(
/*================*/
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h
index 62a5efd11f7..fbeb125ce7b 100644
--- a/storage/innobase/include/row0merge.h
+++ b/storage/innobase/include/row0merge.h
@@ -191,7 +191,7 @@ row_merge_build_indexes(
unless creating a PRIMARY KEY */
dict_index_t** indexes, /*!< in: indexes to be created */
ulint n_indexes, /*!< in: size of indexes[] */
- TABLE* table); /*!< in/out: MySQL table, for
+ struct TABLE* table); /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
#endif /* row0merge.h */
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 6d5d195172e..b05241f00f8 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -756,8 +756,6 @@ struct row_prebuilt_struct {
store it here so that we can return
it to MySQL */
/*----------------------*/
- UT_LIST_NODE_T(row_prebuilt_t) prebuilts;
- /*!< list node of table->prebuilts */
ulint magic_n2; /*!< this should be the same as
magic_n */
};
diff --git a/storage/innobase/include/row0types.h b/storage/innobase/include/row0types.h
index 7920fd75061..1be729206ba 100644
--- a/storage/innobase/include/row0types.h
+++ b/storage/innobase/include/row0types.h
@@ -54,6 +54,6 @@ typedef struct purge_node_struct purge_node_t;
typedef struct row_ext_struct row_ext_t;
/* MySQL data types */
-typedef struct st_table TABLE;
+struct TABLE;
#endif
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 0e14f7b1cba..5d0361658af 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -237,7 +237,7 @@ by one. */
/* Linkage specifier for non-static InnoDB symbols (variables and functions)
that are only referenced from within InnoDB, not from MySQL */
-#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(UNIV_HOTBACKUP)
+#if defined(__GNUC__) && (__GNUC__ >= 4) || defined(__INTEL_COMPILER)
# define UNIV_INTERN __attribute__((visibility ("hidden")))
#else
# define UNIV_INTERN
diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c
index a1d3bad2add..0cb76d1796f 100644
--- a/storage/innobase/os/os0file.c
+++ b/storage/innobase/os/os0file.c
@@ -832,6 +832,23 @@ next_file:
ret = stat(full_path, &statinfo);
if (ret) {
+
+ if (errno == ENOENT) {
+ /* readdir() returned a file that does not exist,
+ it must have been deleted in the meantime. Do what
+ would have happened if the file was deleted before
+ readdir() - ignore and go to the next entry.
+ If this is the last entry then info->name will still
+ contain the name of the deleted file when this
+ function returns, but this is not an issue since the
+ caller shouldn't be looking at info when end of
+ directory is returned. */
+
+ ut_free(full_path);
+
+ goto next_file;
+ }
+
os_file_handle_error_no_exit(full_path, "stat");
ut_free(full_path);
diff --git a/storage/innobase/os/os0proc.c b/storage/innobase/os/os0proc.c
index a0ea9a1b258..48922886f23 100644
--- a/storage/innobase/os/os0proc.c
+++ b/storage/innobase/os/os0proc.c
@@ -97,6 +97,7 @@ os_mem_alloc_large(
fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to"
" attach shared memory segment, errno %d\n",
errno);
+ ptr = NULL;
}
/* Remove the shared memory segment so that it will be
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
index ab3ae70e3e2..fe51fce82c4 100644
--- a/storage/innobase/row/row0ins.c
+++ b/storage/innobase/row/row0ins.c
@@ -141,7 +141,7 @@ row_ins_alloc_sys_fields(
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
- ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN);
+ ptr = mem_heap_zalloc(heap, DATA_ROW_ID_LEN);
dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN);
@@ -152,7 +152,7 @@ row_ins_alloc_sys_fields(
col = dict_table_get_sys_col(table, DATA_TRX_ID);
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
- ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
+ ptr = mem_heap_zalloc(heap, DATA_TRX_ID_LEN);
dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN);
@@ -163,7 +163,7 @@ row_ins_alloc_sys_fields(
col = dict_table_get_sys_col(table, DATA_ROLL_PTR);
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
- ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
+ ptr = mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN);
dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN);
}
diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
index a303a2f3278..54d701444e2 100644
--- a/storage/innobase/row/row0merge.c
+++ b/storage/innobase/row/row0merge.c
@@ -408,7 +408,7 @@ row_merge_buf_add(
/** Structure for reporting duplicate records. */
struct row_merge_dup_struct {
const dict_index_t* index; /*!< index being sorted */
- TABLE* table; /*!< MySQL table object */
+ struct TABLE* table; /*!< MySQL table object */
ulint n_dup; /*!< number of duplicates */
};
@@ -1100,7 +1100,7 @@ ulint
row_merge_read_clustered_index(
/*===========================*/
trx_t* trx, /*!< in: transaction */
- TABLE* table, /*!< in/out: MySQL table object,
+ struct TABLE* table, /*!< in/out: MySQL table object,
for reporting erroneous records */
const dict_table_t* old_table,/*!< in: table where rows are
read from */
@@ -1382,7 +1382,7 @@ row_merge_blocks(
ulint* foffs1, /*!< in/out: offset of second
source list in the file */
merge_file_t* of, /*!< in/out: output file */
- TABLE* table) /*!< in/out: MySQL table, for
+ struct TABLE* table) /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
{
@@ -1563,7 +1563,7 @@ row_merge(
ulint* half, /*!< in/out: half the file */
row_merge_block_t* block, /*!< in/out: 3 buffers */
int* tmpfd, /*!< in/out: temporary file handle */
- TABLE* table) /*!< in/out: MySQL table, for
+ struct TABLE* table) /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
{
@@ -1658,7 +1658,7 @@ row_merge_sort(
index entries */
row_merge_block_t* block, /*!< in/out: 3 buffers */
int* tmpfd, /*!< in/out: temporary file handle */
- TABLE* table) /*!< in/out: MySQL table, for
+ struct TABLE* table) /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
{
@@ -2437,7 +2437,7 @@ row_merge_build_indexes(
unless creating a PRIMARY KEY */
dict_index_t** indexes, /*!< in: indexes to be created */
ulint n_indexes, /*!< in: size of indexes[] */
- TABLE* table) /*!< in/out: MySQL table, for
+ struct TABLE* table) /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
{
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 819381fc280..540a4450045 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -2068,7 +2068,7 @@ Scans a table create SQL string and adds to the data dictionary
the foreign key constraints declared in the string. This function
should be called after the indexes for a table have been created.
Each foreign key constraint must be accompanied with indexes in
-bot participating tables. The indexes are allowed to contain more
+both participating tables. The indexes are allowed to contain more
fields than mentioned in the constraint. Check also that foreign key
constraints which reference this table are ok.
@return error code or DB_SUCCESS */
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index 37263317126..796541a9f1a 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -1376,7 +1376,7 @@ innobase_start_or_create_for_mysql(void)
sum_of_new_sizes += srv_data_file_sizes[i];
}
- if (sum_of_new_sizes < 640) {
+ if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Error: tablespace size must be"
" at least 10 MB\n");
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index b5affc20fc3..612d02bbcd3 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -116,6 +116,10 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
Also we likely need to lock mutex here (in both cases with protocol and
push_warning).
*/
+#ifdef THREAD
+ if (param->need_print_msg_lock)
+ pthread_mutex_lock(&param->print_msg_mutex);
+#endif
protocol->prepare_for_resend();
protocol->store(name, length, system_charset_info);
protocol->store(param->op_name, system_charset_info);
@@ -124,6 +128,10 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
+#ifdef THREAD
+ if (param->need_print_msg_lock)
+ pthread_mutex_unlock(&param->print_msg_mutex);
+#endif
return;
}
@@ -1595,8 +1603,8 @@ bool ha_myisam::check_and_repair(THD *thd)
check_opt.flags|=T_QUICK;
sql_print_warning("Checking table: '%s'",table->s->path.str);
- old_query= thd->query;
- old_query_length= thd->query_length;
+ old_query= thd->query();
+ old_query_length= thd->query_length();
thd->set_query(table->s->table_name.str,
(uint) table->s->table_name.length);
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 8f7b1399aa2..c10cfdd0c9b 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -104,6 +104,9 @@ void myisamchk_init(MI_CHECK *param)
param->max_record_length= LONGLONG_MAX;
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
+#ifdef THREAD
+ param->need_print_msg_lock= 0;
+#endif
}
/* Check the status flags for the table */
@@ -2703,6 +2706,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
/* Initialize pthread structures before goto err. */
pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&sort_info.cond, 0);
+ pthread_mutex_init(&param->print_msg_mutex, MY_MUTEX_INIT_FAST);
+ param->need_print_msg_lock= 1;
if (!(sort_info.key_block=
alloc_key_blocks(param, (uint) param->sort_key_blocks,
@@ -3108,6 +3113,8 @@ err:
pthread_cond_destroy (&sort_info.cond);
pthread_mutex_destroy(&sort_info.mutex);
+ pthread_mutex_destroy(&param->print_msg_mutex);
+ param->need_print_msg_lock= 0;
my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
index 696b9ff93df..79f1ea0e4e5 100644
--- a/storage/myisam/mi_dynrec.c
+++ b/storage/myisam/mi_dynrec.c
@@ -66,9 +66,12 @@ static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
my_bool mi_dynmap_file(MI_INFO *info, my_off_t size)
{
DBUG_ENTER("mi_dynmap_file");
- if (size > (my_off_t) (~((size_t) 0)))
+ if (size == 0 || size > (my_off_t) (~((size_t) 0)))
{
- DBUG_PRINT("warning", ("File is too large for mmap"));
+ if (size)
+ DBUG_PRINT("warning", ("File is too large for mmap"));
+ else
+ DBUG_PRINT("warning", ("Do not mmap zero-length"));
DBUG_RETURN(1);
}
/*
diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c
index 611fb6325c8..de0e53e6a36 100644
--- a/storage/myisam/myisamchk.c
+++ b/storage/myisam/myisamchk.c
@@ -740,7 +740,9 @@ static void get_options(register int *argc,register char ***argv)
{
int ho_error;
- load_defaults("my", load_default_groups, argc, argv);
+ if (load_defaults("my", load_default_groups, argc, argv))
+ exit(1);
+
default_argv= *argv;
if (isatty(fileno(stdout)))
check_param.testflag|=T_WRITE_LOOP;
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index 908c32e48d3..9ebd11b2516 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -208,7 +208,9 @@ int main(int argc, char **argv)
char **default_argv;
MY_INIT(argv[0]);
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ exit(1);
+
default_argv= argv;
get_options(&argc,&argv);
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index fb16af9cddf..b450d27de66 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -466,8 +466,12 @@ ok:
Detach from the share if the writer is involved. Avoid others to
be blocked. This includes a flush of the write buffer. This will
also indicate EOF to the readers.
+ That means that a writer always gets here first and readers -
+ only when they see EOF. But if a reader finishes prematurely
+ because of an error it may reach this earlier - don't allow it
+ to detach the writer thread.
*/
- if (sort_param->sort_info->info->rec_cache.share)
+ if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
remove_io_thread(&sort_param->sort_info->info->rec_cache);
/* Readers detach from the share if any. Avoid others to be blocked. */
@@ -789,6 +793,7 @@ cleanup:
close_cached_file(to_file); /* This holds old result */
if (to_file == t_file)
{
+ DBUG_ASSERT(t_file2.type == WRITE_CACHE);
*t_file=t_file2; /* Copy result file */
t_file->current_pos= &t_file->write_pos;
t_file->current_end= &t_file->write_end;
diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake
index af8c3a85cd1..b920f16452b 100644
--- a/storage/mysql_storage_engine.cmake
+++ b/storage/mysql_storage_engine.cmake
@@ -34,7 +34,7 @@ IF(NOT SOURCE_SUBLIBS)
#The dll is linked to the mysqld executable
SET(dyn_libname ha_${libname})
ADD_LIBRARY(${dyn_libname} SHARED ${${engine}_SOURCES})
- TARGET_LINK_LIBRARIES (${dyn_libname} mysqld)
+ TARGET_LINK_LIBRARIES (${dyn_libname} mysqlservices mysqld)
IF(${engine}_LIBS)
TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS})
ENDIF(${engine}_LIBS)
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index bc8adf6fd32..11e8c1cc191 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -14831,7 +14831,7 @@ void Dblqh::srLogLimits(Signal* signal)
while(true) {
ndbrequire(tmbyte < clogFileSize);
if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP) {
- if (logFilePtr.p->logMaxGciCompleted[tmbyte] < logPartPtr.p->logLastGci) {
+ if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci) {
jam();
/* --------------------------------------------------------------------
* WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index ee4d052b3b3..56f3ddccae4 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -7897,6 +7897,9 @@ static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t))
return 1;
}
+ if (!cs->caseinfo)
+ cs->caseinfo= my_unicase_default;
+
if (!(newweights= (uint16**) (*alloc)(256*sizeof(uint16*))))
return 1;
bzero(newweights, 256*sizeof(uint16*));
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index 3362559972a..ad8e7c8c776 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -260,6 +260,14 @@ static char *process_int_arg(char *to, char *end, size_t length,
{
size_t diff= (length- res_length);
bfill(to, diff, (print_type & PREZERO_ARG) ? '0' : ' ');
+ if (arg_type == 'p' && print_type & PREZERO_ARG)
+ {
+ if (diff > 1)
+ to[1]= 'x';
+ else
+ store_start[0]= 'x';
+ store_start[1]= '0';
+ }
to+= diff;
}
bmove(to, store_start, res_length);
@@ -323,6 +331,7 @@ start:
/* Get print width */
if (*fmt == '*')
{
+ fmt++;
fmt= get_width(fmt, &print_arr[idx].width);
print_arr[idx].width--;
DBUG_ASSERT(*fmt == '$' && print_arr[idx].width < MAX_ARGS);
@@ -472,6 +481,8 @@ start:
/**
Produces output string according to a format string
+ See the detailed documentation around my_snprintf_service_st
+
@param cs string charset
@param to buffer where processed string will be place
@param n size of buffer
@@ -621,54 +632,3 @@ size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
return result;
}
-#ifdef MAIN
-#define OVERRUN_SENTRY 250
-static void my_printf(const char * fmt, ...)
-{
- char buf[33];
- int n;
- va_list ar;
- va_start(ar, fmt);
- buf[sizeof(buf)-1]=OVERRUN_SENTRY;
- n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
- printf(buf);
- printf("n=%d, strlen=%d\n", n, strlen(buf));
- if ((uchar) buf[sizeof(buf)-1] != OVERRUN_SENTRY)
- {
- fprintf(stderr, "Buffer overrun\n");
- abort();
- }
- va_end(ar);
-}
-
-
-int main()
-{
-
- my_printf("Hello\n");
- my_printf("Hello int, %d\n", 1);
- my_printf("Hello string '%s'\n", "I am a string");
- my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
- my_printf("Hello %d hack %d\n", 1, 4);
- my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
- my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
- my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
- my_printf("Hello %u\n", 1);
- my_printf("Hex: %lx '%6lx'\n", 32, 65);
- my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
- `%-.64s' (%-.64s)", 1, 0,0,0,0);
-
- my_printf("Hello string %`s\n", "I am a string");
- my_printf("Hello %05s\n", "TEST");
- my_printf("My %1$`-.1s test\n", "QQQQ");
- my_printf("My %1$s test done %2$s\n", "DDDD", "AAAA");
- my_printf("My %1$s test %2$s, %1$-.3s\n", "DDDD", "CCCC");
- my_printf("My %1$`-.4b test\n", "QQQQ");
- my_printf("My %1$c test\n", 'X');
- my_printf("My `%010d` test1 %4x test2 %4X\n", 10, 10, 10);
- my_printf("My `%1$010d` test1 %2$4x test2 %2$4x\n", 10, 10);
- my_printf("My %1$*02$d test\n", 10, 5);
- my_printf("My %1$`s test %2$s, %1$`-.3s\n", "DDDD", "CCCC");
- return 0;
-}
-#endif
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 8aba7cd8808..e2721415092 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -703,6 +703,29 @@ int my_stmt_result(const char *buff)
return row_count;
}
+/* Print the total number of warnings and the warnings themselves. */
+
+void my_process_warnings(MYSQL *conn, unsigned expected_warning_count)
+{
+ MYSQL_RES *result;
+ int rc;
+
+ if (!opt_silent)
+ fprintf(stdout, "\n total warnings: %u (expected: %u)\n",
+ mysql_warning_count(conn), expected_warning_count);
+
+ DIE_UNLESS(mysql_warning_count(mysql) == expected_warning_count);
+
+ rc= mysql_query(conn, "SHOW WARNINGS");
+ DIE_UNLESS(rc == 0);
+
+ result= mysql_store_result(conn);
+ mytest(result);
+
+ rc= my_process_result_set(result);
+ mysql_free_result(result);
+}
+
/* Utility function to verify a particular column data */
@@ -1516,6 +1539,568 @@ static void test_prepare_simple()
myquery(rc);
}
+/************************************************************************/
+
+#define FILE_PATH_SIZE 4096
+
+char mct_log_file_path[FILE_PATH_SIZE];
+FILE *mct_log_file= NULL;
+
+void mct_start_logging(const char *test_case_name)
+{
+ const char *tmp_dir= getenv("MYSQL_TMP_DIR");
+
+ if (!tmp_dir)
+ {
+ printf("Warning: MYSQL_TMP_DIR is not set. Logging is disabled.\n");
+ return;
+ }
+
+ if (mct_log_file)
+ {
+ printf("Warning: can not start logging for test case '%s' "
+ "because log is already open\n",
+ (const char *) test_case_name);
+ return;
+ }
+
+ /*
+ Path is: <tmp_dir>/<test_case_name>.out.log
+ 10 is length of '/' + '.out.log' + \0
+ */
+
+ if (strlen(tmp_dir) + strlen(test_case_name) + 10 > FILE_PATH_SIZE)
+ {
+ printf("Warning: MYSQL_TMP_DIR is too long. Logging is disabled.\n");
+ return;
+ }
+
+ my_snprintf(mct_log_file_path, FILE_PATH_SIZE,
+ "%s/%s.out.log",
+ (const char *) tmp_dir,
+ (const char *) test_case_name);
+
+ mct_log_file= my_fopen(mct_log_file_path, O_WRONLY | O_BINARY, MYF(MY_WME));
+
+ if (!mct_log_file)
+ {
+ printf("Warning: can not open log file (%s): %s. Logging is disabled.\n",
+ (const char *) mct_log_file_path,
+ (const char *) strerror(errno));
+ return;
+ }
+}
+
+void mct_log(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ if (mct_log_file)
+ {
+ va_list args;
+ va_start(args, format);
+ vfprintf(mct_log_file, format, args);
+ va_end(args);
+ }
+}
+
+void mct_close_log()
+{
+ if (!mct_log_file)
+ return;
+
+ my_fclose(mct_log_file, MYF(0));
+ mct_log_file= NULL;
+}
+
+#define WL4435_NUM_PARAMS 10
+#define WL4435_STRING_SIZE 30
+
+static void test_wl4435()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ char str_data[20][WL4435_STRING_SIZE];
+ double dbl_data[20];
+ char dec_data[20][WL4435_STRING_SIZE];
+ int int_data[20];
+ ulong str_length= WL4435_STRING_SIZE;
+ my_bool is_null;
+ MYSQL_BIND ps_params[WL4435_NUM_PARAMS];
+
+ int exec_counter;
+
+ myheader("test_wl4435");
+ mct_start_logging("test_wl4435");
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p2");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1(a1 INT, a2 CHAR(32), "
+ " a3 DOUBLE(4, 2), a4 DECIMAL(3, 1))");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE t2(b0 INT, b1 INT, b2 CHAR(32), "
+ " b3 DOUBLE(4, 2), b4 DECIMAL(3, 1))");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES"
+ "(1, '11', 12.34, 56.7), "
+ "(2, '12', 56.78, 90.1), "
+ "(3, '13', 23.45, 67.8)");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "INSERT INTO t2 VALUES"
+ "(100, 10, '110', 70.70, 10.1), "
+ "(200, 20, '120', 80.80, 20.2), "
+ "(300, 30, '130', 90.90, 30.3)");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "CREATE PROCEDURE p1("
+ " IN v0 INT, "
+ " OUT v_str_1 CHAR(32), "
+ " OUT v_dbl_1 DOUBLE(4, 2), "
+ " OUT v_dec_1 DECIMAL(6, 3), "
+ " OUT v_int_1 INT, "
+ " IN v1 INT, "
+ " INOUT v_str_2 CHAR(64), "
+ " INOUT v_dbl_2 DOUBLE(5, 3), "
+ " INOUT v_dec_2 DECIMAL(7, 4), "
+ " INOUT v_int_2 INT)"
+ "BEGIN "
+ " SET v0 = -1; "
+ " SET v1 = -1; "
+ " SET v_str_1 = 'test_1'; "
+ " SET v_dbl_1 = 12.34; "
+ " SET v_dec_1 = 567.891; "
+ " SET v_int_1 = 2345; "
+ " SET v_str_2 = 'test_2'; "
+ " SET v_dbl_2 = 67.891; "
+ " SET v_dec_2 = 234.6789; "
+ " SET v_int_2 = 6789; "
+ " SELECT * FROM t1; "
+ " SELECT * FROM t2; "
+ "END");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "CREATE PROCEDURE p2("
+ " IN i1 VARCHAR(255) CHARACTER SET koi8r, "
+ " OUT o1 VARCHAR(255) CHARACTER SET cp1251, "
+ " OUT o2 VARBINARY(255)) "
+ "BEGIN "
+ " SET o1 = i1; "
+ " SET o2 = i1; "
+ "END");
+ myquery(rc);
+
+ strmov(query, "CALL p1(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ /* Init PS-parameters. */
+
+ bzero((char *) ps_params, sizeof (ps_params));
+
+ /* - v0 -- INT */
+
+ ps_params[0].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[0].buffer= (char *) &int_data[0];
+ ps_params[0].length= 0;
+ ps_params[0].is_null= 0;
+
+ /* - v_str_1 -- CHAR(32) */
+
+ ps_params[1].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[1].buffer= (char *) str_data[0];
+ ps_params[1].buffer_length= WL4435_STRING_SIZE;
+ ps_params[1].length= &str_length;
+ ps_params[1].is_null= 0;
+
+ /* - v_dbl_1 -- DOUBLE */
+
+ ps_params[2].buffer_type= MYSQL_TYPE_DOUBLE;
+ ps_params[2].buffer= (char *) &dbl_data[0];
+ ps_params[2].length= 0;
+ ps_params[2].is_null= 0;
+
+ /* - v_dec_1 -- DECIMAL */
+
+ ps_params[3].buffer_type= MYSQL_TYPE_NEWDECIMAL;
+ ps_params[3].buffer= (char *) dec_data[0];
+ ps_params[3].buffer_length= WL4435_STRING_SIZE;
+ ps_params[3].length= 0;
+ ps_params[3].is_null= 0;
+
+ /* - v_int_1 -- INT */
+
+ ps_params[4].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[4].buffer= (char *) &int_data[0];
+ ps_params[4].length= 0;
+ ps_params[4].is_null= 0;
+
+ /* - v1 -- INT */
+
+ ps_params[5].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[5].buffer= (char *) &int_data[0];
+ ps_params[5].length= 0;
+ ps_params[5].is_null= 0;
+
+ /* - v_str_2 -- CHAR(32) */
+
+ ps_params[6].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[6].buffer= (char *) str_data[0];
+ ps_params[6].buffer_length= WL4435_STRING_SIZE;
+ ps_params[6].length= &str_length;
+ ps_params[6].is_null= 0;
+
+ /* - v_dbl_2 -- DOUBLE */
+
+ ps_params[7].buffer_type= MYSQL_TYPE_DOUBLE;
+ ps_params[7].buffer= (char *) &dbl_data[0];
+ ps_params[7].length= 0;
+ ps_params[7].is_null= 0;
+
+ /* - v_dec_2 -- DECIMAL */
+
+ ps_params[8].buffer_type= MYSQL_TYPE_DECIMAL;
+ ps_params[8].buffer= (char *) dec_data[0];
+ ps_params[8].buffer_length= WL4435_STRING_SIZE;
+ ps_params[8].length= 0;
+ ps_params[8].is_null= 0;
+
+ /* - v_int_2 -- INT */
+
+ ps_params[9].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[9].buffer= (char *) &int_data[0];
+ ps_params[9].length= 0;
+ ps_params[9].is_null= 0;
+
+ /* Bind parameters. */
+
+ rc= mysql_stmt_bind_param(stmt, ps_params);
+
+ /* Execute! */
+
+ for (exec_counter= 0; exec_counter < 3; ++exec_counter)
+ {
+ int i;
+ int num_fields;
+ MYSQL_BIND *rs_bind;
+
+ mct_log("\nexec_counter: %d\n", (int) exec_counter);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ while (1)
+ {
+ MYSQL_FIELD *fields;
+
+ MYSQL_RES *rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ fields= mysql_fetch_fields(rs_metadata);
+
+ rs_bind= (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields);
+ bzero(rs_bind, sizeof (MYSQL_BIND) * num_fields);
+
+ mct_log("num_fields: %d\n", (int) num_fields);
+
+ for (i = 0; i < num_fields; ++i)
+ {
+ mct_log(" - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
+ "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
+ "type: %d; decimals: %d\n",
+ (int) i,
+ (const char *) fields[i].name,
+ (const char *) fields[i].org_name,
+ (const char *) fields[i].table,
+ (const char *) fields[i].org_table,
+ (const char *) fields[i].db,
+ (const char *) fields[i].catalog,
+ (int) fields[i].length,
+ (int) fields[i].max_length,
+ (int) fields[i].type,
+ (int) fields[i].decimals);
+
+ rs_bind[i].buffer_type= fields[i].type;
+ rs_bind[i].is_null= &is_null;
+
+ switch (fields[i].type)
+ {
+ case MYSQL_TYPE_LONG:
+ rs_bind[i].buffer= (char *) &(int_data[i]);
+ rs_bind[i].buffer_length= sizeof (int_data);
+ break;
+
+ case MYSQL_TYPE_STRING:
+ rs_bind[i].buffer= (char *) str_data[i];
+ rs_bind[i].buffer_length= WL4435_STRING_SIZE;
+ rs_bind[i].length= &str_length;
+ break;
+
+ case MYSQL_TYPE_DOUBLE:
+ rs_bind[i].buffer= (char *) &dbl_data[i];
+ rs_bind[i].buffer_length= sizeof (dbl_data);
+ break;
+
+ case MYSQL_TYPE_NEWDECIMAL:
+ rs_bind[i].buffer= (char *) dec_data[i];
+ rs_bind[i].buffer_length= WL4435_STRING_SIZE;
+ rs_bind[i].length= &str_length;
+ break;
+
+ default:
+ fprintf(stderr, "ERROR: unexpected type: %d.\n", fields[i].type);
+ exit(1);
+ }
+ }
+
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+ check_execute(stmt, rc);
+
+ mct_log("Data:\n");
+
+ while (1)
+ {
+ int rc= mysql_stmt_fetch(stmt);
+
+ if (rc == 1 || rc == MYSQL_NO_DATA)
+ break;
+
+ mct_log(" ");
+
+ for (i = 0; i < num_fields; ++i)
+ {
+ switch (rs_bind[i].buffer_type)
+ {
+ case MYSQL_TYPE_LONG:
+ mct_log(" int: %ld;",
+ (long) *((int *) rs_bind[i].buffer));
+ break;
+
+ case MYSQL_TYPE_STRING:
+ mct_log(" str: '%s';",
+ (char *) rs_bind[i].buffer);
+ break;
+
+ case MYSQL_TYPE_DOUBLE:
+ mct_log(" dbl: %lf;",
+ (double) *((double *) rs_bind[i].buffer));
+ break;
+
+ case MYSQL_TYPE_NEWDECIMAL:
+ mct_log(" dec: '%s';",
+ (char *) rs_bind[i].buffer);
+ break;
+
+ default:
+ printf(" unexpected type (%d)\n",
+ rs_bind[i].buffer_type);
+ }
+ }
+ mct_log("\n");
+ }
+
+ mct_log("EOF\n");
+
+ rc= mysql_stmt_next_result(stmt);
+ mct_log("mysql_stmt_next_result(): %d; field_count: %d\n",
+ (int) rc, (int) mysql->field_count);
+
+ free(rs_bind);
+ mysql_free_result(rs_metadata);
+
+ if (rc > 0)
+ {
+ printf("Error: %s (errno: %d)\n",
+ mysql_stmt_error(stmt), mysql_stmt_errno(stmt));
+ DIE(rc > 0);
+ }
+
+ if (rc)
+ break;
+
+ if (!mysql->field_count)
+ {
+ /* This is the last OK-packet. No more resultsets. */
+ break;
+ }
+ }
+
+ }
+
+ mysql_stmt_close(stmt);
+
+ mct_close_log();
+
+ rc= mysql_commit(mysql);
+ myquery(rc);
+
+ /* i18n part of test case. */
+
+ {
+ const char *str_koi8r= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
+ const char *str_cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
+ char o1_buffer[255];
+ ulong o1_length;
+ char o2_buffer[255];
+ ulong o2_length;
+
+ MYSQL_BIND rs_bind[2];
+
+ strmov(query, "CALL p2(?, ?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ /* Init PS-parameters. */
+
+ bzero((char *) ps_params, sizeof (ps_params));
+
+ ps_params[0].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[0].buffer= (char *) str_koi8r;
+ ps_params[0].buffer_length= strlen(str_koi8r);
+
+ ps_params[1].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[1].buffer= o1_buffer;
+ ps_params[1].buffer_length= 0;
+
+ ps_params[2].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[2].buffer= o2_buffer;
+ ps_params[2].buffer_length= 0;
+
+ /* Bind parameters. */
+
+ rc= mysql_stmt_bind_param(stmt, ps_params);
+ check_execute(stmt, rc);
+
+ /* Prevent converting to character_set_results. */
+
+ rc= mysql_query(mysql, "SET NAMES binary");
+ myquery(rc);
+
+ /* Execute statement. */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ /* Bind result. */
+
+ bzero(rs_bind, sizeof (rs_bind));
+
+ rs_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ rs_bind[0].buffer= o1_buffer;
+ rs_bind[0].buffer_length= sizeof (o1_buffer);
+ rs_bind[0].length= &o1_length;
+
+ rs_bind[1].buffer_type= MYSQL_TYPE_BLOB;
+ rs_bind[1].buffer= o2_buffer;
+ rs_bind[1].buffer_length= sizeof (o2_buffer);
+ rs_bind[1].length= &o2_length;
+
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+ check_execute(stmt, rc);
+
+ /* Fetch result. */
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ /* Check result. */
+
+ DIE_UNLESS(o1_length == strlen(str_cp1251));
+ DIE_UNLESS(o2_length == strlen(str_koi8r));
+ DIE_UNLESS(!memcmp(o1_buffer, str_cp1251, o1_length));
+ DIE_UNLESS(!memcmp(o2_buffer, str_koi8r, o2_length));
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ rc= mysql_stmt_next_result(stmt);
+ DIE_UNLESS(rc == 0 && mysql->field_count == 0);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_commit(mysql);
+ myquery(rc);
+ }
+}
+
+static void test_wl4435_2()
+{
+ MYSQL_STMT *stmt;
+ int i;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ myheader("test_wl4435_2");
+ mct_start_logging("test_wl4435_2");
+
+ /*
+ Do a few iterations so that we catch any problem with incorrect
+ handling/flushing prepared statement results.
+ */
+
+ for (i= 0; i < 10; ++i)
+ {
+ /*
+ Prepare a procedure. That can be moved out of the loop, but it was
+ left in the loop for the sake of having as many statements as
+ possible.
+ */
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "CREATE PROCEDURE p1()"
+ "BEGIN "
+ " SELECT 1; "
+ " SELECT 2, 3 UNION SELECT 4, 5; "
+ " SELECT 6, 7, 8; "
+ "END");
+ myquery(rc);
+
+ /* Invoke a procedure, that returns several result sets. */
+
+ strmov(query, "CALL p1()");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ /* Execute! */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ /* Flush all the results. */
+
+ mysql_stmt_close(stmt);
+
+ /* Clean up. */
+ rc= mysql_commit(mysql);
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE p1");
+ myquery(rc);
+ }
+}
+
/* Test simple prepare field results */
@@ -12501,7 +13086,7 @@ static void test_datetime_ranges()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- DIE_UNLESS(mysql_warning_count(mysql) != 6);
+ my_process_warnings(mysql, 12);
verify_col_data("t1", "year", "0000-00-00 00:00:00");
verify_col_data("t1", "month", "0000-00-00 00:00:00");
@@ -12532,7 +13117,7 @@ static void test_datetime_ranges()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- DIE_UNLESS(mysql_warning_count(mysql) != 3);
+ my_process_warnings(mysql, 6);
verify_col_data("t1", "year", "0000-00-00 00:00:00");
verify_col_data("t1", "month", "0000-00-00 00:00:00");
@@ -12571,7 +13156,7 @@ static void test_datetime_ranges()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- DIE_UNLESS(mysql_warning_count(mysql) == 2);
+ my_process_warnings(mysql, 2);
verify_col_data("t1", "day_ovfl", "838:59:59");
verify_col_data("t1", "day", "828:30:30");
@@ -14476,9 +15061,8 @@ static void test_bug12001()
/* Create connection that supports multi statements */
if (!mysql_real_connect(mysql_local, opt_host, opt_user,
- opt_password, current_db, opt_port,
- opt_unix_socket, CLIENT_MULTI_STATEMENTS |
- CLIENT_MULTI_RESULTS))
+ opt_password, current_db, opt_port,
+ opt_unix_socket, CLIENT_MULTI_STATEMENTS))
{
fprintf(stdout, "\n mysql_real_connect() failed");
exit(1);
@@ -15846,7 +16430,7 @@ static void test_bug15752()
if (! mysql_real_connect(&mysql_local, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket,
- CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS))
+ CLIENT_MULTI_STATEMENTS))
{
printf("Unable connect to MySQL server: %s\n", mysql_error(&mysql_local));
DIE_UNLESS(0);
@@ -17434,6 +18018,7 @@ static void test_bug28386()
DBUG_VOID_RETURN;
}
+
static void test_wl4166_1()
{
MYSQL_STMT *stmt;
@@ -17645,6 +18230,167 @@ static void test_wl4166_2()
}
+
+/**
+ Test how warnings generated during assignment of parameters
+ are (currently not) preserve in case of reprepare.
+*/
+
+static void test_wl4166_3()
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND my_bind[1];
+ MYSQL_TIME tm[1];
+
+ myheader("test_wl4166_3");
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "create table t1 (year datetime)");
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql, "insert into t1 (year) values (?)");
+ check_stmt(stmt);
+ verify_param_count(stmt, 1);
+
+ bzero((char*) my_bind, sizeof(my_bind));
+ my_bind[0].buffer_type= MYSQL_TYPE_DATETIME;
+ my_bind[0].buffer= &tm[0];
+
+ rc= mysql_stmt_bind_param(stmt, my_bind);
+ check_execute(stmt, rc);
+
+ tm[0].year= 10000;
+ tm[0].month= 1; tm[0].day= 1;
+ tm[0].hour= 1; tm[0].minute= 1; tm[0].second= 1;
+ tm[0].second_part= 0; tm[0].neg= 0;
+
+ /* Cause a statement reprepare */
+ rc= mysql_query(mysql, "alter table t1 add column c int");
+ myquery(rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ /*
+ Sic: only one warning, instead of two. The warning
+ about data truncation when assigning a parameter is lost.
+ This is a bug.
+ */
+ my_process_warnings(mysql, 1);
+
+ verify_col_data("t1", "year", "0000-00-00 00:00:00");
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/**
+ Test that long data parameters, as well as parameters
+ that were originally in a different character set, are
+ preserved in case of reprepare.
+*/
+
+static void test_wl4166_4()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char *stmt_text;
+ MYSQL_BIND bind_array[2];
+
+ /* Represented as numbers to keep UTF8 tools from clobbering them. */
+ const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
+ const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
+ char buf1[16], buf2[16];
+ ulong buf1_len, buf2_len;
+
+ myheader("test_wl4166_4");
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ myquery(rc);
+
+ /*
+ Create table with binary columns, set session character set to cp1251,
+ client character set to koi8, and make sure that there is conversion
+ on insert and no conversion on select
+ */
+ rc= mysql_query(mysql,
+ "create table t1 (c1 varbinary(255), c2 varbinary(255))");
+ myquery(rc);
+ rc= mysql_query(mysql, "set character_set_client=koi8r, "
+ "character_set_connection=cp1251, "
+ "character_set_results=koi8r");
+ myquery(rc);
+
+ bzero((char*) bind_array, sizeof(bind_array));
+
+ bind_array[0].buffer_type= MYSQL_TYPE_STRING;
+
+ bind_array[1].buffer_type= MYSQL_TYPE_STRING;
+ bind_array[1].buffer= (void *) koi8;
+ bind_array[1].buffer_length= strlen(koi8);
+
+ stmt= mysql_stmt_init(mysql);
+ check_stmt(stmt);
+
+ stmt_text= "insert into t1 (c1, c2) values (?, ?)";
+
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ mysql_stmt_bind_param(stmt, bind_array);
+
+ mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
+
+ /* Cause a reprepare at statement execute */
+ rc= mysql_query(mysql, "alter table t1 add column d int");
+ myquery(rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ stmt_text= "select c1, c2 from t1";
+
+ /* c1 and c2 are binary so no conversion will be done on select */
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bind_array[0].buffer= buf1;
+ bind_array[0].buffer_length= sizeof(buf1);
+ bind_array[0].length= &buf1_len;
+
+ bind_array[1].buffer= buf2;
+ bind_array[1].buffer_length= sizeof(buf2);
+ bind_array[1].length= &buf2_len;
+
+ mysql_stmt_bind_result(stmt, bind_array);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ DIE_UNLESS(buf1_len == strlen(cp1251));
+ DIE_UNLESS(buf2_len == strlen(cp1251));
+ DIE_UNLESS(!memcmp(buf1, cp1251, buf1_len));
+ DIE_UNLESS(!memcmp(buf2, cp1251, buf1_len));
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+ rc= mysql_query(mysql, "set names default");
+ myquery(rc);
+}
+
/**
Bug#38486 Crash when using cursor protocol
*/
@@ -17675,6 +18421,49 @@ static void test_bug38486(void)
DBUG_VOID_RETURN;
}
+
+/**
+ Bug# 33831 mysql_real_connect() should fail if
+ given an already connected MYSQL handle.
+*/
+
+static void test_bug33831(void)
+{
+ MYSQL *l_mysql;
+ my_bool error;
+
+ DBUG_ENTER("test_bug33831");
+
+ error= 0;
+
+ if (!(l_mysql= mysql_client_init(NULL)))
+ {
+ myerror("mysql_client_init() failed");
+ DIE_UNLESS(0);
+ }
+ if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0)))
+ {
+ myerror("connection failed");
+ DIE_UNLESS(0);
+ }
+
+ if (mysql_real_connect(l_mysql, opt_host, opt_user,
+ opt_password, current_db, opt_port,
+ opt_unix_socket, 0))
+ {
+ myerror("connection should have failed");
+ DIE_UNLESS(0);
+ }
+
+
+ mysql_close(l_mysql);
+
+ DBUG_VOID_RETURN;
+}
+
+
static void test_bug40365(void)
{
uint rc, i;
@@ -18363,7 +19152,12 @@ static struct my_tests_st my_tests[]= {
{ "test_bug28386", test_bug28386 },
{ "test_wl4166_1", test_wl4166_1 },
{ "test_wl4166_2", test_wl4166_2 },
+ { "test_wl4166_3", test_wl4166_3 },
+ { "test_wl4166_4", test_wl4166_4 },
+ { "test_wl4435", test_wl4435 },
+ { "test_wl4435_2", test_wl4435_2 },
{ "test_bug38486", test_bug38486 },
+ { "test_bug33831", test_bug33831 },
{ "test_bug40365", test_bug40365 },
{ "test_bug43560", test_bug43560 },
#ifdef HAVE_QUERY_CACHE
@@ -18486,7 +19280,9 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
- load_defaults("my", client_test_load_default_groups, &argc, &argv);
+ if (load_defaults("my", client_test_load_default_groups, &argc, &argv))
+ exit(1);
+
defaults_argv= argv;
get_options(&argc, &argv);
diff --git a/tests/thread_test.c b/tests/thread_test.c
index 8e1c58ebbec..5b76eeff2f7 100644
--- a/tests/thread_test.c
+++ b/tests/thread_test.c
@@ -176,9 +176,8 @@ static void get_options(int argc, char **argv)
{
int ho_error;
- load_defaults("my",load_default_groups,&argc,&argv);
-
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ if ((ho_error= load_defaults("my",load_default_groups,&argc,&argv)) ||
+ (ho_error= handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
free_defaults(argv);
diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am
index f0ffc7a6720..56c65d71396 100644
--- a/unittest/mysys/Makefile.am
+++ b/unittest/mysys/Makefile.am
@@ -21,7 +21,7 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a
-noinst_PROGRAMS = bitmap-t base64-t
+noinst_PROGRAMS = bitmap-t base64-t my_vsnprintf-t
if NEED_THREAD
# my_atomic-t is used to check thread functions, so it is safe to
diff --git a/unittest/mysys/my_vsnprintf-t.c b/unittest/mysys/my_vsnprintf-t.c
new file mode 100644
index 00000000000..f3a6b5700da
--- /dev/null
+++ b/unittest/mysys/my_vsnprintf-t.c
@@ -0,0 +1,155 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include <m_string.h>
+#include <tap.h>
+
+char buf[1024]; /* let's hope that's enough */
+
+void test1(const char *res, const char *fmt, ...)
+{
+ va_list args;
+ size_t len;
+ va_start(args,fmt);
+ len= my_vsnprintf(buf, sizeof(buf)-1, fmt, args);
+ va_end(args);
+ ok(strlen(res) == len && strcmp(buf, res) == 0, "\"%s\"", buf);
+}
+
+int main(void)
+{
+ plan(47);
+
+ test1("Constant string",
+ "Constant string");
+
+ test1("Format specifier s works",
+ "Format specifier s %s", "works");
+ test1("Format specifier b works (mysql extension)",
+ "Format specifier b %.5b (mysql extension)", "works!!!");
+ test1("Format specifier c !",
+ "Format specifier c %c", '!');
+ test1("Format specifier d 1",
+ "Format specifier d %d", 1);
+ test1("Format specifier u 2",
+ "Format specifier u %u", 2);
+ test1("Format specifier x a",
+ "Format specifier x %x", 10);
+ test1("Format specifier X B",
+ "Format specifier X %X", 11);
+ test1("Format specifier p 0x5",
+ "Format specifier p %p", 5);
+
+ test1("Flag '-' is ignored < 1>",
+ "Flag '-' is ignored <%-4d>", 1);
+ test1("Flag '0' works <0006>",
+ "Flag '0' works <%04d>", 6);
+
+ test1("Width is ignored for strings <x> <y>",
+ "Width is ignored for strings <%04s> <%5s>", "x", "y");
+
+ test1("Precision works for strings <abcde>",
+ "Precision works for strings <%.5s>", "abcdef!");
+
+ test1("Flag '`' (backtick) works: `abcd` `op``q` (mysql extension)",
+ "Flag '`' (backtick) works: %`s %`.4s (mysql extension)",
+ "abcd", "op`qrst");
+
+ test1("Length modifiers work: 1 * -1 * 2 * 3",
+ "Length modifiers work: %d * %ld * %lld * %zd", 1, -1L, 2LL, (size_t)3);
+
+ test1("(null) pointer is fine",
+ "%s pointer is fine", NULL);
+
+ test1("Positional arguments work: on the dark side they are",
+ "Positional arguments work: %3$s %1$s %2$s",
+ "they", "are", "on the dark side");
+
+ test1("Asterisk '*' as a width works: < 4>",
+ "Asterisk '*' as a width works: <%*d>", 5, 4);
+
+ test1("Asterisk '*' as a precision works: <qwerty>",
+ "Asterisk '*' as a precision works: <%.*s>", 6, "qwertyuiop");
+
+ test1("Positional arguments for a width: < 4>",
+ "Positional arguments for a width: <%1$*2$d>", 4, 5);
+
+ test1("Positional arguments for a precision: <qwerty>",
+ "Positional arguments for a precision: <%1$.*2$s>", "qwertyuiop", 6);
+
+ test1("Positional arguments and a width: <0000ab>",
+ "Positional arguments and a width: <%1$06x>", 0xab);
+
+ test1("Padding and %p <0x12> <0x034> <0x0000ab> < 0xcd>",
+ "Padding and %%p <%04p> <%05p> <%08p> <%8p>", 0x12, 0x34, 0xab, 0xcd);
+
+#if MYSQL_VERSION_ID > 60000
+#error %f/%g tests go here
+#endif
+
+ test1("Hello",
+ "Hello");
+ test1("Hello int, 1",
+ "Hello int, %d", 1);
+ test1("Hello int, -1",
+ "Hello int, %d", -1);
+ test1("Hello string 'I am a string'",
+ "Hello string '%s'", "I am a string");
+ test1("Hello hack hack hack hack hack hack hack 1",
+ "Hello hack hack hack hack hack hack hack %d", 1);
+ test1("Hello 1 hack 4",
+ "Hello %d hack %d", 1, 4);
+ test1("Hello 1 hack hack hack hack hack 4",
+ "Hello %d hack hack hack hack hack %d", 1, 4);
+ test1("Hello 'hack' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+ "Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", "hack");
+ test1("Hello hhhhhhhhhhhhhh 1 sssssssssssssss",
+ "Hello hhhhhhhhhhhhhh %d sssssssssssssss", 1);
+ test1("Hello 1",
+ "Hello %u", 1);
+ test1("Hello 4294967295",
+ "Hello %u", -1);
+ test1("Hex: 20 ' 41'",
+ "Hex: %lx '%6lx'", 32, 65);
+ test1("conn 1 to: '(null)' user: '(null)' host: '(null)' ((null))",
+ "conn %ld to: '%-.64s' user: '%-.32s' host: '%-.64s' (%-.64s)",
+ 1L, NULL, NULL, NULL, NULL);
+ test1("Hello string `I am a string`",
+ "Hello string %`s", "I am a string");
+ test1("Hello TEST",
+ "Hello %05s", "TEST");
+ test1("My `Q` test",
+ "My %1$`-.1s test", "QQQQ");
+ test1("My AAAA test done DDDD",
+ "My %2$s test done %1$s", "DDDD", "AAAA");
+ test1("My DDDD test CCCC, DDD",
+ "My %1$s test %2$s, %1$-.3s", "DDDD", "CCCC");
+ test1("My QQQQ test",
+ "My %1$`-.4b test", "QQQQ");
+ test1("My X test",
+ "My %1$c test", 'X');
+ test1("My <0000000010> test1 < a> test2 < A>",
+ "My <%010d> test1 <%4x> test2 <%4X>", 10, 10, 10);
+ test1("My <0000000010> test1 < a> test2 < a>",
+ "My <%1$010d> test1 <%2$4x> test2 <%2$4x>", 10, 10);
+ test1("My 00010 test",
+ "My %1$*02$d test", 10, 5);
+ test1("My `DDDD` test CCCC, `DDD`",
+ "My %1$`s test %2$s, %1$`-.3s", "DDDD", "CCCC");
+
+ return exit_status();
+}
+
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 6a6e08818c6..51d049b18b9 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -144,55 +144,6 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file,
}
-static int
-vio_verify_callback(int ok, X509_STORE_CTX *ctx)
-{
- char buf[256];
- X509 *err_cert;
-
- DBUG_ENTER("vio_verify_callback");
- DBUG_PRINT("enter", ("ok: %d ctx: 0x%lx", ok, (long) ctx));
-
- err_cert= X509_STORE_CTX_get_current_cert(ctx);
- X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
- DBUG_PRINT("info", ("cert: %s", buf));
- if (!ok)
- {
- int err, depth;
- err= X509_STORE_CTX_get_error(ctx);
- depth= X509_STORE_CTX_get_error_depth(ctx);
-
- DBUG_PRINT("error",("verify error: %d '%s'",err,
- X509_verify_cert_error_string(err)));
- /*
- Approve cert if depth is greater then "verify_depth", currently
- verify_depth is always 0 and there is no way to increase it.
- */
- if (verify_depth >= depth)
- ok= 1;
- }
- switch (ctx->error)
- {
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
- DBUG_PRINT("info",("issuer= %s\n", buf));
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- DBUG_PRINT("error", ("notBefore"));
- /*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- DBUG_PRINT("error", ("notAfter error"));
- /*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/
- break;
- }
- DBUG_PRINT("exit", ("%d", ok));
- DBUG_RETURN(ok);
-}
-
-
#ifdef __NETWARE__
/* NetWare SSL cleanup */
@@ -354,11 +305,7 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
/* Init the VioSSLFd as a "connector" ie. the client side */
- /*
- The verify_callback function is used to control the behaviour
- when the SSL_VERIFY_PEER flag is set.
- */
- SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
+ SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL);
return ssl_fd;
}
@@ -382,11 +329,7 @@ new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
/* Set max number of cached sessions, returns the previous size */
SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128);
- /*
- The verify_callback function is used to control the behaviour
- when the SSL_VERIFY_PEER flag is set.
- */
- SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
+ SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL);
/*
Set session_id - an identifier for this server session