summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzr-mysql/default.conf8
-rw-r--r--.bzrignore8
-rwxr-xr-xBUILD/SETUP.sh2
-rwxr-xr-xBUILD/compile-bintar6
-rwxr-xr-xCMakeLists.txt9
-rw-r--r--Docs/sp-imp-spec.txt4
-rw-r--r--Makefile.am23
-rwxr-xr-xclient/CMakeLists.txt2
-rw-r--r--client/Makefile.am7
-rw-r--r--client/client_priv.h5
-rw-r--r--client/mysql.cc68
-rw-r--r--client/mysqladmin.cc138
-rw-r--r--client/mysqlbinlog.cc144
-rw-r--r--client/mysqltest.cc11
-rw-r--r--client/sql_string.cc9
-rw-r--r--client/sql_string.h5
-rw-r--r--config/ac-macros/plugins.m43
-rw-r--r--configure.in31
-rw-r--r--extra/libevent/epoll.c3
-rw-r--r--include/Makefile.am9
-rw-r--r--include/errmsg.h3
-rw-r--r--include/keycache.h216
-rw-r--r--include/m_ctype.h212
-rw-r--r--include/m_string.h14
-rw-r--r--include/my_base.h14
-rw-r--r--include/my_global.h19
-rw-r--r--include/my_no_pthread.h1
-rw-r--r--include/my_pthread.h4
-rw-r--r--include/my_sys.h17
-rw-r--r--include/mysql.h56
-rw-r--r--include/mysql.h.pp39
-rw-r--r--include/mysql/client_plugin.h164
-rw-r--r--include/mysql/client_plugin.h.pp41
-rw-r--r--include/mysql/plugin.h127
-rw-r--r--include/mysql/plugin_auth.h83
-rw-r--r--include/mysql/plugin_auth.h.pp (renamed from include/mysql/plugin.h.pp)90
-rw-r--r--include/mysql/plugin_auth_common.h105
-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.h24
-rw-r--r--include/service_versions.h24
-rw-r--r--include/sql_common.h65
-rwxr-xr-xlibmysql/CMakeLists.txt3
-rw-r--r--libmysql/Makefile.shared14
-rw-r--r--libmysql/client_settings.h5
-rw-r--r--libmysql/errmsg.c3
-rw-r--r--libmysql/libmysql.c103
-rw-r--r--libmysqld/CMakeLists.txt5
-rw-r--r--libmysqld/Makefile.am12
-rw-r--r--libmysqld/embedded_priv.h2
-rw-r--r--libmysqld/lib_sql.cc81
-rw-r--r--libmysqld/libmysqld.c14
-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/Makefile.am2
-rw-r--r--mysql-test/lib/mtr_cases.pm11
-rwxr-xr-xmysql-test/mysql-test-run.pl29
-rw-r--r--mysql-test/r/change_user.result33
-rw-r--r--mysql-test/r/connect.result14
-rw-r--r--mysql-test/r/events_bugs.result3
-rw-r--r--mysql-test/r/grant.result13
-rw-r--r--mysql-test/r/grant2.result2
-rw-r--r--mysql-test/r/information_schema.result17
-rw-r--r--mysql-test/r/information_schema_all_engines.result32
-rw-r--r--mysql-test/r/information_schema_db.result1
-rw-r--r--mysql-test/r/key_cache.result435
-rw-r--r--mysql-test/r/log_slow.result1
-rw-r--r--mysql-test/r/partition_example.result31
-rw-r--r--mysql-test/r/plugin.result69
-rw-r--r--mysql-test/r/plugin_maturity.result2
-rw-r--r--mysql-test/r/ps.result6
-rw-r--r--mysql-test/r/select_pkeycache.result4799
-rw-r--r--mysql-test/r/sp.result3
-rw-r--r--mysql-test/r/sp_notembedded.result2
-rw-r--r--mysql-test/r/status_user.result186
-rw-r--r--mysql-test/r/system_mysql_db.result6
-rw-r--r--mysql-test/r/table_options.result182
-rw-r--r--mysql-test/std_data/loaddata7.dat5
-rw-r--r--mysql-test/suite/binlog/r/binlog_index.result1
-rw-r--r--mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result416
-rw-r--r--mysql-test/suite/binlog/t/binlog_index.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt1
-rw-r--r--mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test78
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_is.result139
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_is_embedded.result111
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql.result13
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result8
-rw-r--r--mysql-test/suite/funcs_1/r/is_tables_is.result230
-rw-r--r--mysql-test/suite/funcs_1/r/is_user_privileges.result88
-rw-r--r--mysql-test/suite/funcs_1/t/is_tables_is.test1
-rw-r--r--mysql-test/suite/maria/r/group_commit.result17
-rw-r--r--mysql-test/suite/maria/r/maria3.result3
-rw-r--r--mysql-test/suite/maria/t/group_commit.test72
-rw-r--r--mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc4
-rw-r--r--mysql-test/suite/oqgraph/r/basic.result63
-rw-r--r--mysql-test/suite/oqgraph/r/binlog.result18
-rw-r--r--mysql-test/suite/oqgraph/t/basic.test45
-rw-r--r--mysql-test/suite/oqgraph/t/binlog.test28
-rw-r--r--mysql-test/suite/oqgraph/t/suite.opt1
-rw-r--r--mysql-test/suite/parts/r/partition_debug_sync_innodb.result2
-rw-r--r--mysql-test/suite/pbxt/r/grant.result13
-rw-r--r--mysql-test/suite/pbxt/r/group_min_max.result16
-rw-r--r--mysql-test/suite/pbxt/r/mysqlshow.result10
-rw-r--r--mysql-test/suite/pbxt/r/null_key.result6
-rw-r--r--mysql-test/suite/pbxt/r/partition_pruning.result28
-rw-r--r--mysql-test/suite/pbxt/r/update.result24
-rw-r--r--mysql-test/suite/pbxt/t/multi_update.test7
-rw-r--r--mysql-test/suite/rpl/r/rpl_do_grant.result6
-rw-r--r--mysql-test/suite/rpl/r/rpl_ignore_table.result1
-rw-r--r--mysql-test/suite/rpl/r/rpl_stm_000001.result1
-rw-r--r--mysql-test/suite/rpl/r/rpl_table_options.result25
-rw-r--r--mysql-test/suite/rpl/t/rpl_do_grant.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_table_options.test31
-rw-r--r--mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc344
-rw-r--r--mysql-test/suite/vcol/inc/vcol_cleanup.inc25
-rw-r--r--mysql-test/suite/vcol/inc/vcol_column_def_options.inc113
-rw-r--r--mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc43
-rw-r--r--mysql-test/suite/vcol/inc/vcol_handler.inc77
-rw-r--r--mysql-test/suite/vcol/inc/vcol_init_vars.pre17
-rw-r--r--mysql-test/suite/vcol/inc/vcol_ins_upd.inc289
-rw-r--r--mysql-test/suite/vcol/inc/vcol_keys.inc163
-rw-r--r--mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc162
-rw-r--r--mysql-test/suite/vcol/inc/vcol_partition.inc127
-rw-r--r--mysql-test/suite/vcol/inc/vcol_select.inc216
-rw-r--r--mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc42
-rw-r--r--mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc1229
-rw-r--r--mysql-test/suite/vcol/inc/vcol_trigger_sp.inc110
-rw-r--r--mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc21
-rw-r--r--mysql-test/suite/vcol/inc/vcol_view.inc201
-rw-r--r--mysql-test/suite/vcol/r/rpl_vcol.result25
-rw-r--r--mysql-test/suite/vcol/r/vcol_archive.result7
-rw-r--r--mysql-test/suite/vcol/r/vcol_blackhole.result7
-rw-r--r--mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result243
-rw-r--r--mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result245
-rw-r--r--mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result146
-rw-r--r--mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result146
-rw-r--r--mysql-test/suite/vcol/r/vcol_csv.result7
-rw-r--r--mysql-test/suite/vcol/r/vcol_handler_innodb.result76
-rw-r--r--mysql-test/suite/vcol/r/vcol_handler_maria.result76
-rw-r--r--mysql-test/suite/vcol/r/vcol_handler_myisam.result76
-rw-r--r--mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result427
-rw-r--r--mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result365
-rw-r--r--mysql-test/suite/vcol/r/vcol_keys_innodb.result151
-rw-r--r--mysql-test/suite/vcol/r/vcol_keys_myisam.result158
-rw-r--r--mysql-test/suite/vcol/r/vcol_memory.result7
-rw-r--r--mysql-test/suite/vcol/r/vcol_merge.result8
-rw-r--r--mysql-test/suite/vcol/r/vcol_misc.result135
-rw-r--r--mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result242
-rw-r--r--mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result242
-rw-r--r--mysql-test/suite/vcol/r/vcol_partition_innodb.result80
-rw-r--r--mysql-test/suite/vcol/r/vcol_partition_myisam.result80
-rw-r--r--mysql-test/suite/vcol/r/vcol_select_innodb.result264
-rw-r--r--mysql-test/suite/vcol/r/vcol_select_myisam.result264
-rw-r--r--mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result2943
-rw-r--r--mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result2943
-rw-r--r--mysql-test/suite/vcol/r/vcol_syntax.result52
-rw-r--r--mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result87
-rw-r--r--mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result87
-rw-r--r--mysql-test/suite/vcol/r/vcol_view_innodb.result276
-rw-r--r--mysql-test/suite/vcol/r/vcol_view_myisam.result276
-rw-r--r--mysql-test/suite/vcol/t/rpl_vcol.test69
-rw-r--r--mysql-test/suite/vcol/t/vcol_archive.test49
-rw-r--r--mysql-test/suite/vcol/t/vcol_blackhole.test49
-rw-r--r--mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test52
-rw-r--r--mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test49
-rw-r--r--mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test50
-rw-r--r--mysql-test/suite/vcol/t/vcol_csv.test54
-rw-r--r--mysql-test/suite/vcol/t/vcol_handler_innodb.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_handler_maria.test52
-rw-r--r--mysql-test/suite/vcol/t/vcol_handler_myisam.test50
-rw-r--r--mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test50
-rw-r--r--mysql-test/suite/vcol/t/vcol_keys_innodb.test52
-rw-r--r--mysql-test/suite/vcol/t/vcol_keys_myisam.test50
-rw-r--r--mysql-test/suite/vcol/t/vcol_memory.test48
-rw-r--r--mysql-test/suite/vcol/t/vcol_merge.test57
-rw-r--r--mysql-test/suite/vcol/t/vcol_misc.test140
-rw-r--r--mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test53
-rw-r--r--mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test52
-rw-r--r--mysql-test/suite/vcol/t/vcol_partition_innodb.test52
-rw-r--r--mysql-test/suite/vcol/t/vcol_partition_myisam.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_select_innodb.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_select_myisam.test50
-rw-r--r--mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test50
-rw-r--r--mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test49
-rw-r--r--mysql-test/suite/vcol/t/vcol_syntax.test30
-rw-r--r--mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test52
-rw-r--r--mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_view_innodb.test51
-rw-r--r--mysql-test/suite/vcol/t/vcol_view_myisam.test50
-rw-r--r--mysql-test/t/change_user.test57
-rw-r--r--mysql-test/t/connect.test28
-rw-r--r--mysql-test/t/events_bugs.test1
-rw-r--r--mysql-test/t/key_cache.test277
-rw-r--r--mysql-test/t/log_slow.test6
-rw-r--r--mysql-test/t/partition_example.test23
-rw-r--r--mysql-test/t/plugin.test57
-rw-r--r--mysql-test/t/plugin_maturity-master.opt1
-rw-r--r--mysql-test/t/plugin_maturity.test6
-rw-r--r--mysql-test/t/select_pkeycache-master.opt1
-rw-r--r--mysql-test/t/select_pkeycache.test8
-rw-r--r--mysql-test/t/sp.test1
-rw-r--r--mysql-test/t/status_user-master.opt1
-rw-r--r--mysql-test/t/status_user.test89
-rw-r--r--mysql-test/t/table_options.test68
-rw-r--r--mysql-test/valgrind.supp28
-rw-r--r--mysys/Makefile.am10
-rw-r--r--mysys/charset-def.c80
-rw-r--r--mysys/charset.c73
-rw-r--r--mysys/mf_keycache.c2444
-rw-r--r--mysys/my_getsystime.c26
-rw-r--r--plugin/auth/Makefile.am15
-rw-r--r--plugin/auth/auth_socket.c119
-rw-r--r--plugin/auth/dialog.c346
-rw-r--r--plugin/auth/plug.in15
-rw-r--r--plugin/daemon_example/Makefile.am3
-rw-r--r--plugin/daemon_example/daemon_example.cc17
-rw-r--r--plugin/fulltext/plugin_example.c17
-rw-r--r--randgen/conf/maria_group_commit.yy181
-rwxr-xr-xscripts/make_win_bin_dist4
-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.sql9
-rw-r--r--server-tools/CMakeLists.txt2
-rwxr-xr-xserver-tools/instance-manager/CMakeLists.txt4
-rw-r--r--server-tools/instance-manager/Makefile.am5
-rw-r--r--server-tools/instance-manager/user_map.cc2
-rw-r--r--sql-common/Makefile.am2
-rw-r--r--sql-common/client.c1111
-rw-r--r--sql-common/client_plugin.c436
-rwxr-xr-xsql/CMakeLists.txt7
-rw-r--r--sql/Makefile.am19
-rw-r--r--sql/authors.h36
-rw-r--r--sql/client_settings.h5
-rw-r--r--sql/create_options.cc612
-rw-r--r--sql/create_options.h92
-rw-r--r--sql/event_data_objects.cc2
-rw-r--r--sql/event_db_repository.cc29
-rw-r--r--sql/events.cc7
-rw-r--r--sql/field.cc177
-rw-r--r--sql/field.h117
-rw-r--r--sql/filesort.cc28
-rw-r--r--sql/ha_ndbcluster.cc19
-rw-r--r--sql/ha_ndbcluster_binlog.cc2
-rw-r--r--sql/ha_partition.cc148
-rw-r--r--sql/ha_partition.h31
-rw-r--r--sql/handler.cc264
-rw-r--r--sql/handler.h262
-rw-r--r--sql/item.cc30
-rw-r--r--sql/item.h115
-rw-r--r--sql/item_cmpfunc.cc16
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_func.cc30
-rw-r--r--sql/item_func.h75
-rw-r--r--sql/item_row.h3
-rw-r--r--sql/item_strfunc.h17
-rw-r--r--sql/item_subselect.cc29
-rw-r--r--sql/item_subselect.h4
-rw-r--r--sql/item_sum.h12
-rw-r--r--sql/item_timefunc.h37
-rw-r--r--sql/item_xmlfunc.cc9
-rw-r--r--sql/item_xmlfunc.h4
-rw-r--r--sql/key.cc3
-rw-r--r--sql/lex.h15
-rw-r--r--sql/log.cc86
-rw-r--r--sql/log.h5
-rw-r--r--sql/log_event.cc158
-rw-r--r--sql/log_event.h20
-rw-r--r--sql/log_event_old.cc74
-rw-r--r--sql/mysql_priv.h56
-rw-r--r--sql/mysqld.cc111
-rw-r--r--sql/opt_range.cc159
-rw-r--r--sql/opt_range.h2
-rw-r--r--sql/opt_sum.cc49
-rw-r--r--sql/opt_table_elimination.cc2
-rw-r--r--sql/password.c12
-rw-r--r--sql/procedure.h6
-rw-r--r--sql/protocol.cc18
-rw-r--r--sql/protocol.h1
-rw-r--r--sql/records.cc29
-rw-r--r--sql/rpl_filter.cc9
-rw-r--r--sql/rpl_filter.h5
-rw-r--r--sql/set_var.cc49
-rw-r--r--sql/set_var.h18
-rw-r--r--sql/share/errmsg.txt35
-rw-r--r--sql/sp.cc22
-rw-r--r--sql/sp_head.cc7
-rw-r--r--sql/sql_acl.cc2221
-rw-r--r--sql/sql_acl.h54
-rw-r--r--sql/sql_base.cc159
-rw-r--r--sql/sql_builtin.cc.in11
-rw-r--r--sql/sql_class.cc163
-rw-r--r--sql/sql_class.h215
-rw-r--r--sql/sql_connect.cc934
-rw-r--r--sql/sql_cursor.cc4
-rw-r--r--sql/sql_delete.cc17
-rw-r--r--sql/sql_handler.cc20
-rw-r--r--sql/sql_help.cc41
-rw-r--r--sql/sql_insert.cc47
-rw-r--r--sql/sql_lex.cc8
-rw-r--r--sql/sql_lex.h25
-rw-r--r--sql/sql_parse.cc272
-rw-r--r--sql/sql_partition.cc3
-rw-r--r--sql/sql_plugin.cc489
-rw-r--r--sql/sql_plugin.h20
-rw-r--r--sql/sql_plugin_services.h44
-rw-r--r--sql/sql_prepare.cc15
-rw-r--r--sql/sql_select.cc158
-rw-r--r--sql/sql_servers.cc29
-rw-r--r--sql/sql_show.cc641
-rw-r--r--sql/sql_string.cc4
-rw-r--r--sql/sql_string.h8
-rw-r--r--sql/sql_table.cc164
-rw-r--r--sql/sql_test.cc4
-rw-r--r--sql/sql_udf.cc16
-rw-r--r--sql/sql_update.cc57
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/sql_yacc.yy289
-rw-r--r--sql/structs.h114
-rw-r--r--sql/table.cc764
-rw-r--r--sql/table.h50
-rw-r--r--sql/thr_malloc.cc2
-rw-r--r--sql/tztime.cc42
-rw-r--r--sql/unireg.cc118
-rw-r--r--sql/unireg.h7
-rw-r--r--storage/archive/ha_archive.cc39
-rw-r--r--storage/blackhole/ha_blackhole.cc17
-rw-r--r--storage/csv/ha_tina.cc18
-rw-r--r--storage/example/Makefile.am2
-rw-r--r--storage/example/ha_example.cc239
-rw-r--r--storage/example/ha_example.h3
-rw-r--r--storage/federated/ha_federated.cc17
-rw-r--r--storage/federatedx/ha_federatedx.cc19
-rw-r--r--storage/heap/ha_heap.cc17
-rw-r--r--storage/heap/hp_create.c6
-rw-r--r--storage/heap/hp_rkey.c2
-rw-r--r--storage/ibmdb2i/ha_ibmdb2i.cc21
-rw-r--r--storage/innodb_plugin/Makefile.am2
-rw-r--r--storage/maria/CMakeLists.txt2
-rw-r--r--storage/maria/Makefile.am5
-rw-r--r--storage/maria/ha_maria.cc148
-rw-r--r--storage/maria/ha_maria.h1
-rw-r--r--storage/maria/ma_checkpoint.c68
-rw-r--r--storage/maria/ma_ft_boolean_search.c2
-rw-r--r--storage/maria/ma_ft_parser.c3
-rw-r--r--storage/maria/ma_init.c5
-rw-r--r--storage/maria/ma_loghandler.c737
-rw-r--r--storage/maria/ma_loghandler.h16
-rw-r--r--storage/maria/ma_search.c4
-rw-r--r--storage/maria/ma_servicethread.c134
-rw-r--r--storage/maria/ma_servicethread.h22
-rw-r--r--storage/myisam/ft_boolean_search.c2
-rw-r--r--storage/myisam/ft_parser.c3
-rw-r--r--storage/myisam/ha_myisam.cc89
-rw-r--r--storage/myisam/ha_myisam.h2
-rw-r--r--storage/myisam/mi_check.c24
-rw-r--r--storage/myisam/mi_close.c1
-rw-r--r--storage/myisam/mi_delete_all.c3
-rw-r--r--storage/myisam/mi_extra.c4
-rw-r--r--storage/myisam/mi_keycache.c7
-rw-r--r--storage/myisam/mi_locking.c7
-rw-r--r--storage/myisam/mi_page.c12
-rw-r--r--storage/myisam/mi_panic.c3
-rw-r--r--storage/myisam/mi_preload.c5
-rw-r--r--storage/myisam/mi_search.c5
-rw-r--r--storage/myisam/mi_test1.c3
-rw-r--r--storage/myisam/mi_test2.c3
-rw-r--r--storage/myisam/mi_test3.c3
-rw-r--r--storage/myisam/myisam_ftdump.c2
-rw-r--r--storage/myisam/myisamchk.c11
-rw-r--r--storage/myisam/myisamdef.h5
-rw-r--r--storage/myisam/myisamlog.c2
-rw-r--r--storage/myisammrg/ha_myisammrg.cc17
-rw-r--r--storage/mysql_storage_engine.cmake2
-rw-r--r--storage/oqgraph/CMakeFiles.txt22
-rw-r--r--storage/oqgraph/Makefile.am98
-rw-r--r--storage/oqgraph/README16
-rw-r--r--storage/oqgraph/graphcore-graph.h48
-rw-r--r--storage/oqgraph/graphcore-types.h36
-rw-r--r--storage/oqgraph/graphcore.cc1101
-rw-r--r--storage/oqgraph/graphcore.h116
-rw-r--r--storage/oqgraph/graphstore.c356
-rw-r--r--storage/oqgraph/graphstore.h90
-rw-r--r--storage/oqgraph/ha_oqgraph.cc1041
-rw-r--r--storage/oqgraph/ha_oqgraph.h114
-rw-r--r--storage/oqgraph/oqgraph_config.h.in73
-rw-r--r--storage/oqgraph/oqgraph_probes.d19
-rw-r--r--storage/oqgraph/plug.in40
-rw-r--r--storage/pbxt/src/datadic_xt.cc4
-rw-r--r--storage/pbxt/src/discover_xt.cc3
-rw-r--r--storage/pbxt/src/ha_pbxt.cc43
-rw-r--r--storage/pbxt/src/myxt_xt.h12
-rw-r--r--storage/pbxt/src/xt_defs.h4
-rw-r--r--storage/sphinx/CMakeLists.txt11
-rw-r--r--storage/sphinx/Makefile.am55
-rw-r--r--storage/sphinx/gen_data.php37
-rw-r--r--storage/sphinx/ha_sphinx.cc3115
-rw-r--r--storage/sphinx/ha_sphinx.h158
-rw-r--r--storage/sphinx/make-patch.sh36
-rw-r--r--storage/sphinx/plug.in6
-rw-r--r--storage/sphinx/snippets_udf.cc766
-rw-r--r--storage/sphinx/sphinx.5.0.22.diff284
-rw-r--r--storage/sphinx/sphinx.5.0.27.diff284
-rw-r--r--storage/sphinx/sphinx.5.0.37.diff338
-rw-r--r--storage/xtradb/Makefile.am2
-rw-r--r--storage/xtradb/fil/fil0fil.c2
-rw-r--r--storage/xtradb/handler/ha_innodb.cc108
-rw-r--r--storage/xtradb/handler/ha_innodb.h1
-rw-r--r--storage/xtradb/handler/i_s.cc724
-rw-r--r--storage/xtradb/handler/i_s.h18
-rw-r--r--strings/conf_to_src.c16
-rw-r--r--strings/ctype-big5.c38
-rw-r--r--strings/ctype-bin.c8
-rw-r--r--strings/ctype-cp932.c50
-rw-r--r--strings/ctype-czech.c34
-rw-r--r--strings/ctype-euc_kr.c38
-rw-r--r--strings/ctype-eucjpms.c536
-rw-r--r--strings/ctype-extra.c568
-rw-r--r--strings/ctype-gb2312.c38
-rw-r--r--strings/ctype-gbk.c35
-rw-r--r--strings/ctype-latin1.c36
-rw-r--r--strings/ctype-mb.c40
-rw-r--r--strings/ctype-simple.c44
-rw-r--r--strings/ctype-sjis.c36
-rw-r--r--strings/ctype-tis620.c22
-rw-r--r--strings/ctype-uca.c284
-rw-r--r--strings/ctype-ucs2.c26
-rw-r--r--strings/ctype-ujis.c508
-rw-r--r--strings/ctype-utf8.c62
-rw-r--r--strings/ctype-win1250ch.c28
-rw-r--r--strings/ctype.c23
-rw-r--r--strings/int2str.c6
-rw-r--r--strings/my_vsnprintf.c666
-rw-r--r--tests/mysql_client_test.c1
-rw-r--r--unittest/mysys/Makefile.am3
-rw-r--r--unittest/mysys/my_vsnprintf-t.c155
-rw-r--r--win/Makefile.am3
-rw-r--r--win/build-vs10.bat18
-rw-r--r--win/build-vs10_x64.bat18
-rw-r--r--win/configure-mariadb.sh8
445 files changed, 50010 insertions, 5158 deletions
diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf
index 84dab2dc819..4eb39d5426c 100644
--- a/.bzr-mysql/default.conf
+++ b/.bzr-mysql/default.conf
@@ -1,6 +1,6 @@
[MYSQL]
-tree_location = lp:maria
+tree_location = lp:maria/5.2
post_commit_to = commits@mariadb.org
-post_commit_url = lp:maria
-tree_name = maria
-project_name = "MariaDB 5.1, with Maria 1.5"
+post_commit_url = lp:maria/5.2
+tree_name = maria/5.2
+project_name = "Mariadb 5.2, with Maria 2.0"
diff --git a/.bzrignore b/.bzrignore
index a5358590417..9907f5b4e12 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1927,4 +1927,12 @@ libmysqld/opt_table_elimination.cc
libmysqld/ha_federatedx.cc
tmp
libmysqld/debug_sync.cc
+client/rpl_filter.cc
+client/rpl_filter.h
+client/sql_list.cc
+client/sql_list.h
+libmysqld/client_plugin.c
+sql/client_plugin.c
+*.dgcov
+libmysqld/create_options.cc
storage/pbxt/bin/xtstat
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index fe572562750..0ad5351f545 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -208,7 +208,7 @@ if test -z "$CC" ; then
fi
if test -z "$CXX" ; then
- CXX=gcc
+ CXX=g++
fi
# If ccache (a compiler cache which reduces build time)
diff --git a/BUILD/compile-bintar b/BUILD/compile-bintar
index 8777cfb2670..2b039e439c0 100755
--- a/BUILD/compile-bintar
+++ b/BUILD/compile-bintar
@@ -32,8 +32,7 @@
# .so files at runtime (either system stuff like NSS, or server
# plugins).
#
-# We link libgcc statically (and avoid linking libstdc++ at all by
-# CXX=gcc), to avoid reduce nasty library version dependencies.
+# We link libgcc statically to avoid reduce nasty library version dependencies.
test -f Makefile && make distclean
@@ -52,13 +51,12 @@ get_cpuopt
get_make_parallel_flag
# Use gcc rather than g++ to avoid linking libstdc++.so (which we don't need).
-COMP="gcc -static-libgcc"
FLAGS="-O2 -fno-omit-frame-pointer -g -pipe -Wall $CPUOPT"
# Don't press on in case of error.
set -e
-CC="$COMP" CXX="$COMP" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \
+CC="gcc -static-libgcc" CXX="g++ -static-libgcc" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \
./configure \
--prefix=/usr/local/mysql \
--exec-prefix=/usr/local/mysql \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5cfe5dc8319..a94dcd8817c 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,7 @@ ADD_DEFINITIONS(-DMYSQL_DATADIR="c:/Program Files/MySQL/MySQL Server ${MYSQL_BAS
ADD_DEFINITIONS(-DDEFAULT_CHARSET_HOME="c:/Program Files/MySQL/MySQL Server ${MYSQL_BASE_VERSION}/")
ADD_DEFINITIONS(-DPACKAGE=mysql)
ADD_DEFINITIONS(-DSHAREDIR="share")
+ADD_DEFINITIONS(-DPLUGINDIR="lib/plugin")
# Set debug options
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS")
@@ -115,8 +116,7 @@ IF(MSVC)
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG_INIT ${CMAKE_CXX_FLAGS_DEBUG_INIT})
- # generate map files, set stack size (see bug#20815)
- SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MAP /MAPINFO:EXPORTS")
+ # set stack size (see bug#20815)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1048576")
# remove support for Exception handling
@@ -260,7 +260,7 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${PLUGIN_NAME}_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin")
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
@@ -279,7 +279,7 @@ ENDFOREACH(SUBDIR ${STORAGE_SUBDIRS})
# Special handling for partition(not really pluggable)
IF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_PARTITION_STORAGE_ENGINE")
- SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_partition_plugin")
ENDIF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
# Special handling for tmp tables with the maria engine
@@ -325,6 +325,7 @@ ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(sql)
ADD_SUBDIRECTORY(server-tools/instance-manager)
ADD_SUBDIRECTORY(libmysql)
+ADD_SUBDIRECTORY(libservices)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(unittest/mytap)
ADD_SUBDIRECTORY(unittest/mysys)
diff --git a/Docs/sp-imp-spec.txt b/Docs/sp-imp-spec.txt
index ac17a375926..9795dd72252 100644
--- a/Docs/sp-imp-spec.txt
+++ b/Docs/sp-imp-spec.txt
@@ -1075,7 +1075,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'IGNORE_BAD_TABLE_OPTIONS',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -1097,4 +1097,4 @@
) comment='Stored Procedures';
--
- \ No newline at end of file
+
diff --git a/Makefile.am b/Makefile.am
index 85b4018d6bf..7474177f5f5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,7 +25,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@ storage \
@sql_server@ @man_dirs@ tests \
netware @libmysqld_dirs@ \
@@ -34,7 +34,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 \
@@ -140,14 +140,14 @@ smoke:
test-full: test test-nr test-ps
test-force:
- $(MAKE) force=--force test
+ $(MAKE) -k force=--force test
test-force-full:
- $(MAKE) force=--force test-full
+ $(MAKE) -k force=--force test-full
#used by autopush.pl to run memory based tests
test-force-mem:
- $(MAKE) force=--force mem=--mem test
+ $(MAKE) -k force=--force mem=--mem test
test-bt:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@@ -261,7 +261,7 @@ test-fast-prepare:
$(MAKE) subset=--ps-protocol test-fast
test-full-qa:
- $(MAKE) force=--force test-pr \
+ $(MAKE) -k force=--force test-pr \
test-binlog-statement test-ext test-fast-view \
test-fast-cursor test-unit
@@ -271,12 +271,13 @@ test-full-qa:
# after which TEST_PREPROCESSOR_HEADER will be used.
#
-API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \
- $(top_srcdir)/include/mysql.h
+API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql.h \
+ $(top_srcdir)/include/mysql/client_plugin.h \
+ $(top_srcdir)/include/mysql/plugin_auth.h
-TEST_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \
- $(top_srcdir)/sql/mysql_priv.h \
- $(top_srcdir)/include/mysql.h
+TEST_PREPROCESSOR_HEADER = $(API_PREPROCESSOR_HEADER) \
+ $(top_srcdir)/sql/mysql_priv.h
+
#
# Rules for checking that the abi/api has not changed.
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index abd9923d49d..b22a83faff9 100755
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -83,5 +83,7 @@ IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("echo" "asInvoker")
ENDIF(EMBED_MANIFESTS)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
+
INSTALL(TARGETS mysql mysqltest mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow
mysqlbinlog mysqladmin mysqlslap echo DESTINATION bin COMPONENT runtime)
diff --git a/client/Makefile.am b/client/Makefile.am
index ccd0d8aada0..bfca0ba4bb2 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -100,14 +100,15 @@ mysql_upgrade_SOURCES= mysql_upgrade.c \
# Fix for mit-threads
DEFS = -DMYSQL_CLIENT_NO_THREADS \
- -DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \
- -DMYSQL_DATADIR="\"$(localstatedir)\""
+ -DDEFAULT_MYSQL_HOME='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(localstatedir)"'
sql_src=log_event.h mysql_priv.h rpl_constants.h \
rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
log_event.cc my_decimal.h my_decimal.cc \
log_event_old.h log_event_old.cc \
- rpl_record_old.h rpl_record_old.cc
+ rpl_record_old.h rpl_record_old.cc \
+ sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc
strings_src=decimal.c
link_sources:
diff --git a/client/client_priv.h b/client/client_priv.h
index 6a23af23594..f6bde7a594c 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -92,5 +92,8 @@ enum options_client
OPT_ABORT_SOURCE_ON_ERROR,
OPT_FIRST_SLAVE,
OPT_ALL,
- OPT_MAX_CLIENT_OPTION
+ OPT_REWRITE_DB,
+ OPT_PLUGIN_DIR,
+ OPT_DEFAULT_PLUGIN,
+ OPT_MAX_CLIENT_OPTION /* should be always the last */
};
diff --git a/client/mysql.cc b/client/mysql.cc
index fb090cd74d5..71a9e44fa23 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -173,6 +173,7 @@ static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char mysql_charsets_dir[FN_REFLEN+1];
+static char *opt_plugin_dir= 0, *opt_default_auth;
static const char *xmlmeta[] = {
"&", "&",
"<", "&lt;",
@@ -1569,6 +1570,13 @@ static struct my_option my_long_options[] =
{"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
&show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_PLUGIN_DIR,
+ "Default authentication client-side plugin to use.",
+ (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -3607,7 +3615,7 @@ static void print_warnings()
mysql_store_result_for_lazy(&result);
/* Bail out when no warnings */
- if (!(num_rows= mysql_num_rows(result)))
+ if (!result || !(num_rows= mysql_num_rows(result)))
goto end;
cur= mysql_fetch_row(result);
@@ -4265,6 +4273,57 @@ char *get_arg(char *line, my_bool get_next_arg)
}
+/**
+ An example of mysql_authentication_dialog_ask callback.
+
+ The C function with the name "mysql_authentication_dialog_ask", if exists,
+ will be used by the "dialog" client authentication plugin when user
+ input is needed. This function should be of mysql_authentication_dialog_ask_t
+ type. If the function does not exists, a built-in implementation will be
+ used.
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - normal string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+
+extern "C" char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ char *s=buf;
+
+ fputs("[mariadb] ", stdout);
+ fputs(prompt, stdout);
+ fputs(" ", stdout);
+
+ if (type == 2) /* password */
+ {
+ s= get_tty_password("");
+ strnmov(buf, s, buf_len);
+ buf[buf_len-1]= 0;
+ my_free(s, MYF(0));
+ }
+ else
+ {
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else if (buf[0] && (s= strend(buf))[-1] == '\n')
+ s[-1]= 0;
+ }
+
+ return buf;
+}
+
static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
@@ -4310,6 +4369,13 @@ sql_real_connect(char *host,char *database,char *user,char *password,
}
if (default_charset_used)
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 2df08483b49..018b07690e3 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -24,7 +24,7 @@
#include <mysql.h>
#include <sql_common.h>
-#define ADMIN_VERSION "8.42"
+#define ADMIN_VERSION "9.0"
#define MAX_MYSQL_VAR 512
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@@ -97,7 +97,10 @@ enum commands {
ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
- ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
+ ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG,
+ ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS,
+ ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS,
+ ADMIN_FLUSH_ALL_STATUS, ADMIN_FLUSH_ALL_STATISTICS
};
static const char *command_names[]= {
"create", "drop", "shutdown",
@@ -107,7 +110,10 @@ static const char *command_names[]= {
"flush-hosts", "flush-tables", "password",
"ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave",
- "flush-threads","old-password",
+ "flush-threads", "old-password", "flush-slow-log",
+ "flush-table-statistics", "flush-index-statistics",
+ "flush-user-statistics", "flush-client-statistics",
+ "flush-all-status", "flush-all-statistics",
NullS
};
@@ -592,7 +598,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
for (; argc > 0 ; argv++,argc--)
{
- switch (find_type(argv[0],&command_typelib,2)) {
+ int command;
+ switch ((command= find_type(argv[0],&command_typelib,2))) {
case ADMIN_CREATE:
{
char buff[FN_REFLEN+20];
@@ -669,7 +676,11 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_refresh(mysql,
(uint) ~(REFRESH_GRANT | REFRESH_STATUS |
REFRESH_READ_LOCK | REFRESH_SLAVE |
- REFRESH_MASTER)))
+ REFRESH_MASTER | REFRESH_TABLE_STATS |
+ REFRESH_INDEX_STATS |
+ REFRESH_USER_STATS |
+ REFRESH_SLOW_QUERY_LOG |
+ REFRESH_CLIENT_STATS)))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -687,7 +698,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_VER:
new_line=1;
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
+ puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n"
+ "2009 Monty Program Ab");
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
@@ -863,9 +875,19 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_LOGS:
{
- if (mysql_refresh(mysql,REFRESH_LOG))
+ if (mysql_query(mysql,"flush logs"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_SLOW_LOG:
+ {
+ if (mysql_query(mysql,"flush slow query logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -875,7 +897,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush hosts"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -885,7 +907,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush tables"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -895,7 +917,71 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush status"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_TABLE_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush table_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_INDEX_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush index_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_USER_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush user_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_CLIENT_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ALL_STATISTICS:
+ {
+ if (mysql_query(mysql,
+ "flush table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ALL_STATUS:
+ {
+ if (mysql_query(mysql,
+ "flush status,table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -1067,7 +1153,8 @@ static void print_version(void)
static void usage(void)
{
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
+ puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n"
+ "2009 Monty Program Ab");
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
puts("Administration program for the mysqld daemon.");
printf("Usage: %s [OPTIONS] command command....\n", my_progname);
@@ -1075,16 +1162,23 @@ static void usage(void)
my_print_variables(my_long_options);
print_defaults("my",load_default_groups);
puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
- create databasename Create a new database\n\
- debug Instruct server to write debug information to log\n\
- drop databasename Delete a database and all its tables\n\
- extended-status Gives an extended status message from the server\n\
- flush-hosts Flush all cached hosts\n\
- flush-logs Flush all logs\n\
- flush-status Clear status variables\n\
- flush-tables Flush all tables\n\
- flush-threads Flush the thread cache\n\
- flush-privileges Reload grant tables (same as reload)\n\
+ create databasename Create a new database\n\
+ debug Instruct server to write debug information to log\n\
+ drop databasename Delete a database and all its tables\n\
+ extended-status Gives an extended status message from the server\n\
+ flush-all-statistics Flush all statistics tables\n\
+ flush-all-status Flush status and statistics\n\
+ flush-client-statistics Flush client statistics\n\
+ flush-hosts Flush all cached hosts\n\
+ flush-index-statistics Flush index statistics\n\
+ flush-logs Flush all logs\n\
+ flush-privileges Reload grant tables (same as reload)\n\
+ flush-slow-log Flush slow query log\n\
+ flush-status Clear status variables\n\
+ flush-table-statistics Clear table statistics\n\
+ flush-tables Flush all tables\n\
+ flush-threads Flush the thread cache\n\
+ flush-user-statistics Flush user statistics\n\
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index b931bd125d6..420042e6055 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -35,6 +35,15 @@
#include "log_event.h"
#include "sql_common.h"
+/* Needed for Rpl_filter */
+CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
+
+#include "sql_string.h" // needed for Rpl_filter
+#include "sql_list.h" // needed for Rpl_filter
+#include "rpl_filter.h"
+
+Rpl_filter *binlog_filter;
+
#define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
@@ -620,6 +629,42 @@ static bool shall_skip_database(const char *log_dbname)
/**
+ Print "use <db>" statement when current db is to be changed.
+
+ We have to control emiting USE statements according to rewrite-db options.
+ We have to do it here (see process_event() below) and to suppress
+ producing USE statements by corresponding log event print-functions.
+*/
+
+void print_use_stmt(PRINT_EVENT_INFO* pinfo, const char* db, size_t db_len)
+{
+ // pinfo->db is the current db.
+ // If current db is the same as required db, do nothing.
+ if (!db || !memcmp(pinfo->db, db, db_len + 1))
+ return;
+
+ // Current db and required db are different.
+ // Check for rewrite rule for required db. (Note that in a rewrite rule
+ // neither db_from nor db_to part can be empty).
+ size_t len_to= 0;
+ const char *db_to= binlog_filter->get_rewrite_db(db, &len_to);
+
+ // If there is no rewrite rule for db (in this case len_to is left = 0),
+ // printing of the corresponding USE statement is left for log event
+ // print-function.
+ if (!len_to)
+ return;
+
+ // In case of rewrite rule print USE statement for db_to
+ fprintf(result_file, "use %s%s\n", db_to, pinfo->delimiter);
+
+ // Copy the *original* db to pinfo to suppress emiting
+ // of USE stmts by log_event print-functions.
+ memcpy(pinfo->db, db, db_len + 1);
+}
+
+
+/**
Prints the given event in base64 format.
The header is printed to the head cache and the body is printed to
@@ -730,9 +775,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
switch (ev_type) {
case QUERY_EVENT:
- if (!((Query_log_event*)ev)->is_trans_keyword() &&
- shall_skip_database(((Query_log_event*)ev)->db))
+ {
+ Query_log_event *qe= (Query_log_event*)ev;
+ if (!qe->is_trans_keyword() && shall_skip_database(qe->db))
goto end;
+ print_use_stmt(print_event_info, qe->db, qe->db_len);
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
{
if ((retval= write_event_header_and_base64(ev, result_file,
@@ -743,6 +790,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
else
ev->print(result_file, print_event_info);
break;
+ }
case CREATE_FILE_EVENT:
{
@@ -864,6 +912,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (!shall_skip_database(exlq->db))
{
+ print_use_stmt(print_event_info, exlq->db, exlq->db_len);
if (fname)
{
convert_path_to_forward_slashes(fname);
@@ -887,6 +936,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
destroy_evt= FALSE;
goto end;
}
+ size_t len_to= 0;
+ const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
+ if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
+ {
+ error("Could not rewrite database name");
+ goto err;
+ }
}
case WRITE_ROWS_EVENT:
case DELETE_ROWS_EVENT:
@@ -971,14 +1027,16 @@ err:
retval= ERROR_STOP;
end:
rec_count++;
+
/*
- Destroy the log_event object. If reading from a remote host,
- set the temp_buf to NULL so that memory isn't freed twice.
+ Destroy the log_event object.
+ MariaDB MWL#36: mainline does this:
+ If reading from a remote host,
+ set the temp_buf to NULL so that memory isn't freed twice.
+ We no longer do that, we use Rpl_filter::event_owns_temp_buf instead.
*/
if (ev)
{
- if (remote_opt)
- ev->temp_buf= 0;
if (destroy_evt) /* destroy it later if not set (ignored table map) */
delete ev;
}
@@ -1144,6 +1202,10 @@ that may lead to an endless loop.",
"Used to reserve file descriptors for use by this program.",
&open_files_limit, &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
+ {"rewrite-db", OPT_REWRITE_DB,
+ "Updates to a database with a different name than the original. \
+Example: rewrite-db='from->to'.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1338,6 +1400,53 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
}
break;
+ case OPT_REWRITE_DB: // db_from->db_to
+ {
+ /* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */
+ char* ptr;
+ char* key= argument; // db-from
+ char* val; // db-to
+
+ // Where key begins
+ while (*key && my_isspace(&my_charset_latin1, *key))
+ key++;
+
+ // Where val begins
+ if (!(ptr= strstr(argument, "->")))
+ {
+ sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
+ return 1;
+ }
+ val= ptr + 2;
+ while (*val && my_isspace(&my_charset_latin1, *val))
+ val++;
+
+ // Write \0 and skip blanks at the end of key
+ *ptr-- = 0;
+ while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
+ *ptr-- = 0;
+
+ if (!*key)
+ {
+ sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
+ return 1;
+ }
+
+ // Skip blanks at the end of val
+ ptr= val;
+ while (*ptr && !my_isspace(&my_charset_latin1, *ptr))
+ ptr++;
+ *ptr= 0;
+
+ if (!*val)
+ {
+ sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
+ return 1;
+ }
+
+ binlog_filter->add_db_rewrite(key, val);
+ break;
+ }
case 'v':
if (argument == disabled_my_option)
verbose= 0;
@@ -1611,7 +1720,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
If reading from a remote host, ensure the temp_buf for the
Log_event class is pointing to the incoming stream.
*/
- ev->register_temp_buf((char *) net->read_pos + 1);
+ ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
Log_event_type type= ev->get_type_code();
if (glob_description_event->binlog_version >= 3 ||
@@ -2011,6 +2120,8 @@ end:
return retval;
}
+/* Used in sql_alloc(). Inited and freed in main() */
+MEM_ROOT s_mem_root;
int main(int argc, char** argv)
{
@@ -2023,8 +2134,16 @@ int main(int argc, char** argv)
my_init_time(); // for time functions
+ init_alloc_root(&s_mem_root, 16384, 0);
+ if (!(binlog_filter= new Rpl_filter))
+ {
+ error("Failed to create Rpl_filter");
+ exit(1);
+ }
+
if (load_defaults("my", load_default_groups, &argc, &argv))
exit(1);
+
defaults_argv= argv;
parse_args(&argc, (char***)&argv);
@@ -2111,6 +2230,8 @@ int main(int argc, char** argv)
if (result_file != stdout)
my_fclose(result_file, MYF(0));
cleanup();
+ delete binlog_filter;
+ free_root(&s_mem_root, MYF(0));
free_defaults(defaults_argv);
my_free_open_file_info();
load_processor.destroy();
@@ -2122,6 +2243,12 @@ int main(int argc, char** argv)
DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
}
+
+void *sql_alloc(size_t size)
+{
+ return alloc_root(&s_mem_root, size);
+}
+
/*
We must include this here as it's compiled with different options for
the server
@@ -2132,4 +2259,7 @@ int main(int argc, char** argv)
#include "my_decimal.cc"
#include "log_event.cc"
#include "log_event_old.cc"
+#include "sql_string.cc"
+#include "sql_list.cc"
+#include "rpl_filter.cc"
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 5e8499f739a..466de547a26 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -36,6 +36,7 @@
#include "client_priv.h"
#include <mysql_version.h>
#include <mysqld_error.h>
+#include <sql_common.h>
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -3709,13 +3710,15 @@ void do_change_user(struct st_command *command)
}
if (!ds_user.length)
+ {
dynstr_set(&ds_user, mysql->user);
- if (!ds_passwd.length)
- dynstr_set(&ds_passwd, mysql->passwd);
+ if (!ds_passwd.length)
+ dynstr_set(&ds_passwd, mysql->passwd);
- if (!ds_db.length)
- dynstr_set(&ds_db, mysql->db);
+ if (!ds_db.length)
+ dynstr_set(&ds_db, mysql->db);
+ }
DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
diff --git a/client/sql_string.cc b/client/sql_string.cc
index dc6147b563f..9fa8fae2860 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -26,15 +26,6 @@
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
-
-/*
- The following extern declarations are ok as these are interface functions
- required by the string function
-*/
-
-extern void sql_alloc(size_t size);
-extern void sql_element_free(void *ptr);
-
#include "sql_string.h"
/*****************************************************************************
diff --git a/client/sql_string.h b/client/sql_string.h
index da19c1ccfe5..0a23f9ee92f 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -15,6 +15,9 @@
/* This file is originally from the mysql distribution. Coded by monty */
+#ifndef CLIENT_SQL_STRING_H
+#define CLIENT_SQL_STRING_H
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -353,3 +356,5 @@ public:
return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
}
};
+
+#endif
diff --git a/config/ac-macros/plugins.m4 b/config/ac-macros/plugins.m4
index e05bbc48d0e..f74c4daba61 100644
--- a/config/ac-macros/plugins.m4
+++ b/config/ac-macros/plugins.m4
@@ -38,6 +38,7 @@ AC_DEFUN([_MYSQL_PLUGIN],[
_MYSQL_PLUGAPPEND([__mysql_plugin_list__],[$1])
m4_define([MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]), [$3])
m4_define([MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]), [$4])
+ m4_ifdef([_AC_ENABLE_IF], [_AC_ENABLE_IF([with],[plugin-$1])])
_MYSQL_PLUGAPPEND_META([$1], $5)
ifelse(m4_bregexp(__mysql_include__,[/plug\.in$]),-1,[],[
MYSQL_PLUGIN_DIRECTORY([$1],
@@ -459,7 +460,7 @@ dnl Although this is "pretty", it breaks libmysqld build
])
])
])
- mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ maria_plugin_defs="$maria_plugin_defs, [builtin_maria_]$2[_plugin]"
[with_plugin_]$2=yes
AC_MSG_RESULT([yes])
m4_ifdef([$11], [
diff --git a/configure.in b/configure.in
index d3a46025e5a..673146f64f9 100644
--- a/configure.in
+++ b/configure.in
@@ -12,7 +12,12 @@ dnl
dnl When changing the major version number please also check the switch
dnl statement in mysqlbinlog::check_master_version(). You may also need
dnl to update version.c in ndb.
-AC_INIT([MySQL Server], [5.1.49-MariaDB], [], [mysql])
+dnl
+dnl When merging new MySQL releases, update the version number to match the
+dnl MySQL version number.
+dnl
+dnl Note: the following line must be parseable by win/configure.js:GetVersion()
+AC_INIT([MariaDB Server], [5.2.1-MariaDB-beta], [], [mysql])
AC_CONFIG_SRCDIR([sql/mysqld.cc])
AC_CANONICAL_SYSTEM
@@ -836,7 +841,7 @@ AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \
sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h \
- sys/prctl.h sys/resource.h sys/param.h port.h ieeefp.h \
+ sys/prctl.h sys/resource.h sys/param.h port.h ieeefp.h linux/unistd.h \
execinfo.h)
AC_CHECK_HEADERS([xfs/xfs.h])
@@ -1606,9 +1611,8 @@ case "$with_mysqld_ldflags " in
;;
*)
- # Check for dlopen, needed for user definable functions
+ # Check for dlopen, needed for user definable functions and plugins
# This must be checked after threads on AIX
- # We only need this for mysqld, not for the clients.
my_save_LIBS="$LIBS"
LIBS=""
@@ -2132,7 +2136,18 @@ case "$target" in
# We also disable for SCO for the time being, the headers for the
# thread library we use conflicts with other headers.
;;
- *) AC_CHECK_FUNCS(clock_gettime)
+*)
+ # most systems require the program be linked with librt library to use
+ # the function clock_gettime
+ my_save_LIBS="$LIBS"
+ LIBS=""
+ AC_CHECK_LIB(rt,clock_gettime)
+ LIBRT=$LIBS
+ LIBS="$my_save_LIBS"
+ AC_SUBST(LIBRT)
+
+ LIBS="$LIBS $LIBRT"
+ AC_CHECK_FUNCS(clock_gettime)
;;
esac
@@ -2822,7 +2837,7 @@ then
fi
sql_client_dirs="$sql_client_dirs client"
-CLIENT_LIBS="$NON_THREADED_LIBS $openssl_libs $ZLIB_LIBS $STATIC_NSS_FLAGS"
+CLIENT_LIBS="$NON_THREADED_LIBS $openssl_libs $ZLIB_LIBS $STATIC_NSS_FLAGS $LIBRT"
AC_SUBST(CLIENT_LIBS)
AC_SUBST(CLIENT_THREAD_LIBS)
@@ -2874,7 +2889,7 @@ AC_SUBST(server_scripts)
AC_SUBST(mysql_plugin_dirs)
AC_SUBST(mysql_plugin_libs)
-AC_SUBST(mysql_plugin_defs)
+AC_SUBST(maria_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
@@ -2922,7 +2937,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/extra/libevent/epoll.c b/extra/libevent/epoll.c
index de10dac2425..7c8c60bdffa 100644
--- a/extra/libevent/epoll.c
+++ b/extra/libevent/epoll.c
@@ -155,7 +155,8 @@ epoll_init(struct event_base *base)
}
static int
-epoll_recalc(struct event_base *base, void *arg, int max)
+epoll_recalc(struct event_base *base __attribute__((unused)),
+ void *arg, int max)
{
struct epollop *epollop = arg;
diff --git a/include/Makefile.am b/include/Makefile.am
index 4d932d3159c..8a0b4610a90 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -21,8 +21,11 @@ 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 \
+ mysql/plugin_auth.h mysql/client_plugin.h \
+ mysql/plugin_auth_common.h \
decimal.h errmsg.h my_global.h my_valgrind.h my_net.h \
my_getopt.h sslopt-longopts.h my_dir.h \
sslopt-vars.h sslopt-case.h sql_common.h keycache.h \
@@ -36,12 +39,12 @@ noinst_HEADERS = config-win.h config-netware.h lf.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/generic-msvc.h \
atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \
wqueue.h waiting_threads.h
-EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp
+EXTRA_DIST = mysql.h.pp mysql/plugin_auth.h.pp mysql/client_plugin.h.pp
# Remove built files and the symlinked directories
CLEANFILES = $(BUILT_SOURCES) readline openssl
diff --git a/include/errmsg.h b/include/errmsg.h
index a6d8c770de8..94209f35a61 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -97,6 +97,7 @@ 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_AUTH_PLUGIN_CANNOT_LOAD 2058
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2058
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
diff --git a/include/keycache.h b/include/keycache.h
index 8c4ee4afe81..25a204cede2 100644
--- a/include/keycache.h
+++ b/include/keycache.h
@@ -19,96 +19,156 @@
#define _keycache_h
C_MODE_START
-/* declare structures that is used by st_key_cache */
-struct st_block_link;
-typedef struct st_block_link BLOCK_LINK;
-struct st_keycache_page;
-typedef struct st_keycache_page KEYCACHE_PAGE;
-struct st_hash_link;
-typedef struct st_hash_link HASH_LINK;
-/* info about requests in a waiting queue */
-typedef struct st_keycache_wqueue
-{
- struct st_my_thread_var *last_thread; /* circular list of waiting threads */
-} KEYCACHE_WQUEUE;
+/*
+ Currently the default key cache is created as non-partitioned at
+ the start of the server unless the server is started with the parameter
+ --key-cache-partitions that is greater than 0
+*/
+
+#define DEFAULT_KEY_CACHE_PARTITIONS 0
+
+/*
+ MAX_KEY_CACHE_PARTITIONS cannot be greater than
+ sizeof(MYISAM_SHARE::dirty_part_map)
+ Currently sizeof(MYISAM_SHARE::dirty_part_map)=sizeof(ulonglong)
+*/
-#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
+#define MAX_KEY_CACHE_PARTITIONS 64
+
+/* The structure to get statistical data about a key cache */
+
+typedef struct st_key_cache_statistics
+{
+ ulonglong mem_size; /* memory for cache buffers/auxiliary structures */
+ ulonglong block_size; /* size of the each buffers in the key cache */
+ ulonglong blocks_used; /* maximum number of used blocks/buffers */
+ ulonglong blocks_unused; /* number of currently unused blocks */
+ ulonglong blocks_changed; /* number of currently dirty blocks */
+ ulonglong read_requests; /* number of read requests (read hits) */
+ ulonglong reads; /* number of actual reads from files into buffers */
+ ulonglong write_requests; /* number of write requests (write hits) */
+ ulonglong writes; /* number of actual writes from buffers into files */
+} KEY_CACHE_STATISTICS;
+
+#define NUM_LONG_KEY_CACHE_STAT_VARIABLES 3
+
+/* The type of a key cache object */
+typedef enum key_cache_type
+{
+ SIMPLE_KEY_CACHE,
+ PARTITIONED_KEY_CACHE
+} KEY_CACHE_TYPE;
+
+
+typedef
+ int (*INIT_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ int (*RESIZE_KEY_CACHE)
+ (void *, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold);
+typedef
+ void (*CHANGE_KEY_CACHE_PARAM)
+ (void *keycache_cb,
+ uint division_limit, uint age_threshold);
+typedef
+ uchar* (*KEY_CACHE_READ)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int return_buffer);
+typedef
+ int (*KEY_CACHE_INSERT)
+ (void *keycache_cb,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length);
+typedef
+ int (*KEY_CACHE_WRITE)
+ (void *keycache_cb,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int force_write);
+typedef
+ int (*FLUSH_KEY_BLOCKS)
+ (void *keycache_cb,
+ int file, void *file_extra,
+ enum flush_type type);
+typedef
+ int (*RESET_KEY_CACHE_COUNTERS)
+ (const char *name, void *keycache_cb);
+typedef
+ void (*END_KEY_CACHE)
+ (void *keycache_cb, my_bool cleanup);
+typedef
+ void (*GET_KEY_CACHE_STATISTICS)
+ (void *keycache_cb, uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats);
+typedef
+ ulonglong (*GET_KEY_CACHE_STAT_VALUE)
+ (void *keycache_cb, uint var_no);
/*
- The key cache structure
- It also contains read-only statistics parameters.
+ An object of the type KEY_CACHE_FUNCS contains pointers to all functions
+ from the key cache interface.
+ Currently a key cache can be of two types: simple and partitioned.
+ For each of them its own static structure of the type KEY_CACHE_FUNCS is
+ defined . The structures contain the pointers to the implementations of
+ the interface functions used by simple key caches and partitioned key
+ caches respectively. Pointers to these structures are assigned to key cache
+ objects at the time of their creation.
*/
+typedef struct st_key_cache_funcs
+{
+ INIT_KEY_CACHE init;
+ RESIZE_KEY_CACHE resize;
+ CHANGE_KEY_CACHE_PARAM change_param;
+ KEY_CACHE_READ read;
+ KEY_CACHE_INSERT insert;
+ KEY_CACHE_WRITE write;
+ FLUSH_KEY_BLOCKS flush;
+ RESET_KEY_CACHE_COUNTERS reset_counters;
+ END_KEY_CACHE end;
+ GET_KEY_CACHE_STATISTICS get_stats;
+ GET_KEY_CACHE_STAT_VALUE get_stat_val;
+} KEY_CACHE_FUNCS;
+
+
typedef struct st_key_cache
{
- my_bool key_cache_inited;
- my_bool in_resize; /* true during resize operation */
- my_bool resize_in_flush; /* true during flush of resize operation */
+ KEY_CACHE_TYPE key_cache_type; /* type of the key cache used for debugging */
+ void *keycache_cb; /* control block of the used key cache */
+ KEY_CACHE_FUNCS *interface_funcs; /* interface functions of the key cache */
+ ulonglong param_buff_size; /* size the memory allocated for the cache */
+ ulong param_block_size; /* size of the blocks in the key cache */
+ ulong param_division_limit; /* min. percentage of warm blocks */
+ ulong param_age_threshold; /* determines when hot block is downgraded */
+ ulong param_partitions; /* number of the key cache partitions */
+ my_bool key_cache_inited; /* <=> key cache has been created */
my_bool can_be_used; /* usage of cache for read/write is allowed */
- size_t key_cache_mem_size; /* specified size of the cache memory */
- uint key_cache_block_size; /* size of the page buffer of a cache block */
- ulong min_warm_blocks; /* min number of warm blocks; */
- ulong age_threshold; /* age threshold for hot blocks */
- ulonglong keycache_time; /* total number of block link operations */
- uint hash_entries; /* max number of entries in the hash table */
- int hash_links; /* max number of hash links */
- int hash_links_used; /* number of hash links currently used */
- int disk_blocks; /* max number of blocks in the cache */
- ulong blocks_used; /* maximum number of concurrently used blocks */
- ulong blocks_unused; /* number of currently unused blocks */
- ulong blocks_changed; /* number of currently dirty blocks */
- ulong warm_blocks; /* number of blocks in warm sub-chain */
- ulong cnt_for_resize_op; /* counter to block resize operation */
- long blocks_available; /* number of blocks available in the LRU chain */
- HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
- HASH_LINK *hash_link_root; /* memory for hash table links */
- HASH_LINK *free_hash_list; /* list of free hash links */
- BLOCK_LINK *free_block_list; /* list of free blocks */
- BLOCK_LINK *block_root; /* memory for block links */
- uchar HUGE_PTR *block_mem; /* memory for block buffers */
- BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */
- BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */
- pthread_mutex_t cache_lock; /* to lock access to the cache structure */
- KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
- /*
- Waiting for a zero resize count. Using a queue for symmetry though
- only one thread can wait here.
- */
- KEYCACHE_WQUEUE waiting_for_resize_cnt;
- KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */
- KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
- BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/
- BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/
-
- /*
- The following variables are and variables used to hold parameters for
- initializing the key cache.
- */
-
- ulonglong param_buff_size; /* size the memory allocated for the cache */
- ulong param_block_size; /* size of the blocks in the key cache */
- ulong param_division_limit; /* min. percentage of warm blocks */
- ulong param_age_threshold; /* determines when hot block is downgraded */
-
- /* Statistics variables. These are reset in reset_key_cache_counters(). */
- ulong global_blocks_changed; /* number of currently dirty blocks */
+ my_bool in_init; /* Set to 1 in MySQL during init/resize */
+ uint partitions; /* actual number of partitions */
+ size_t key_cache_mem_size; /* specified size of the cache memory */
+ ulong blocks_used; /* maximum number of concurrently used blocks */
+ ulong blocks_unused; /* number of currently unused blocks */
+ ulong global_blocks_changed; /* number of currently dirty blocks */
ulonglong global_cache_w_requests;/* number of write requests (write hits) */
ulonglong global_cache_write; /* number of writes from cache to files */
ulonglong global_cache_r_requests;/* number of read requests (read hits) */
ulonglong global_cache_read; /* number of reads from files to cache */
-
- int blocks; /* max number of blocks in the cache */
- my_bool in_init; /* Set to 1 in MySQL during init/resize */
} KEY_CACHE;
+
/* The default key cache */
extern KEY_CACHE dflt_key_cache_var, *dflt_key_cache;
extern int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
size_t use_mem, uint division_limit,
- uint age_threshold);
+ uint age_threshold, uint partitions);
extern int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
size_t use_mem, uint division_limit,
uint age_threshold);
@@ -122,12 +182,18 @@ extern int key_cache_insert(KEY_CACHE *keycache,
File file, my_off_t filepos, int level,
uchar *buff, uint length);
extern int key_cache_write(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
uchar *buff, uint length,
- uint block_length,int force_write);
+ uint block_length, int force_write);
extern int flush_key_blocks(KEY_CACHE *keycache,
- int file, enum flush_type type);
+ int file, void *file_extra,
+ enum flush_type type);
extern void end_key_cache(KEY_CACHE *keycache, my_bool cleanup);
+extern void get_key_cache_statistics(KEY_CACHE *keycache,
+ uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats);
+extern ulonglong get_key_cache_stat_value(KEY_CACHE *keycache, uint var_no);
/* Functions to handle multiple key caches */
extern my_bool multi_keycache_init(void);
@@ -140,5 +206,11 @@ extern void multi_key_cache_change(KEY_CACHE *old_data,
KEY_CACHE *new_data);
extern int reset_key_cache_counters(const char *name,
KEY_CACHE *key_cache);
+extern int repartition_key_cache(KEY_CACHE *keycache,
+ uint key_cache_block_size,
+ size_t use_mem,
+ uint division_limit,
+ uint age_threshold,
+ uint partitions);
C_MODE_END
#endif /* _keycache_h */
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 6229a82ee9c..c2551b5d309 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -38,16 +38,23 @@ extern "C" {
#define my_wc_t ulong
-typedef struct unicase_info_st
+typedef const struct charset_info_st CHARSET_INFO;
+typedef const struct my_charset_handler_st MY_CHARSET_HANDLER;
+typedef const struct my_collation_handler_st MY_COLLATION_HANDLER;
+
+typedef const struct unicase_info_st MY_UNICASE_INFO;
+typedef const struct uni_ctype_st MY_UNI_CTYPE;
+typedef const struct my_uni_idx_st MY_UNI_IDX;
+
+struct unicase_info_st
{
uint16 toupper;
uint16 tolower;
uint16 sort;
-} MY_UNICASE_INFO;
-
+};
-extern MY_UNICASE_INFO *my_unicase_default[256];
-extern MY_UNICASE_INFO *my_unicase_turkish[256];
+extern MY_UNICASE_INFO *const my_unicase_default[256];
+extern MY_UNICASE_INFO *const my_unicase_turkish[256];
#define MY_UCA_MAX_CONTRACTION 4
#define MY_UCA_MAX_WEIGHT_SIZE 8
@@ -67,11 +74,11 @@ typedef struct my_contraction_list_t
} MY_CONTRACTIONS;
-typedef struct uni_ctype_st
+struct uni_ctype_st
{
uchar pctype;
- uchar *ctype;
-} MY_UNI_CTYPE;
+ const uchar *ctype;
+};
extern MY_UNI_CTYPE my_uni_ctype[256];
@@ -114,12 +121,12 @@ extern MY_UNI_CTYPE my_uni_ctype[256];
#define MY_REPERTOIRE_UNICODE30 3 /* ASCII | EXTENDED: U+0000..U+FFFF */
-typedef struct my_uni_idx_st
+struct my_uni_idx_st
{
uint16 from;
uint16 to;
- uchar *tab;
-} MY_UNI_IDX;
+ const uchar *tab;
+};
typedef struct
{
@@ -148,41 +155,41 @@ struct charset_info_st;
/* See strings/CHARSET_INFO.txt for information about this structure */
-typedef struct my_collation_handler_st
+struct my_collation_handler_st
{
my_bool (*init)(struct charset_info_st *, void *(*alloc)(size_t));
/* Collation routines */
- int (*strnncoll)(struct charset_info_st *,
+ int (*strnncoll)(CHARSET_INFO *,
const uchar *, size_t, const uchar *, size_t, my_bool);
- int (*strnncollsp)(struct charset_info_st *,
+ int (*strnncollsp)(CHARSET_INFO *,
const uchar *, size_t, const uchar *, size_t,
my_bool diff_if_only_endspace_difference);
- size_t (*strnxfrm)(struct charset_info_st *,
+ size_t (*strnxfrm)(CHARSET_INFO *,
uchar *, size_t, const uchar *, size_t);
- size_t (*strnxfrmlen)(struct charset_info_st *, size_t);
- my_bool (*like_range)(struct charset_info_st *,
+ size_t (*strnxfrmlen)(CHARSET_INFO *, size_t);
+ my_bool (*like_range)(CHARSET_INFO *,
const char *s, size_t s_length,
pchar w_prefix, pchar w_one, pchar w_many,
size_t res_length,
char *min_str, char *max_str,
size_t *min_len, size_t *max_len);
- int (*wildcmp)(struct charset_info_st *,
+ int (*wildcmp)(CHARSET_INFO *,
const char *str,const char *str_end,
const char *wildstr,const char *wildend,
int escape,int w_one, int w_many);
- int (*strcasecmp)(struct charset_info_st *, const char *, const char *);
+ int (*strcasecmp)(CHARSET_INFO *, const char *, const char *);
- uint (*instr)(struct charset_info_st *,
+ uint (*instr)(CHARSET_INFO *,
const char *b, size_t b_length,
const char *s, size_t s_length,
my_match_t *match, uint nmatch);
/* Hash calculation */
- void (*hash_sort)(struct charset_info_st *cs, const uchar *key, size_t len,
+ void (*hash_sort)(CHARSET_INFO *cs, const uchar *key, size_t len,
ulong *nr1, ulong *nr2);
- my_bool (*propagate)(struct charset_info_st *cs, const uchar *str, size_t len);
-} MY_COLLATION_HANDLER;
+ my_bool (*propagate)(CHARSET_INFO *cs, const uchar *str, size_t len);
+};
extern MY_COLLATION_HANDLER my_collation_mb_bin_handler;
extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler;
@@ -190,83 +197,83 @@ extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler;
extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler;
/* Some typedef to make it easy for C++ to make function pointers */
-typedef int (*my_charset_conv_mb_wc)(struct charset_info_st *, my_wc_t *,
+typedef int (*my_charset_conv_mb_wc)(CHARSET_INFO *, my_wc_t *,
const uchar *, const uchar *);
-typedef int (*my_charset_conv_wc_mb)(struct charset_info_st *, my_wc_t,
+typedef int (*my_charset_conv_wc_mb)(CHARSET_INFO *, my_wc_t,
uchar *, uchar *);
-typedef size_t (*my_charset_conv_case)(struct charset_info_st *,
+typedef size_t (*my_charset_conv_case)(CHARSET_INFO *,
char *, size_t, char *, size_t);
/* See strings/CHARSET_INFO.txt about information on this structure */
-typedef struct my_charset_handler_st
+struct my_charset_handler_st
{
my_bool (*init)(struct charset_info_st *, void *(*alloc)(size_t));
/* Multibyte routines */
- uint (*ismbchar)(struct charset_info_st *, const char *, const char *);
- uint (*mbcharlen)(struct charset_info_st *, uint c);
- size_t (*numchars)(struct charset_info_st *, const char *b, const char *e);
- size_t (*charpos)(struct charset_info_st *, const char *b, const char *e,
+ uint (*ismbchar)(CHARSET_INFO *, const char *, const char *);
+ uint (*mbcharlen)(CHARSET_INFO *, uint c);
+ size_t (*numchars)(CHARSET_INFO *, const char *b, const char *e);
+ size_t (*charpos)(CHARSET_INFO *, const char *b, const char *e,
size_t pos);
- size_t (*well_formed_len)(struct charset_info_st *,
+ size_t (*well_formed_len)(CHARSET_INFO *,
const char *b,const char *e,
size_t nchars, int *error);
- size_t (*lengthsp)(struct charset_info_st *, const char *ptr, size_t length);
- size_t (*numcells)(struct charset_info_st *, const char *b, const char *e);
+ size_t (*lengthsp)(CHARSET_INFO *, const char *ptr, size_t length);
+ size_t (*numcells)(CHARSET_INFO *, const char *b, const char *e);
/* Unicode conversion */
my_charset_conv_mb_wc mb_wc;
my_charset_conv_wc_mb wc_mb;
/* CTYPE scanner */
- int (*ctype)(struct charset_info_st *cs, int *ctype,
+ int (*ctype)(CHARSET_INFO *cs, int *ctype,
const uchar *s, const uchar *e);
/* Functions for case and sort conversion */
- size_t (*caseup_str)(struct charset_info_st *, char *);
- size_t (*casedn_str)(struct charset_info_st *, char *);
+ size_t (*caseup_str)(CHARSET_INFO *, char *);
+ size_t (*casedn_str)(CHARSET_INFO *, char *);
my_charset_conv_case caseup;
my_charset_conv_case casedn;
/* Charset dependant snprintf() */
- size_t (*snprintf)(struct charset_info_st *, char *to, size_t n,
+ size_t (*snprintf)(CHARSET_INFO *, char *to, size_t n,
const char *fmt,
...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5);
- size_t (*long10_to_str)(struct charset_info_st *, char *to, size_t n,
+ size_t (*long10_to_str)(CHARSET_INFO *, char *to, size_t n,
int radix, long int val);
- size_t (*longlong10_to_str)(struct charset_info_st *, char *to, size_t n,
+ size_t (*longlong10_to_str)(CHARSET_INFO *, char *to, size_t n,
int radix, longlong val);
- void (*fill)(struct charset_info_st *, char *to, size_t len, int fill);
+ void (*fill)(CHARSET_INFO *, char *to, size_t len, int fill);
/* String-to-number conversion routines */
- long (*strntol)(struct charset_info_st *, const char *s, size_t l,
+ long (*strntol)(CHARSET_INFO *, const char *s, size_t l,
int base, char **e, int *err);
- ulong (*strntoul)(struct charset_info_st *, const char *s, size_t l,
+ ulong (*strntoul)(CHARSET_INFO *, const char *s, size_t l,
int base, char **e, int *err);
- longlong (*strntoll)(struct charset_info_st *, const char *s, size_t l,
+ longlong (*strntoll)(CHARSET_INFO *, const char *s, size_t l,
int base, char **e, int *err);
- ulonglong (*strntoull)(struct charset_info_st *, const char *s, size_t l,
+ ulonglong (*strntoull)(CHARSET_INFO *, const char *s, size_t l,
int base, char **e, int *err);
- double (*strntod)(struct charset_info_st *, char *s, size_t l, char **e,
+ double (*strntod)(CHARSET_INFO *, char *s, size_t l, char **e,
int *err);
- longlong (*strtoll10)(struct charset_info_st *cs,
+ longlong (*strtoll10)(CHARSET_INFO *cs,
const char *nptr, char **endptr, int *error);
- ulonglong (*strntoull10rnd)(struct charset_info_st *cs,
+ ulonglong (*strntoull10rnd)(CHARSET_INFO *cs,
const char *str, size_t length,
int unsigned_fl,
char **endptr, int *error);
- size_t (*scan)(struct charset_info_st *, const char *b, const char *e,
+ size_t (*scan)(CHARSET_INFO *, const char *b, const char *e,
int sq);
-} MY_CHARSET_HANDLER;
+};
extern MY_CHARSET_HANDLER my_charset_8bit_handler;
extern MY_CHARSET_HANDLER my_charset_ucs2_handler;
/* See strings/CHARSET_INFO.txt about information on this structure */
-typedef struct charset_info_st
+struct charset_info_st
{
uint number;
uint primary_number;
@@ -276,17 +283,17 @@ typedef struct charset_info_st
const char *name;
const char *comment;
const char *tailoring;
- uchar *ctype;
- uchar *to_lower;
- uchar *to_upper;
- uchar *sort_order;
- MY_CONTRACTIONS *contractions;
- uint16 **sort_order_big;
- uint16 *tab_to_uni;
- MY_UNI_IDX *tab_from_uni;
- MY_UNICASE_INFO **caseinfo;
- uchar *state_map;
- uchar *ident_map;
+ const uchar *ctype;
+ const uchar *to_lower;
+ const uchar *to_upper;
+ const uchar *sort_order;
+ const MY_CONTRACTIONS *contractions;
+ const uint16 *const *sort_order_big;
+ const uint16 *tab_to_uni;
+ MY_UNI_IDX *tab_from_uni;
+ MY_UNICASE_INFO *const *caseinfo;
+ const uchar *state_map;
+ const uchar *ident_map;
uint strxfrm_multiply;
uchar caseup_multiply;
uchar casedn_multiply;
@@ -300,41 +307,41 @@ typedef struct charset_info_st
MY_CHARSET_HANDLER *cset;
MY_COLLATION_HANDLER *coll;
-} CHARSET_INFO;
+};
#define ILLEGAL_CHARSET_INFO_NUMBER (~0U)
-
-extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_bin;
-extern CHARSET_INFO my_charset_big5_chinese_ci;
-extern CHARSET_INFO my_charset_big5_bin;
-extern CHARSET_INFO my_charset_cp932_japanese_ci;
-extern CHARSET_INFO my_charset_cp932_bin;
-extern CHARSET_INFO my_charset_eucjpms_japanese_ci;
-extern CHARSET_INFO my_charset_eucjpms_bin;
-extern CHARSET_INFO my_charset_euckr_korean_ci;
-extern CHARSET_INFO my_charset_euckr_bin;
-extern CHARSET_INFO my_charset_gb2312_chinese_ci;
-extern CHARSET_INFO my_charset_gb2312_bin;
-extern CHARSET_INFO my_charset_gbk_chinese_ci;
-extern CHARSET_INFO my_charset_gbk_bin;
-extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_latin1;
-extern CHARSET_INFO my_charset_latin1_german2_ci;
-extern CHARSET_INFO my_charset_latin1_bin;
-extern CHARSET_INFO my_charset_latin2_czech_ci;
-extern CHARSET_INFO my_charset_sjis_japanese_ci;
-extern CHARSET_INFO my_charset_sjis_bin;
-extern CHARSET_INFO my_charset_tis620_thai_ci;
-extern CHARSET_INFO my_charset_tis620_bin;
-extern CHARSET_INFO my_charset_ucs2_general_ci;
-extern CHARSET_INFO my_charset_ucs2_bin;
-extern CHARSET_INFO my_charset_ucs2_unicode_ci;
-extern CHARSET_INFO my_charset_ujis_japanese_ci;
-extern CHARSET_INFO my_charset_ujis_bin;
-extern CHARSET_INFO my_charset_utf8_general_ci;
-extern CHARSET_INFO my_charset_utf8_unicode_ci;
-extern CHARSET_INFO my_charset_utf8_bin;
-extern CHARSET_INFO my_charset_cp1250_czech_ci;
-extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_filename;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_bin;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_latin1;
+extern MYSQL_PLUGIN_IMPORT struct charset_info_st my_charset_filename;
+
+extern struct charset_info_st my_charset_big5_chinese_ci;
+extern struct charset_info_st my_charset_big5_bin;
+extern struct charset_info_st my_charset_cp932_japanese_ci;
+extern struct charset_info_st my_charset_cp932_bin;
+extern struct charset_info_st my_charset_eucjpms_japanese_ci;
+extern struct charset_info_st my_charset_eucjpms_bin;
+extern struct charset_info_st my_charset_euckr_korean_ci;
+extern struct charset_info_st my_charset_euckr_bin;
+extern struct charset_info_st my_charset_gb2312_chinese_ci;
+extern struct charset_info_st my_charset_gb2312_bin;
+extern struct charset_info_st my_charset_gbk_chinese_ci;
+extern struct charset_info_st my_charset_gbk_bin;
+extern struct charset_info_st my_charset_latin1_german2_ci;
+extern struct charset_info_st my_charset_latin1_bin;
+extern struct charset_info_st my_charset_latin2_czech_ci;
+extern struct charset_info_st my_charset_sjis_japanese_ci;
+extern struct charset_info_st my_charset_sjis_bin;
+extern struct charset_info_st my_charset_tis620_thai_ci;
+extern struct charset_info_st my_charset_tis620_bin;
+extern struct charset_info_st my_charset_ucs2_general_ci;
+extern struct charset_info_st my_charset_ucs2_bin;
+extern struct charset_info_st my_charset_ucs2_unicode_ci;
+extern struct charset_info_st my_charset_ujis_japanese_ci;
+extern struct charset_info_st my_charset_ujis_bin;
+extern struct charset_info_st my_charset_utf8_general_ci;
+extern struct charset_info_st my_charset_utf8_unicode_ci;
+extern struct charset_info_st my_charset_utf8_bin;
+extern struct charset_info_st my_charset_cp1250_czech_ci;
/* declarations for simple charsets */
extern size_t my_strnxfrm_simple(CHARSET_INFO *, uchar *, size_t,
@@ -353,7 +360,7 @@ extern void my_hash_sort_simple(CHARSET_INFO *cs,
extern size_t my_lengthsp_8bit(CHARSET_INFO *cs, const char *ptr, size_t length);
-extern uint my_instr_simple(struct charset_info_st *,
+extern uint my_instr_simple(CHARSET_INFO *,
const char *b, size_t b_length,
const char *s, size_t s_length,
my_match_t *match, uint nmatch);
@@ -377,7 +384,7 @@ int my_mb_ctype_mb(CHARSET_INFO *,int *, const uchar *,const uchar *);
size_t my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq);
-size_t my_snprintf_8bit(struct charset_info_st *, char *to, size_t n,
+size_t my_snprintf_8bit(CHARSET_INFO *, char *to, size_t n,
const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 4, 5);
@@ -468,7 +475,7 @@ size_t my_numcells_mb(CHARSET_INFO *, const char *b, const char *e);
size_t my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, size_t pos);
size_t my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e,
size_t pos, int *error);
-uint my_instr_mb(struct charset_info_st *,
+uint my_instr_mb(CHARSET_INFO *,
const char *b, size_t b_length,
const char *s, size_t s_length,
my_match_t *match, uint nmatch);
@@ -477,10 +484,10 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
const char *str, const char *str_end,
const char *wildstr, const char *wildend,
int escape, int w_one, int w_many,
- MY_UNICASE_INFO **weights);
+ MY_UNICASE_INFO *const *weights);
extern my_bool my_parse_charset_xml(const char *bug, size_t len,
- int (*add)(CHARSET_INFO *cs));
+ int (*add)(struct charset_info_st *cs));
extern char *my_strchr(CHARSET_INFO *cs, const char *str, const char *end,
pchar c);
@@ -496,9 +503,8 @@ uint my_charset_repertoire(CHARSET_INFO *cs);
my_bool my_uca_have_contractions(CHARSET_INFO *cs);
my_bool my_uca_can_be_contraction_head(CHARSET_INFO *cs, my_wc_t wc);
my_bool my_uca_can_be_contraction_tail(CHARSET_INFO *cs, my_wc_t wc);
-uint16 *my_uca_contraction2_weight(CHARSET_INFO *cs, my_wc_t wc1, my_wc_t wc2);
-
-
+const uint16 *my_uca_contraction2_weight(CHARSET_INFO *cs, my_wc_t wc1,
+ my_wc_t wc2);
#define _MY_U 01 /* Upper case */
diff --git a/include/m_string.h b/include/m_string.h
index 6af7c7f9fa2..31719781a48 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -89,8 +89,8 @@ extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */
#endif
/* Declared in int2str() */
-extern char NEAR _dig_vec_upper[];
-extern char NEAR _dig_vec_lower[];
+extern const char NEAR _dig_vec_upper[];
+extern const char NEAR _dig_vec_lower[];
/* Defined in strtod.c */
extern const double log_10[309];
@@ -245,16 +245,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 00a13f28f57..8065441d4d7 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -272,17 +272,6 @@ enum ha_base_keytype {
#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */
#define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
-#if MYSQL_VERSION_ID < 50200
-/*
- Key has a part that can have end space. If this is an unique key
- we have to handle it differently from other unique keys as we can find
- many matching rows for one key (because end space are not compared)
-*/
-#define HA_END_SPACE_KEY 0 /* was: 4096 */
-#else
-#error HA_END_SPACE_KEY is obsolete, please remove it
-#endif
-
/* These flags can be added to key-seg-flag */
@@ -300,6 +289,7 @@ enum ha_base_keytype {
*/
#define HA_END_SPACE_ARE_EQUAL 512
#define HA_BIT_PART 1024
+#define HA_CAN_MEMCMP 2048 /* internal, never stored in frm */
/* optionbits for database */
#define HA_OPTION_PACK_RECORD 1
@@ -314,6 +304,8 @@ enum ha_base_keytype {
#define HA_OPTION_RELIES_ON_SQL_LAYER 512
#define HA_OPTION_NULL_FIELDS 1024
#define HA_OPTION_PAGE_CHECKSUM 2048
+/* .frm has extra create options in linked-list format */
+#define HA_OPTION_TEXT_CREATE_OPTIONS (1L << 14)
#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */
#define HA_OPTION_READ_ONLY_DATA (1L << 16) /* Set by isamchk */
#define HA_OPTION_NO_CHECKSUM (1L << 17)
diff --git a/include/my_global.h b/include/my_global.h
index b4579248dfa..6add808ed55 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -581,6 +581,14 @@ int __void__;
#define VALGRIND_OR_LINT_INIT(var)
#endif
+#ifdef _WIN32
+#define SO_EXT ".dll"
+#elif defined(__APPLE__)
+#define SO_EXT ".dylib"
+#else
+#define SO_EXT ".so"
+#endif
+
/*
Suppress uninitialized variable warning without generating code.
@@ -1517,6 +1525,9 @@ do { doubleget_union _tmp; \
#elif defined(HAVE_DLFCN_H)
#include <dlfcn.h>
#endif
+#ifndef HAVE_DLERROR
+#define dlerror() ""
+#endif
#endif
/* FreeBSD 2.2.2 does not define RTLD_NOW) */
@@ -1524,11 +1535,13 @@ do { doubleget_union _tmp; \
#define RTLD_NOW 1
#endif
-#ifndef HAVE_DLERROR
-#define dlerror() ""
+#ifndef HAVE_DLOPEN
+#define dlerror() "No support for dynamic loading (static build?)"
+#define dlopen(A,B) 0
+#define dlsym(A,B) 0
+#define dlclose(A) 0
#endif
-
#ifndef __NETWARE__
/*
* Include standard definitions of operator new and delete.
diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h
index 511fac407d5..ca3fbe2d13b 100644
--- a/include/my_no_pthread.h
+++ b/include/my_no_pthread.h
@@ -46,6 +46,7 @@
#define rw_wrlock(A)
#define rw_unlock(A)
#define rwlock_destroy(A)
+#define safe_mutex_assert_owner(mp)
typedef int my_pthread_once_t;
#define MY_PTHREAD_ONCE_INIT 0
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 9b01146cdde..ee5a77f0216 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -128,7 +128,9 @@ struct tm *gmtime_r(const time_t *timep,struct tm *tmp);
void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
-#define ETIMEDOUT 145 /* Win32 doesn't have this */
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 145
+#endif
#define getpid() GetCurrentThreadId()
#define HAVE_LOCALTIME_R 1
#define _REENTRANT 1
diff --git a/include/my_sys.h b/include/my_sys.h
index c5b3008e8bc..81917c48acd 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -206,10 +206,14 @@ extern void my_large_free(uchar * ptr, myf my_flags);
#define alloca __builtin_alloca
#endif /* GNUC */
#define my_alloca(SZ) alloca((size_t) (SZ))
-#define my_afree(PTR) {}
+#define my_afree(PTR) ((void)0)
+#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(MY_FAE)))
+#define my_safe_afree(ptr, size, min_length) ((size <= min_length) ? (void)0 : my_free(ptr,MYF(MY_WME)))
#else
-#define my_alloca(SZ) my_malloc(SZ,MYF(0))
+#define my_alloca(SZ) my_malloc(SZ,MYF(MY_FAE))
#define my_afree(PTR) my_free(PTR,MYF(MY_WME))
+#define my_safe_alloca(size, min_length) my_alloca(size)
+#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
#endif /* HAVE_ALLOCA */
#ifndef errno /* did we already get it? */
@@ -240,7 +244,7 @@ extern uint my_large_page_size;
/* charsets */
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *default_charset_info;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *all_charsets[256];
-extern CHARSET_INFO compiled_charsets[];
+extern struct charset_info_st compiled_charsets[];
/* statistics */
extern ulong my_file_opened,my_stream_opened, my_tmp_file_created;
@@ -868,6 +872,10 @@ extern void set_prealloc_root(MEM_ROOT *root, char *ptr);
extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
size_t prealloc_size);
extern char *strdup_root(MEM_ROOT *root,const char *str);
+static inline char *safe_strdup_root(MEM_ROOT *root, const char *str)
+{
+ return str ? strdup_root(root, str) : 0;
+}
extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len);
extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len);
extern int get_defaults_options(int argc, char **argv,
@@ -913,6 +921,7 @@ void my_free_open_file_info(void);
extern time_t my_time(myf flags);
extern ulonglong my_getsystime(void);
+extern ulonglong my_getcputime(void);
extern ulonglong my_micro_time();
extern ulonglong my_micro_time_and_time(time_t *time_arg);
time_t my_time_possible_from_micro(ulonglong microtime);
@@ -1000,7 +1009,7 @@ extern void free_charsets(void);
extern char *get_charsets_dir(char *buf);
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
extern my_bool init_compiled_charsets(myf flags);
-extern void add_compiled_collation(CHARSET_INFO *cs);
+extern void add_compiled_collation(struct charset_info_st *cs);
extern size_t escape_string_for_mysql(CHARSET_INFO *charset_info,
char *to, size_t to_length,
const char *from, size_t length);
diff --git a/include/mysql.h b/include/mysql.h
index 074098aef1b..52475dbc0dd 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -167,9 +167,15 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
};
+/**
+ @todo remove the "extension", move st_mysql_options completely
+ out of mysql.h
+*/
+struct st_mysql_options_extention;
+
struct st_mysql_options {
unsigned int connect_timeout, read_timeout, write_timeout;
unsigned int port, protocol;
@@ -217,7 +223,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
- void *extension;
+ struct st_mysql_options_extention *extension;
};
enum mysql_status
@@ -261,7 +267,7 @@ typedef struct st_mysql
unsigned char *connector_fd; /* ConnectorFd for SSL */
char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
char *info, *db;
- struct charset_info_st *charset;
+ const struct charset_info_st *charset;
MYSQL_FIELD *fields;
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
@@ -752,38 +758,6 @@ enum enum_stmt_attr_type
};
-typedef struct st_mysql_methods
-{
- my_bool (*read_query_result)(MYSQL *mysql);
- my_bool (*advanced_command)(MYSQL *mysql,
- enum enum_server_command command,
- const unsigned char *header,
- unsigned long header_length,
- const unsigned char *arg,
- unsigned long arg_length,
- my_bool skip_check,
- MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields);
- 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);
-#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
- MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
- my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
- int (*stmt_execute)(MYSQL_STMT *stmt);
- int (*read_binary_rows)(MYSQL_STMT *stmt);
- int (*unbuffered_fetch)(MYSQL *mysql, char **row);
- void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistics)(MYSQL *mysql);
- my_bool (*next_result)(MYSQL *mysql);
- int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
- int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
-#endif
-} MYSQL_METHODS;
-
-
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
@@ -846,18 +820,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
#endif
#define HAVE_MYSQL_REAL_CONNECT
-/*
- The following functions are mainly exported because of mysqlbinlog;
- They are not for general usage
-*/
-
-#define simple_command(mysql, command, arg, length, skip_check) \
- (*(mysql)->methods->advanced_command)(mysql, command, 0, \
- 0, arg, length, skip_check, NULL)
-#define stmt_command(mysql, command, arg, length, stmt) \
- (*(mysql)->methods->advanced_command)(mysql, command, 0, \
- 0, arg, length, 1, stmt)
-
#ifdef __NETWARE__
#pragma pack(pop) /* restore alignment */
#endif
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 3fb232cea51..88a2dce1555 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -128,13 +128,13 @@ void create_random_string(char *to, unsigned int length,
void hash_password(unsigned long *to, const char *password, unsigned int password_len);
void make_scrambled_password_323(char *to, const char *password);
void scramble_323(char *to, const char *message, const char *password);
-my_bool check_scramble_323(const char *, const char *message,
+my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
-my_bool check_scramble(const char *reply, const char *message,
+my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
@@ -258,8 +258,9 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
};
+struct st_mysql_options_extention;
struct st_mysql_options {
unsigned int connect_timeout, read_timeout, write_timeout;
unsigned int port, protocol;
@@ -289,7 +290,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
- void *extension;
+ struct st_mysql_options_extention *extension;
};
enum mysql_status
{
@@ -323,7 +324,7 @@ typedef struct st_mysql
unsigned char *connector_fd;
char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
char *info, *db;
- struct charset_info_st *charset;
+ const struct charset_info_st *charset;
MYSQL_FIELD *fields;
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
@@ -601,34 +602,6 @@ enum enum_stmt_attr_type
STMT_ATTR_CURSOR_TYPE,
STMT_ATTR_PREFETCH_ROWS
};
-typedef struct st_mysql_methods
-{
- my_bool (*read_query_result)(MYSQL *mysql);
- my_bool (*advanced_command)(MYSQL *mysql,
- enum enum_server_command command,
- const unsigned char *header,
- unsigned long header_length,
- const unsigned char *arg,
- unsigned long arg_length,
- my_bool skip_check,
- MYSQL_STMT *stmt);
- MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
- unsigned int fields);
- 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);
- MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
- my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
- int (*stmt_execute)(MYSQL_STMT *stmt);
- int (*read_binary_rows)(MYSQL_STMT *stmt);
- int (*unbuffered_fetch)(MYSQL *mysql, char **row);
- void (*free_embedded_thd)(MYSQL *mysql);
- const char *(*read_statistics)(MYSQL *mysql);
- my_bool (*next_result)(MYSQL *mysql);
- int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
- int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
-} MYSQL_METHODS;
MYSQL_STMT * mysql_stmt_init(MYSQL *mysql);
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
diff --git a/include/mysql/client_plugin.h b/include/mysql/client_plugin.h
new file mode 100644
index 00000000000..5e9a337dfc6
--- /dev/null
+++ b/include/mysql/client_plugin.h
@@ -0,0 +1,164 @@
+#ifndef MYSQL_CLIENT_PLUGIN_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program 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 */
+
+/**
+ @file
+
+ MySQL Client Plugin API
+
+ This file defines the API for plugins that work on the client side
+*/
+#define MYSQL_CLIENT_PLUGIN_INCLUDED
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* known plugin types */
+#define MYSQL_CLIENT_reserved1 0
+#define MYSQL_CLIENT_reserved2 1
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2
+
+#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
+
+#define MYSQL_CLIENT_MAX_PLUGINS 3
+
+#define mysql_declare_client_plugin(X) \
+ struct st_mysql_client_plugin_ ## X \
+ _mysql_client_plugin_declaration_ = { \
+ MYSQL_CLIENT_ ## X ## _PLUGIN, \
+ MYSQL_CLIENT_ ## X ## _PLUGIN_INTERFACE_VERSION,
+#define mysql_end_client_plugin }
+
+/* generic plugin header structure */
+#define MYSQL_CLIENT_PLUGIN_HEADER \
+ int type; \
+ unsigned int interface_version; \
+ const char *name; \
+ const char *author; \
+ const char *desc; \
+ unsigned int version[3]; \
+ int (*init)(char *, size_t, int, va_list); \
+ int (*deinit)();
+
+struct st_mysql_client_plugin
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+};
+
+struct st_mysql;
+
+/******** authentication plugin specific declarations *********/
+#include <mysql/plugin_auth_common.h>
+
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ MYSQL_CLIENT_PLUGIN_HEADER
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+
+/**
+ type of the mysql_authentication_dialog_ask function
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - ordinary string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+/******** using plugins ************/
+
+/**
+ loads a plugin and initializes it
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param ... arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+
+/**
+ loads a plugin and initializes it, taking va_list as an argument
+
+ This is the same as mysql_load_plugin, but take va_list instead of
+ a list of arguments.
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded, -1 to disable type check
+ @param argc number of arguments to pass to the plugin initialization
+ function
+ @param args arguments for the plugin initialization function
+
+ @retval
+ a pointer to the loaded plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+
+/**
+ finds an already loaded plugin by name, or loads it, if necessary
+
+ @param mysql MYSQL structure. only MYSQL_PLUGIN_DIR option value is used,
+ and last_errno/last_error, for error reporting
+ @param name a name of the plugin to load
+ @param type type of plugin that should be loaded
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+
+/**
+ adds a plugin structure to the list of loaded plugins
+
+ This is useful if an application has the necessary functionality
+ (for example, a special load data handler) statically linked into
+ the application binary. It can use this function to register the plugin
+ directly, avoiding the need to factor it out into a shared object.
+
+ @param mysql MYSQL structure. It is only used for error reporting
+ @param plugin an st_mysql_client_plugin structure to register
+
+ @retval
+ a pointer to the plugin, or NULL in case of a failure
+*/
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
+
+#endif
+
diff --git a/include/mysql/client_plugin.h.pp b/include/mysql/client_plugin.h.pp
new file mode 100644
index 00000000000..20d353422dd
--- /dev/null
+++ b/include/mysql/client_plugin.h.pp
@@ -0,0 +1,41 @@
+#include <stdarg.h>
+#include <stdlib.h>
+struct st_mysql_client_plugin
+{
+ int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; int (*init)(char *, size_t, int, va_list); int (*deinit)();
+};
+struct st_mysql;
+#include <mysql/plugin_auth_common.h>
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket;
+} MYSQL_PLUGIN_VIO_INFO;
+typedef struct st_plugin_vio
+{
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+} MYSQL_PLUGIN_VIO;
+struct st_mysql_client_plugin_AUTHENTICATION
+{
+ int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; int (*init)(char *, size_t, int, va_list); int (*deinit)();
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
+};
+typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
+ int type, const char *prompt, char *buf, int buf_len);
+struct st_mysql_client_plugin *
+mysql_load_plugin(struct st_mysql *mysql, const char *name, int type,
+ int argc, ...);
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type,
+ int argc, va_list args);
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(struct st_mysql *mysql,
+ struct st_mysql_client_plugin *plugin);
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index e1852f2929e..ad3427a3ab5 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
@@ -34,15 +34,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
/**
@@ -65,7 +57,10 @@ typedef struct st_mysql_xid MYSQL_XID;
Plugin API. Common for all plugin types.
*/
-#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0100
+/* MySQL plugin interface version */
+#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
+/* MariaDB plugin interface version */
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x0100
/*
The allowable types of plugins
@@ -75,7 +70,10 @@ typedef struct st_mysql_xid MYSQL_XID;
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */
#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */
-#define MYSQL_MAX_PLUGIN_TYPE_NUM 5 /* The number of plugin types */
+#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */
+#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */
+#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */
+#define MYSQL_MAX_PLUGIN_TYPE_NUM 8 /* The number of plugin types */
/* We use the following strings to define licenses for plugins */
#define PLUGIN_LICENSE_PROPRIETARY 0
@@ -86,6 +84,14 @@ typedef struct st_mysql_xid MYSQL_XID;
#define PLUGIN_LICENSE_GPL_STRING "GPL"
#define PLUGIN_LICENSE_BSD_STRING "BSD"
+/* definitions of code maturity for plugins */
+#define MariaDB_PLUGIN_MATURITY_UNKNOWN 0
+#define MariaDB_PLUGIN_MATURITY_EXPERIMENTAL 1
+#define MariaDB_PLUGIN_MATURITY_ALPHA 2
+#define MariaDB_PLUGIN_MATURITY_BETA 3
+#define MariaDB_PLUGIN_MATURITY_GAMMA 4
+#define MariaDB_PLUGIN_MATURITY_STABLE 5
+
/*
Macros for beginning and ending plugin declarations. Between
mysql_declare_plugin and mysql_declare_plugin_end there should
@@ -98,11 +104,24 @@ typedef struct st_mysql_xid MYSQL_XID;
int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
int PSIZE= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin DECLS[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MARIA_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_maria_plugin); \
+struct st_maria_plugin DECLS[]= {
+
#else
+
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+
+#define MARIA_DECLARE_PLUGIN__(NAME, VERSION, PSIZE, DECLS) \
+MYSQL_PLUGIN_EXPORT int _maria_plugin_interface_version_= MARIA_PLUGIN_INTERFACE_VERSION; \
+MYSQL_PLUGIN_EXPORT int _maria_sizeof_struct_st_plugin_= sizeof(struct st_maria_plugin); \
+MYSQL_PLUGIN_EXPORT struct st_maria_plugin _maria_plugin_declarations_[]= {
+
#endif
#define mysql_declare_plugin(NAME) \
@@ -111,7 +130,14 @@ __MYSQL_DECLARE_PLUGIN(NAME, \
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
builtin_ ## NAME ## _plugin)
+#define maria_declare_plugin(NAME) \
+MARIA_DECLARE_PLUGIN__(NAME, \
+ builtin_maria_ ## NAME ## _plugin_interface_version, \
+ builtin_maria_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_maria_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0}}
+#define maria_declare_plugin_end ,{0,0,0,0,0,0,0,0,0,0,0,0,0}}
/*
declarations for SHOW STATUS support in plugins
@@ -120,7 +146,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 {
@@ -407,6 +434,30 @@ struct st_mysql_plugin
void * __reserved1; /* reserved for dependency checking */
};
+/*
+ MariaDB extension for plugins declaration structure.
+
+ It also copy current MySQL plugin fields to have more independency
+ in plugins extension
+*/
+
+struct st_maria_plugin
+{
+ int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ void *info; /* pointer to type-specific plugin descriptor */
+ const char *name; /* plugin name */
+ const char *author; /* plugin author (for SHOW PLUGINS) */
+ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
+ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
+ int (*init)(void *); /* the function to invoke when plugin is loaded */
+ int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
+ unsigned int version; /* plugin version (for SHOW PLUGINS) */
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info; /* plugin version string */
+ unsigned int maturity; /* MariaDB_PLUGIN_MATURITY_XXX */
+};
+
/*************************************************************************
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
*/
@@ -576,7 +627,7 @@ typedef struct st_mysql_ftparser_param
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
void *ftparser_state;
void *mysql_ftparam;
- struct charset_info_st *cs;
+ const struct charset_info_st *cs;
const unsigned char *doc;
mysql_ft_size_t length;
unsigned int flags;
@@ -739,54 +790,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
diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h
new file mode 100644
index 00000000000..2b84a6c73af
--- /dev/null
+++ b/include/mysql/plugin_auth.h
@@ -0,0 +1,83 @@
+#ifndef MYSQL_PLUGIN_AUTH_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program 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 */
+
+/**
+ @file
+
+ Authentication Plugin API.
+
+ This file defines the API for server authentication plugins.
+*/
+
+#define MYSQL_PLUGIN_AUTH_INCLUDED
+
+#include <mysql/plugin.h>
+
+#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0100
+
+#include <mysql/plugin_auth_common.h>
+
+/**
+ Provides server plugin access to authentication information
+*/
+typedef struct st_mysql_server_auth_info
+{
+ /**
+ User name as sent by the client and shown in USER().
+ NULL if the client packet with the user name was not received yet.
+ */
+ const char *user_name;
+ /**
+ A corresponding column value from the mysql.user table for the
+ matching account name
+ */
+ const char *auth_string;
+
+ /**
+ Matching account name as found in the mysql.user table.
+ A plugin can override it with another name that will be
+ used by MySQL for authorization, and shown in CURRENT_USER()
+ */
+ char authenticated_as[MYSQL_USERNAME_LENGTH+1];
+ /**
+ This only affects the "Authentication failed. Password used: %s"
+ error message. If set, %s will be YES, otherwise - NO.
+ Set it as appropriate or ignore at will.
+ */
+ int password_used;
+} MYSQL_SERVER_AUTH_INFO;
+
+/**
+ Server authentication plugin descriptor
+*/
+struct st_mysql_auth
+{
+ int interface_version; /**< version plugin uses */
+ /**
+ A plugin that a client must use for authentication with this server
+ plugin. Can be NULL to mean "any plugin".
+ */
+ const char *client_auth_plugin;
+ /**
+ Function provided by the plugin which should perform authentication (using
+ the vio functions if necessary) and return 0 if successful. The plugin can
+ also fill the info.authenticated_as field if a different username should be
+ used for authorization.
+ */
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
+};
+#endif
+
diff --git a/include/mysql/plugin.h.pp b/include/mysql/plugin_auth.h.pp
index ac86f687723..977c87493a4 100644
--- a/include/mysql/plugin.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -1,9 +1,39 @@
+#include <mysql/plugin.h>
+#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>
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;
@@ -15,7 +45,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;
@@ -46,6 +77,22 @@ struct st_mysql_plugin
struct st_mysql_sys_var **system_vars;
void * __reserved1;
};
+struct st_maria_plugin
+{
+ int type;
+ void *info;
+ const char *name;
+ const char *author;
+ const char *descr;
+ int license;
+ int (*init)(void *);
+ int (*deinit)(void *);
+ unsigned int version;
+ struct st_mysql_show_var *status_vars;
+ struct st_mysql_sys_var **system_vars;
+ const char *version_info;
+ unsigned int maturity;
+};
enum enum_ftparser_mode
{
MYSQL_FTPARSER_SIMPLE_MODE= 0,
@@ -80,7 +127,7 @@ typedef struct st_mysql_ftparser_param
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
void *ftparser_state;
void *mysql_ftparam;
- struct charset_info_st *cs;
+ const struct charset_info_st *cs;
const unsigned char *doc;
mysql_ft_size_t length;
unsigned int flags;
@@ -127,14 +174,6 @@ const char *set_thd_proc_info(void*, const char * info, const char *func,
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,
@@ -142,3 +181,32 @@ void mysql_query_cache_invalidate4(void* thd,
void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
void thd_set_ha_data(void* thd, const struct handlerton *hton,
const void *ha_data);
+#include <mysql/plugin_auth_common.h>
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket;
+} MYSQL_PLUGIN_VIO_INFO;
+typedef struct st_plugin_vio
+{
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+} MYSQL_PLUGIN_VIO;
+typedef struct st_mysql_server_auth_info
+{
+ const char *user_name;
+ const char *auth_string;
+ char authenticated_as[48 +1];
+ int password_used;
+} MYSQL_SERVER_AUTH_INFO;
+struct st_mysql_auth
+{
+ int interface_version;
+ const char *client_auth_plugin;
+ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
+};
diff --git a/include/mysql/plugin_auth_common.h b/include/mysql/plugin_auth_common.h
new file mode 100644
index 00000000000..b71591d6eb6
--- /dev/null
+++ b/include/mysql/plugin_auth_common.h
@@ -0,0 +1,105 @@
+#ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program 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 */
+
+/**
+ @file
+
+ This file defines constants and data structures that are the same for
+ both client- and server-side authentication plugins.
+*/
+#define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED
+
+/** the max allowed length for a user name */
+#define MYSQL_USERNAME_LENGTH 48
+
+/**
+ return values of the plugin authenticate_user() method.
+*/
+
+/**
+ Authentication failed. Additionally, all other CR_xxx values
+ (libmysql error code) can be used too.
+
+ The client plugin may set the error code and the error message directly
+ in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error
+ code was returned, an error message in the MYSQL structure will be
+ overwritten. If CR_ERROR is returned without setting the error in MYSQL,
+ CR_UNKNOWN_ERROR will be user.
+*/
+#define CR_ERROR 0
+/**
+ Authentication (client part) was successful. It does not mean that the
+ authentication as a whole was successful, usually it only means
+ that the client was able to send the user name and the password to the
+ server. If CR_OK is returned, the libmysql reads the next packet expecting
+ it to be one of OK, ERROR, or CHANGE_PLUGIN packets.
+*/
+#define CR_OK -1
+/**
+ Authentication was successful.
+ It means that the client has done its part successfully and also that
+ a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN).
+ In this case, libmysql will not read a packet from the server,
+ but it will use the data at mysql->net.read_pos.
+
+ A plugin may return this value if the number of roundtrips in the
+ authentication protocol is not known in advance, and the client plugin
+ needs to read one packet more to determine if the authentication is finished
+ or not.
+*/
+#define CR_OK_HANDSHAKE_COMPLETE -2
+
+typedef struct st_plugin_vio_info
+{
+ enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
+ MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
+ int socket; /**< it's set, if the protocol is SOCKET or TCP */
+#ifdef _WIN32
+ HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
+#endif
+} MYSQL_PLUGIN_VIO_INFO;
+
+/**
+ Provides plugin access to communication channel
+*/
+typedef struct st_plugin_vio
+{
+ /**
+ Plugin provides a pointer reference and this function sets it to the
+ contents of any incoming packet. Returns the packet length, or -1 if
+ the plugin should terminate.
+ */
+ int (*read_packet)(struct st_plugin_vio *vio,
+ unsigned char **buf);
+
+ /**
+ Plugin provides a buffer with data and the length and this
+ function sends it as a packet. Returns 0 on success, 1 on failure.
+ */
+ int (*write_packet)(struct st_plugin_vio *vio,
+ const unsigned char *packet,
+ int packet_len);
+
+ /**
+ Fills in a st_plugin_vio_info structure, providing the information
+ about the connection.
+ */
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+
+} MYSQL_PLUGIN_VIO;
+
+#endif
+
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 96eb8f21d3f..093807a65cb 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -29,6 +29,7 @@
#define SERVER_VERSION_LENGTH 60
#define SQLSTATE_LENGTH 5
+#define LIST_PROCESS_HOST_LEN 64
/*
USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain
@@ -67,7 +68,8 @@ enum enum_server_command
COM_END
};
-
+/* sql type stored in .frm files for virtual fields */
+#define MYSQL_TYPE_VIRTUAL 245
/*
Length of random string sent by server on handshake; this is also length of
obfuscated password, recieved from client
@@ -115,6 +117,11 @@ enum enum_server_command
thread */
#define REFRESH_MASTER 128 /* Remove all bin logs in the index
and truncate the index */
+#define REFRESH_TABLE_STATS 256 /* Refresh table stats hash table */
+#define REFRESH_INDEX_STATS 512 /* Refresh index stats hash table */
+#define REFRESH_USER_STATS 1024 /* Refresh user stats hash table */
+#define REFRESH_SLOW_QUERY_LOG 4096 /* Flush slow query log and rotate*/
+#define REFRESH_CLIENT_STATS 8192 /* Refresh client stats hash table */
/* The following can't be set with mysql_refresh() */
#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
@@ -145,9 +152,17 @@ enum enum_server_command
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
+#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */
+
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
+#ifdef HAVE_COMPRESS
+#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS
+#else
+#define CAN_CLIENT_COMPRESS 0
+#endif
+
/* Gather all possible capabilites (flags) supported by the server */
#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \
CLIENT_FOUND_ROWS | \
@@ -168,7 +183,8 @@ enum enum_server_command
CLIENT_MULTI_STATEMENTS | \
CLIENT_MULTI_RESULTS | \
CLIENT_SSL_VERIFY_SERVER_CERT | \
- CLIENT_REMEMBER_OPTIONS)
+ CLIENT_REMEMBER_OPTIONS | \
+ CLIENT_PLUGIN_AUTH)
/*
Switch off the flags that are optional and depending on build flags
@@ -481,14 +497,14 @@ void create_random_string(char *to, unsigned int length,
void hash_password(unsigned long *to, const char *password, unsigned int password_len);
void make_scrambled_password_323(char *to, const char *password);
void scramble_323(char *to, const char *message, const char *password);
-my_bool check_scramble_323(const char *, const char *message,
+my_bool check_scramble_323(const unsigned char *reply, const char *message,
unsigned long *salt);
void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
void scramble(char *to, const char *message, const char *password);
-my_bool check_scramble(const char *reply, const char *message,
+my_bool check_scramble(const unsigned char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
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/include/sql_common.h b/include/sql_common.h
index 9e43d076ba9..6b66ae2fd81 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -1,3 +1,4 @@
+#ifndef SQL_COMMON_INCLUDED
/* Copyright (C) 2003-2004, 2006 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -13,14 +14,60 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#define SQL_COMMON_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mysql.h>
extern const char *unknown_sqlstate;
extern const char *cant_connect_sqlstate;
extern const char *not_error_sqlstate;
-#ifdef __cplusplus
-extern "C" {
+struct st_mysql_options_extention {
+ char *plugin_dir;
+ char *default_auth;
+};
+
+typedef struct st_mysql_methods
+{
+ my_bool (*read_query_result)(MYSQL *mysql);
+ my_bool (*advanced_command)(MYSQL *mysql,
+ enum enum_server_command command,
+ const unsigned char *header,
+ unsigned long header_length,
+ const unsigned char *arg,
+ unsigned long arg_length,
+ my_bool skip_check,
+ MYSQL_STMT *stmt);
+ MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
+ unsigned int fields);
+ 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);
+ int (*read_change_user_result)(MYSQL *mysql);
+#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+ MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
+ my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
+ int (*stmt_execute)(MYSQL_STMT *stmt);
+ int (*read_binary_rows)(MYSQL_STMT *stmt);
+ int (*unbuffered_fetch)(MYSQL *mysql, char **row);
+ void (*free_embedded_thd)(MYSQL *mysql);
+ const char *(*read_statistics)(MYSQL *mysql);
+ my_bool (*next_result)(MYSQL *mysql);
+ int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif
+} MYSQL_METHODS;
+
+#define simple_command(mysql, command, arg, length, skip_check) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, skip_check, NULL)
+#define stmt_command(mysql, command, arg, length, stmt) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, 1, stmt)
extern CHARSET_INFO *default_client_charset_info;
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
@@ -42,9 +89,23 @@ void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net);
void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate,
const char *err);
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);
+void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate,
+ const char *format, ...);
+
+/* client side of the pluggable authentication */
+struct st_plugin_vio_info;
+void mpvio_info(Vio *vio, struct st_plugin_vio_info *info);
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ const char *data_plugin, const char *db);
+int mysql_client_plugin_init();
+void mysql_client_plugin_deinit();
+struct st_mysql_client_plugin;
+extern struct st_mysql_client_plugin *mysql_client_builtins[];
+
#ifdef __cplusplus
}
#endif
#define protocol_41(A) ((A)->server_capabilities & CLIENT_PROTOCOL_41)
+#endif
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index 5a0c0bf9e22..a048b596828 100755
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -98,7 +98,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c
../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c
../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c
../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c
- ../mysys/my_getsystime.c ../mysys/my_sync.c ${LIB_SOURCES})
+ ../mysys/my_getsystime.c ../mysys/my_sync.c ../sql-common/client_plugin.c ${LIB_SOURCES})
# Need to set USE_TLS for building the DLL, since __declspec(thread)
# approach to thread local storage does not work properly in DLLs.
@@ -125,6 +125,7 @@ IF(WIN32)
ENDIF(WIN32)
ADD_DEPENDENCIES(libmysql GenError)
TARGET_LINK_LIBRARIES(libmysql wsock32)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index c5e1acab2d1..34e8f2e3b92 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -23,6 +23,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
+pkgplugindir = $(pkglibdir)/plugin
## We'll use CLIENT_EXTRA_LDFLAGS for threaded and non-threaded
## until someone complains that they need separate options.
LDADD = @CLIENT_EXTRA_LDFLAGS@ $(target)
@@ -71,26 +72,27 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
my_getopt.lo my_gethostbyname.lo my_port.lo \
my_rename.lo my_chsize.lo my_sync.lo my_getsystime.lo
sqlobjects = net.lo
-sql_cmn_objects = pack.lo client.lo my_time.lo
+sql_cmn_objects = pack.lo client.lo my_time.lo client_plugin.lo
# Not needed in the minimum library
mysysobjects2 = my_lib.lo mf_qsort.lo
mysysobjects = $(mysysobjects1) $(mysysobjects2)
target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \
$(sql_cmn_objects) $(vio_objects) $(sqlobjects)
-target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@
+target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ @LIBDL@
vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo
BUILT_SOURCES = link_sources
CLEANFILES = $(target_libadd) $(SHLIBOBJS) \
$(target) $(BUILT_SOURCES)
-DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
+DEFS = -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
-DDEFAULT_HOME_ENV=MYSQL_HOME \
+ -DPLUGINDIR='"$(pkgplugindir)"' \
-DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
+ -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' $(target_defs)
if HAVE_YASSL
yassl_las = $(top_builddir)/extra/yassl/src/libyassl.la \
diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h
index f87e625771f..b486c101327 100644
--- a/libmysql/client_settings.h
+++ b/libmysql/client_settings.h
@@ -18,7 +18,8 @@ extern char * mysql_unix_port;
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
+ CLIENT_PLUGIN_AUTH)
sig_handler my_pipe_sig_handler(int sig);
void read_user_name(char *name);
@@ -57,7 +58,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt);
int cli_read_binary_rows(MYSQL_STMT *stmt);
int cli_unbuffered_fetch(MYSQL *mysql, char **row);
const char * cli_read_statistics(MYSQL *mysql);
-int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd);
+int cli_read_change_user_result(MYSQL *mysql);
#ifdef EMBEDDED_LIBRARY
int init_embedded_server(int argc, char **argv, char **groups);
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 95ee6862aa8..fc77db151aa 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",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
@@ -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",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
@@ -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",
+ "Authentication plugin '%s' cannot be loaded: %s",
""
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 9c974d25bb0..8ce7f0ee69b 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -126,12 +126,13 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
if (my_init()) /* Will init threads */
return 1;
init_client_errs();
+ if (mysql_client_plugin_init())
+ return 1;
if (!mysql_port)
{
mysql_port = MYSQL_PORT;
#ifndef MSDOS
{
- struct servent *serv_ptr;
char *env;
/*
@@ -145,6 +146,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
*/
#if MYSQL_PORT_DEFAULT == 0
+ struct servent *serv_ptr;
if ((serv_ptr = getservbyname("mysql", "tcp")))
mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
#endif
@@ -198,6 +200,8 @@ void STDCALL mysql_server_end()
if (!mysql_client_init)
return;
+ mysql_client_plugin_deinit();
+
#ifdef EMBEDDED_LIBRARY
end_embedded_server();
#endif
@@ -663,44 +667,14 @@ mysql_connect(MYSQL *mysql,const char *host,
Change user and database
**************************************************************************/
-int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
-{
- NET *net= &mysql->net;
- ulong pkt_length;
-
- pkt_length= cli_safe_read(mysql);
-
- if (pkt_length == packet_error)
- return 1;
-
- if (pkt_length == 1 && net->read_pos[0] == 254 &&
- mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- By sending this very specific reply server asks us to send scrambled
- password in old format. The reply contains scramble_323.
- */
- scramble_323(buff, mysql->scramble, passwd);
- if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net))
- {
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
- return 1;
- }
- /* Read what server thinks about out new auth message report */
- if (cli_safe_read(mysql) == packet_error)
- return 1;
- }
- return 0;
-}
-
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db)
{
- char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
- char *end= buff;
int rc;
CHARSET_INFO *saved_cs= mysql->charset;
+ char *saved_user= mysql->user;
+ char *saved_passwd= mysql->passwd;
+ char *saved_db= mysql->db;
DBUG_ENTER("mysql_change_user");
@@ -714,49 +688,11 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
/* Use an empty string instead of NULL. */
- if (!user)
- user="";
- if (!passwd)
- passwd="";
-
- /*
- Store user into the buffer.
- Advance position as strmake returns a pointer to the closing NUL.
- */
- end= strmake(end, user, USERNAME_LENGTH) + 1;
-
- /* write scrambled password according to server capabilities */
- if (passwd[0])
- {
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- *end++= SCRAMBLE_LENGTH;
- scramble(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH;
- }
- else
- {
- scramble_323(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH_323 + 1;
- }
- }
- else
- *end++= '\0'; /* empty password */
- /* Add database if needed */
- end= strmake(end, db ? db : "", NAME_LEN) + 1;
-
- /* Add character set number. */
-
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- int2store(end, (ushort) mysql->charset->number);
- end+= 2;
- }
-
- /* Write authentication package */
- simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1);
+ mysql->user= (char*)(user ? user : "");
+ mysql->passwd= (char*)(passwd ? passwd : "");
+ mysql->db= 0;
- rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
+ rc= run_plugin_auth(mysql, 0, 0, 0, db);
/*
The server will close all statements no matter was the attempt
@@ -766,18 +702,21 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
if (rc == 0)
{
/* Free old connect information */
- my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_user, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_passwd, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(saved_db, MYF(MY_ALLOW_ZERO_PTR));
/* alloc new connect information */
- mysql->user= my_strdup(user,MYF(MY_WME));
- mysql->passwd=my_strdup(passwd,MYF(MY_WME));
- mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
+ mysql->user= my_strdup(mysql->user, MYF(MY_WME));
+ mysql->passwd= my_strdup(mysql->passwd, MYF(MY_WME));
+ mysql->db= db ? my_strdup(db, MYF(MY_WME)) : 0;
}
else
{
mysql->charset= saved_cs;
+ mysql->user= saved_user;
+ mysql->passwd= saved_passwd;
+ mysql->db= saved_db;
}
DBUG_RETURN(rc);
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 332dd206e15..2105585cc54 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -104,7 +104,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql-common/client.c ../sql-common/my_time.c
../sql-common/my_user.c ../sql-common/pack.c
../sql/password.c ../sql/discover.cc ../sql/derror.cc
- ../sql/field.cc ../sql/field_conv.cc
+ ../sql/field.cc ../sql/field_conv.cc ../sql-common/client_plugin.c
../sql/filesort.cc ../sql/gstream.cc ../sql/ha_partition.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
@@ -139,7 +139,8 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
- ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/scheduler.cc ../sql/event_parse_data.cc
+ ../sql/create_options.cc
${GEN_SOURCES}
${LIB_SOURCES})
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index f5da13b145b..0fef36db6b3 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -25,10 +25,10 @@ pkgplugindir = $(pkglibdir)/plugin
EXTRA_DIST = libmysqld.def CMakeLists.txt
DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
- -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
- -DPLUGINDIR="\"$(pkgplugindir)\""
+ -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' \
+ -DPLUGINDIR='"$(pkgplugindir)"'
INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/sql -I$(top_srcdir)/sql \
-I$(top_srcdir)/sql/examples \
@@ -41,7 +41,7 @@ pkglib_LIBRARIES = libmysqld.a
SUBDIRS = . examples
libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc
libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
- my_time.c
+ my_time.c client_plugin.c
noinst_HEADERS = embedded_priv.h emb_qcache.h
@@ -75,7 +75,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
debug_sync.cc \
- sql_tablespace.cc \
+ sql_tablespace.cc create_options.cc \
rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc event_parse_data.cc opt_table_elimination.cc
diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h
index 369b344d4bd..c246693594b 100644
--- a/libmysqld/embedded_priv.h
+++ b/libmysqld/embedded_priv.h
@@ -15,6 +15,8 @@
/* Prototypes for the embedded version of MySQL */
+#include <sql_common.h>
+
C_MODE_START
void lib_connection_phase(NET *net, int phase);
void init_embedded_mysql(MYSQL *mysql, int client_flag);
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 7de1ecd6ef3..ecf668490e6 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -35,7 +35,6 @@ C_MODE_START
#include <mysql.h>
#undef ER
#include "errmsg.h"
-#include <sql_common.h>
#include "embedded_priv.h"
extern unsigned int mysql_server_last_errno;
@@ -413,11 +412,10 @@ static MYSQL_RES * emb_store_result(MYSQL *mysql)
return mysql_store_result(mysql);
}
-int emb_read_change_user_result(MYSQL *mysql,
- char *buff __attribute__((unused)),
- const char *passwd __attribute__((unused)))
+int emb_read_change_user_result(MYSQL *mysql)
{
- return mysql_errno(mysql);
+ mysql->net.read_pos= (uchar*)""; // fake an OK packet
+ return mysql_errno(mysql) ? packet_error : 1 /* length of the OK packet */;
}
MYSQL_METHODS embedded_methods=
@@ -428,6 +426,7 @@ MYSQL_METHODS embedded_methods=
emb_store_result,
emb_fetch_lengths,
emb_flush_use_result,
+ emb_read_change_user_result,
emb_list_fields,
emb_read_prepare_result,
emb_stmt_execute,
@@ -436,7 +435,6 @@ MYSQL_METHODS embedded_methods=
emb_free_embedded_thd,
emb_read_statistics,
emb_read_query_result,
- emb_read_change_user_result,
emb_read_rows_from_cursor
};
@@ -584,6 +582,8 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag)
THD *thd = (THD *)mysql->thd;
thd->mysql= mysql;
mysql->server_version= server_version;
+ mysql->client_flag= client_flag;
+ mysql->server_capabilities= client_flag;
init_alloc_root(&mysql->field_alloc, 8192, 0);
}
@@ -648,14 +648,19 @@ err:
int check_embedded_connection(MYSQL *mysql, const char *db)
{
int result;
+ LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 };
THD *thd= (THD*)mysql->thd;
thd_init_client_charset(thd, mysql->charset->number);
thd->update_charset();
Security_context *sctx= thd->security_ctx;
sctx->host_or_ip= sctx->host= (char*) my_localhost;
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);
+ strmake(sctx->priv_user, mysql->user, USERNAME_LENGTH-1);
+ sctx->user= my_strdup(mysql->user, MYF(0));
+ sctx->master_access= GLOBAL_ACLS; // Full rights
+ /* Change database if necessary */
+ if (!(result= (db && db[0] && mysql_change_db(thd, &db_str, FALSE))))
+ my_ok(thd);
net_end_statement(thd);
emb_read_query_result(mysql);
return result;
@@ -664,14 +669,15 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
#else
int check_embedded_connection(MYSQL *mysql, const char *db)
{
+ /*
+ we emulate a COM_CHANGE_USER user here,
+ it's easier than to emulate the complete 3-way handshake
+ */
+ char buf[USERNAME_LENGTH + SCRAMBLE_LENGTH + 1 + 2*NAME_LEN + 2], *end;
+ NET *net= &mysql->net;
THD *thd= (THD*)mysql->thd;
Security_context *sctx= thd->security_ctx;
- int result;
- char scramble_buff[SCRAMBLE_LENGTH];
- int passwd_len;
- thd_init_client_charset(thd, mysql->charset->number);
- thd->update_charset();
if (mysql->options.client_ip)
{
sctx->host= my_strdup(mysql->options.client_ip, MYF(0));
@@ -682,36 +688,45 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
sctx->host_or_ip= sctx->host;
if (acl_check_host(sctx->host, sctx->ip))
- {
- result= ER_HOST_NOT_PRIVILEGED;
goto err;
- }
- sctx->user= my_strdup(mysql->user, MYF(0));
+ /* construct a COM_CHANGE_USER packet */
+ end= strmake(buf, mysql->user, USERNAME_LENGTH) + 1;
+
+ memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
+ thd->scramble[SCRAMBLE_LENGTH]= 0;
+ strcpy(mysql->scramble, thd->scramble);
+
if (mysql->passwd && mysql->passwd[0])
{
- memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
- thd->scramble[SCRAMBLE_LENGTH]= 0;
- scramble(scramble_buff, thd->scramble, mysql->passwd);
- passwd_len= SCRAMBLE_LENGTH;
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, thd->scramble, mysql->passwd);
+ end+= SCRAMBLE_LENGTH;
}
else
- passwd_len= 0;
+ *end++= 0;
- if((result= check_user(thd, COM_CONNECT,
- scramble_buff, passwd_len, db, true)))
- goto err;
+ end= strmake(end, db ? db : "", NAME_LEN) + 1;
- return 0;
-err:
+ int2store(end, (ushort) mysql->charset->number);
+ end+= 2;
+
+ /* acl_authenticate() takes the data from thd->net->read_pos */
+ thd->net.read_pos= (uchar*)buf;
+
+ if (acl_authenticate(thd, 0, end - buf))
{
- NET *net= &mysql->net;
- strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
- memcpy(net->sqlstate,
- mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
- sizeof(net->sqlstate)-1);
+ x_free(thd->security_ctx->user);
+ goto err;
}
- return result;
+ return 0;
+
+err:
+ strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
+ memcpy(net->sqlstate,
+ mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
+ sizeof(net->sqlstate)-1);
+ return 1;
}
#endif
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 0c20b35236d..afb91b7ff81 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -18,7 +18,6 @@
#include <mysql_embed.h>
#include <mysqld_error.h>
#include <my_pthread.h>
-#include "embedded_priv.h"
#include <my_sys.h>
#include <mysys_err.h>
#include <m_string.h>
@@ -28,6 +27,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
+#include "embedded_priv.h"
#include "client_settings.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -81,9 +81,9 @@ static my_bool is_NT(void)
** Shut down connection
**************************************************************************/
-static void end_server(MYSQL *mysql)
+void embedded_end_server(MYSQL *mysql)
{
- DBUG_ENTER("end_server");
+ DBUG_ENTER("embedded_end_server");
free_old_query(mysql);
DBUG_VOID_RETURN;
}
@@ -169,7 +169,11 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_STATEMENTS)
client_flag|= CLIENT_MULTI_RESULTS;
- client_flag&= ~CLIENT_COMPRESS;
+ /*
+ no compression in embedded as we don't send any data,
+ and no pluggable auth, as we cannot do a client-server dialog
+ */
+ client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
@@ -216,7 +220,7 @@ error:
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;
- end_server(mysql);
+ embedded_end_server(mysql);
mysql->free_me=0;
mysql_close(mysql);
mysql->free_me=free_me;
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..3e5597105ab
--- /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(...); /* fix the prototype as appropriate */
+ void foo_func2(...); /* 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.c 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/Makefile.am b/mysql-test/Makefile.am
index 4ea634688fe..991c8116f1b 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -103,6 +103,8 @@ TEST_DIRS = t r include std_data std_data/parts collections \
suite/parts suite/parts/t suite/parts/r suite/parts/inc \
suite/pbxt/t suite/pbxt/r \
suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \
+ suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc \
+ suite/oqgraph suite/oqgraph/t suite/oqgraph/r suite/oqgraph/include \
suite/innodb_plugin suite/innodb_plugin/t suite/innodb_plugin/r suite/innodb_plugin/include \
suite/percona \
suite/engines suite/engines/funcs suite/engines/iuds suite/engines/rr_trx \
diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm
index b068b2e542e..7bdb0e37604 100644
--- a/mysql-test/lib/mtr_cases.pm
+++ b/mysql-test/lib/mtr_cases.pm
@@ -1117,6 +1117,16 @@ sub collect_one_test_case {
}
}
+ if ( $tinfo->{'oqgraph_test'} )
+ {
+ if ( !$ENV{'GRAPH_ENGINE_SO'} )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test requires the OQGraph storage engine";
+ return $tinfo;
+ }
+ }
+
# Set extra config file to use
if (defined $defaults_extra_file) {
@@ -1176,6 +1186,7 @@ my @tags=
["include/not_embedded.inc", "not_embedded", 1],
["include/not_valgrind.inc", "not_valgrind", 1],
["include/have_example_plugin.inc", "example_plugin_test", 1],
+ ["include/have_oqgraph_engine.inc", "oqgraph_test", 1],
["include/have_ssl.inc", "need_ssl", 1],
);
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 4df5d04dac7..cd61ad47883 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -130,7 +130,7 @@ my $path_config_file; # The generated config file, var/my.cnf
# executables will be used by the test suite.
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
-my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts,innodb,innodb_plugin,percona";
+my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts,innodb,innodb_plugin,percona,vcol,oqgraph";
my $opt_suites;
our $opt_verbose= 0; # Verbose output, enable with --verbose
@@ -1320,21 +1320,18 @@ sub command_line_setup {
if ($opt_gdb)
{
- mtr_warning("Silently converting --gdb to --client-gdb in embedded mode");
$opt_client_gdb= $opt_gdb;
$opt_gdb= undef;
}
if ($opt_ddd)
{
- mtr_warning("Silently converting --ddd to --client-ddd in embedded mode");
$opt_client_ddd= $opt_ddd;
$opt_ddd= undef;
}
if ($opt_debugger)
{
- mtr_warning("Silently converting --debugger to --client-debugger in embedded mode");
$opt_client_debugger= $opt_debugger;
$opt_debugger= undef;
}
@@ -5394,20 +5391,12 @@ sub gdb_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
else
{
# write init file for mysqld
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break mysql_parse\n" .
- "commands 1\n" .
- "disable 1\n" .
- "end\n" .
- "run");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
if ( $opt_manual_gdb )
@@ -5458,20 +5447,12 @@ sub ddd_arguments {
if ( $type eq "client" )
{
# write init file for client
- mtr_tofile($gdb_init_file,
- "set args $str\n" .
- "break main\n");
+ mtr_tofile($gdb_init_file, "set args $str\n");
}
else
{
# write init file for mysqld
- mtr_tofile($gdb_init_file,
- "file $$exe\n" .
- "set args $str\n" .
- "break mysql_parse\n" .
- "commands 1\n" .
- "disable 1\n" .
- "end");
+ mtr_tofile($gdb_init_file, "file $$exe\nset args $str\n");
}
if ( $opt_manual_ddd )
diff --git a/mysql-test/r/change_user.result b/mysql-test/r/change_user.result
index 679e656c381..3c1e2b6f262 100644
--- a/mysql-test/r/change_user.result
+++ b/mysql-test/r/change_user.result
@@ -1,3 +1,36 @@
+grant select on test.* to test_nopw;
+grant select on test.* to test_oldpw identified by password "09301740536db389";
+grant select on test.* to test_newpw identified by "newpw";
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_nopw@localhost> <test_nopw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_oldpw@localhost> <test_oldpw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_newpw@localhost> <test_newpw@%> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> NULL
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_nopw@localhost> <test_nopw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_oldpw@localhost> <test_oldpw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<test_newpw@localhost> <test_newpw@%> test
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+concat('<', user(), '>') concat('<', current_user(), '>') database()
+<root@localhost> <root@localhost> test
+drop user test_nopw;
+drop user test_oldpw;
+drop user test_newpw;
Bug#20023
SELECT @@session.sql_big_selects;
@@session.sql_big_selects
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index fbe562c283c..690a6fb3bc3 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -225,3 +225,17 @@ Connection on extra port 2 ok
# ------------------------------------------------------------------
# -- End of 5.1 tests
# ------------------------------------------------------------------
+CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
+CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
+connect(localhost,mysqltest_up1,foo,test,MASTER_PORT,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'mysqltest_up1'@'localhost' (using password: YES)
+select user(), current_user();
+user() current_user()
+mysqltest_up1@localhost mysqltest_up1@%
+connect(localhost,mysqltest_up2,newpw,test,MASTER_PORT,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'mysqltest_up2'@'localhost' (using password: YES)
+select user(), current_user();
+user() current_user()
+mysqltest_up2@localhost mysqltest_up2@%
+DROP USER mysqltest_up1@'%';
+DROP USER mysqltest_up2@'%';
diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result
index 50bfa97c59f..da53790acd6 100644
--- a/mysql-test/r/events_bugs.result
+++ b/mysql-test/r/events_bugs.result
@@ -729,9 +729,8 @@ set @@sql_mode= pow(2,32)-1;
create event e1 on schedule every 1 day do select 1;
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,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,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,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,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
name
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index b8f13723eb8..f410b26a1fe 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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
@@ -164,6 +164,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 12269f0cb1c..ee3fe1540b9 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -287,6 +287,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
create user mysqltest_A@'%';
rename user mysqltest_B@'%' to mysqltest_C@'%';
drop user mysqltest_C@'%';
@@ -354,6 +355,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
INSERT INTO mysql.db (host, db, user, select_priv) VALUES
('%','TESTDB','mysqltest_1','Y');
FLUSH PRIVILEGES;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index f58e92b186f..ee8b91631bb 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -45,6 +45,7 @@ NOT (table_schema = 'INFORMATION_SCHEMA' AND table_name LIKE 'PBXT_%');
select * from v1 ORDER BY c COLLATE utf8_bin;
c
CHARACTER_SETS
+CLIENT_STATISTICS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
@@ -54,6 +55,7 @@ EVENTS
FILES
GLOBAL_STATUS
GLOBAL_VARIABLES
+INDEX_STATISTICS
INNODB_BUFFER_POOL_PAGES
INNODB_BUFFER_POOL_PAGES_BLOB
INNODB_BUFFER_POOL_PAGES_INDEX
@@ -69,6 +71,7 @@ INNODB_SYS_INDEXES
INNODB_SYS_TABLES
INNODB_TABLE_STATS
INNODB_TRX
+KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
@@ -84,8 +87,10 @@ STATISTICS
TABLES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
+TABLE_STATISTICS
TRIGGERS
USER_PRIVILEGES
+USER_STATISTICS
VIEWS
XTRADB_ADMIN_COMMAND
XTRADB_ENHANCEMENTS
@@ -124,6 +129,7 @@ c table_name
TABLES TABLES
TABLE_CONSTRAINTS TABLE_CONSTRAINTS
TABLE_PRIVILEGES TABLE_PRIVILEGES
+TABLE_STATISTICS TABLE_STATISTICS
TRIGGERS TRIGGERS
tables_priv tables_priv
time_zone time_zone
@@ -143,6 +149,7 @@ c table_name
TABLES TABLES
TABLE_CONSTRAINTS TABLE_CONSTRAINTS
TABLE_PRIVILEGES TABLE_PRIVILEGES
+TABLE_STATISTICS TABLE_STATISTICS
TRIGGERS TRIGGERS
tables_priv tables_priv
time_zone time_zone
@@ -162,6 +169,7 @@ c table_name
TABLES TABLES
TABLE_CONSTRAINTS TABLE_CONSTRAINTS
TABLE_PRIVILEGES TABLE_PRIVILEGES
+TABLE_STATISTICS TABLE_STATISTICS
TRIGGERS TRIGGERS
tables_priv tables_priv
time_zone time_zone
@@ -610,7 +618,7 @@ proc body longblob
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 sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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 character_set_client char(32)
proc collation_connection char(32)
@@ -643,12 +651,13 @@ from information_schema.tables
where table_schema='information_schema' limit 2;
TABLE_NAME TABLE_TYPE ENGINE
CHARACTER_SETS SYSTEM VIEW MEMORY
-COLLATIONS SYSTEM VIEW MEMORY
+CLIENT_STATISTICS SYSTEM VIEW MEMORY
show tables from information_schema like "T%";
Tables_in_information_schema (T%)
TABLES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
+TABLE_STATISTICS
TRIGGERS
create database information_schema;
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
@@ -658,6 +667,7 @@ Tables_in_information_schema (T%) Table_type
TABLES SYSTEM VIEW
TABLE_CONSTRAINTS SYSTEM VIEW
TABLE_PRIVILEGES SYSTEM VIEW
+TABLE_STATISTICS SYSTEM VIEW
TRIGGERS SYSTEM VIEW
create table t1(a int);
ERROR 42S02: Unknown table 't1' in information_schema
@@ -670,6 +680,7 @@ Tables_in_information_schema (T%)
TABLES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
+TABLE_STATISTICS
TRIGGERS
select table_name from tables where table_name='user';
table_name
@@ -859,6 +870,7 @@ TABLE_NAME COLUMN_NAME PRIVILEGES
COLUMNS TABLE_NAME select
COLUMN_PRIVILEGES TABLE_NAME select
FILES TABLE_NAME select
+INDEX_STATISTICS TABLE_NAME select
INNODB_BUFFER_POOL_PAGES_INDEX table_name select
INNODB_INDEX_STATS table_name select
INNODB_TABLE_STATS table_name select
@@ -869,6 +881,7 @@ STATISTICS TABLE_NAME select
TABLES TABLE_NAME select
TABLE_CONSTRAINTS TABLE_NAME select
TABLE_PRIVILEGES TABLE_NAME select
+TABLE_STATISTICS TABLE_NAME select
VIEWS TABLE_NAME select
delete from mysql.user where user='mysqltest_4';
delete from mysql.db where user='mysqltest_4';
diff --git a/mysql-test/r/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result
index a2f34fad221..dfe7570266c 100644
--- a/mysql-test/r/information_schema_all_engines.result
+++ b/mysql-test/r/information_schema_all_engines.result
@@ -2,6 +2,7 @@ use INFORMATION_SCHEMA;
show tables;
Tables_in_information_schema
CHARACTER_SETS
+CLIENT_STATISTICS
COLLATIONS
COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
@@ -11,6 +12,8 @@ EVENTS
FILES
GLOBAL_STATUS
GLOBAL_VARIABLES
+INDEX_STATISTICS
+KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
@@ -26,8 +29,10 @@ STATISTICS
TABLES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
+TABLE_STATISTICS
TRIGGERS
USER_PRIVILEGES
+USER_STATISTICS
VIEWS
INNODB_BUFFER_POOL_PAGES
PBXT_STATISTICS
@@ -63,6 +68,7 @@ c2.column_name LIKE '%SCHEMA%'
);
table_name column_name
CHARACTER_SETS CHARACTER_SET_NAME
+CLIENT_STATISTICS CLIENT
COLLATIONS COLLATION_NAME
COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
COLUMNS TABLE_SCHEMA
@@ -72,6 +78,8 @@ EVENTS EVENT_SCHEMA
FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
+INDEX_STATISTICS TABLE_SCHEMA
+KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@@ -87,8 +95,10 @@ STATISTICS TABLE_SCHEMA
TABLES TABLE_SCHEMA
TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
TABLE_PRIVILEGES TABLE_SCHEMA
+TABLE_STATISTICS TABLE_SCHEMA
TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
+USER_STATISTICS USER
VIEWS TABLE_SCHEMA
INNODB_BUFFER_POOL_PAGES page_type
PBXT_STATISTICS ID
@@ -124,6 +134,7 @@ c2.column_name LIKE '%SCHEMA%'
);
table_name column_name
CHARACTER_SETS CHARACTER_SET_NAME
+CLIENT_STATISTICS CLIENT
COLLATIONS COLLATION_NAME
COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
COLUMNS TABLE_SCHEMA
@@ -133,6 +144,8 @@ EVENTS EVENT_SCHEMA
FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
+INDEX_STATISTICS TABLE_SCHEMA
+KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@@ -148,8 +161,10 @@ STATISTICS TABLE_SCHEMA
TABLES TABLE_SCHEMA
TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
TABLE_PRIVILEGES TABLE_SCHEMA
+TABLE_STATISTICS TABLE_SCHEMA
TRIGGERS TRIGGER_SCHEMA
USER_PRIVILEGES GRANTEE
+USER_STATISTICS USER
VIEWS TABLE_SCHEMA
INNODB_BUFFER_POOL_PAGES page_type
PBXT_STATISTICS ID
@@ -191,6 +206,7 @@ group by c2.column_type order by num limit 1)
group by t.table_name order by num1, t.table_name;
table_name group_concat(t.table_schema, '.', t.table_name) num1
CHARACTER_SETS information_schema.CHARACTER_SETS 1
+CLIENT_STATISTICS information_schema.CLIENT_STATISTICS 1
COLLATIONS information_schema.COLLATIONS 1
COLLATION_CHARACTER_SET_APPLICABILITY information_schema.COLLATION_CHARACTER_SET_APPLICABILITY 1
COLUMNS information_schema.COLUMNS 1
@@ -200,6 +216,7 @@ EVENTS information_schema.EVENTS 1
FILES information_schema.FILES 1
GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
+INDEX_STATISTICS information_schema.INDEX_STATISTICS 1
INNODB_BUFFER_POOL_PAGES information_schema.INNODB_BUFFER_POOL_PAGES 1
INNODB_BUFFER_POOL_PAGES_BLOB information_schema.INNODB_BUFFER_POOL_PAGES_BLOB 1
INNODB_BUFFER_POOL_PAGES_INDEX information_schema.INNODB_BUFFER_POOL_PAGES_INDEX 1
@@ -215,6 +232,7 @@ INNODB_SYS_INDEXES information_schema.INNODB_SYS_INDEXES 1
INNODB_SYS_TABLES information_schema.INNODB_SYS_TABLES 1
INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1
INNODB_TRX information_schema.INNODB_TRX 1
+KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PBXT_STATISTICS information_schema.PBXT_STATISTICS 1
@@ -231,8 +249,10 @@ STATISTICS information_schema.STATISTICS 1
TABLES information_schema.TABLES 1
TABLE_CONSTRAINTS information_schema.TABLE_CONSTRAINTS 1
TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1
+TABLE_STATISTICS information_schema.TABLE_STATISTICS 1
TRIGGERS information_schema.TRIGGERS 1
USER_PRIVILEGES information_schema.USER_PRIVILEGES 1
+USER_STATISTICS information_schema.USER_STATISTICS 1
VIEWS information_schema.VIEWS 1
XTRADB_ENHANCEMENTS information_schema.XTRADB_ENHANCEMENTS 1
Database: information_schema
@@ -240,6 +260,7 @@ Database: information_schema
| Tables |
+---------------------------------------+
| CHARACTER_SETS |
+| CLIENT_STATISTICS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
@@ -249,6 +270,8 @@ Database: information_schema
| FILES |
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
+| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -264,8 +287,10 @@ Database: information_schema
| TABLES |
| TABLE_CONSTRAINTS |
| TABLE_PRIVILEGES |
+| TABLE_STATISTICS |
| TRIGGERS |
| USER_PRIVILEGES |
+| USER_STATISTICS |
| VIEWS |
| INNODB_BUFFER_POOL_PAGES |
| PBXT_STATISTICS |
@@ -291,6 +316,7 @@ Database: INFORMATION_SCHEMA
| Tables |
+---------------------------------------+
| CHARACTER_SETS |
+| CLIENT_STATISTICS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
@@ -300,6 +326,8 @@ Database: INFORMATION_SCHEMA
| FILES |
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
+| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -315,8 +343,10 @@ Database: INFORMATION_SCHEMA
| TABLES |
| TABLE_CONSTRAINTS |
| TABLE_PRIVILEGES |
+| TABLE_STATISTICS |
| TRIGGERS |
| USER_PRIVILEGES |
+| USER_STATISTICS |
| VIEWS |
| INNODB_BUFFER_POOL_PAGES |
| PBXT_STATISTICS |
@@ -345,5 +375,5 @@ Wildcard: inf_rmation_schema
+--------------------+
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 46
+information_schema 51
mysql 22
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index a6f81d7688b..b5be0137520 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -7,6 +7,7 @@ Tables_in_information_schema (T%)
TABLES
TABLE_CONSTRAINTS
TABLE_PRIVILEGES
+TABLE_STATISTICS
TRIGGERS
create database `inf%`;
create database mbase;
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index 08d8059f61b..8ebc8ff1fa0 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -1,5 +1,7 @@
drop table if exists t1, t2, t3;
-SET @save_key_buffer=@@key_buffer_size;
+SET @save_key_buffer_size=@@key_buffer_size;
+SET @save_key_cache_block_size=@@key_cache_block_size;
+SET @save_key_cache_segments=@@key_cache_segments;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@key_buffer_size @@small.key_buffer_size
2097152 131072
@@ -37,7 +39,7 @@ SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size;
@@medium.key_buffer_size
0
-SET @@global.key_buffer_size=@save_key_buffer;
+SET @@global.key_buffer_size=@save_key_buffer_size;
SELECT @@default.key_buffer_size;
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 'default.key_buffer_size' at line 1
SELECT @@skr.storage_engine="test";
@@ -366,3 +368,432 @@ Variable_name Value
key_cache_block_size 1536
SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_block_size=@save_key_cache_block_size;
+select @@key_buffer_size;
+@@key_buffer_size
+2097152
+select @@key_cache_block_size;
+@@key_cache_block_size
+1024
+select @@key_cache_segments;
+@@key_cache_segments
+0
+create table t1 (
+p int not null auto_increment primary key,
+a char(10));
+create table t2 (
+p int not null auto_increment primary key,
+i int, a char(10), key k1(i), key k2(a));
+select @@key_cache_segments;
+@@key_cache_segments
+0
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+show status like 'key_%';
+Variable_name Value
+Key_blocks_not_flushed 0
+Key_blocks_unused KEY_BLOCKS_UNUSED
+Key_blocks_used 4
+Key_read_requests 22
+Key_reads 0
+Key_write_requests 26
+Key_writes 6
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t2 where a='zzzz';
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 4 # 0 29 0 32 9
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t1;
+delete from t2;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default NULL NULL 2097152 1024 4 # 0 29 0 32 9
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+set global key_cache_segments=2;
+select @@key_cache_segments;
+@@key_cache_segments
+2
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 2097152 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+show status like 'key_%';
+Variable_name Value
+Key_blocks_not_flushed 0
+Key_blocks_unused KEY_BLOCKS_UNUSED
+Key_blocks_used 4
+Key_read_requests 22
+Key_reads 0
+Key_write_requests 26
+Key_writes 6
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t1;
+delete from t2;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+set global key_cache_segments=1;
+select @@key_cache_segments;
+@@key_cache_segments
+1
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+show status like 'key_%';
+Variable_name Value
+Key_blocks_not_flushed 0
+Key_blocks_unused KEY_BLOCKS_UNUSED
+Key_blocks_used 4
+Key_read_requests 22
+Key_reads 0
+Key_write_requests 26
+Key_writes 6
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+delete from t1;
+delete from t2;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 1 0 2 1
+flush tables;
+flush status;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 1 NULL 2097152 1024 4 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 0 0 0 0
+set global key_buffer_size=32*1024;
+select @@key_buffer_size;
+@@key_buffer_size
+32768
+set global key_cache_segments=2;
+select @@key_cache_segments;
+@@key_cache_segments
+2
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 0 # 0 0 0 0 0
+small NULL NULL 1048576 1024 1 # 0 0 0 0 0
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+(3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+p a
+1 qqqq
+2 yyyy
+select * from t2;
+p i a
+1 1 qqqq
+2 1 pppp
+3 1 yyyy
+4 3 zzzz
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 4 # 0 22 0 26 6
+small NULL NULL 1048576 1024 1 # 0 0 0 0 0
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 6733 # 3684 103
+small NULL NULL 1048576 1024 # # 0 0 # 0 0
+select * from t1 where p between 1010 and 1020 ;
+p a
+select * from t2 where p between 1010 and 1020 ;
+p i a
+1010 2 pppp
+1011 2 yyyy
+1012 3 zzzz
+1013 2 qqqq
+1014 2 pppp
+1015 2 yyyy
+1016 3 zzzz
+1017 2 qqqq
+1018 2 pppp
+1019 2 yyyy
+1020 3 zzzz
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 6750 # 3684 103
+small NULL NULL 1048576 1024 # # 0 0 # 0 0
+flush tables;
+flush status;
+update t1 set a='zzzz' where a='qqqq';
+update t2 set i=1 where i=2;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3076 18 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+set global keycache1.key_buffer_size=256*1024;
+select @@keycache1.key_buffer_size;
+@@keycache1.key_buffer_size
+262144
+set global keycache1.key_cache_segments=7;
+select @@keycache1.key_cache_segments;
+@@keycache1.key_cache_segments
+7
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3076 18 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 0 0 0 0
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 0 # 0 0 0 0 0
+cache index t1 key (`primary`) in keycache1;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+explain select p from t1 where p between 1010 and 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where; Using index
+select p from t1 where p between 1010 and 1020;
+p
+explain select i from t2 where p between 1010 and 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 28 Using where
+select i from t2 where p between 1010 and 1020;
+i
+1
+1
+3
+1
+1
+1
+3
+1
+1
+1
+3
+explain select count(*) from t1, t2 where t1.p = t2.i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index k1 k1 5 NULL 1024 Using index
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.i 1 Using index
+select count(*) from t1, t2 where t1.p = t2.i;
+count(*)
+256
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 14 3 0 0
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 3 # 0 14 3 0 0
+cache index t2 in keycache1;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+update t2 set p=p+3000, i=2 where a='qqqq';
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
+set global keycache2.key_buffer_size=1024*1024;
+cache index t2 in keycache2;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+insert into t2 values (2000, 3, 'yyyy');
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
+select * from information_schema.key_caches where key_cache_name like "key%"
+and segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
+keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
+cache index t2 in keycache1;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+update t2 set p=p+5000 where a='zzzz';
+select * from t2 where p between 1010 and 1020;
+p i a
+1010 1 pppp
+1011 1 yyyy
+1014 1 pppp
+1015 1 yyyy
+1018 1 pppp
+1019 1 yyyy
+explain select p from t2 where p between 1010 and 1020;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 7 Using where; Using index
+select p from t2 where p between 1010 and 1020;
+p
+1010
+1011
+1014
+1015
+1018
+1019
+explain select i from t2 where a='yyyy' and i=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref k1,k2 k1 5 const 188 Using where
+select i from t2 where a='yyyy' and i=3;
+i
+3
+explain select a from t2 where a='yyyy' and i=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref k1,k2 k1 5 const 188 Using where
+select a from t2 where a='yyyy' and i=3 ;
+a
+yyyy
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=2*1024;
+insert into t2 values (7000, 3, 'yyyy');
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 262143 8192 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+insert into t2 values (8000, 3, 'yyyy');
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=64*1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=2*1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=0;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=8*1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=0;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_buffer_size=128*1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+set global keycache1.key_cache_block_size=1024;
+select * from information_schema.key_caches where segment_number is null;
+KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
+default 2 NULL 32768 1024 # # 0 3172 24 1552 18
+small NULL NULL 1048576 1024 # # 0 0 0 0 0
+keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
+keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
+drop table t1,t2;
+set global keycache1.key_buffer_size=0;
+set global keycache2.key_buffer_size=0;
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_segments=@save_key_cache_segments;
diff --git a/mysql-test/r/log_slow.result b/mysql-test/r/log_slow.result
index 57d12a64f5a..b6341109556 100644
--- a/mysql-test/r/log_slow.result
+++ b/mysql-test/r/log_slow.result
@@ -56,5 +56,6 @@ last_insert_id int(11) NO NULL
insert_id int(11) NO NULL
server_id int(10) unsigned NO NULL
sql_text mediumtext NO NULL
+flush slow query logs;
set @@log_slow_filter=default;
set @@log_slow_verbosity=default;
diff --git a/mysql-test/r/partition_example.result b/mysql-test/r/partition_example.result
new file mode 100644
index 00000000000..2129eea0818
--- /dev/null
+++ b/mysql-test/r/partition_example.result
@@ -0,0 +1,31 @@
+install plugin example soname 'ha_example.so';
+create table t1 (a int not null)
+engine=example
+partition by list (a)
+(partition p0 values in (1), partition p1 values in (2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST (a)
+(PARTITION p0 VALUES IN (1) ENGINE = EXAMPLE,
+ PARTITION p1 VALUES IN (2) ENGINE = EXAMPLE) */
+drop table t1;
+create table t1 (a int not null)
+engine=example ull=12340
+partition by list (a)
+(partition p0 values in (1), partition p1 values in (2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ull`=12340
+/*!50100 PARTITION BY LIST (a)
+(PARTITION p0 VALUES IN (1) ENGINE = EXAMPLE,
+ PARTITION p1 VALUES IN (2) ENGINE = EXAMPLE) */
+drop table t1;
+select 1;
+1
+1
+uninstall plugin example;
diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
index 782d2a5a9a4..8169bd458e8 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
@@ -53,4 +62,64 @@ select @@global.example_ulong_var;
set session sql_mode=@old_sql_mode;
set session old=bla;
ERROR HY000: Variable 'old' is a read only variable
+#legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `complex`='c,f,f,f'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000 `STR`='dskj' `one_or_two`='one' `YESNO`=0
+drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
+#illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+Warnings:
+Warning 1652 Incorrect value '10000000000000000000' for option 'ULL'
+Warning 1652 Incorrect value 'ttt' for option 'one_or_two'
+Warning 1652 Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`=SSS
+#alter table
+alter table t1 ULL=10000000;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `ULL`=10000000
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `complex`='c,c,c'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `ULL`=10000000
+drop table t1;
+#illegal value error
+SET SQL_MODE='';
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+ERROR HY000: Incorrect value '10000000000000000000' for option 'ULL'
+CREATE TABLE t1 (a int) ENGINE=example ULL=10.00;
+ERROR 42000: Only integers allowed as number here near '10.00' at line 1
+CREATE TABLE t1 (a int) ENGINE=example ULL=1e2;
+ERROR 42000: Only integers allowed as number here near '1e2' at line 1
+CREATE TABLE t1 (a int) ENGINE=example ULL=0x1234;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=4660
+ALTER TABLE t1 ULL=DEFAULT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SET @@SQL_MODE=@OLD_SQL_MODE;
+select 1;
+1
+1
UNINSTALL PLUGIN example;
diff --git a/mysql-test/r/plugin_maturity.result b/mysql-test/r/plugin_maturity.result
new file mode 100644
index 00000000000..97147459f6f
--- /dev/null
+++ b/mysql-test/r/plugin_maturity.result
@@ -0,0 +1,2 @@
+INSTALL PLUGIN example SONAME 'ha_example.so';
+ERROR HY000: Can't open shared library 'ha_example.so' (errno: 0 Loading of experimental plugins is prohibited by --plugin-maturity=stable)
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index f21f1d83acd..c802fc0f209 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
+41
execute my_stmt;
COUNT(*)
-39
+41
execute my_stmt;
COUNT(*)
-39
+41
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result
new file mode 100644
index 00000000000..c1aa5704f56
--- /dev/null
+++ b/mysql-test/r/select_pkeycache.result
@@ -0,0 +1,4799 @@
+drop table if exists t1,t2,t3,t4,t11;
+drop table if exists t1_1,t1_2,t9_1,t9_2,t1aa,t2aa;
+drop view if exists v1;
+CREATE TABLE t1 (
+Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
+Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
+);
+INSERT INTO t1 VALUES (9410,9412);
+select period from t1;
+period
+9410
+select * from t1;
+Period Varor_period
+9410 9412
+select t1.* from t1;
+Period Varor_period
+9410 9412
+CREATE TABLE t2 (
+auto int not null auto_increment,
+fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL,
+companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+fld3 char(30) DEFAULT '' NOT NULL,
+fld4 char(35) DEFAULT '' NOT NULL,
+fld5 char(35) DEFAULT '' NOT NULL,
+fld6 char(4) DEFAULT '' NOT NULL,
+UNIQUE fld1 (fld1),
+KEY fld3 (fld3),
+PRIMARY KEY (auto)
+);
+select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%";
+fld3
+imaginable
+select fld3 from t2 where fld3 like "%cultivation" ;
+fld3
+cultivation
+select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3,companynr from t2 where companynr = 58 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3 from t2 order by fld3 desc limit 10;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select fld3 from t2 order by fld3 desc limit 5;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+select fld3 from t2 order by fld3 desc limit 5,5;
+fld3
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select t2.fld3 from t2 where fld3 = 'honeysuckle';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'h%le';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_';
+fld3
+select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
+fld3
+explain select t2.fld3 from t2 where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 ignore index (fld3,not_used);
+ERROR 42000: Key 'not_used' doesn't exist in table 't2'
+explain select fld3 from t2 use index (not_used);
+ERROR 42000: Key 'not_used' doesn't exist in table 't2'
+select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+fld3
+honeysuckle
+honoring
+explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index
+select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
+fld1 fld3
+148504 Colombo
+068305 Colombo
+000000 nondecreasing
+select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes';
+fld1 fld3
+232605 appendixes
+1232605 appendixes
+1232606 appendixes
+1232607 appendixes
+1232608 appendixes
+1232609 appendixes
+select fld1 from t2 where fld1=250501 or fld1="250502";
+fld1
+250501
+250502
+explain select fld1 from t2 where fld1=250501 or fld1="250502";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index
+select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
+fld1
+250501
+250502
+250505
+250601
+explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index
+select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
+fld1 fld3
+218401 faithful
+018007 fanatic
+228311 fated
+018017 featherweight
+218022 feed
+088303 feminine
+058004 Fenton
+038017 fetched
+018054 fetters
+208101 fiftieth
+238007 filial
+013606 fingerings
+218008 finishers
+038205 firearm
+188505 fitting
+202301 Fitzpatrick
+238008 fixedly
+012001 flanking
+018103 flint
+018104 flopping
+188007 flurried
+013602 foldout
+226205 foothill
+232102 forgivably
+228306 forthcoming
+186002 freakish
+208113 freest
+231315 freezes
+036002 funereal
+226209 furnishings
+198006 furthermore
+select fld3 from t2 where fld3 like "L%" and fld3 = "ok";
+fld3
+select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly");
+fld3
+Chantilly
+select fld1,fld3 from t2 where fld1 like "25050%";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select fld1,fld3 from t2 where fld1 like "25050_";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select distinct companynr from t2;
+companynr
+00
+37
+36
+50
+58
+29
+40
+53
+65
+41
+34
+68
+select distinct companynr from t2 order by companynr;
+companynr
+00
+29
+34
+36
+37
+40
+41
+50
+53
+58
+65
+68
+select distinct companynr from t2 order by companynr desc;
+companynr
+68
+65
+58
+53
+50
+41
+40
+37
+36
+34
+29
+00
+select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%";
+fld3 period
+obliterates 9410
+offload 9410
+opaquely 9410
+organizer 9410
+overestimating 9410
+overlay 9410
+select distinct fld3 from t2 where companynr = 34 order by fld3;
+fld3
+absentee
+accessed
+ahead
+alphabetic
+Asiaticizations
+attitude
+aye
+bankruptcies
+belays
+Blythe
+bomb
+boulevard
+bulldozes
+cannot
+caressing
+charcoal
+checksumming
+chess
+clubroom
+colorful
+cosy
+creator
+crying
+Darius
+diffusing
+duality
+Eiffel
+Epiphany
+Ernestine
+explorers
+exterminated
+famine
+forked
+Gershwins
+heaving
+Hodges
+Iraqis
+Italianization
+Lagos
+landslide
+libretto
+Majorca
+mastering
+narrowed
+occurred
+offerers
+Palestine
+Peruvianizes
+pharmaceutic
+poisoning
+population
+Pygmalion
+rats
+realest
+recording
+regimented
+retransmitting
+reviver
+rouses
+scars
+sicker
+sleepwalk
+stopped
+sugars
+translatable
+uncles
+unexpected
+uprisings
+versatility
+vest
+select distinct fld3 from t2 limit 10;
+fld3
+abates
+abiding
+Abraham
+abrogating
+absentee
+abut
+accessed
+accruing
+accumulating
+accuracies
+select distinct fld3 from t2 having fld3 like "A%" limit 10;
+fld3
+abates
+abiding
+Abraham
+abrogating
+absentee
+abut
+accessed
+accruing
+accumulating
+accuracies
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%";
+substring(fld3,1,3)
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+Adl
+adm
+Ado
+ads
+adv
+aer
+aff
+afi
+afl
+afo
+agi
+ahe
+aim
+air
+Ald
+alg
+ali
+all
+alp
+alr
+ama
+ame
+amm
+ana
+and
+ane
+Ang
+ani
+Ann
+Ant
+api
+app
+aqu
+Ara
+arc
+Arm
+arr
+Art
+Asi
+ask
+asp
+ass
+ast
+att
+aud
+Aug
+aut
+ave
+avo
+awe
+aye
+Azt
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10;
+a
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10;
+substring(fld3,1,3)
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10;
+a
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+create table t3 (
+period int not null,
+name char(32) not null,
+companynr int not null,
+price double(11,0),
+price2 double(11,0),
+key (period),
+key (name)
+);
+create temporary table tmp engine = myisam select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+alter table t3 add t2nr int not null auto_increment primary key first;
+drop table tmp;
+SET SQL_BIG_TABLES=1;
+select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10;
+namn
+Abraham Abraham
+abrogating abrogating
+admonishing admonishing
+Adolph Adolph
+afield afield
+aging aging
+ammonium ammonium
+analyzable analyzable
+animals animals
+animized animized
+SET SQL_BIG_TABLES=0;
+select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10;
+concat(fld3," ",fld3)
+Abraham Abraham
+abrogating abrogating
+admonishing admonishing
+Adolph Adolph
+afield afield
+aging aging
+ammonium ammonium
+analyzable analyzable
+animals animals
+animized animized
+select distinct fld5 from t2 limit 10;
+fld5
+neat
+Steinberg
+jarring
+tinily
+balled
+persist
+attainments
+fanatic
+measures
+rightfulness
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
+fld3 count(*)
+affixed 1
+and 1
+annoyers 1
+Anthony 1
+assayed 1
+assurers 1
+attendants 1
+bedlam 1
+bedpost 1
+boasted 1
+SET SQL_BIG_TABLES=1;
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
+fld3 count(*)
+affixed 1
+and 1
+annoyers 1
+Anthony 1
+assayed 1
+assurers 1
+attendants 1
+bedlam 1
+bedpost 1
+boasted 1
+SET SQL_BIG_TABLES=0;
+select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10;
+fld3 repeat("a",length(fld3)) count(*)
+circus aaaaaa 1
+cited aaaaa 1
+Colombo aaaaaaa 1
+congresswoman aaaaaaaaaaaaa 1
+contrition aaaaaaaaaa 1
+corny aaaaa 1
+cultivation aaaaaaaaaaa 1
+definiteness aaaaaaaaaaaa 1
+demultiplex aaaaaaaaaaa 1
+disappointing aaaaaaaaaaaaa 1
+select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2;
+companynr rtrim(space(512+companynr))
+37
+78
+101
+154
+311
+447
+512
+select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3;
+fld3
+explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index period period 4 NULL 1
+1 SIMPLE t1 ref period period 4 test.t3.period 4181
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index period period 4 NULL 1
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
+select period from t1;
+period
+9410
+select period from t1 where period=1900;
+period
+select fld3,period from t1,t2 where fld1 = 011401 order by period;
+fld3 period
+breaking 9410
+select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001;
+fld3 period
+breaking 1001
+explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const fld1 fld1 4 const 1
+1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1
+select fld3,period from t2,t1 where companynr*10 = 37*10;
+fld3 period
+breaking 9410
+Romans 9410
+intercepted 9410
+bewilderingly 9410
+astound 9410
+admonishing 9410
+sumac 9410
+flanking 9410
+combed 9410
+subjective 9410
+scatterbrain 9410
+Eulerian 9410
+Kane 9410
+overlay 9410
+perturb 9410
+goblins 9410
+annihilates 9410
+Wotan 9410
+snatching 9410
+concludes 9410
+laterally 9410
+yelped 9410
+grazing 9410
+Baird 9410
+celery 9410
+misunderstander 9410
+handgun 9410
+foldout 9410
+mystic 9410
+succumbed 9410
+Nabisco 9410
+fingerings 9410
+aging 9410
+afield 9410
+ammonium 9410
+boat 9410
+intelligibility 9410
+Augustine 9410
+teethe 9410
+dreaded 9410
+scholastics 9410
+audiology 9410
+wallet 9410
+parters 9410
+eschew 9410
+quitter 9410
+neat 9410
+Steinberg 9410
+jarring 9410
+tinily 9410
+balled 9410
+persist 9410
+attainments 9410
+fanatic 9410
+measures 9410
+rightfulness 9410
+capably 9410
+impulsive 9410
+starlet 9410
+terminators 9410
+untying 9410
+announces 9410
+featherweight 9410
+pessimist 9410
+daughter 9410
+decliner 9410
+lawgiver 9410
+stated 9410
+readable 9410
+attrition 9410
+cascade 9410
+motors 9410
+interrogate 9410
+pests 9410
+stairway 9410
+dopers 9410
+testicle 9410
+Parsifal 9410
+leavings 9410
+postulation 9410
+squeaking 9410
+contrasted 9410
+leftover 9410
+whiteners 9410
+erases 9410
+Punjab 9410
+Merritt 9410
+Quixotism 9410
+sweetish 9410
+dogging 9410
+scornfully 9410
+bellow 9410
+bills 9410
+cupboard 9410
+sureties 9410
+puddings 9410
+fetters 9410
+bivalves 9410
+incurring 9410
+Adolph 9410
+pithed 9410
+Miles 9410
+trimmings 9410
+tragedies 9410
+skulking 9410
+flint 9410
+flopping 9410
+relaxing 9410
+offload 9410
+suites 9410
+lists 9410
+animized 9410
+multilayer 9410
+standardizes 9410
+Judas 9410
+vacuuming 9410
+dentally 9410
+humanness 9410
+inch 9410
+Weissmuller 9410
+irresponsibly 9410
+luckily 9410
+culled 9410
+medical 9410
+bloodbath 9410
+subschema 9410
+animals 9410
+Micronesia 9410
+repetitions 9410
+Antares 9410
+ventilate 9410
+pityingly 9410
+interdependent 9410
+Graves 9410
+neonatal 9410
+chafe 9410
+honoring 9410
+realtor 9410
+elite 9410
+funereal 9410
+abrogating 9410
+sorters 9410
+Conley 9410
+lectured 9410
+Abraham 9410
+Hawaii 9410
+cage 9410
+hushes 9410
+Simla 9410
+reporters 9410
+Dutchman 9410
+descendants 9410
+groupings 9410
+dissociate 9410
+coexist 9410
+Beebe 9410
+Taoism 9410
+Connally 9410
+fetched 9410
+checkpoints 9410
+rusting 9410
+galling 9410
+obliterates 9410
+traitor 9410
+resumes 9410
+analyzable 9410
+terminator 9410
+gritty 9410
+firearm 9410
+minima 9410
+Selfridge 9410
+disable 9410
+witchcraft 9410
+betroth 9410
+Manhattanize 9410
+imprint 9410
+peeked 9410
+swelling 9410
+interrelationships 9410
+riser 9410
+Gandhian 9410
+peacock 9410
+bee 9410
+kanji 9410
+dental 9410
+scarf 9410
+chasm 9410
+insolence 9410
+syndicate 9410
+alike 9410
+imperial 9410
+convulsion 9410
+railway 9410
+validate 9410
+normalizes 9410
+comprehensive 9410
+chewing 9410
+denizen 9410
+schemer 9410
+chronicle 9410
+Kline 9410
+Anatole 9410
+partridges 9410
+brunch 9410
+recruited 9410
+dimensions 9410
+Chicana 9410
+announced 9410
+praised 9410
+employing 9410
+linear 9410
+quagmire 9410
+western 9410
+relishing 9410
+serving 9410
+scheduling 9410
+lore 9410
+eventful 9410
+arteriole 9410
+disentangle 9410
+cured 9410
+Fenton 9410
+avoidable 9410
+drains 9410
+detectably 9410
+husky 9410
+impelling 9410
+undoes 9410
+evened 9410
+squeezes 9410
+destroyer 9410
+rudeness 9410
+beaner 9410
+boorish 9410
+Everhart 9410
+encompass 9410
+mushrooms 9410
+Alison 9410
+externally 9410
+pellagra 9410
+cult 9410
+creek 9410
+Huffman 9410
+Majorca 9410
+governing 9410
+gadfly 9410
+reassigned 9410
+intentness 9410
+craziness 9410
+psychic 9410
+squabbled 9410
+burlesque 9410
+capped 9410
+extracted 9410
+DiMaggio 9410
+exclamation 9410
+subdirectory 9410
+Gothicism 9410
+feminine 9410
+metaphysically 9410
+sanding 9410
+Miltonism 9410
+freakish 9410
+index 9410
+straight 9410
+flurried 9410
+denotative 9410
+coming 9410
+commencements 9410
+gentleman 9410
+gifted 9410
+Shanghais 9410
+sportswriting 9410
+sloping 9410
+navies 9410
+leaflet 9410
+shooter 9410
+Joplin 9410
+babies 9410
+assails 9410
+admiring 9410
+swaying 9410
+Goldstine 9410
+fitting 9410
+Norwalk 9410
+analogy 9410
+deludes 9410
+cokes 9410
+Clayton 9410
+exhausts 9410
+causality 9410
+sating 9410
+icon 9410
+throttles 9410
+communicants 9410
+dehydrate 9410
+priceless 9410
+publicly 9410
+incidentals 9410
+commonplace 9410
+mumbles 9410
+furthermore 9410
+cautioned 9410
+parametrized 9410
+registration 9410
+sadly 9410
+positioning 9410
+babysitting 9410
+eternal 9410
+hoarder 9410
+congregates 9410
+rains 9410
+workers 9410
+sags 9410
+unplug 9410
+garage 9410
+boulder 9410
+specifics 9410
+Teresa 9410
+Winsett 9410
+convenient 9410
+buckboards 9410
+amenities 9410
+resplendent 9410
+sews 9410
+participated 9410
+Simon 9410
+certificates 9410
+Fitzpatrick 9410
+Evanston 9410
+misted 9410
+textures 9410
+save 9410
+count 9410
+rightful 9410
+chaperone 9410
+Lizzy 9410
+clenched 9410
+effortlessly 9410
+accessed 9410
+beaters 9410
+Hornblower 9410
+vests 9410
+indulgences 9410
+infallibly 9410
+unwilling 9410
+excrete 9410
+spools 9410
+crunches 9410
+overestimating 9410
+ineffective 9410
+humiliation 9410
+sophomore 9410
+star 9410
+rifles 9410
+dialysis 9410
+arriving 9410
+indulge 9410
+clockers 9410
+languages 9410
+Antarctica 9410
+percentage 9410
+ceiling 9410
+specification 9410
+regimented 9410
+ciphers 9410
+pictures 9410
+serpents 9410
+allot 9410
+realized 9410
+mayoral 9410
+opaquely 9410
+hostess 9410
+fiftieth 9410
+incorrectly 9410
+decomposition 9410
+stranglings 9410
+mixture 9410
+electroencephalography 9410
+similarities 9410
+charges 9410
+freest 9410
+Greenberg 9410
+tinting 9410
+expelled 9410
+warm 9410
+smoothed 9410
+deductions 9410
+Romano 9410
+bitterroot 9410
+corset 9410
+securing 9410
+environing 9410
+cute 9410
+Crays 9410
+heiress 9410
+inform 9410
+avenge 9410
+universals 9410
+Kinsey 9410
+ravines 9410
+bestseller 9410
+equilibrium 9410
+extents 9410
+relatively 9410
+pressure 9410
+critiques 9410
+befouled 9410
+rightfully 9410
+mechanizing 9410
+Latinizes 9410
+timesharing 9410
+Aden 9410
+embassies 9410
+males 9410
+shapelessly 9410
+mastering 9410
+Newtonian 9410
+finishers 9410
+abates 9410
+teem 9410
+kiting 9410
+stodgy 9410
+feed 9410
+guitars 9410
+airships 9410
+store 9410
+denounces 9410
+Pyle 9410
+Saxony 9410
+serializations 9410
+Peruvian 9410
+taxonomically 9410
+kingdom 9410
+stint 9410
+Sault 9410
+faithful 9410
+Ganymede 9410
+tidiness 9410
+gainful 9410
+contrary 9410
+Tipperary 9410
+tropics 9410
+theorizers 9410
+renew 9410
+already 9410
+terminal 9410
+Hegelian 9410
+hypothesizer 9410
+warningly 9410
+journalizing 9410
+nested 9410
+Lars 9410
+saplings 9410
+foothill 9410
+labeled 9410
+imperiously 9410
+reporters 9410
+furnishings 9410
+precipitable 9410
+discounts 9410
+excises 9410
+Stalin 9410
+despot 9410
+ripeness 9410
+Arabia 9410
+unruly 9410
+mournfulness 9410
+boom 9410
+slaughter 9410
+Sabine 9410
+handy 9410
+rural 9410
+organizer 9410
+shipyard 9410
+civics 9410
+inaccuracy 9410
+rules 9410
+juveniles 9410
+comprised 9410
+investigations 9410
+stabilizes 9410
+seminaries 9410
+Hunter 9410
+sporty 9410
+test 9410
+weasels 9410
+CERN 9410
+tempering 9410
+afore 9410
+Galatean 9410
+techniques 9410
+error 9410
+veranda 9410
+severely 9410
+Cassites 9410
+forthcoming 9410
+guides 9410
+vanish 9410
+lied 9410
+sawtooth 9410
+fated 9410
+gradually 9410
+widens 9410
+preclude 9410
+evenhandedly 9410
+percentage 9410
+disobedience 9410
+humility 9410
+gleaning 9410
+petted 9410
+bloater 9410
+minion 9410
+marginal 9410
+apiary 9410
+measures 9410
+precaution 9410
+repelled 9410
+primary 9410
+coverings 9410
+Artemia 9410
+navigate 9410
+spatial 9410
+Gurkha 9410
+meanwhile 9410
+Melinda 9410
+Butterfield 9410
+Aldrich 9410
+previewing 9410
+glut 9410
+unaffected 9410
+inmate 9410
+mineral 9410
+impending 9410
+meditation 9410
+ideas 9410
+miniaturizes 9410
+lewdly 9410
+title 9410
+youthfulness 9410
+creak 9410
+Chippewa 9410
+clamored 9410
+freezes 9410
+forgivably 9410
+reduce 9410
+McGovern 9410
+Nazis 9410
+epistle 9410
+socializes 9410
+conceptions 9410
+Kevin 9410
+uncovering 9410
+chews 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+raining 9410
+infest 9410
+compartment 9410
+minting 9410
+ducks 9410
+roped 9410
+waltz 9410
+Lillian 9410
+repressions 9410
+chillingly 9410
+noncritical 9410
+lithograph 9410
+spongers 9410
+parenthood 9410
+posed 9410
+instruments 9410
+filial 9410
+fixedly 9410
+relives 9410
+Pandora 9410
+watering 9410
+ungrateful 9410
+secures 9410
+poison 9410
+dusted 9410
+encompasses 9410
+presentation 9410
+Kantian 9410
+select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price;
+fld3 period price price2
+admonishing 1002 28357832 8723648
+analyzable 1002 28357832 8723648
+annihilates 1001 5987435 234724
+Antares 1002 28357832 8723648
+astound 1001 5987435 234724
+audiology 1001 5987435 234724
+Augustine 1002 28357832 8723648
+Baird 1002 28357832 8723648
+bewilderingly 1001 5987435 234724
+breaking 1001 5987435 234724
+Conley 1001 5987435 234724
+dentally 1002 28357832 8723648
+dissociate 1002 28357832 8723648
+elite 1001 5987435 234724
+eschew 1001 5987435 234724
+Eulerian 1001 5987435 234724
+flanking 1001 5987435 234724
+foldout 1002 28357832 8723648
+funereal 1002 28357832 8723648
+galling 1002 28357832 8723648
+Graves 1001 5987435 234724
+grazing 1001 5987435 234724
+groupings 1001 5987435 234724
+handgun 1001 5987435 234724
+humility 1002 28357832 8723648
+impulsive 1002 28357832 8723648
+inch 1001 5987435 234724
+intelligibility 1001 5987435 234724
+jarring 1001 5987435 234724
+lawgiver 1001 5987435 234724
+lectured 1002 28357832 8723648
+Merritt 1002 28357832 8723648
+neonatal 1001 5987435 234724
+offload 1002 28357832 8723648
+parters 1002 28357832 8723648
+pityingly 1002 28357832 8723648
+puddings 1002 28357832 8723648
+Punjab 1001 5987435 234724
+quitter 1002 28357832 8723648
+realtor 1001 5987435 234724
+relaxing 1001 5987435 234724
+repetitions 1001 5987435 234724
+resumes 1001 5987435 234724
+Romans 1002 28357832 8723648
+rusting 1001 5987435 234724
+scholastics 1001 5987435 234724
+skulking 1002 28357832 8723648
+stated 1002 28357832 8723648
+suites 1002 28357832 8723648
+sureties 1001 5987435 234724
+testicle 1002 28357832 8723648
+tinily 1002 28357832 8723648
+tragedies 1001 5987435 234724
+trimmings 1001 5987435 234724
+vacuuming 1001 5987435 234724
+ventilate 1001 5987435 234724
+wallet 1001 5987435 234724
+Weissmuller 1002 28357832 8723648
+Wotan 1002 28357832 8723648
+select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37;
+fld1 fld3 period price price2
+018201 relaxing 1001 5987435 234724
+018601 vacuuming 1001 5987435 234724
+018801 inch 1001 5987435 234724
+018811 repetitions 1001 5987435 234724
+create table t4 (
+companynr tinyint(2) unsigned zerofill NOT NULL default '00',
+companyname char(30) NOT NULL default '',
+PRIMARY KEY (companynr),
+UNIQUE KEY companyname(companyname)
+) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames';
+select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
+companynr companyname
+00 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
+companynr companyname
+00 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select * from t1,t1 t12;
+Period Varor_period Period Varor_period
+9410 9412 9410 9412
+select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505;
+fld1 fld1
+250501 250501
+250502 250501
+250503 250501
+250504 250501
+250505 250501
+250501 250502
+250502 250502
+250503 250502
+250504 250502
+250505 250502
+250501 250503
+250502 250503
+250503 250503
+250504 250503
+250505 250503
+250501 250504
+250502 250504
+250503 250504
+250504 250504
+250505 250504
+250501 250505
+250502 250505
+250503 250505
+250504 250505
+250505 250505
+insert into t2 (fld1, companynr) values (999999,99);
+select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
+companynr companyname
+99 NULL
+select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null;
+count(*)
+1199
+explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists
+select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+companynr companyname
+select count(*) from t2 left join t4 using (companynr) where companynr is not null;
+count(*)
+1200
+explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+delete from t2 where fld1=999999;
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
+companynr companynr
+37 36
+41 40
+explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909);
+period
+9410
+select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6)));
+period
+9410
+select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1;
+fld1
+250501
+250502
+250503
+250505
+select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606);
+fld1
+250502
+250503
+select fld1 from t2 where fld1 between 250502 and 250504;
+fld1
+250502
+250503
+250504
+select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ;
+fld3
+label
+labeled
+labeled
+landslide
+laterally
+leaflet
+lewdly
+Lillian
+luckily
+select count(*) from t1;
+count(*)
+1
+select companynr,count(*),sum(fld1) from t2 group by companynr;
+companynr count(*) sum(fld1)
+00 82 10355753
+29 95 14473298
+34 70 17788966
+36 215 22786296
+37 588 83602098
+40 37 6618386
+41 52 12816335
+50 11 1595438
+53 4 793210
+58 23 2254293
+65 10 2284055
+68 12 3097288
+select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
+companynr count(*)
+68 12
+65 10
+58 23
+53 4
+50 11
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 100.00 Using where
+Warnings:
+Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> ''))
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
+companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
+29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
+34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
+companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
+37 1 1 5987435 5987435 5987435 5987435.0000
+37 2 1 28357832 28357832 28357832 28357832.0000
+37 3 1 39654943 39654943 39654943 39654943.0000
+37 11 1 5987435 5987435 5987435 5987435.0000
+37 12 1 28357832 28357832 28357832 28357832.0000
+37 13 1 39654943 39654943 39654943 39654943.0000
+37 21 1 5987435 5987435 5987435 5987435.0000
+37 22 1 28357832 28357832 28357832 28357832.0000
+37 23 1 39654943 39654943 39654943 39654943.0000
+37 31 1 5987435 5987435 5987435 5987435.0000
+select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
+companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
+37 1 1 5987435 5987435 5987435 5987435.0000
+37 2 1 28357832 28357832 28357832 28357832.0000
+37 3 1 39654943 39654943 39654943 39654943.0000
+37 11 1 5987435 5987435 5987435 5987435.0000
+37 12 1 28357832 28357832 28357832 28357832.0000
+37 13 1 39654943 39654943 39654943 39654943.0000
+37 21 1 5987435 5987435 5987435 5987435.0000
+37 22 1 28357832 28357832 28357832 28357832.0000
+37 23 1 39654943 39654943 39654943 39654943.0000
+37 31 1 5987435 5987435 5987435 5987435.0000
+select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
+companynr count(price) sum(price) min(price) max(price) avg(price)
+37 12543 309394878010 5987435 39654943 24666736.6667
+78 8362 414611089292 726498 98439034 49582766.0000
+101 4181 3489454238 834598 834598 834598.0000
+154 4181 4112197254950 983543950 983543950 983543950.0000
+311 4181 979599938 234298 234298 234298.0000
+447 4181 9929180954 2374834 2374834 2374834.0000
+512 4181 3288532102 786542 786542 786542.0000
+select distinct mod(companynr,10) from t4 group by companynr;
+mod(companynr,10)
+0
+9
+4
+6
+7
+1
+3
+8
+5
+select distinct 1 from t4 group by companynr;
+1
+1
+select count(distinct fld1) from t2;
+count(distinct fld1)
+1199
+select companynr,count(distinct fld1) from t2 group by companynr;
+companynr count(distinct fld1)
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(*) from t2 group by companynr;
+companynr count(*)
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr;
+companynr count(distinct concat(fld1,repeat(65,1000)))
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr;
+companynr count(distinct concat(fld1,repeat(65,200)))
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct floor(fld1/100)) from t2 group by companynr;
+companynr count(distinct floor(fld1/100))
+00 47
+29 35
+34 14
+36 69
+37 108
+40 16
+41 11
+50 9
+53 1
+58 1
+65 1
+68 1
+select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr;
+companynr count(distinct concat(repeat(65,1000),floor(fld1/100)))
+00 47
+29 35
+34 14
+36 69
+37 108
+40 16
+41 11
+50 9
+53 1
+58 1
+65 1
+68 1
+select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10;
+sum(fld1) fld3
+11402 Romans
+select name,count(*) from t3 where name='cloakroom' group by name;
+name count(*)
+cloakroom 4181
+select name,count(*) from t3 where name='cloakroom' and price>10 group by name;
+name count(*)
+cloakroom 4181
+select count(*) from t3 where name='cloakroom' and price2=823742;
+count(*)
+4181
+select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name;
+name count(*)
+cloakroom 4181
+select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name;
+name count(*)
+extramarital 4181
+gazer 4181
+gems 4181
+Iranizes 4181
+spates 4181
+tucked 4181
+violinist 4181
+select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
+fld3 count(*)
+spates 4181
+select companynr|0,companyname from t4 group by 1;
+companynr|0 companyname
+0 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname;
+companynr companyname count(*)
+29 company 1 95
+68 company 10 12
+50 company 11 11
+34 company 2 70
+36 company 3 215
+37 company 4 588
+40 company 5 37
+41 company 6 52
+53 company 7 4
+58 company 8 23
+65 company 9 10
+00 Unknown 82
+select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
+fld1 count(*)
+158402 4181
+select sum(Period)/count(*) from t1;
+sum(Period)/count(*)
+9410.0000
+select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr;
+companynr count sum diff func
+37 12543 309394878010 0.0000 464091
+78 8362 414611089292 0.0000 652236
+101 4181 3489454238 0.0000 422281
+154 4181 4112197254950 0.0000 643874
+311 4181 979599938 0.0000 1300291
+447 4181 9929180954 0.0000 1868907
+512 4181 3288532102 0.0000 2140672
+select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg;
+companynr avg
+154 983543950.0000
+select companynr,count(*) from t2 group by companynr order by 2 desc;
+companynr count(*)
+37 588
+36 215
+29 95
+00 82
+34 70
+41 52
+40 37
+58 23
+68 12
+50 11
+65 10
+53 4
+select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc;
+companynr count(*)
+41 52
+58 23
+68 12
+50 11
+65 10
+53 4
+select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4;
+fld4 fld1 count(price) sum(price) min(price) max(price) avg(price)
+teethe 000001 1 5987435 5987435 5987435 5987435.0000
+dreaded 011401 1 5987435 5987435 5987435 5987435.0000
+scholastics 011402 1 28357832 28357832 28357832 28357832.0000
+audiology 011403 1 39654943 39654943 39654943 39654943.0000
+wallet 011501 1 5987435 5987435 5987435 5987435.0000
+parters 011701 1 5987435 5987435 5987435 5987435.0000
+eschew 011702 1 28357832 28357832 28357832 28357832.0000
+quitter 011703 1 39654943 39654943 39654943 39654943.0000
+neat 012001 1 5987435 5987435 5987435 5987435.0000
+Steinberg 012003 1 39654943 39654943 39654943 39654943.0000
+balled 012301 1 5987435 5987435 5987435 5987435.0000
+persist 012302 1 28357832 28357832 28357832 28357832.0000
+attainments 012303 1 39654943 39654943 39654943 39654943.0000
+capably 012501 1 5987435 5987435 5987435 5987435.0000
+impulsive 012602 1 28357832 28357832 28357832 28357832.0000
+starlet 012603 1 39654943 39654943 39654943 39654943.0000
+featherweight 012701 1 5987435 5987435 5987435 5987435.0000
+pessimist 012702 1 28357832 28357832 28357832 28357832.0000
+daughter 012703 1 39654943 39654943 39654943 39654943.0000
+lawgiver 013601 1 5987435 5987435 5987435 5987435.0000
+stated 013602 1 28357832 28357832 28357832 28357832.0000
+readable 013603 1 39654943 39654943 39654943 39654943.0000
+testicle 013801 1 5987435 5987435 5987435 5987435.0000
+Parsifal 013802 1 28357832 28357832 28357832 28357832.0000
+leavings 013803 1 39654943 39654943 39654943 39654943.0000
+squeaking 013901 1 5987435 5987435 5987435 5987435.0000
+contrasted 016001 1 5987435 5987435 5987435 5987435.0000
+leftover 016201 1 5987435 5987435 5987435 5987435.0000
+whiteners 016202 1 28357832 28357832 28357832 28357832.0000
+erases 016301 1 5987435 5987435 5987435 5987435.0000
+Punjab 016302 1 28357832 28357832 28357832 28357832.0000
+Merritt 016303 1 39654943 39654943 39654943 39654943.0000
+sweetish 018001 1 5987435 5987435 5987435 5987435.0000
+dogging 018002 1 28357832 28357832 28357832 28357832.0000
+scornfully 018003 1 39654943 39654943 39654943 39654943.0000
+fetters 018012 1 28357832 28357832 28357832 28357832.0000
+bivalves 018013 1 39654943 39654943 39654943 39654943.0000
+skulking 018021 1 5987435 5987435 5987435 5987435.0000
+flint 018022 1 28357832 28357832 28357832 28357832.0000
+flopping 018023 1 39654943 39654943 39654943 39654943.0000
+Judas 018032 1 28357832 28357832 28357832 28357832.0000
+vacuuming 018033 1 39654943 39654943 39654943 39654943.0000
+medical 018041 1 5987435 5987435 5987435 5987435.0000
+bloodbath 018042 1 28357832 28357832 28357832 28357832.0000
+subschema 018043 1 39654943 39654943 39654943 39654943.0000
+interdependent 018051 1 5987435 5987435 5987435 5987435.0000
+Graves 018052 1 28357832 28357832 28357832 28357832.0000
+neonatal 018053 1 39654943 39654943 39654943 39654943.0000
+sorters 018061 1 5987435 5987435 5987435 5987435.0000
+epistle 018062 1 28357832 28357832 28357832 28357832.0000
+Conley 018101 1 5987435 5987435 5987435 5987435.0000
+lectured 018102 1 28357832 28357832 28357832 28357832.0000
+Abraham 018103 1 39654943 39654943 39654943 39654943.0000
+cage 018201 1 5987435 5987435 5987435 5987435.0000
+hushes 018202 1 28357832 28357832 28357832 28357832.0000
+Simla 018402 1 28357832 28357832 28357832 28357832.0000
+reporters 018403 1 39654943 39654943 39654943 39654943.0000
+coexist 018601 1 5987435 5987435 5987435 5987435.0000
+Beebe 018602 1 28357832 28357832 28357832 28357832.0000
+Taoism 018603 1 39654943 39654943 39654943 39654943.0000
+Connally 018801 1 5987435 5987435 5987435 5987435.0000
+fetched 018802 1 28357832 28357832 28357832 28357832.0000
+checkpoints 018803 1 39654943 39654943 39654943 39654943.0000
+gritty 018811 1 5987435 5987435 5987435 5987435.0000
+firearm 018812 1 28357832 28357832 28357832 28357832.0000
+minima 019101 1 5987435 5987435 5987435 5987435.0000
+Selfridge 019102 1 28357832 28357832 28357832 28357832.0000
+disable 019103 1 39654943 39654943 39654943 39654943.0000
+witchcraft 019201 1 5987435 5987435 5987435 5987435.0000
+betroth 030501 1 5987435 5987435 5987435 5987435.0000
+Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000
+imprint 030503 1 39654943 39654943 39654943 39654943.0000
+swelling 031901 1 5987435 5987435 5987435 5987435.0000
+interrelationships 036001 1 5987435 5987435 5987435 5987435.0000
+riser 036002 1 28357832 28357832 28357832 28357832.0000
+bee 038001 1 5987435 5987435 5987435 5987435.0000
+kanji 038002 1 28357832 28357832 28357832 28357832.0000
+dental 038003 1 39654943 39654943 39654943 39654943.0000
+railway 038011 1 5987435 5987435 5987435 5987435.0000
+validate 038012 1 28357832 28357832 28357832 28357832.0000
+normalizes 038013 1 39654943 39654943 39654943 39654943.0000
+Kline 038101 1 5987435 5987435 5987435 5987435.0000
+Anatole 038102 1 28357832 28357832 28357832 28357832.0000
+partridges 038103 1 39654943 39654943 39654943 39654943.0000
+recruited 038201 1 5987435 5987435 5987435 5987435.0000
+dimensions 038202 1 28357832 28357832 28357832 28357832.0000
+Chicana 038203 1 39654943 39654943 39654943 39654943.0000
+select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3;
+companynr fld3 sum(price)
+512 boat 786542
+512 capably 786542
+512 cupboard 786542
+512 decliner 786542
+512 descendants 786542
+512 dopers 786542
+512 erases 786542
+512 Micronesia 786542
+512 Miles 786542
+512 skies 786542
+select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr;
+companynr count(*) min(fld3) max(fld3) sum(price) avg(price)
+00 1 Omaha Omaha 5987435 5987435.0000
+36 1 dubbed dubbed 28357832 28357832.0000
+37 83 Abraham Wotan 1908978016 22999735.1325
+50 2 scribbled tapestry 68012775 34006387.5000
+select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1;
+t3.companynr+0 t2nr fld3 sum(price)
+37 1 Omaha 5987435
+37 11401 breaking 5987435
+37 11402 Romans 28357832
+37 11403 intercepted 39654943
+37 11501 bewilderingly 5987435
+37 11701 astound 5987435
+37 11702 admonishing 28357832
+37 11703 sumac 39654943
+37 12001 flanking 5987435
+37 12003 combed 39654943
+37 12301 Eulerian 5987435
+37 12302 dubbed 28357832
+37 12303 Kane 39654943
+37 12501 annihilates 5987435
+37 12602 Wotan 28357832
+37 12603 snatching 39654943
+37 12701 grazing 5987435
+37 12702 Baird 28357832
+37 12703 celery 39654943
+37 13601 handgun 5987435
+37 13602 foldout 28357832
+37 13603 mystic 39654943
+37 13801 intelligibility 5987435
+37 13802 Augustine 28357832
+37 13803 teethe 39654943
+37 13901 scholastics 5987435
+37 16001 audiology 5987435
+37 16201 wallet 5987435
+37 16202 parters 28357832
+37 16301 eschew 5987435
+37 16302 quitter 28357832
+37 16303 neat 39654943
+37 18001 jarring 5987435
+37 18002 tinily 28357832
+37 18003 balled 39654943
+37 18012 impulsive 28357832
+37 18013 starlet 39654943
+37 18021 lawgiver 5987435
+37 18022 stated 28357832
+37 18023 readable 39654943
+37 18032 testicle 28357832
+37 18033 Parsifal 39654943
+37 18041 Punjab 5987435
+37 18042 Merritt 28357832
+37 18043 Quixotism 39654943
+37 18051 sureties 5987435
+37 18052 puddings 28357832
+37 18053 tapestry 39654943
+37 18061 trimmings 5987435
+37 18062 humility 28357832
+37 18101 tragedies 5987435
+37 18102 skulking 28357832
+37 18103 flint 39654943
+37 18201 relaxing 5987435
+37 18202 offload 28357832
+37 18402 suites 28357832
+37 18403 lists 39654943
+37 18601 vacuuming 5987435
+37 18602 dentally 28357832
+37 18603 humanness 39654943
+37 18801 inch 5987435
+37 18802 Weissmuller 28357832
+37 18803 irresponsibly 39654943
+37 18811 repetitions 5987435
+37 18812 Antares 28357832
+37 19101 ventilate 5987435
+37 19102 pityingly 28357832
+37 19103 interdependent 39654943
+37 19201 Graves 5987435
+37 30501 neonatal 5987435
+37 30502 scribbled 28357832
+37 30503 chafe 39654943
+37 31901 realtor 5987435
+37 36001 elite 5987435
+37 36002 funereal 28357832
+37 38001 Conley 5987435
+37 38002 lectured 28357832
+37 38003 Abraham 39654943
+37 38011 groupings 5987435
+37 38012 dissociate 28357832
+37 38013 coexist 39654943
+37 38101 rusting 5987435
+37 38102 galling 28357832
+37 38103 obliterates 39654943
+37 38201 resumes 5987435
+37 38202 analyzable 28357832
+37 38203 terminator 39654943
+select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008;
+sum(price)
+234298
+select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1;
+fld1 sum(price)
+038008 234298
+explain select fld3 from t2 where 1>2 or 2>3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select fld3 from t2 where fld1=fld1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
+companynr fld1
+34 250501
+34 250502
+select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502;
+companynr fld1
+34 250501
+34 250502
+select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000;
+companynr count sum
+00 82 10355753
+29 95 14473298
+34 70 17788966
+37 588 83602098
+41 52 12816335
+select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ;
+companynr
+00
+29
+34
+37
+41
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40;
+companynr companyname count(*)
+68 company 10 12
+50 company 11 11
+40 company 5 37
+41 company 6 52
+53 company 7 4
+58 company 8 23
+65 company 9 10
+select count(*) from t2;
+count(*)
+1199
+select count(*) from t2 where fld1 < 098024;
+count(*)
+387
+select min(fld1) from t2 where fld1>= 098024;
+min(fld1)
+98024
+select max(fld1) from t2 where fld1>= 098024;
+max(fld1)
+1232609
+select count(*) from t3 where price2=76234234;
+count(*)
+4181
+select count(*) from t3 where companynr=512 and price2=76234234;
+count(*)
+4181
+explain select min(fld1),max(fld1),count(*) from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+select min(fld1),max(fld1),count(*) from t2;
+min(fld1) max(fld1) count(*)
+0 1232609 1199
+select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742;
+min(t2nr) max(t2nr)
+2115 2115
+select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78;
+count(*) min(t2nr) max(t2nr)
+4181 4 41804
+select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20;
+t2nr count(*)
+9 1
+19 1
+29 1
+39 1
+49 1
+59 1
+69 1
+79 1
+89 1
+99 1
+109 1
+119 1
+129 1
+139 1
+149 1
+159 1
+169 1
+179 1
+189 1
+199 1
+select max(t2nr) from t3 where price=983543950;
+max(t2nr)
+41807
+select t1.period from t3 = t1 limit 1;
+period
+1001
+select t1.period from t1 as t1 limit 1;
+period
+9410
+select t1.period as "Nuvarande period" from t1 as t1 limit 1;
+Nuvarande period
+9410
+select period as ok_period from t1 limit 1;
+ok_period
+9410
+select period as ok_period from t1 group by ok_period limit 1;
+ok_period
+9410
+select 1+1 as summa from t1 group by summa limit 1;
+summa
+2
+select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1;
+Nuvarande period
+9410
+show tables;
+Tables_in_test
+t1
+t2
+t3
+t4
+show tables from test like "s%";
+Tables_in_test (s%)
+show tables from test like "t?";
+Tables_in_test (t?)
+show full columns from t2;
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(11) NULL NO PRI NULL auto_increment #
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+companynr tinyint(2) unsigned zerofill NULL NO 00 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
+show full columns from t2 from test like 'f%';
+Field Type Collation Null Key Default Extra Privileges Comment
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
+show full columns from t2 from test like 's%';
+Field Type Collation Null Key Default Extra Privileges Comment
+show keys from t2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE
+t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE
+t2 1 fld3 1 fld3 A NULL NULL NULL BTREE
+drop table t4, t3, t2, t1;
+DO 1;
+DO benchmark(100,1+1),1,1;
+do default;
+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 '' at line 1
+do foobar;
+ERROR 42S22: Unknown column 'foobar' in 'field list'
+CREATE TABLE t1 (
+id mediumint(8) unsigned NOT NULL auto_increment,
+pseudo varchar(35) NOT NULL default '',
+PRIMARY KEY (id),
+UNIQUE KEY pseudo (pseudo)
+);
+INSERT INTO t1 (pseudo) VALUES ('test');
+INSERT INTO t1 (pseudo) VALUES ('test1');
+SELECT 1 as rnd1 from t1 where rand() > 2;
+rnd1
+DROP TABLE t1;
+CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL);
+CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35);
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+gvid the_success the_fail the_size the_time
+Warnings:
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
+SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
+gvid the_success the_fail the_size the_time
+DROP TABLE t1,t2;
+create table t1 ( A_Id bigint(20) NOT NULL default '0', A_UpdateBy char(10) NOT NULL default '', A_UpdateDate bigint(20) NOT NULL default '0', A_UpdateSerial int(11) NOT NULL default '0', other_types bigint(20) NOT NULL default '0', wss_type bigint(20) NOT NULL default '0');
+INSERT INTO t1 VALUES (102935998719055004,'brade',1029359987,2,102935229116544068,102935229216544093);
+select wss_type from t1 where wss_type ='102935229216544106';
+wss_type
+select wss_type from t1 where wss_type ='102935229216544105';
+wss_type
+select wss_type from t1 where wss_type ='102935229216544104';
+wss_type
+select wss_type from t1 where wss_type ='102935229216544093';
+wss_type
+102935229216544093
+select wss_type from t1 where wss_type =102935229216544093;
+wss_type
+102935229216544093
+drop table t1;
+select 1+2,"aaaa",3.13*2.0 into @a,@b,@c;
+select @a;
+@a
+3
+select @b;
+@b
+aaaa
+select @c;
+@c
+6.260
+create table t1 (a int not null auto_increment primary key);
+insert into t1 values ();
+insert into t1 values ();
+insert into t1 values ();
+select * from (t1 as t2 left join t1 as t3 using (a)), t1;
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1, (t1 as t2 left join t1 as t3 using (a));
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) straight_join t1;
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1 straight_join (t1 as t2 left join t1 as t3 using (a));
+a a
+1 1
+2 1
+3 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 on t1.a>1;
+a a
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 using ( a );
+a
+1
+2
+3
+select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) using ( a );
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) left outer join t1 on t1.a>1;
+a a
+1 2
+1 3
+2 2
+2 3
+3 2
+3 3
+select * from t1 left outer join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+1 NULL
+2 1
+2 2
+2 3
+3 1
+3 2
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) left join t1 using ( a );
+a
+1
+2
+3
+select * from t1 left join (t1 as t2 left join t1 as t3 using (a)) using ( a );
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
+a
+1
+2
+3
+select * from t1 natural left join (t1 as t2 left join t1 as t3 using (a));
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
+a a
+NULL 1
+1 2
+2 2
+3 2
+1 3
+2 3
+3 3
+select * from t1 right join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a a
+2 1
+3 1
+2 2
+3 2
+2 3
+3 3
+select * from (t1 as t2 left join t1 as t3 using (a)) right outer join t1 using ( a );
+a
+1
+2
+3
+select * from t1 right outer join (t1 as t2 left join t1 as t3 using (a)) using ( a );
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) natural right join t1;
+a
+1
+2
+3
+select * from t1 natural right join (t1 as t2 left join t1 as t3 using (a));
+a
+1
+2
+3
+select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
+a
+1
+2
+3
+select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
+a
+1
+2
+3
+drop table t1;
+CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
+CREATE TABLE t2 ( id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (2517), (2518), (2519), (2520), (2521), (2522);
+select * from t1, t2 WHERE t1.t2_id = t2.id and t1.t2_id > 0 order by t1.id LIMIT 0, 5;
+aa id t2_id id
+2 8299 2517 2517
+3 8301 2518 2518
+4 8302 2519 2519
+5 8303 2520 2520
+6 8304 2521 2521
+drop table t1,t2;
+create table t1 (id1 int NOT NULL);
+create table t2 (id2 int NOT NULL);
+create table t3 (id3 int NOT NULL);
+create table t4 (id4 int NOT NULL, id44 int NOT NULL, KEY (id4));
+insert into t1 values (1);
+insert into t1 values (2);
+insert into t2 values (1);
+insert into t4 values (1,1);
+explain select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3
+left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t4 const id4 NULL NULL NULL 1
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where
+select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3
+left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
+id1 id2 id3 id4 id44
+1 1 NULL NULL NULL
+drop table t1,t2,t3,t4;
+create table t1(s varchar(10) not null);
+create table t2(s varchar(10) not null primary key);
+create table t3(s varchar(10) not null primary key);
+insert into t1 values ('one\t'), ('two\t');
+insert into t2 values ('one\r'), ('two\t');
+insert into t3 values ('one '), ('two\t');
+select * from t1 where s = 'one';
+s
+select * from t2 where s = 'one';
+s
+select * from t3 where s = 'one';
+s
+one
+select * from t1,t2 where t1.s = t2.s;
+s s
+two two
+select * from t2,t3 where t2.s = t3.s;
+s s
+two two
+drop table t1, t2, t3;
+create table t1 (a integer, b integer, index(a), index(b));
+create table t2 (c integer, d integer, index(c), index(d));
+insert into t1 values (1,2), (2,2), (3,2), (4,2);
+insert into t2 values (1,3), (2,3), (3,4), (4,4);
+explain select * from t1 left join t2 on a=c where d in (4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer
+select * from t1 left join t2 on a=c where d in (4);
+a b c d
+3 2 3 4
+4 2 4 4
+explain select * from t1 left join t2 on a=c where d = 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 4 Using where; Using join buffer
+select * from t1 left join t2 on a=c where d = 4;
+a b c d
+3 2 3 4
+4 2 4 4
+drop table t1, t2;
+CREATE TABLE t1 (
+i int(11) NOT NULL default '0',
+c char(10) NOT NULL default '',
+PRIMARY KEY (i),
+UNIQUE KEY c (c)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,'a');
+INSERT INTO t1 VALUES (2,'b');
+INSERT INTO t1 VALUES (3,'c');
+EXPLAIN SELECT i FROM t1 WHERE i=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+DROP TABLE t1;
+CREATE TABLE t1 ( a BLOB, INDEX (a(20)) );
+CREATE TABLE t2 ( a BLOB, INDEX (a(20)) );
+INSERT INTO t1 VALUES ('one'),('two'),('three'),('four'),('five');
+INSERT INTO t2 VALUES ('one'),('two'),('three'),('four'),('five');
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref a a 23 test.t1.a 2
+DROP TABLE t1, t2;
+CREATE TABLE t1 ( city char(30) );
+INSERT INTO t1 VALUES ('London');
+INSERT INTO t1 VALUES ('Paris');
+SELECT * FROM t1 WHERE city='London';
+city
+London
+SELECT * FROM t1 WHERE city='london';
+city
+London
+EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+SELECT * FROM t1 WHERE city='London' AND city='london';
+city
+London
+EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London';
+city
+London
+DROP TABLE t1;
+create table t1 (a int(11) unsigned, b int(11) unsigned);
+insert into t1 values (1,0), (1,1), (1,2);
+select a-b from t1 order by 1;
+a-b
+0
+1
+18446744073709551615
+select a-b , (a-b < 0) from t1 order by 1;
+a-b (a-b < 0)
+0 0
+1 0
+18446744073709551615 0
+select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0;
+d (a-b >= 0) b
+1 1 0
+0 1 1
+18446744073709551615 1 2
+select cast((a - b) as unsigned) from t1 order by 1;
+cast((a - b) as unsigned)
+0
+1
+18446744073709551615
+drop table t1;
+create table t1 (a int(11));
+select all all * from t1;
+a
+select distinct distinct * from t1;
+a
+select all distinct * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+select distinct all * from t1;
+ERROR HY000: Incorrect usage of ALL and DISTINCT
+drop table t1;
+CREATE TABLE t1 (
+kunde_intern_id int(10) unsigned NOT NULL default '0',
+kunde_id int(10) unsigned NOT NULL default '0',
+FK_firma_id int(10) unsigned NOT NULL default '0',
+aktuell enum('Ja','Nein') NOT NULL default 'Ja',
+vorname varchar(128) NOT NULL default '',
+nachname varchar(128) NOT NULL default '',
+geloescht enum('Ja','Nein') NOT NULL default 'Nein',
+firma varchar(128) NOT NULL default ''
+);
+INSERT INTO t1 VALUES
+(3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'),
+(3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX');
+SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1
+WHERE
+(
+(
+( '' != '' AND firma LIKE CONCAT('%', '', '%'))
+OR
+(vorname LIKE CONCAT('%', 'Vorname1', '%') AND
+nachname LIKE CONCAT('%', '1Nachname', '%') AND
+'Vorname1' != '' AND 'xxxx' != '')
+)
+AND
+(
+aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2
+)
+)
+;
+kunde_id FK_firma_id aktuell vorname nachname geloescht
+SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname,
+geloescht FROM t1
+WHERE
+(
+(
+aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2
+)
+AND
+(
+( '' != '' AND firma LIKE CONCAT('%', '', '%') )
+OR
+( vorname LIKE CONCAT('%', 'Vorname1', '%') AND
+nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND
+'xxxx' != '')
+)
+)
+;
+kunde_id FK_firma_id aktuell vorname nachname geloescht
+SELECT COUNT(*) FROM t1 WHERE
+( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1))
+AND FK_firma_id = 2;
+COUNT(*)
+0
+drop table t1;
+CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b));
+INSERT INTO t1 VALUES (0x8000000000000000);
+SELECT b FROM t1 WHERE b=0x8000000000000000;
+b
+9223372036854775808
+DROP TABLE t1;
+CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL);
+CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL);
+INSERT INTO `t2` VALUES (0,'READ');
+CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL);
+INSERT INTO `t3` VALUES (1,'fs');
+select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0);
+id name gid uid ident level
+1 fs NULL NULL 0 READ
+drop table t1,t2,t3;
+CREATE TABLE t1 (
+acct_id int(11) NOT NULL default '0',
+profile_id smallint(6) default NULL,
+UNIQUE KEY t1$acct_id (acct_id),
+KEY t1$profile_id (profile_id)
+);
+INSERT INTO t1 VALUES (132,17),(133,18);
+CREATE TABLE t2 (
+profile_id smallint(6) default NULL,
+queue_id int(11) default NULL,
+seq int(11) default NULL,
+KEY t2$queue_id (queue_id)
+);
+INSERT INTO t2 VALUES (17,31,4),(17,30,3),(17,36,2),(17,37,1);
+CREATE TABLE t3 (
+id int(11) NOT NULL default '0',
+qtype int(11) default NULL,
+seq int(11) default NULL,
+warn_lvl int(11) default NULL,
+crit_lvl int(11) default NULL,
+rr1 tinyint(4) NOT NULL default '0',
+rr2 int(11) default NULL,
+default_queue tinyint(4) NOT NULL default '0',
+KEY t3$qtype (qtype),
+KEY t3$id (id)
+);
+INSERT INTO t3 VALUES (30,1,29,NULL,NULL,0,NULL,0),(31,1,28,NULL,NULL,0,NULL,0),
+(36,1,34,NULL,NULL,0,NULL,0),(37,1,35,NULL,NULL,0,121,0);
+SELECT COUNT(*) FROM t1 a STRAIGHT_JOIN t2 pq STRAIGHT_JOIN t3 q
+WHERE
+(pq.profile_id = a.profile_id) AND (a.acct_id = 132) AND
+(pq.queue_id = q.id) AND (q.rr1 <> 1);
+COUNT(*)
+4
+drop table t1,t2,t3;
+create table t1 (f1 int);
+insert into t1 values (1),(NULL);
+create table t2 (f2 int, f3 int, f4 int);
+create index idx1 on t2 (f4);
+insert into t2 values (1,2,3),(2,4,6);
+select A.f2 from t1 left join t2 A on A.f2 = f1 where A.f3=(select min(f3)
+from t2 C where A.f4 = C.f4) or A.f3 IS NULL;
+f2
+1
+NULL
+drop table t1,t2;
+create table t2 (a tinyint unsigned);
+create index t2i on t2(a);
+insert into t2 values (0), (254), (255);
+explain select * from t2 where a > -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index t2i t2i 2 NULL 3 Using where; Using index
+select * from t2 where a > -1;
+a
+0
+254
+255
+drop table t2;
+CREATE TABLE t1 (a int, b int, c int);
+INSERT INTO t1
+SELECT 50, 3, 3 FROM DUAL
+WHERE NOT EXISTS
+(SELECT * FROM t1 WHERE a = 50 AND b = 3);
+SELECT * FROM t1;
+a b c
+50 3 3
+INSERT INTO t1
+SELECT 50, 3, 3 FROM DUAL
+WHERE NOT EXISTS
+(SELECT * FROM t1 WHERE a = 50 AND b = 3);
+select found_rows();
+found_rows()
+0
+SELECT * FROM t1;
+a b c
+50 3 3
+select count(*) from t1;
+count(*)
+1
+select found_rows();
+found_rows()
+1
+select count(*) from t1 limit 2,3;
+count(*)
+select found_rows();
+found_rows()
+0
+select SQL_CALC_FOUND_ROWS count(*) from t1 limit 2,3;
+count(*)
+select found_rows();
+found_rows()
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT);
+(SELECT a, b AS c FROM t1) ORDER BY c+1;
+a c
+(SELECT a, b AS c FROM t1) ORDER BY b+1;
+a c
+SELECT a, b AS c FROM t1 ORDER BY c+1;
+a c
+SELECT a, b AS c FROM t1 ORDER BY b+1;
+a c
+drop table t1;
+create table t1(f1 int, f2 int);
+create table t2(f3 int);
+select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,1));
+f1
+select f1 from t1,t2 where f1=f2 and (f1,NULL) = ((1,1));
+f1
+select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,NULL));
+f1
+insert into t1 values(1,1),(2,null);
+insert into t2 values(2);
+select * from t1,t2 where f1=f3 and (f1,f2) = (2,null);
+f1 f2 f3
+select * from t1,t2 where f1=f3 and (f1,f2) <=> (2,null);
+f1 f2 f3
+2 NULL 2
+drop table t1,t2;
+create table t1 (f1 int not null auto_increment primary key, f2 varchar(10));
+create table t11 like t1;
+insert into t1 values(1,""),(2,"");
+show table status like 't1%';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 10 Dynamic 2 20 X X X X X X X X latin1_swedish_ci NULL
+t11 MyISAM 10 Dynamic 0 0 X X X X X X X X latin1_swedish_ci NULL
+select 123 as a from t1 where f1 is null;
+a
+drop table t1,t11;
+CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL, UNIQUE idx (a,b) );
+INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4);
+CREATE TABLE t2 ( a INT NOT NULL, b INT NOT NULL, e INT );
+INSERT INTO t2 VALUES ( 1,10,1), (1,10,2), (1,11,1), (1,11,2), (1,2,1), (1,2,2),(1,2,3);
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2 LEFT JOIN
+t1 ON t2.a = t1.a AND t2.b = t1.b GROUP BY a, b, c;
+a b c d
+1 2 1 1
+1 2 2 1
+1 2 3 1
+1 10 2
+1 11 2
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2 LEFT JOIN
+t1 ON t2.a = t1.a AND t2.b = t1.b GROUP BY t1.a, t1.b, c;
+a b c d
+1 10 4
+1 2 1 1
+1 2 2 1
+1 2 3 1
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2 LEFT JOIN
+t1 ON t2.a = t1.a AND t2.b = t1.b GROUP BY t2.a, t2.b, c;
+a b c d
+1 2 1 1
+1 2 2 1
+1 2 3 1
+1 10 2
+1 11 2
+SELECT t2.a, t2.b, IF(t1.b IS NULL,'',e) AS c, COUNT(*) AS d FROM t2,t1
+WHERE t2.a = t1.a AND t2.b = t1.b GROUP BY a, b, c;
+a b c d
+1 2 1 1
+1 2 2 1
+1 2 3 1
+DROP TABLE IF EXISTS t1, t2;
+create table t1 (f1 int primary key, f2 int);
+create table t2 (f3 int, f4 int, primary key(f3,f4));
+insert into t1 values (1,1);
+insert into t2 values (1,1),(1,2);
+select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1;
+count(f2) >0
+1
+drop table t1,t2;
+create table t1 (f1 int,f2 int);
+insert into t1 values(1,1);
+create table t2 (f3 int, f4 int, primary key(f3,f4));
+insert into t2 values(1,1);
+select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2));
+f1 f2
+1 1
+drop table t1,t2;
+CREATE TABLE t1(a int, b int, c int, KEY b(b), KEY c(c));
+insert into t1 values (1,0,0),(2,0,0);
+CREATE TABLE t2 (a int, b varchar(2), c varchar(2), PRIMARY KEY(a));
+insert into t2 values (1,'',''), (2,'','');
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a,b), KEY a (a), KEY b (b));
+insert into t3 values (1,1),(1,2);
+explain select straight_join DISTINCT t2.a,t2.b, t1.c from t1, t3, t2
+where (t1.c=t2.a or (t1.c=t3.a and t2.a=t3.b)) and t1.b=556476786 and
+t2.b like '%%' order by t2.b limit 0,1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref b,c b 5 const 1 Using where; Using temporary; Using filesort
+1 SIMPLE t3 index PRIMARY,a,b PRIMARY 8 NULL 2 Using index; Using join buffer
+1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 2 Range checked for each record (index map: 0x1)
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 (a int, INDEX idx(a));
+INSERT INTO t1 VALUES (2), (3), (1);
+EXPLAIN SELECT * FROM t1 IGNORE INDEX (idx);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+EXPLAIN SELECT * FROM t1 IGNORE INDEX (a);
+ERROR 42000: Key 'a' doesn't exist in table 't1'
+EXPLAIN SELECT * FROM t1 FORCE INDEX (a);
+ERROR 42000: Key 'a' doesn't exist in table 't1'
+DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,1), (2,1), (4,10);
+CREATE TABLE t2 (a int PRIMARY KEY, b int, KEY b (b));
+INSERT INTO t2 VALUES (1,NULL), (2,10);
+ALTER TABLE t1 ENABLE KEYS;
+EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index b b 5 NULL 2 Using index
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+a b a b
+1 NULL 1 1
+1 NULL 2 1
+1 NULL 4 10
+2 10 4 10
+EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 index b b 5 NULL 2 Using index
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL;
+a b a b
+1 NULL 1 1
+1 NULL 2 1
+1 NULL 4 10
+2 10 4 10
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1));
+CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2));
+INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941);
+INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941);
+explain select max(key1) from t1 where key1 <= 0.6158;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select max(key2) from t2 where key2 <= 1.6158;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select min(key1) from t1 where key1 >= 0.3762;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select min(key2) from t2 where key2 >= 1.3762;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select max(key1), min(key2) from t1, t2
+where key1 <= 0.6158 and key2 >= 1.3762;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+select max(key1) from t1 where key1 <= 0.6158;
+max(key1)
+0.615800023078918
+select max(key2) from t2 where key2 <= 1.6158;
+max(key2)
+1.61580002307892
+select min(key1) from t1 where key1 >= 0.3762;
+min(key1)
+0.376199990510941
+select min(key2) from t2 where key2 >= 1.3762;
+min(key2)
+1.37619996070862
+select max(key1), min(key2) from t1, t2
+where key1 <= 0.6158 and key2 >= 1.3762;
+max(key1) min(key2)
+0.615800023078918 1.37619996070862
+select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
+max(key1)
+0.615800023078918
+select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
+min(key1)
+0.376199990510941
+DROP TABLE t1,t2;
+CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL);
+INSERT INTO t1 VALUES (10);
+SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1;
+i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01')
+1 1 1 1
+DROP TABLE t1;
+create table t1(a bigint unsigned, b bigint);
+insert into t1 values (0xfffffffffffffffff, 0xfffffffffffffffff),
+(0x10000000000000000, 0x10000000000000000),
+(0x8fffffffffffffff, 0x8fffffffffffffff);
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+Warning 1264 Out of range value for column 'b' at row 1
+Warning 1264 Out of range value for column 'a' at row 2
+Warning 1264 Out of range value for column 'b' at row 2
+Warning 1264 Out of range value for column 'b' at row 3
+select hex(a), hex(b) from t1;
+hex(a) hex(b)
+FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF
+8FFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF
+drop table t1;
+CREATE TABLE t1 (c0 int);
+CREATE TABLE t2 (c0 int);
+INSERT INTO t1 VALUES(@@connect_timeout);
+INSERT INTO t2 VALUES(@@connect_timeout);
+SELECT * FROM t1 JOIN t2 ON t1.c0 = t2.c0 WHERE (t1.c0 <=> @@connect_timeout);
+c0 c0
+X X
+DROP TABLE t1, t2;
+End of 4.1 tests
+CREATE TABLE t1 (
+K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
+K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
+F2I4 int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES
+('W%RT', '0100', 1),
+('W-RT', '0100', 1),
+('WART', '0100', 1),
+('WART', '0200', 1),
+('WERT', '0100', 2),
+('WORT','0200', 2),
+('WT', '0100', 2),
+('W_RT', '0100', 2),
+('WaRT', '0100', 3),
+('WART', '0300', 3),
+('WRT' , '0400', 3),
+('WURM', '0500', 3),
+('W%T', '0600', 4),
+('WA%T', '0700', 4),
+('WA_T', '0800', 4);
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND
+(F2I4 = 2 AND K2C4 = 'WART' OR (F2I4 = 2 OR K4N4 = '0200'));
+K2C4 K4N4 F2I4
+WART 0200 1
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND (K2C4 = 'WART' OR K4N4 = '0200');
+K2C4 K4N4 F2I4
+WART 0100 1
+WART 0200 1
+WART 0300 3
+DROP TABLE t1;
+create table t1 (a int, b int);
+create table t2 like t1;
+select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
+a
+select t1.a from ((t1 inner join t2 on t1.a=t2.a)) where t2.a=1;
+a
+select x.a, y.a, z.a from ( (t1 x inner join t2 y on x.a=y.a) inner join t2 z on y.a=z.a) WHERE x.a=1;
+a a a
+drop table t1,t2;
+create table t1 (s1 varchar(5));
+insert into t1 values ('Wall');
+select min(s1) from t1 group by s1 with rollup;
+min(s1)
+Wall
+Wall
+drop table t1;
+create table t1 (s1 int) engine=myisam;
+insert into t1 values (0);
+select avg(distinct s1) from t1 group by s1 with rollup;
+avg(distinct s1)
+0.0000
+0.0000
+drop table t1;
+create table t1 (s1 int);
+insert into t1 values (null),(1);
+select distinct avg(s1) as x from t1 group by s1 with rollup;
+x
+NULL
+1.0000
+drop table t1;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
+INSERT INTO t2 VALUES (2), (4), (6);
+SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+a
+2
+4
+EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer
+EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer
+DROP TABLE t1,t2;
+select x'10' + 0, X'10' + 0, b'10' + 0, B'10' + 0;
+x'10' + 0 X'10' + 0 b'10' + 0 B'10' + 0
+16 16 2 2
+create table t1 (f1 varchar(6) default NULL, f2 int(6) primary key not null);
+create table t2 (f3 varchar(5) not null, f4 varchar(5) not null, UNIQUE KEY UKEY (f3,f4));
+insert into t1 values (" 2", 2);
+insert into t2 values (" 2", " one "),(" 2", " two ");
+select * from t1 left join t2 on f1 = f3;
+f1 f2 f3 f4
+ 2 2 2 one
+ 2 2 2 two
+drop table t1,t2;
+create table t1 (empnum smallint, grp int);
+create table t2 (empnum int, name char(5));
+insert into t1 values(1,1);
+insert into t2 values(1,'bob');
+create view v1 as select * from t2 inner join t1 using (empnum);
+select * from v1;
+empnum name grp
+1 bob 1
+drop table t1,t2;
+drop view v1;
+create table t1 (pk int primary key, b int);
+create table t2 (pk int primary key, c int);
+select pk from t1 inner join t2 using (pk);
+pk
+drop table t1,t2;
+create table t1 (s1 int, s2 char(5), s3 decimal(10));
+create view v1 as select s1, s2, 'x' as s3 from t1;
+select * from t1 natural join v1;
+s1 s2 s3
+insert into t1 values (1,'x',5);
+select * from t1 natural join v1;
+s1 s2 s3
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'x'
+drop table t1;
+drop view v1;
+create table t1(a1 int);
+create table t2(a2 int);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+create view v2 (c) as select a1 from t1;
+select * from t1 natural left join t2;
+a1 a2
+1 1
+1 2
+2 1
+2 2
+select * from t1 natural right join t2;
+a2 a1
+1 1
+1 2
+2 1
+2 2
+select * from v2 natural left join t2;
+c a2
+1 1
+1 2
+2 1
+2 2
+select * from v2 natural right join t2;
+a2 c
+1 1
+1 2
+2 1
+2 2
+drop table t1, t2;
+drop view v2;
+create table t1 (a int(10), t1_val int(10));
+create table t2 (b int(10), t2_val int(10));
+create table t3 (a int(10), b int(10));
+insert into t1 values (1,1),(2,2);
+insert into t2 values (1,1),(2,2),(3,3);
+insert into t3 values (1,1),(2,1),(3,1),(4,1);
+select * from t1 natural join t2 natural join t3;
+a b t1_val t2_val
+1 1 1 1
+2 1 2 1
+select * from t1 natural join t3 natural join t2;
+b a t1_val t2_val
+1 1 1 1
+1 2 2 1
+drop table t1, t2, t3;
+DO IFNULL(NULL, NULL);
+SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
+CAST(IFNULL(NULL, NULL) AS DECIMAL)
+NULL
+SELECT ABS(IFNULL(NULL, NULL));
+ABS(IFNULL(NULL, NULL))
+NULL
+SELECT IFNULL(NULL, NULL);
+IFNULL(NULL, NULL)
+NULL
+SET @OLD_SQL_MODE12595=@@SQL_MODE, @@SQL_MODE='';
+SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
+Variable_name Value
+sql_mode
+CREATE TABLE BUG_12595(a varchar(100));
+INSERT INTO BUG_12595 VALUES ('hakan%'), ('hakank'), ("ha%an");
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
+a
+hakan%
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
+a
+hakan%
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
+a
+hakan%
+hakank
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '';
+a
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha%%an' ESCAPE '%';
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE '\\';
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
+a
+ha%an
+SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
+SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
+Variable_name Value
+sql_mode NO_BACKSLASH_ESCAPES
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
+a
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
+a
+hakan%
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '\\';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
+ERROR HY000: Incorrect arguments to ESCAPE
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
+a
+ha%an
+SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\n%' ESCAPE '\n';
+ERROR HY000: Incorrect arguments to ESCAPE
+SET @@SQL_MODE=@OLD_SQL_MODE12595;
+DROP TABLE BUG_12595;
+create table t1 (a char(1));
+create table t2 (a char(1));
+insert into t1 values ('a'),('b'),('c');
+insert into t2 values ('b'),('c'),('d');
+select a from t1 natural join t2;
+a
+b
+c
+select * from t1 natural join t2 where a = 'b';
+a
+b
+drop table t1, t2;
+CREATE TABLE t1 (`id` TINYINT);
+CREATE TABLE t2 (`id` TINYINT);
+CREATE TABLE t3 (`id` TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t2 VALUES (2);
+INSERT INTO t3 VALUES (3);
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.notacolumn=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id);
+ERROR 23000: Column 'id' in from clause is ambiguous
+drop table t1, t2, t3;
+create table t1 (a int(10),b int(10));
+create table t2 (a int(10),b int(10));
+insert into t1 values (1,10),(2,20),(3,30);
+insert into t2 values (1,10);
+select * from t1 inner join t2 using (A);
+a b b
+1 10 10
+select * from t1 inner join t2 using (a);
+a b b
+1 10 10
+drop table t1, t2;
+create table t1 (a int, c int);
+create table t2 (b int);
+create table t3 (b int, a int);
+create table t4 (c int);
+insert into t1 values (1,1);
+insert into t2 values (1);
+insert into t3 values (1,1);
+insert into t4 values (1);
+select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+a c b b a
+1 1 1 1 1
+select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a);
+ERROR 42S22: Unknown column 't1.a' in 'on clause'
+select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c);
+a c b b a c
+1 1 1 1 1 1
+select * from t1 join t2 join t4 using (c);
+c a b
+1 1 1
+drop table t1, t2, t3, t4;
+create table t1(x int, y int);
+create table t2(x int, y int);
+create table t3(x int, primary key(x));
+insert into t1 values (1, 1), (2, 1), (3, 1), (4, 3), (5, 6), (6, 6);
+insert into t2 values (1, 1), (2, 1), (3, 3), (4, 6), (5, 6);
+insert into t3 values (1), (2), (3), (4), (5);
+select t1.x, t3.x from t1, t2, t3 where t1.x = t2.x and t3.x >= t1.y and t3.x <= t2.y;
+x x
+1 1
+2 1
+3 1
+3 2
+3 3
+4 3
+4 4
+4 5
+drop table t1,t2,t3;
+create table t1 (id char(16) not null default '', primary key (id));
+insert into t1 values ('100'),('101'),('102');
+create table t2 (id char(16) default null);
+insert into t2 values (1);
+create view v1 as select t1.id from t1;
+create view v2 as select t2.id from t2;
+create view v3 as select (t1.id+2) as id from t1 natural left join t2;
+select t1.id from t1 left join v2 using (id);
+id
+100
+101
+102
+select t1.id from v2 right join t1 using (id);
+id
+100
+101
+102
+select t1.id from t1 left join v3 using (id);
+id
+100
+101
+102
+select * from t1 left join v2 using (id);
+id
+100
+101
+102
+select * from v2 right join t1 using (id);
+id
+100
+101
+102
+select * from t1 left join v3 using (id);
+id
+100
+101
+102
+select v1.id from v1 left join v2 using (id);
+id
+100
+101
+102
+select v1.id from v2 right join v1 using (id);
+id
+100
+101
+102
+select v1.id from v1 left join v3 using (id);
+id
+100
+101
+102
+select * from v1 left join v2 using (id);
+id
+100
+101
+102
+select * from v2 right join v1 using (id);
+id
+100
+101
+102
+select * from v1 left join v3 using (id);
+id
+100
+101
+102
+drop table t1, t2;
+drop view v1, v2, v3;
+create table t1 (id int(11) not null default '0');
+insert into t1 values (123),(191),(192);
+create table t2 (id char(16) character set utf8 not null);
+insert into t2 values ('58013'),('58014'),('58015'),('58016');
+create table t3 (a_id int(11) not null, b_id char(16) character set utf8);
+insert into t3 values (123,null),(123,null),(123,null),(123,null),(123,null),(123,'58013');
+select count(*)
+from t1 inner join (t3 left join t2 on t2.id = t3.b_id) on t1.id = t3.a_id;
+count(*)
+6
+select count(*)
+from t1 inner join (t2 right join t3 on t2.id = t3.b_id) on t1.id = t3.a_id;
+count(*)
+6
+drop table t1,t2,t3;
+create table t1 (a int);
+create table t2 (b int);
+create table t3 (c int);
+select * from t1 join t2 join t3 on (t1.a=t3.c);
+a b c
+select * from t1 join t2 left join t3 on (t1.a=t3.c);
+a b c
+select * from t1 join t2 right join t3 on (t1.a=t3.c);
+a b c
+select * from t1 join t2 straight_join t3 on (t1.a=t3.c);
+a b c
+drop table t1, t2 ,t3;
+create table t1(f1 int, f2 date);
+insert into t1 values(1,'2005-01-01'),(2,'2005-09-01'),(3,'2005-09-30'),
+(4,'2005-10-01'),(5,'2005-12-30');
+select * from t1 where f2 >= 0 order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+3 2005-09-30
+4 2005-10-01
+5 2005-12-30
+select * from t1 where f2 >= '0000-00-00' order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+3 2005-09-30
+4 2005-10-01
+5 2005-12-30
+select * from t1 where f2 >= '2005-09-31' order by f2;
+f1 f2
+4 2005-10-01
+5 2005-12-30
+select * from t1 where f2 >= '2005-09-3a' order by f2;
+f1 f2
+3 2005-09-30
+4 2005-10-01
+5 2005-12-30
+Warnings:
+Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1
+select * from t1 where f2 <= '2005-09-31' order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+3 2005-09-30
+select * from t1 where f2 <= '2005-09-3a' order by f2;
+f1 f2
+1 2005-01-01
+2 2005-09-01
+Warnings:
+Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1
+drop table t1;
+create table t1 (f1 int, f2 int);
+insert into t1 values (1, 30), (2, 20), (3, 10);
+create algorithm=merge view v1 as select f1, f2 from t1;
+create algorithm=merge view v2 (f2, f1) as select f1, f2 from t1;
+create algorithm=merge view v3 as select t1.f1 as f2, t1.f2 as f1 from t1;
+select t1.f1 as x1, f1 from t1 order by t1.f1;
+x1 f1
+1 1
+2 2
+3 3
+select v1.f1 as x1, f1 from v1 order by v1.f1;
+x1 f1
+1 1
+2 2
+3 3
+select v2.f1 as x1, f1 from v2 order by v2.f1;
+x1 f1
+10 10
+20 20
+30 30
+select v3.f1 as x1, f1 from v3 order by v3.f1;
+x1 f1
+10 10
+20 20
+30 30
+select f1, f2, v1.f1 as x1 from v1 order by v1.f1;
+f1 f2 x1
+1 30 1
+2 20 2
+3 10 3
+select f1, f2, v2.f1 as x1 from v2 order by v2.f1;
+f1 f2 x1
+10 3 10
+20 2 20
+30 1 30
+select f1, f2, v3.f1 as x1 from v3 order by v3.f1;
+f1 f2 x1
+10 3 10
+20 2 20
+30 1 30
+drop table t1;
+drop view v1, v2, v3;
+CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a));
+CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a));
+CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32),
+PRIMARY KEY(key_a,key_b));
+INSERT INTO t1 VALUES (0,'');
+INSERT INTO t1 VALUES (1,'i');
+INSERT INTO t1 VALUES (2,'j');
+INSERT INTO t1 VALUES (3,'k');
+INSERT INTO t2 VALUES (1,'r');
+INSERT INTO t2 VALUES (2,'s');
+INSERT INTO t2 VALUES (3,'t');
+INSERT INTO t3 VALUES (1,5,'x');
+INSERT INTO t3 VALUES (1,6,'y');
+INSERT INTO t3 VALUES (2,5,'xx');
+INSERT INTO t3 VALUES (2,6,'yy');
+INSERT INTO t3 VALUES (2,7,'zz');
+INSERT INTO t3 VALUES (3,5,'xxx');
+SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+key_a foo
+2 xx
+EXPLAIN SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1
+SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+key_a foo
+2 xx
+EXPLAIN SELECT t2.key_a,foo
+FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
+INNER JOIN t3 ON t1.key_a = t3.key_a
+WHERE t2.key_a=2 and key_b=5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index
+1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1
+DROP TABLE t1,t2,t3;
+create table t1 (f1 int);
+insert into t1 values(1),(2);
+create table t2 (f2 int, f3 int, key(f2));
+insert into t2 values(1,1),(2,2);
+create table t3 (f4 int not null);
+insert into t3 values (2),(2),(2);
+select f1,(select count(*) from t2,t3 where f2=f1 and f3=f4) as count from t1;
+f1 count
+1 0
+2 3
+drop table t1,t2,t3;
+create table t1 (f1 int unique);
+create table t2 (f2 int unique);
+create table t3 (f3 int unique);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+insert into t3 values(1),(NULL);
+select * from t3 where f3 is null;
+f3
+NULL
+select t2.f2 from t1 left join t2 on f1=f2 join t3 on f1=f3 where f1=1;
+f2
+1
+drop table t1,t2,t3;
+create table t1(f1 char, f2 char not null);
+insert into t1 values(null,'a');
+create table t2 (f2 char not null);
+insert into t2 values('b');
+select * from t1 left join t2 on f1=t2.f2 where t1.f2='a';
+f1 f2 f2
+NULL a NULL
+drop table t1,t2;
+select * from (select * left join t on f1=f2) tt;
+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 'on f1=f2) tt' at line 1
+CREATE TABLE t1 (sku int PRIMARY KEY, pr int);
+CREATE TABLE t2 (sku int PRIMARY KEY, sppr int, name varchar(255));
+INSERT INTO t1 VALUES
+(10, 10), (20, 10), (30, 20), (40, 30), (50, 10), (60, 10);
+INSERT INTO t2 VALUES
+(10, 10, 'aaa'), (20, 10, 'bbb'), (30, 10, 'ccc'), (40, 20, 'ddd'),
+(50, 10, 'eee'), (60, 20, 'fff'), (70, 20, 'ggg'), (80, 30, 'hhh');
+SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
+FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku);
+sku sppr name sku pr
+20 10 bbb 10 10
+20 10 bbb 20 10
+EXPLAIN
+SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
+FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where
+DROP TABLE t1,t2;
+CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
+INSERT t1 SET i = 0;
+UPDATE t1 SET i = -1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = CAST(i - 1 AS SIGNED);
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = i - 1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+255
+DROP TABLE t1;
+create table t1 (a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2 (a int, b int, c int, e int, primary key(a,b,c));
+insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C;
+analyze table t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+select 'In next EXPLAIN, B.rows must be exactly 10:' Z;
+Z
+In next EXPLAIN, B.rows must be exactly 10:
+explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5
+and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A range PRIMARY PRIMARY 12 NULL 4 Using where
+1 SIMPLE B ref PRIMARY PRIMARY 8 const,test.A.e 10
+drop table t1, t2;
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b));
+INSERT INTO t1 VALUES (1, 3), (9,4), (7,5), (4,5), (6,2),
+(3,1), (5,1), (8,9), (2,2), (0,9);
+CREATE TABLE t2 (c int, d int, f int, INDEX(c,f));
+INSERT INTO t2 VALUES
+(1,0,0), (1,0,1), (2,0,0), (2,0,1), (3,0,0), (4,0,1),
+(5,0,0), (5,0,1), (6,0,0), (0,0,1), (7,0,0), (7,0,1),
+(0,0,0), (0,0,1), (8,0,0), (8,0,1), (9,0,0), (9,0,1);
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where
+EXPLAIN
+SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where
+DROP TABLE t1, t2;
+create table t1 (
+a int unsigned not null auto_increment primary key,
+b bit not null,
+c bit not null
+);
+create table t2 (
+a int unsigned not null auto_increment primary key,
+b bit not null,
+c int unsigned not null,
+d varchar(50)
+);
+insert into t1 (b,c) values (0,1), (0,1);
+insert into t2 (b,c) values (0,1);
+select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
+from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
+where t1.b <> 1 order by t1.a;
+a t1.b + 0 t1.c + 0 a t2.b + 0 c d
+1 0 1 1 0 1 NULL
+2 0 1 NULL NULL NULL NULL
+drop table t1,t2;
+SELECT 0.9888889889 * 1.011111411911;
+0.9888889889 * 1.011111411911
+0.9998769417899202067879
+prepare stmt from 'select 1 as " a "';
+Warnings:
+Warning 1466 Leading spaces are removed from name ' a '
+execute stmt;
+a
+1
+CREATE TABLE t1 (a int NOT NULL PRIMARY KEY, b int NOT NULL);
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
+CREATE TABLE t2 (c int NOT NULL, INDEX idx(c));
+INSERT INTO t2 VALUES
+(1), (1), (1), (1), (1), (1), (1), (1),
+(2), (2), (2), (2),
+(3), (3),
+(4);
+EXPLAIN SELECT b FROM t1, t2 WHERE b=c AND a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 ref idx idx 4 const 7 Using index
+EXPLAIN SELECT b FROM t1, t2 WHERE b=c AND a=4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 ref idx idx 4 const 1 Using index
+DROP TABLE t1, t2;
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a int);
+INSERT INTO t1 VALUES (1,2), (2,NULL), (3,2);
+CREATE TABLE t2 (b int, c INT, INDEX idx1(b));
+INSERT INTO t2 VALUES (2,1), (3,2);
+CREATE TABLE t3 (d int, e int, INDEX idx1(d));
+INSERT INTO t3 VALUES (2,10), (2,20), (1,30), (2,40), (2,50);
+EXPLAIN
+SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
+WHERE t1.id=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 const idx1 NULL NULL NULL 1
+1 SIMPLE t3 ref idx1 idx1 5 const 3 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
+WHERE t1.id=2;
+id a b c d e
+2 NULL NULL NULL 2 10
+2 NULL NULL NULL 2 20
+2 NULL NULL NULL 2 40
+2 NULL NULL NULL 2 50
+DROP TABLE t1,t2,t3;
+create table t1 (c1 varchar(1), c2 int, c3 int, c4 int, c5 int, c6 int,
+c7 int, c8 int, c9 int, fulltext key (`c1`));
+select distinct match (`c1`) against ('z') , c2, c3, c4,c5, c6,c7, c8
+from t1 where c9=1 order by c2, c2;
+match (`c1`) against ('z') c2 c3 c4 c5 c6 c7 c8
+drop table t1;
+CREATE TABLE t1 (pk varchar(10) PRIMARY KEY, fk varchar(16));
+CREATE TABLE t2 (pk varchar(16) PRIMARY KEY, fk varchar(10));
+INSERT INTO t1 VALUES
+('d','dddd'), ('i','iii'), ('a','aa'), ('b','bb'), ('g','gg'),
+('e','eee'), ('c','cccc'), ('h','hhh'), ('j','jjj'), ('f','fff');
+INSERT INTO t2 VALUES
+('jjj', 'j'), ('cc','c'), ('ccc','c'), ('aaa', 'a'), ('jjjj','j'),
+('hhh','h'), ('gg','g'), ('fff','f'), ('ee','e'), ('ffff','f'),
+('bbb','b'), ('ff','f'), ('cccc','c'), ('dddd','d'), ('jj','j'),
+('aaaa','a'), ('bb','b'), ('eeee','e'), ('aa','a'), ('hh','h');
+EXPLAIN SELECT t2.*
+FROM t1 JOIN t2 ON t2.fk=t1.pk
+WHERE t2.fk < 'c' AND t2.pk=t1.fk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
+EXPLAIN SELECT t2.*
+FROM t1 JOIN t2 ON t2.fk=t1.pk
+WHERE t2.fk BETWEEN 'a' AND 'b' AND t2.pk=t1.fk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
+EXPLAIN SELECT t2.*
+FROM t1 JOIN t2 ON t2.fk=t1.pk
+WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
+CREATE TABLE t2 (a int, b varchar(20) NOT NULL,
+PRIMARY KEY (a), UNIQUE KEY (b));
+INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c');
+INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
+EXPLAIN SELECT t1.a FROM t1 LEFT JOIN t2 ON t2.b=t1.b WHERE t1.a=3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+DROP TABLE t1,t2;
+CREATE TABLE t1(id int PRIMARY KEY, b int, e int);
+CREATE TABLE t2(i int, a int, INDEX si(i), INDEX ai(a));
+CREATE TABLE t3(a int PRIMARY KEY, c char(4), INDEX ci(c));
+INSERT INTO t1 VALUES
+(1,10,19), (2,20,22), (4,41,42), (9,93,95), (7, 77,79),
+(6,63,67), (5,55,58), (3,38,39), (8,81,89);
+INSERT INTO t2 VALUES
+(21,210), (41,410), (82,820), (83,830), (84,840),
+(65,650), (51,510), (37,370), (94,940), (76,760),
+(22,220), (33,330), (40,400), (95,950), (38,380),
+(67,670), (88,880), (57,570), (96,960), (97,970);
+INSERT INTO t3 VALUES
+(210,'bb'), (950,'ii'), (400,'ab'), (500,'ee'), (220,'gg'),
+(440,'gg'), (310,'eg'), (380,'ee'), (840,'bb'), (830,'ff'),
+(230,'aa'), (960,'ii'), (410,'aa'), (510,'ee'), (290,'bb'),
+(450,'gg'), (320,'dd'), (390,'hh'), (850,'jj'), (860,'ff');
+EXPLAIN
+SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
+WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
+t3.a=t2.a AND t3.c IN ('bb','ee');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si si 5 NULL 4 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN
+SELECT t3.a FROM t1,t2,t3
+WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
+t3.a=t2.a AND t3.c IN ('bb','ee') ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si,ai si 5 NULL 4 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN
+SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
+WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
+t3.c IN ('bb','ee');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si si 5 NULL 2 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+EXPLAIN
+SELECT t3.a FROM t1,t2,t3
+WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
+t3.c IN ('bb','ee');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
+1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 ( f1 int primary key, f2 int, f3 int, f4 int, f5 int, f6 int, checked_out int);
+CREATE TABLE t2 ( f11 int PRIMARY KEY );
+INSERT INTO t1 VALUES (1,1,1,0,0,0,0),(2,1,1,3,8,1,0),(3,1,1,4,12,1,0);
+INSERT INTO t2 VALUES (62);
+SELECT * FROM t1 LEFT JOIN t2 ON f11 = t1.checked_out GROUP BY f1 ORDER BY f2, f3, f4, f5 LIMIT 0, 1;
+f1 f2 f3 f4 f5 f6 checked_out f11
+1 1 1 0 0 0 0 NULL
+DROP TABLE t1, t2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a int);
+INSERT into t1 values (1), (2), (3);
+SELECT * FROM t1 LIMIT 2, -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 '-1' at line 1
+DROP TABLE t1;
+CREATE TABLE t1 (
+ID_with_null int NULL,
+ID_better int NOT NULL,
+INDEX idx1 (ID_with_null),
+INDEX idx2 (ID_better)
+);
+INSERT INTO t1 VALUES (1,1), (2,1), (null,3), (null,3), (null,3), (null,3);
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID_with_null IS NULL;
+SELECT COUNT(*) FROM t1 WHERE ID_with_null IS NULL;
+COUNT(*)
+128
+SELECT COUNT(*) FROM t1 WHERE ID_better=1;
+COUNT(*)
+2
+EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP INDEX idx1 ON t1;
+CREATE UNIQUE INDEX idx1 ON t1(ID_with_null);
+EXPLAIN SELECT * FROM t1 WHERE ID_better=1 AND ID_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP TABLE t1;
+CREATE TABLE t1 (
+ID1_with_null int NULL,
+ID2_with_null int NULL,
+ID_better int NOT NULL,
+INDEX idx1 (ID1_with_null, ID2_with_null),
+INDEX idx2 (ID_better)
+);
+INSERT INTO t1 VALUES (1,1,1), (2,2,1), (3,null,3), (null,3,3), (null,null,3),
+(3,null,3), (null,3,3), (null,null,3), (3,null,3), (null,3,3), (null,null,3);
+INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
+INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null=3;
+COUNT(*)
+24
+SELECT COUNT(*) FROM t1 WHERE ID1_with_null=3 AND ID2_with_null IS NULL;
+COUNT(*)
+24
+SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null IS NULL;
+COUNT(*)
+192
+SELECT COUNT(*) FROM t1 WHERE ID_better=1;
+COUNT(*)
+2
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null=3 IS NULL ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP INDEX idx1 ON t1;
+CREATE UNIQUE INDEX idx1 ON t1(ID1_with_null,ID2_with_null);
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null=3 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null=3 AND ID2_with_null IS NULL ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND ID2_with_null IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+EXPLAIN SELECT * FROM t1
+WHERE ID_better=1 AND ID1_with_null IS NULL AND
+(ID2_with_null=1 OR ID2_with_null=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref idx1,idx2 idx2 4 const 1 Using where
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, ts TIMESTAMP, KEY ts(ts));
+INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+CREATE TABLE t2 (a INT, dt1 DATETIME, dt2 DATETIME, PRIMARY KEY (a));
+INSERT INTO t2 VALUES (30, "2006-01-01 00:00:00", "2999-12-31 00:00:00");
+INSERT INTO t2 SELECT a+1,dt1,dt2 FROM t2;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+EXPLAIN
+SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30
+AND t1.ts BETWEEN t2.dt1 AND t2.dt2
+AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
+1 SIMPLE t1 range ts ts 4 NULL 1 Using where
+Warnings:
+Warning 1292 Incorrect datetime value: '2999-12-31 00:00:00' for column 'ts' at row 1
+SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30
+AND t1.ts BETWEEN t2.dt1 AND t2.dt2
+AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
+a ts a dt1 dt2
+30 2006-01-03 23:00:00 30 2006-01-01 00:00:00 2999-12-31 00:00:00
+Warnings:
+Warning 1292 Incorrect datetime value: '2999-12-31 00:00:00' for column 'ts' at row 1
+DROP TABLE t1,t2;
+create table t1 (a bigint unsigned);
+insert into t1 values
+(if(1, 9223372036854775808, 1)),
+(case when 1 then 9223372036854775808 else 1 end),
+(coalesce(9223372036854775808, 1));
+select * from t1;
+a
+9223372036854775808
+9223372036854775808
+9223372036854775808
+drop table t1;
+create table t1 select
+if(1, 9223372036854775808, 1) i,
+case when 1 then 9223372036854775808 else 1 end c,
+coalesce(9223372036854775808, 1) co;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` decimal(19,0) NOT NULL DEFAULT '0',
+ `c` decimal(19,0) NOT NULL DEFAULT '0',
+ `co` decimal(19,0) NOT NULL DEFAULT '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+select
+if(1, cast(1111111111111111111 as unsigned), 1) i,
+case when 1 then cast(1111111111111111111 as unsigned) else 1 end c,
+coalesce(cast(1111111111111111111 as unsigned), 1) co;
+i c co
+1111111111111111111 1111111111111111111 1111111111111111111
+CREATE TABLE t1 (name varchar(255));
+CREATE TABLE t2 (name varchar(255), n int, KEY (name(3)));
+INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
+INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
+INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
+INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
+SELECT * FROM t2;
+name n
+bb 1
+aa 2
+cc 3
+cc  4
+cc 5
+bb 6
+cc 7
+SELECT * FROM t2 ORDER BY name;
+name n
+aa 2
+bb 1
+bb 6
+cc  4
+cc 3
+cc 5
+cc 7
+SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
+name LENGTH(name) n
+aa 2 2
+bb 2 1
+bb 3 6
+cc  4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref name name 6 const 3 Using where
+SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+name LENGTH(name) n
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+name LENGTH(name) n
+cc 5 3
+cc  4 4
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where; Using filesort
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+name LENGTH(name) n
+cc  4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref name name 6 test.t1.name 2
+SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+name name n
+ccc NULL NULL
+bb bb 1
+bb bb 6
+cc cc 3
+cc cc 5
+cc cc 7
+aa aa 2
+aa aa 2
+DROP TABLE t1,t2;
+CREATE TABLE t1 (name text);
+CREATE TABLE t2 (name text, n int, KEY (name(3)));
+INSERT INTO t1 VALUES ('ccc'), ('bb'), ('cc '), ('aa '), ('aa');
+INSERT INTO t2 VALUES ('bb',1), ('aa',2), ('cc ',3);
+INSERT INTO t2 VALUES (concat('cc ', 0x06), 4);
+INSERT INTO t2 VALUES ('cc',5), ('bb ',6), ('cc ',7);
+SELECT * FROM t2;
+name n
+bb 1
+aa 2
+cc 3
+cc  4
+cc 5
+bb 6
+cc 7
+SELECT * FROM t2 ORDER BY name;
+name n
+aa 2
+bb 1
+bb 6
+cc  4
+cc 3
+cc 5
+cc 7
+SELECT name, LENGTH(name), n FROM t2 ORDER BY name;
+name LENGTH(name) n
+aa 2 2
+bb 2 1
+bb 3 6
+cc  4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref name name 6 const 3 Using where
+SELECT name, LENGTH(name), n FROM t2 WHERE name='cc ';
+name LENGTH(name) n
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%';
+name LENGTH(name) n
+cc 5 3
+cc  4 4
+cc 2 5
+cc 3 7
+EXPLAIN SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range name name 6 NULL 3 Using where; Using filesort
+SELECT name , LENGTH(name), n FROM t2 WHERE name LIKE 'cc%' ORDER BY name;
+name LENGTH(name) n
+cc  4 4
+cc 5 3
+cc 2 5
+cc 3 7
+EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t2 ref name name 6 test.t1.name 2
+SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
+name name n
+ccc NULL NULL
+bb bb 1
+bb bb 6
+cc cc 3
+cc cc 5
+cc cc 7
+aa aa 2
+aa aa 2
+DROP TABLE t1,t2;
+CREATE TABLE t1 (
+access_id int NOT NULL default '0',
+name varchar(20) default NULL,
+rank int NOT NULL default '0',
+KEY idx (access_id)
+);
+CREATE TABLE t2 (
+faq_group_id int NOT NULL default '0',
+faq_id int NOT NULL default '0',
+access_id int default NULL,
+UNIQUE KEY idx1 (faq_id),
+KEY idx2 (faq_group_id,faq_id)
+);
+INSERT INTO t1 VALUES
+(1,'Everyone',2),(2,'Help',3),(3,'Technical Support',1),(4,'Chat User',4);
+INSERT INTO t2 VALUES
+(261,265,1),(490,494,1);
+SELECT t2.faq_id
+FROM t1 INNER JOIN t2 IGNORE INDEX (idx1)
+ON (t1.access_id = t2.access_id)
+LEFT JOIN t2 t
+ON (t.faq_group_id = t2.faq_group_id AND
+find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
+WHERE
+t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
+faq_id
+265
+SELECT t2.faq_id
+FROM t1 INNER JOIN t2
+ON (t1.access_id = t2.access_id)
+LEFT JOIN t2 t
+ON (t.faq_group_id = t2.faq_group_id AND
+find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
+WHERE
+t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
+faq_id
+265
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a INT, b INT, KEY inx (b,a));
+INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1, 6), (1,7);
+EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER JOIN t1 f2
+ON ( f1.b=f2.b AND f1.a<f2.a )
+WHERE 1 AND f1.b NOT IN (100,2232,3343,51111);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE f1 index inx inx 10 NULL 7 Using where; Using index
+1 SIMPLE f2 ref inx inx 5 test.f1.b 1 Using where; Using index
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (1,11), (2,22), (2,22);
+EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2)))))))))))))))))))))))))))))))) > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+31 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
+32 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
+EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) > 0;
+ERROR HY000: Too high level of nesting for select
+DROP TABLE t1;
+CREATE TABLE t1 (
+c1 int(11) NOT NULL AUTO_INCREMENT,
+c2 varchar(1000) DEFAULT NULL,
+c3 bigint(20) DEFAULT NULL,
+c4 bigint(20) DEFAULT NULL,
+PRIMARY KEY (c1)
+);
+EXPLAIN EXTENDED
+SELECT join_2.c1
+FROM
+t1 AS join_0,
+t1 AS join_1,
+t1 AS join_2,
+t1 AS join_3,
+t1 AS join_4,
+t1 AS join_5,
+t1 AS join_6,
+t1 AS join_7
+WHERE
+join_0.c1=join_1.c1 AND
+join_1.c1=join_2.c1 AND
+join_2.c1=join_3.c1 AND
+join_3.c1=join_4.c1 AND
+join_4.c1=join_5.c1 AND
+join_5.c1=join_6.c1 AND
+join_6.c1=join_7.c1
+OR
+join_0.c2 < '?' AND
+join_1.c2 < '?' AND
+join_2.c2 > '?' AND
+join_2.c2 < '!' AND
+join_3.c2 > '?' AND
+join_4.c2 = '?' AND
+join_5.c2 <> '?' AND
+join_6.c2 <> '?' AND
+join_7.c2 >= '?' AND
+join_0.c1=join_1.c1 AND
+join_1.c1=join_2.c1 AND
+join_2.c1=join_3.c1 AND
+join_3.c1=join_4.c1 AND
+join_4.c1=join_5.c1 AND
+join_5.c1=join_6.c1 AND
+join_6.c1=join_7.c1
+GROUP BY
+join_3.c1,
+join_2.c1,
+join_7.c1,
+join_1.c1,
+join_0.c1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Note 1003 select NULL AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by NULL,NULL,NULL,NULL,NULL
+SHOW WARNINGS;
+Level Code Message
+Note 1003 select NULL AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by NULL,NULL,NULL,NULL,NULL
+DROP TABLE t1;
+SELECT 1 AS ` `;
+
+1
+Warnings:
+Warning 1474 Name ' ' has become ''
+SELECT 1 AS ` `;
+
+1
+Warnings:
+Warning 1474 Name ' ' has become ''
+SELECT 1 AS ` x`;
+x
+1
+Warnings:
+Warning 1466 Leading spaces are removed from name ' x'
+CREATE VIEW v1 AS SELECT 1 AS ``;
+ERROR 42000: Incorrect column name ''
+CREATE VIEW v1 AS SELECT 1 AS ` `;
+ERROR 42000: Incorrect column name ' '
+CREATE VIEW v1 AS SELECT 1 AS ` `;
+ERROR 42000: Incorrect column name ' '
+CREATE VIEW v1 AS SELECT (SELECT 1 AS ` `);
+ERROR 42000: Incorrect column name ' '
+CREATE VIEW v1 AS SELECT 1 AS ` x`;
+Warnings:
+Warning 1466 Leading spaces are removed from name ' x'
+SELECT `x` FROM v1;
+x
+1
+ALTER VIEW v1 AS SELECT 1 AS ` `;
+ERROR 42000: Incorrect column name ' '
+DROP VIEW v1;
+select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT'
+ and '2007/10/20 00:00:00 GMT';
+str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT'
+ and '2007/10/20 00:00:00 GMT'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT'
+Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT'
+select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6';
+str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007/10/01 00:00:00 GMT-6'
+select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6';
+str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007/10/2000:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007-10-1 00:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect date value: '2007-10-01 x00:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:x00:00 GMT-6'
+select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6';
+str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 x12:34:56 GMT-6'
+select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6';
+str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6'
+select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6';
+str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6'
+select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56';
+str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'
+1
+select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00';
+str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'
+0
+select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00';
+str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'
+1
+select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00';
+str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'
+1
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34'
+select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34';
+str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'
+1
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'
+1
+select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00'
+ and '2007/10/20 00:00:00';
+str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00'
+ and '2007/10/20 00:00:00'
+1
+set SQL_MODE=TRADITIONAL;
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34'
+select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34';
+str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34'
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34:00'
+select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01'
+ and '2007/10/20';
+str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01'
+ and '2007/10/20'
+0
+Warnings:
+Warning 1292 Incorrect datetime value: '2007-10-00' for column '2007/09/01' at row 1
+Warning 1292 Incorrect datetime value: '2007-10-00' for column '2007/10/20' at row 1
+set SQL_MODE=DEFAULT;
+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('','%Y-%m-%d') between '2007/10/01' and '2007/10/20';
+str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'
+0
+select str_to_date('','%Y-%m-%d %H:%i') = '2007-10-01 12:34';
+str_to_date('','%Y-%m-%d %H:%i') = '2007-10-01 12:34'
+0
+select str_to_date(NULL,'%Y-%m-%d %H:%i') = '2007-10-01 12:34';
+str_to_date(NULL,'%Y-%m-%d %H:%i') = '2007-10-01 12:34'
+NULL
+select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '';
+str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = ''
+0
+Warnings:
+Warning 1292 Truncated incorrect datetime value: ''
+select str_to_date('1','%Y-%m-%d') = '1';
+str_to_date('1','%Y-%m-%d') = '1'
+0
+Warnings:
+Warning 1292 Truncated incorrect date value: '1'
+select str_to_date('1','%Y-%m-%d') = '1';
+str_to_date('1','%Y-%m-%d') = '1'
+0
+Warnings:
+Warning 1292 Truncated incorrect date value: '1'
+select str_to_date('','%Y-%m-%d') = '';
+str_to_date('','%Y-%m-%d') = ''
+0
+Warnings:
+Warning 1292 Truncated incorrect date value: ''
+select str_to_date('1000-01-01','%Y-%m-%d') between '0000-00-00' and NULL;
+str_to_date('1000-01-01','%Y-%m-%d') between '0000-00-00' and NULL
+0
+select str_to_date('1000-01-01','%Y-%m-%d') between NULL and '2000-00-00';
+str_to_date('1000-01-01','%Y-%m-%d') between NULL and '2000-00-00'
+0
+select str_to_date('1000-01-01','%Y-%m-%d') between NULL and NULL;
+str_to_date('1000-01-01','%Y-%m-%d') between NULL and NULL
+0
+CREATE TABLE t1 (c11 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t2 (c21 INT UNSIGNED NOT NULL,
+c22 INT DEFAULT NULL,
+KEY(c21, c22));
+CREATE TABLE t3 (c31 INT UNSIGNED NOT NULL DEFAULT 0,
+c32 INT DEFAULT NULL,
+c33 INT NOT NULL,
+c34 INT UNSIGNED DEFAULT 0,
+KEY (c33, c34, c32));
+INSERT INTO t1 values (),(),(),(),();
+INSERT INTO t2 SELECT a.c11, b.c11 FROM t1 a, t1 b;
+INSERT INTO t3 VALUES (1, 1, 1, 0),
+(2, 2, 0, 0),
+(3, 3, 1, 0),
+(4, 4, 0, 0),
+(5, 5, 1, 0);
+SELECT c32 FROM t1, t2, t3 WHERE t1.c11 IN (1, 3, 5) AND
+t3.c31 = t1.c11 AND t2.c21 = t1.c11 AND
+t3.c33 = 1 AND t2.c22 in (1, 3)
+ORDER BY c32;
+c32
+1
+1
+3
+3
+5
+5
+SELECT c32 FROM t1, t2, t3 WHERE t1.c11 IN (1, 3, 5) AND
+t3.c31 = t1.c11 AND t2.c21 = t1.c11 AND
+t3.c33 = 1 AND t2.c22 in (1, 3)
+ORDER BY c32 DESC;
+c32
+5
+5
+3
+3
+1
+1
+DROP TABLE t1, t2, t3;
+
+#
+# Bug#30736: Row Size Too Large Error Creating a Table and
+# Inserting Data.
+#
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+
+CREATE TABLE t1(
+c1 DECIMAL(10, 2),
+c2 FLOAT);
+
+INSERT INTO t1 VALUES (0, 1), (2, 3), (4, 5);
+
+CREATE TABLE t2(
+c3 DECIMAL(10, 2))
+SELECT
+c1 * c2 AS c3
+FROM t1;
+
+SELECT * FROM t1;
+c1 c2
+0.00 1
+2.00 3
+4.00 5
+
+SELECT * FROM t2;
+c3
+0.00
+6.00
+20.00
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+CREATE TABLE t1 (c1 BIGINT NOT NULL);
+INSERT INTO t1 (c1) VALUES (1);
+SELECT * FROM t1 WHERE c1 > NULL + 1;
+c1
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY);
+INSERT INTO t1 (a) VALUES ('foo0'), ('bar0'), ('baz0');
+SELECT * FROM t1 WHERE a IN (CONCAT('foo', 0), 'bar');
+a
+foo0
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT);
+CREATE TABLE t2 (a INT, c INT, KEY(a));
+INSERT INTO t1 VALUES (1, 1), (2, 2);
+INSERT INTO t2 VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
+(2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
+(3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
+(4, 1), (4, 2), (4, 3), (4, 4), (4, 5);
+FLUSH STATUS;
+SELECT DISTINCT b FROM t1 LEFT JOIN t2 USING(a) WHERE c <= 3;
+b
+1
+2
+SHOW STATUS LIKE 'Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 6
+DROP TABLE t1, t2;
+CREATE TABLE t1 (f1 bigint(20) NOT NULL default '0',
+f2 int(11) NOT NULL default '0',
+f3 bigint(20) NOT NULL default '0',
+f4 varchar(255) NOT NULL default '',
+PRIMARY KEY (f1),
+KEY key1 (f4),
+KEY key2 (f2));
+CREATE TABLE t2 (f1 int(11) NOT NULL default '0',
+f2 enum('A1','A2','A3') NOT NULL default 'A1',
+f3 int(11) NOT NULL default '0',
+PRIMARY KEY (f1),
+KEY key1 (f3));
+CREATE TABLE t3 (f1 bigint(20) NOT NULL default '0',
+f2 datetime NOT NULL default '1980-01-01 00:00:00',
+PRIMARY KEY (f1));
+insert into t1 values (1, 1, 1, 'abc');
+insert into t1 values (2, 1, 2, 'def');
+insert into t1 values (3, 1, 2, 'def');
+insert into t2 values (1, 'A1', 1);
+insert into t3 values (1, '1980-01-01');
+SELECT a.f3, cr.f4, count(*) count
+FROM t2 a
+STRAIGHT_JOIN t1 cr ON cr.f2 = a.f1
+LEFT JOIN
+(t1 cr2
+JOIN t3 ae2 ON cr2.f3 = ae2.f1
+) ON a.f1 = cr2.f2 AND ae2.f2 < now() - INTERVAL 7 DAY AND
+cr.f4 = cr2.f4
+GROUP BY a.f3, cr.f4;
+f3 f4 count
+1 abc 1
+1 def 2
+drop table t1, t2, t3;
+CREATE TABLE t1 (a INT KEY, b INT);
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
+EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 1)) limit 2
+EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+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;
+#
+# Bug #48458: simple query tries to allocate enormous amount of
+# memory
+#
+CREATE TABLE t1(a INT NOT NULL, b YEAR);
+INSERT INTO t1 VALUES ();
+Warnings:
+Warning 1364 Field 'a' doesn't have a default value
+CREATE TABLE t2(c INT);
+# Should not err out because of out-of-memory
+SELECT 1 FROM t2 JOIN t1 ON 1=1
+WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a);
+1
+DROP TABLE t1,t2;
+#
+# Bug #49199: Optimizer handles incorrectly:
+# field='const1' AND field='const2' in some cases
+
+CREATE TABLE t1(a DATETIME NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+a
+2001-01-01 00:00:00
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATE NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+a
+2001-01-01
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01' AS `a` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a TIMESTAMP NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+a
+2001-01-01 00:00:00
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+a b
+2001-01-01 00:00:00 2001-01-01
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
+SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+a b
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 0
+SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
+a b
+2001-01-01 00:00:00 2001-01-01
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1
+DROP TABLE t1;
+CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
+INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
+SELECT x.a, y.a, z.a FROM t1 x
+JOIN t1 y ON x.a=y.a
+JOIN t1 z ON y.a=z.a
+WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
+a a a
+2001-01-01 00:00:00 2001-01-01 00:00:00 2001-01-01 00:00:00
+EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x
+JOIN t1 y ON x.a=y.a
+JOIN t1 z ON y.a=z.a
+WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE x system NULL NULL NULL NULL 1 100.00
+1 SIMPLE y system NULL NULL NULL NULL 1 100.00
+1 SIMPLE z system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1
+DROP TABLE t1;
+#
+# Bug #49897: crash in ptr_compare when char(0) NOT NULL
+# column is used for ORDER BY
+#
+SET @old_sort_buffer_size= @@session.sort_buffer_size;
+SET @@sort_buffer_size= 40000;
+CREATE TABLE t1(a CHAR(0) NOT NULL);
+INSERT INTO t1 VALUES (0), (0), (0);
+INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a FROM t1 t11, t1 t12;
+EXPLAIN SELECT a FROM t1 ORDER BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492
+SELECT a FROM t1 ORDER BY a;
+DROP TABLE t1;
+CREATE TABLE t1(a CHAR(0) NOT NULL, b CHAR(0) NOT NULL, c int);
+INSERT INTO t1 VALUES (0, 0, 0), (0, 0, 2), (0, 0, 1);
+INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12;
+INSERT INTO t1 SELECT t11.a, t11.b, t11.c FROM t1 t11, t1 t12;
+EXPLAIN SELECT a FROM t1 ORDER BY a LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492
+SELECT a FROM t1 ORDER BY a LIMIT 5;
+a
+
+
+
+
+
+EXPLAIN SELECT * FROM t1 ORDER BY a, b LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492
+SELECT * FROM t1 ORDER BY a, b LIMIT 5;
+a b c
+ 0
+ 2
+ 1
+ 0
+ 2
+EXPLAIN SELECT * FROM t1 ORDER BY a, b, c LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 Using filesort
+SELECT * FROM t1 ORDER BY a, b, c LIMIT 5;
+a b c
+ 0
+ 0
+ 0
+ 0
+ 0
+EXPLAIN SELECT * FROM t1 ORDER BY c, a LIMIT 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 24492 Using filesort
+SELECT * FROM t1 ORDER BY c, a LIMIT 5;
+a b c
+ 0
+ 0
+ 0
+ 0
+ 0
+SET @@sort_buffer_size= @old_sort_buffer_size;
+DROP TABLE t1;
+End of 5.0 tests
+create table t1(a INT, KEY (a));
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
+SELECT a FROM t1 ORDER BY a LIMIT 2;
+a
+1
+2
+SELECT a FROM t1 ORDER BY a LIMIT 2,4294967296;
+a
+3
+4
+5
+SELECT a FROM t1 ORDER BY a LIMIT 2,4294967297;
+a
+3
+4
+5
+DROP TABLE t1;
+CREATE TABLE A (date_key date);
+CREATE TABLE C (
+pk int,
+int_nokey int,
+int_key int,
+date_key date NOT NULL,
+date_nokey date,
+varchar_key varchar(1)
+);
+INSERT INTO C VALUES
+(1,1,1,'0000-00-00',NULL,NULL),
+(1,1,1,'0000-00-00',NULL,NULL);
+SELECT 1 FROM C WHERE pk > ANY (SELECT 1 FROM C);
+1
+SELECT COUNT(DISTINCT 1) FROM C
+WHERE date_key = (SELECT 1 FROM A WHERE C.date_key IS NULL) GROUP BY pk;
+COUNT(DISTINCT 1)
+SELECT date_nokey FROM C
+WHERE int_key IN (SELECT 1 FROM A)
+HAVING date_nokey = '10:41:7'
+ORDER BY date_key;
+date_nokey
+Warnings:
+Warning 1292 Incorrect date value: '10:41:7' for column 'date_nokey' at row 1
+DROP TABLE A,C;
+CREATE TABLE t1 (a INT NOT NULL, b INT);
+INSERT INTO t1 VALUES (1, 1);
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND a=a) OR b > 2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '1' AS `a`,'1' AS `b` from `test`.`t1` where 1
+SELECT * FROM t1 WHERE (a=a AND a=a) OR b > 2;
+a b
+1 1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL);
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND b=b AND c=c) OR b > 20;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1003 select NULL AS `a`,NULL AS `b`,NULL AS `c` from `test`.`t1` where 1
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND a=a AND b=b) OR b > 20;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1003 select NULL AS `a`,NULL AS `b`,NULL AS `c` from `test`.`t1` where 1
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND b=b AND a=a) OR b > 20;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found
+Warnings:
+Note 1003 select NULL AS `a`,NULL AS `b`,NULL AS `c` from `test`.`t1` where 1
+DROP TABLE t1;
+#
+# Bug#45266: Uninitialized variable lead to an empty result.
+#
+drop table if exists A,AA,B,BB;
+CREATE TABLE `A` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`date_key` date NOT NULL,
+`date_nokey` date NOT NULL,
+`datetime_key` datetime NOT NULL,
+`int_nokey` int(11) NOT NULL,
+`time_key` time NOT NULL,
+`time_nokey` time NOT NULL,
+PRIMARY KEY (`pk`),
+KEY `date_key` (`date_key`),
+KEY `time_key` (`time_key`),
+KEY `datetime_key` (`datetime_key`)
+);
+CREATE TABLE `AA` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) NOT NULL,
+`time_key` time NOT NULL,
+KEY `time_key` (`time_key`),
+PRIMARY KEY (`pk`)
+);
+CREATE TABLE `B` (
+`date_nokey` date NOT NULL,
+`date_key` date NOT NULL,
+`time_key` time NOT NULL,
+`datetime_nokey` datetime NOT NULL,
+`varchar_key` varchar(1) NOT NULL,
+KEY `date_key` (`date_key`),
+KEY `time_key` (`time_key`),
+KEY `varchar_key` (`varchar_key`)
+);
+INSERT INTO `B` VALUES ('2003-07-28','2003-07-28','15:13:38','0000-00-00 00:00:00','f'),('0000-00-00','0000-00-00','00:05:48','2004-07-02 14:34:13','x');
+CREATE TABLE `BB` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) NOT NULL,
+`date_key` date NOT NULL,
+`varchar_nokey` varchar(1) NOT NULL,
+`date_nokey` date NOT NULL,
+PRIMARY KEY (`pk`),
+KEY `date_key` (`date_key`)
+);
+INSERT INTO `BB` VALUES (10,8,'0000-00-00','i','0000-00-00'),(11,0,'2005-08-18','','2005-08-18');
+SELECT table1 . `pk` AS field1
+FROM
+(BB AS table1 INNER JOIN
+(AA AS table2 STRAIGHT_JOIN A AS table3
+ON ( table3 . `date_key` = table2 . `pk` ))
+ON ( table3 . `datetime_key` = table2 . `int_nokey` ))
+WHERE ( table3 . `date_key` <= 4 AND table2 . `pk` = table1 . `varchar_nokey`)
+GROUP BY field1 ;
+field1
+SELECT table3 .`date_key` field1
+FROM
+B table1 LEFT JOIN B table3 JOIN
+(BB table6 JOIN A table7 ON table6 .`varchar_nokey`)
+ON table6 .`int_nokey` ON table6 .`date_key`
+ WHERE NOT ( table1 .`varchar_key` AND table7 .`pk`) GROUP BY field1;
+field1
+NULL
+SELECT table4 . `time_nokey` AS field1 FROM
+(AA AS table1 CROSS JOIN
+(AA AS table2 STRAIGHT_JOIN
+(B AS table3 STRAIGHT_JOIN A AS table4
+ON ( table4 . `date_key` = table3 . `time_key` ))
+ON ( table4 . `pk` = table3 . `date_nokey` ))
+ON ( table4 . `time_key` = table3 . `datetime_nokey` ))
+WHERE ( table4 . `time_key` < table1 . `time_key` AND
+table1 . `int_nokey` != 'f')
+GROUP BY field1 ORDER BY field1 , field1;
+field1
+SELECT table1 .`time_key` field2 FROM B table1 LEFT JOIN BB JOIN A table5 ON table5 .`date_nokey` ON table5 .`int_nokey` GROUP BY field2;
+field2
+00:05:48
+15:13:38
+drop table A,AA,B,BB;
+#end of test for bug#45266
+#
+# BUG#48052: Valgrind warning - uninitialized value in init_read_record()
+#
+CREATE TABLE t1 (
+pk int(11) NOT NULL,
+i int(11) DEFAULT NULL,
+v varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (2,7,'m');
+INSERT INTO t1 VALUES (3,9,'m');
+SELECT v
+FROM t1
+WHERE NOT pk > 0
+HAVING v <= 't'
+ORDER BY pk;
+v
+DROP TABLE t1;
+#
+# Bug#49489 Uninitialized cache led to a wrong result.
+#
+CREATE TABLE t1(c1 DOUBLE(5,4));
+INSERT INTO t1 VALUES (9.1234);
+SELECT * FROM t1 WHERE c1 < 9.12345;
+c1
+9.1234
+DROP TABLE t1;
+# End of test for bug#49489.
+#
+# Bug #49517: Inconsistent behavior while using
+# NULLable BIGINT and INT columns in comparison
+#
+CREATE TABLE t1(a BIGINT UNSIGNED NOT NULL, b BIGINT NULL, c INT NULL);
+INSERT INTO t1 VALUES(105, NULL, NULL);
+SELECT * FROM t1 WHERE b < 102;
+a b c
+SELECT * FROM t1 WHERE c < 102;
+a b c
+SELECT * FROM t1 WHERE 102 < b;
+a b c
+SELECT * FROM t1 WHERE 102 < c;
+a b c
+DROP TABLE t1;
+#
+# Bug #54459: Assertion failed: param.sort_length,
+# file .\filesort.cc, line 149 (part II)
+#
+CREATE TABLE t1(a ENUM('') NOT NULL);
+INSERT INTO t1 VALUES (), (), ();
+EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci;
+1
+1
+1
+1
+DROP TABLE t1;
+End of 5.1 tests
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 2180a23b91a..72079ee03a0 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -6940,9 +6940,8 @@ create procedure p() begin end;
call p();
select @@sql_mode;
@@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,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,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,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,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
name
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index b21395d9623..880531f4b47 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -191,6 +191,8 @@ max_updates, max_connections, max_user_connections)
VALUES('%', 'mysqltest_1', password(''), 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N',
'N', 'N', 'N', 'Y', 'Y', 'N', 'N', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', 'Y', 'Y', 'N', '',
'', '', '', '0', '0', '0', '0');
+Warnings:
+Warning 1364 Field 'auth_string' doesn't have a default value
FLUSH PRIVILEGES;
CREATE PROCEDURE p1(i INT) BEGIN END;
DROP PROCEDURE p1;
diff --git a/mysql-test/r/status_user.result b/mysql-test/r/status_user.result
new file mode 100644
index 00000000000..636eeabfffc
--- /dev/null
+++ b/mysql-test/r/status_user.result
@@ -0,0 +1,186 @@
+DROP TABLE IF EXISTS t1;
+select variable_value from information_schema.global_status where variable_name="handler_read_key" into @global_read_key;
+show columns from information_schema.client_statistics;
+Field Type Null Key Default Extra
+CLIENT varchar(64) NO
+TOTAL_CONNECTIONS bigint(21) NO 0
+CONCURRENT_CONNECTIONS bigint(21) NO 0
+CONNECTED_TIME bigint(21) NO 0
+BUSY_TIME double NO 0
+CPU_TIME double NO 0
+BYTES_RECEIVED bigint(21) NO 0
+BYTES_SENT bigint(21) NO 0
+BINLOG_BYTES_WRITTEN bigint(21) NO 0
+ROWS_READ bigint(21) NO 0
+ROWS_SENT bigint(21) NO 0
+ROWS_DELETED bigint(21) NO 0
+ROWS_INSERTED bigint(21) NO 0
+ROWS_UPDATED bigint(21) NO 0
+SELECT_COMMANDS bigint(21) NO 0
+UPDATE_COMMANDS bigint(21) NO 0
+OTHER_COMMANDS bigint(21) NO 0
+COMMIT_TRANSACTIONS bigint(21) NO 0
+ROLLBACK_TRANSACTIONS bigint(21) NO 0
+DENIED_CONNECTIONS bigint(21) NO 0
+LOST_CONNECTIONS bigint(21) NO 0
+ACCESS_DENIED bigint(21) NO 0
+EMPTY_QUERIES bigint(21) NO 0
+show columns from information_schema.user_statistics;
+Field Type Null Key Default Extra
+USER varchar(48) NO
+TOTAL_CONNECTIONS int(11) NO 0
+CONCURRENT_CONNECTIONS int(11) NO 0
+CONNECTED_TIME int(11) NO 0
+BUSY_TIME double NO 0
+CPU_TIME double NO 0
+BYTES_RECEIVED bigint(21) NO 0
+BYTES_SENT bigint(21) NO 0
+BINLOG_BYTES_WRITTEN bigint(21) NO 0
+ROWS_READ bigint(21) NO 0
+ROWS_SENT bigint(21) NO 0
+ROWS_DELETED bigint(21) NO 0
+ROWS_INSERTED bigint(21) NO 0
+ROWS_UPDATED bigint(21) NO 0
+SELECT_COMMANDS bigint(21) NO 0
+UPDATE_COMMANDS bigint(21) NO 0
+OTHER_COMMANDS bigint(21) NO 0
+COMMIT_TRANSACTIONS bigint(21) NO 0
+ROLLBACK_TRANSACTIONS bigint(21) NO 0
+DENIED_CONNECTIONS bigint(21) NO 0
+LOST_CONNECTIONS bigint(21) NO 0
+ACCESS_DENIED bigint(21) NO 0
+EMPTY_QUERIES bigint(21) NO 0
+show columns from information_schema.index_statistics;
+Field Type Null Key Default Extra
+TABLE_SCHEMA varchar(192) NO
+TABLE_NAME varchar(192) NO
+INDEX_NAME varchar(192) NO
+ROWS_READ bigint(21) NO 0
+show columns from information_schema.table_statistics;
+Field Type Null Key Default Extra
+TABLE_SCHEMA varchar(192) NO
+TABLE_NAME varchar(192) NO
+ROWS_READ bigint(21) NO 0
+ROWS_CHANGED bigint(21) NO 0
+ROWS_CHANGED_X_INDEXES bigint(21) NO 0
+set @save_general_log=@@global.general_log;
+set @@global.general_log=0;
+set @@global.userstat=1;
+flush status;
+create table t1 (a int, primary key (a), b int default 0) engine=innodb;
+insert into t1 (a) values (1),(2),(3),(4);
+update t1 set b=1;
+update t1 set b=5 where a=2;
+delete from t1 where a=3;
+/* Empty query */
+select * from t1 where a=999;
+a b
+drop table t1;
+create table t1 (a int, primary key (a), b int default 0) engine=innodb;
+begin;
+insert into t1 values(1,1);
+commit;
+begin;
+insert into t1 values(2,2);
+commit;
+begin;
+insert into t1 values(3,3);
+rollback;
+drop table t1;
+select sleep(1);
+sleep(1)
+0
+show status like "rows%";
+Variable_name Value
+Rows_read 6
+Rows_sent 1
+show status like "ha%";
+Variable_name Value
+Handler_commit 19
+Handler_delete 1
+Handler_discover 0
+Handler_prepare 18
+Handler_read_first 0
+Handler_read_key 3
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 5
+Handler_rollback 2
+Handler_savepoint 0
+Handler_savepoint_rollback 0
+Handler_update 5
+Handler_write 7
+select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key";
+handler_read_key
+3
+set @@global.userstat=0;
+select * from information_schema.index_statistics;
+TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
+test t1 PRIMARY 2
+select * from information_schema.table_statistics;
+TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
+test t1 6 13 13
+show table_statistics;
+Table_schema Table_name Rows_read Rows_changed Rows_changed_x_#indexes
+test t1 6 13 13
+show index_statistics;
+Table_schema Table_name Index_name Rows_read
+test t1 PRIMARY 2
+select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, ACCESS_DENIED, EMPTY_QUERIES from information_schema.client_statistics;;
+TOTAL_CONNECTIONS 1
+CONCURRENT_CONNECTIONS 0
+ROWS_READ 6
+ROWS_SENT 2
+ROWS_DELETED 1
+ROWS_INSERTED 8
+ROWS_UPDATED 5
+SELECT_COMMANDS 3
+UPDATE_COMMANDS 11
+OTHER_COMMANDS 7
+COMMIT_TRANSACTIONS 19
+ROLLBACK_TRANSACTIONS 2
+DENIED_CONNECTIONS 0
+LOST_CONNECTIONS 0
+ACCESS_DENIED 0
+EMPTY_QUERIES 1
+select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, ACCESS_DENIED, EMPTY_QUERIES from information_schema.user_statistics;;
+TOTAL_CONNECTIONS 1
+CONCURRENT_CONNECTIONS 0
+ROWS_READ 6
+ROWS_SENT 2
+ROWS_DELETED 1
+ROWS_INSERTED 8
+ROWS_UPDATED 5
+SELECT_COMMANDS 3
+UPDATE_COMMANDS 11
+OTHER_COMMANDS 7
+COMMIT_TRANSACTIONS 19
+ROLLBACK_TRANSACTIONS 2
+DENIED_CONNECTIONS 0
+LOST_CONNECTIONS 0
+ACCESS_DENIED 0
+EMPTY_QUERIES 1
+flush table_statistics;
+flush index_statistics;
+select * from information_schema.index_statistics;
+TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
+select * from information_schema.table_statistics;
+TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
+show status like "%statistics%";
+Variable_name Value
+Com_show_client_statistics 0
+Com_show_index_statistics 1
+Com_show_table_statistics 1
+Com_show_user_statistics 0
+select connected_time <> 0, busy_time <> 0, bytes_received <> 0,
+bytes_sent <> 0, binlog_bytes_written <> 0
+from information_schema.user_statistics;
+connected_time <> 0 busy_time <> 0 bytes_received <> 0 bytes_sent <> 0 binlog_bytes_written <> 0
+1 1 1 1 1
+select connected_time <> 0, busy_time <> 0, bytes_received <> 0,
+bytes_sent <> 0, binlog_bytes_written <> 0
+from information_schema.client_statistics;
+connected_time <> 0 busy_time <> 0 bytes_received <> 0 bytes_sent <> 0 binlog_bytes_written <> 0
+1 1 1 1 1
+set @@global.general_log=@save_general_log;
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 17fd95ab1c8..aa407b25401 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -118,6 +118,8 @@ user CREATE TABLE `user` (
`max_updates` int(11) unsigned NOT NULL DEFAULT '0',
`max_connections` int(11) unsigned NOT NULL DEFAULT '0',
`max_user_connections` int(11) unsigned NOT NULL DEFAULT '0',
+ `plugin` char(60) CHARACTER SET latin1 NOT NULL DEFAULT '',
+ `auth_string` text COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
@@ -200,7 +202,7 @@ proc CREATE TABLE `proc` (
`definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`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 '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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 '',
`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,
@@ -225,7 +227,7 @@ event CREATE TABLE `event` (
`ends` datetime DEFAULT NULL,
`status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
`on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
- `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 '',
+ `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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 '',
`originator` int(10) unsigned NOT NULL,
`time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',
diff --git a/mysql-test/r/table_options.result b/mysql-test/r/table_options.result
new file mode 100644
index 00000000000..ed6fe4fb3de
--- /dev/null
+++ b/mysql-test/r/table_options.result
@@ -0,0 +1,182 @@
+drop table if exists t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1='1v1';
+Warnings:
+Warning 1651 Unknown option 'fkey'
+Warning 1651 Unknown option 'dff'
+Warning 1651 Unknown option 'tkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`=vvv,
+ KEY `akey` (`a`) `dff`=vvv
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v1'
+drop table t1;
+#reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+Warnings:
+Warning 1651 Unknown option 'fkey'
+Warning 1651 Unknown option 'dff'
+Warning 1651 Unknown option 'tkey1'
+Warning 1651 Unknown option 'tkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`=vvv,
+ KEY `akey` (`a`) `dff`=vvv
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=1v2 `tkey2`=2v1
+#add option
+alter table t1 tkey4=4v1;
+Warnings:
+Warning 1651 Unknown option 'tkey4'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`=vvv,
+ KEY `akey` (`a`) `dff`=vvv
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=1v2 `tkey2`=2v1 `tkey4`=4v1
+#remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+Warnings:
+Warning 1651 Unknown option 'tkey3'
+Warning 1651 Unknown option 'tkey4'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey`=vvv,
+ KEY `akey` (`a`) `dff`=vvv
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=1v2 `tkey2`=2v1
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1651 Unknown option 'fkey1'
+Warning 1651 Unknown option 'kkey1'
+Warning 1651 Unknown option 'TKEY1'
+Warning 1651 Unknown option 'tkey2'
+Warning 1651 Unknown option 'tkey3'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v1,
+ KEY `akey` (`a`) `kkey1`=v1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#change field with option with the same value
+alter table t1 change a a int `FKEY1`='v1';
+Warnings:
+Warning 1651 Unknown option 'FKEY1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `FKEY1`='v1',
+ KEY `akey` (`a`) `kkey1`=v1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#change field with option with a different value
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning 1651 Unknown option 'fkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ KEY `akey` (`a`) `kkey1`=v1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#new column no options
+alter table t1 add column b int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) `kkey1`=v1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning 1651 Unknown option 'kkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `b` int(11) DEFAULT NULL,
+ KEY `akey` (`a`) `kkey1`=v1,
+ KEY `bkey` (`b`) `kkey2`=v1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+Warnings:
+Warning 1651 Unknown option 'fkey1'
+Warning 1651 Unknown option 'fkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL `fkey1`=v1 `fkey2`=v2,
+ KEY `akey` (`a`) `kkey1`=v1,
+ KEY `bkey` (`b`) `kkey2`=v1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL `fkey1`=v1 `fkey2`=v2,
+ KEY `akey` (`a`) `kkey1`=v1,
+ KEY `bkey` (`b`) `kkey2`=v1,
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#drop column
+alter table t1 drop b;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `c` int(11) DEFAULT NULL `fkey1`=v1 `fkey2`=v2,
+ KEY `akey` (`a`) `kkey1`=v1,
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#add column with options after delete
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning 1651 Unknown option 'fkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `c` int(11) DEFAULT NULL `fkey1`=v1 `fkey2`=v2,
+ `b` int(11) DEFAULT NULL `fkey2`=v1,
+ KEY `akey` (`a`) `kkey1`=v1,
+ KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+#add key
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning 1651 Unknown option 'kkey2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL `fkey1`=v2,
+ `c` int(11) DEFAULT NULL `fkey1`=v1 `fkey2`=v2,
+ `b` int(11) DEFAULT NULL `fkey2`=v1,
+ KEY `akey` (`a`) `kkey1`=v1,
+ KEY `ckey` (`c`),
+ KEY `bkey` (`b`) `kkey2`=v2
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`=2v1 `tkey3`=3v1
+drop table t1;
+create table t1 (a int) tkey1=100;
+Warnings:
+Warning 1651 Unknown option 'tkey1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=100
+drop table t1;
+#error on unknown option
+SET SQL_MODE='';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+ERROR HY000: Unknown option 'fkey'
+SET @@SQL_MODE=@OLD_SQL_MODE;
diff --git a/mysql-test/std_data/loaddata7.dat b/mysql-test/std_data/loaddata7.dat
new file mode 100644
index 00000000000..e86d1621bd4
--- /dev/null
+++ b/mysql-test/std_data/loaddata7.dat
@@ -0,0 +1,5 @@
+2,2
+3,3
+4,4
+5,5
+6,6 \ No newline at end of file
diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result
index 01a41b55125..e2688a15899 100644
--- a/mysql-test/suite/binlog/r/binlog_index.result
+++ b/mysql-test/suite/binlog/r/binlog_index.result
@@ -13,6 +13,7 @@ master-bin.000001 #
master-bin.000002 #
master-bin.000003 #
master-bin.000004 #
+flush tables;
purge binary logs TO 'master-bin.000004';
Warnings:
Warning 1612 Being purged log master-bin.000001 was not found
diff --git a/mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result b/mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result
new file mode 100644
index 00000000000..5a6fbc953b4
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_options.result
@@ -0,0 +1,416 @@
+DROP DATABASE IF EXISTS test1;
+DROP DATABASE IF EXISTS test2;
+DROP DATABASE IF EXISTS test3;
+CREATE DATABASE test1;
+CREATE DATABASE test2;
+CREATE DATABASE test3;
+SET timestamp=1000000000;
+RESET MASTER;
+USE test1;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,1),(2,2);
+USE test2;
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (1),(2);
+DELETE FROM test1.t1 WHERE a=1;
+USE test3;
+CREATE TABLE t3 (a INT);
+INSERT INTO t3 VALUES (1),(2);
+INSERT INTO test1.t1 VALUES (3,3);
+USE test1;
+LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE t1
+FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n';
+DELETE FROM test3.t3 WHERE a=1;
+flush logs;
+#
+# mysqlbinlog output
+# --base64-output = decode-rows
+# --rewrite-db = test1->new_test1
+# --rewrite-db = test3->new_test3
+#
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+use new_test1/*!*/;
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+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.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+CREATE TABLE t1 (a INT, b INT)
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### @2=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### @2=2 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+use test2/*!*/;
+SET TIMESTAMP=1000000000/*!*/;
+CREATE TABLE t2 (a INT)
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM new_test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### @2=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+use new_test3/*!*/;
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE TABLE t3 (a INT)
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test3.t3
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test3.t3
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### @2=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+use new_test1/*!*/;
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### @2=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### @2=3 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=4 /* INT meta=0 nullable=1 is_null=0 */
+### @2=4 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=5 /* INT meta=0 nullable=1 is_null=0 */
+### @2=5 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=6 /* INT meta=0 nullable=1 is_null=0 */
+### @2=6 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM new_test3.t3
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+#
+# mysqlbinlog output
+# --base64-output = decode-rows
+# --rewrite-db = test1->new_test1
+# --rewrite-db = test3->new_test3
+# --read-from-remote-server
+#
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 4:46:40 at startup
+ROLLBACK/*!*/;
+# at #
+use new_test1/*!*/;
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+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.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+CREATE TABLE t1 (a INT, b INT)
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test1.t1
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### @2=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### @2=2 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+use test2/*!*/;
+SET TIMESTAMP=1000000000/*!*/;
+CREATE TABLE t2 (a INT)
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `test2`.`t2` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO test2.t2
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO test2.t2
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM new_test1.t1
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### @2=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+use new_test3/*!*/;
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE TABLE t3 (a INT)
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test3.t3
+### SET
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test3.t3
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### @2=3 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+use new_test1/*!*/;
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test1`.`t1` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+### INSERT INTO new_test1.t1
+### SET
+### @1=2 /* INT meta=0 nullable=1 is_null=0 */
+### @2=2 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=3 /* INT meta=0 nullable=1 is_null=0 */
+### @2=3 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=4 /* INT meta=0 nullable=1 is_null=0 */
+### @2=4 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=5 /* INT meta=0 nullable=1 is_null=0 */
+### @2=5 /* INT meta=0 nullable=1 is_null=0 */
+### INSERT INTO new_test1.t1
+### SET
+### @1=6 /* INT meta=0 nullable=1 is_null=0 */
+### @2=6 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 4:46:40 server id # end_log_pos # Table_map: `new_test3`.`t3` mapped to number #
+#010909 4:46:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+### DELETE FROM new_test3.t3
+### WHERE
+### @1=1 /* INT meta=0 nullable=1 is_null=0 */
+# at #
+#010909 4:46:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 4:46:40 server id # end_log_pos # Rotate to master-bin.000002 pos: 4
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+DROP DATABASE test1;
+DROP DATABASE test2;
+DROP DATABASE test3;
diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test
index 94923275a5f..3847e40aeb2 100644
--- a/mysql-test/suite/binlog/t/binlog_index.test
+++ b/mysql-test/suite/binlog/t/binlog_index.test
@@ -28,6 +28,7 @@ flush logs;
source include/show_binary_logs.inc;
remove_file $MYSQLD_DATADIR/master-bin.000001;
+flush tables;
# there must be a warning with file names
replace_regex /\.[\\\/]master/master/;
diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt
new file mode 100644
index 00000000000..4d69f3359db
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options-master.opt
@@ -0,0 +1 @@
+--timezone=GMT-3
diff --git a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test
new file mode 100644
index 00000000000..c1756b22eab
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_options.test
@@ -0,0 +1,78 @@
+--source include/have_log_bin.inc
+--source include/have_binlog_format_row.inc
+
+#
+# MWL36: Add a mysqlbinlog option to change the used database
+# (Adding --rewrite-db option)
+#
+--disable_warnings
+DROP DATABASE IF EXISTS test1;
+DROP DATABASE IF EXISTS test2;
+DROP DATABASE IF EXISTS test3;
+--enable_warnings
+
+# For SBR --rewrite-db affects only default database and doesn't affect
+# a query (specifically CREATE DATABASE) itself. Hence (for testing
+# purpose) we start binary logging after all databases have been created.
+
+CREATE DATABASE test1;
+CREATE DATABASE test2;
+CREATE DATABASE test3;
+
+# Fix timestamp to avoid varying results.
+SET timestamp=1000000000;
+
+# Delete all existing binary logs.
+RESET MASTER;
+
+# Whe'll call mysqlbinlog with two rewrite rules:
+# --rewrite-db="test1->new_test1"
+# --rewrite-db="test3->new_test3"
+
+USE test1;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,1),(2,2);
+
+USE test2;
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (1),(2);
+
+DELETE FROM test1.t1 WHERE a=1;
+
+USE test3;
+CREATE TABLE t3 (a INT);
+INSERT INTO t3 VALUES (1),(2);
+INSERT INTO test1.t1 VALUES (3,3);
+
+USE test1;
+LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE t1
+ FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n';
+DELETE FROM test3.t3 WHERE a=1;
+
+flush logs;
+
+--echo #
+--echo # mysqlbinlog output
+--echo # --base64-output = decode-rows
+--echo # --rewrite-db = test1->new_test1
+--echo # --rewrite-db = test3->new_test3
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --rewrite-db="test1->new_test1" --rewrite-db="test3->new_test3" -v -v $MYSQLD_DATADIR/master-bin.000001
+
+--echo #
+--echo # mysqlbinlog output
+--echo # --base64-output = decode-rows
+--echo # --rewrite-db = test1->new_test1
+--echo # --rewrite-db = test3->new_test3
+--echo # --read-from-remote-server
+--echo #
+
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows --rewrite-db="test1->new_test1" --rewrite-db="test3->new_test3" -v -v --read-from-remote-server --user=root --host=localhost --port=$MASTER_MYPORT master-bin.000001
+
+DROP DATABASE test1;
+DROP DATABASE test2;
+DROP DATABASE test3;
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 b1578b552bc..89c0d29016f 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result
@@ -7,6 +7,29 @@ NULL information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 NO varchar 32 96 NU
NULL information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32) select
NULL information_schema CHARACTER_SETS DESCRIPTION 3 NO varchar 60 180 NULL NULL utf8 utf8_general_ci varchar(60) select
NULL information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(3) select
+NULL information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL double select
+NULL information_schema CLIENT_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS CLIENT 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
+NULL information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS CONNECTED_TIME 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL double select
+NULL information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS 2 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema CLIENT_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
NULL information_schema COLLATIONS CHARACTER_SET_NAME 2 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32) select
NULL information_schema COLLATIONS COLLATION_NAME 1 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32) select
NULL information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(11) select
@@ -113,6 +136,10 @@ NULL information_schema GLOBAL_STATUS VARIABLE_NAME 1 NO varchar 64 192 NULL NU
NULL information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024) select
NULL information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024) select
+NULL information_schema INDEX_STATISTICS INDEX_NAME 3 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
+NULL information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema INDEX_STATISTICS TABLE_NAME 2 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
+NULL information_schema INDEX_STATISTICS TABLE_SCHEMA 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
NULL information_schema INNODB_BUFFER_POOL_PAGES fix_count 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema INNODB_BUFFER_POOL_PAGES flush_type 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema INNODB_BUFFER_POOL_PAGES lru_position 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
@@ -221,6 +248,18 @@ NULL information_schema INNODB_TRX trx_started 3 0000-00-00 00:00:00 NO datetime
NULL information_schema INNODB_TRX trx_state 2 NO varchar 13 39 NULL NULL utf8 utf8_general_ci varchar(13) select
NULL information_schema INNODB_TRX trx_wait_started 5 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select
NULL information_schema INNODB_TRX trx_weight 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES KEY_CACHE_NAME 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
+NULL information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES SEGMENTS 2 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
+NULL information_schema KEY_CACHES SEGMENT_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
+NULL information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
+NULL information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
@@ -262,10 +301,12 @@ NULL information_schema PBXT_STATISTICS ID 1 0 NO int NULL NULL 10 0 NULL NULL i
NULL information_schema PBXT_STATISTICS Name 2 NO varchar 40 120 NULL NULL utf8 utf8_general_ci varchar(40) select
NULL information_schema PBXT_STATISTICS Value 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(8) select
NULL information_schema PLUGINS PLUGIN_AUTHOR 8 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
+NULL information_schema PLUGINS PLUGIN_AUTH_VERSION 12 NULL YES varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
NULL information_schema PLUGINS PLUGIN_DESCRIPTION 9 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
NULL information_schema PLUGINS PLUGIN_LIBRARY 6 NULL YES varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema PLUGINS PLUGIN_LIBRARY_VERSION 7 NULL YES varchar 20 60 NULL NULL utf8 utf8_general_ci varchar(20) select
NULL information_schema PLUGINS PLUGIN_LICENSE 10 NULL YES varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
+NULL information_schema PLUGINS PLUGIN_MATURITY 11 NULL YES varchar 12 36 NULL NULL utf8 utf8_general_ci varchar(12) select
NULL information_schema PLUGINS PLUGIN_NAME 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema PLUGINS PLUGIN_STATUS 3 NO varchar 10 30 NULL NULL utf8 utf8_general_ci varchar(10) select
NULL information_schema PLUGINS PLUGIN_TYPE 4 NO varchar 80 240 NULL NULL utf8 utf8_general_ci varchar(80) select
@@ -376,6 +417,11 @@ NULL information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE 5 NO varchar 64 192 NUL
NULL information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
NULL information_schema TABLE_PRIVILEGES TABLE_NAME 4 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema TABLE_STATISTICS ROWS_READ 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema TABLE_STATISTICS TABLE_NAME 2 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
+NULL information_schema TABLE_STATISTICS TABLE_SCHEMA 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
NULL information_schema TRIGGERS ACTION_CONDITION 9 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext select
NULL information_schema TRIGGERS ACTION_ORDER 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(4) select
NULL information_schema TRIGGERS ACTION_ORIENTATION 11 NO varchar 9 27 NULL NULL utf8 utf8_general_ci varchar(9) select
@@ -402,6 +448,29 @@ NULL information_schema USER_PRIVILEGES GRANTEE 1 NO varchar 81 243 NULL NULL u
NULL information_schema USER_PRIVILEGES IS_GRANTABLE 4 NO varchar 3 9 NULL NULL utf8 utf8_general_ci varchar(3) select
NULL information_schema USER_PRIVILEGES PRIVILEGE_TYPE 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema USER_PRIVILEGES TABLE_CATALOG 2 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
+NULL information_schema USER_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL double select
+NULL information_schema USER_STATISTICS BYTES_RECEIVED 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS BYTES_SENT 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS COMMIT_TRANSACTIONS 18 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL int(11) select
+NULL information_schema USER_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL int(11) select
+NULL information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL double select
+NULL information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS ROWS_INSERTED 13 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS ROWS_READ 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS ROWS_SENT 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS ROWS_UPDATED 14 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS SELECT_COMMANDS 15 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL int(11) select
+NULL information_schema USER_STATISTICS UPDATE_COMMANDS 16 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) select
+NULL information_schema USER_STATISTICS USER 1 NO varchar 48 144 NULL NULL utf8 utf8_general_ci varchar(48) select
NULL information_schema VIEWS CHARACTER_SET_CLIENT 9 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32) select
NULL information_schema VIEWS CHECK_OPTION 5 NO varchar 8 24 NULL NULL utf8 utf8_general_ci varchar(8) select
NULL information_schema VIEWS COLLATION_CONNECTION 10 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32) select
@@ -458,6 +527,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME
NULL bigint NULL NULL
NULL datetime NULL NULL
NULL decimal NULL NULL
+NULL double NULL NULL
NULL int NULL NULL
--> CHAR(0) is allowed (see manual), and here both CHARACHTER_* values
--> are 0, which is intended behavior, and the result of 0 / 0 IS NULL
@@ -480,6 +550,29 @@ COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH C
3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 60 180 utf8 utf8_general_ci varchar(60)
NULL information_schema CHARACTER_SETS MAXLEN bigint NULL NULL NULL NULL bigint(3)
+3.0000 information_schema CLIENT_STATISTICS CLIENT varchar 64 192 utf8 utf8_general_ci varchar(64)
+NULL information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS CONNECTED_TIME bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS BUSY_TIME double NULL NULL NULL NULL double
+NULL information_schema CLIENT_STATISTICS CPU_TIME double NULL NULL NULL NULL double
+NULL information_schema CLIENT_STATISTICS BYTES_RECEIVED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS BYTES_SENT bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ROWS_READ bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ROWS_SENT bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ROWS_DELETED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ROWS_INSERTED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ROWS_UPDATED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS SELECT_COMMANDS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS UPDATE_COMMANDS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS OTHER_COMMANDS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS DENIED_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS LOST_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS ACCESS_DENIED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS EMPTY_QUERIES bigint NULL NULL NULL NULL bigint(21)
3.0000 information_schema COLLATIONS COLLATION_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema COLLATIONS CHARACTER_SET_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
NULL information_schema COLLATIONS ID bigint NULL NULL NULL NULL bigint(11)
@@ -586,6 +679,10 @@ NULL information_schema FILES CHECKSUM bigint NULL NULL NULL NULL bigint(21) uns
3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema INDEX_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema INDEX_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema INDEX_STATISTICS INDEX_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema INDEX_STATISTICS ROWS_READ bigint NULL NULL NULL NULL bigint(21)
3.0000 information_schema INNODB_BUFFER_POOL_PAGES page_type varchar 64 192 utf8 utf8_general_ci varchar(64)
NULL information_schema INNODB_BUFFER_POOL_PAGES space_id bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema INNODB_BUFFER_POOL_PAGES page_no bigint NULL NULL NULL NULL bigint(21) unsigned
@@ -694,6 +791,18 @@ NULL information_schema INNODB_TRX trx_wait_started datetime NULL NULL NULL NULL
NULL information_schema INNODB_TRX trx_weight bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema INNODB_TRX trx_mysql_thread_id bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema INNODB_TRX trx_query varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema KEY_CACHES KEY_CACHE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema KEY_CACHES SEGMENTS int NULL NULL NULL NULL int(3) unsigned
+NULL information_schema KEY_CACHES SEGMENT_NUMBER int NULL NULL NULL NULL int(3) unsigned
+NULL information_schema KEY_CACHES FULL_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES BLOCK_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES USED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES UNUSED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES DIRTY_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES READ_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES READS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES WRITE_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
+NULL information_schema KEY_CACHES WRITES bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
@@ -744,6 +853,8 @@ NULL information_schema PBXT_STATISTICS Value bigint NULL NULL NULL NULL bigint(
3.0000 information_schema PLUGINS PLUGIN_AUTHOR varchar 64 192 utf8 utf8_general_ci varchar(64)
1.0000 information_schema PLUGINS PLUGIN_DESCRIPTION longtext 4294967295 4294967295 utf8 utf8_general_ci longtext
3.0000 information_schema PLUGINS PLUGIN_LICENSE varchar 80 240 utf8 utf8_general_ci varchar(80)
+3.0000 information_schema PLUGINS PLUGIN_MATURITY varchar 12 36 utf8 utf8_general_ci varchar(12)
+3.0000 information_schema PLUGINS PLUGIN_AUTH_VERSION varchar 80 240 utf8 utf8_general_ci varchar(80)
NULL information_schema PROCESSLIST ID bigint NULL NULL NULL NULL bigint(4)
3.0000 information_schema PROCESSLIST USER varchar 16 48 utf8 utf8_general_ci varchar(16)
3.0000 information_schema PROCESSLIST HOST varchar 64 192 utf8 utf8_general_ci varchar(64)
@@ -849,6 +960,11 @@ NULL information_schema TABLES CHECKSUM bigint NULL NULL NULL NULL bigint(21) un
3.0000 information_schema TABLE_PRIVILEGES TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema TABLE_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3)
+3.0000 information_schema TABLE_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema TABLE_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema TABLE_STATISTICS ROWS_READ bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES bigint NULL NULL NULL NULL bigint(21)
3.0000 information_schema TRIGGERS TRIGGER_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema TRIGGERS TRIGGER_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema TRIGGERS TRIGGER_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
@@ -875,6 +991,29 @@ NULL information_schema TRIGGERS CREATED datetime NULL NULL NULL NULL datetime
3.0000 information_schema USER_PRIVILEGES TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema USER_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema USER_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3)
+3.0000 information_schema USER_STATISTICS USER varchar 48 144 utf8 utf8_general_ci varchar(48)
+NULL information_schema USER_STATISTICS TOTAL_CONNECTIONS int NULL NULL NULL NULL int(11)
+NULL information_schema USER_STATISTICS CONCURRENT_CONNECTIONS int NULL NULL NULL NULL int(11)
+NULL information_schema USER_STATISTICS CONNECTED_TIME int NULL NULL NULL NULL int(11)
+NULL information_schema USER_STATISTICS BUSY_TIME double NULL NULL NULL NULL double
+NULL information_schema USER_STATISTICS CPU_TIME double NULL NULL NULL NULL double
+NULL information_schema USER_STATISTICS BYTES_RECEIVED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS BYTES_SENT bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ROWS_READ bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ROWS_SENT bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ROWS_DELETED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ROWS_INSERTED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ROWS_UPDATED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS SELECT_COMMANDS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS UPDATE_COMMANDS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS OTHER_COMMANDS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS COMMIT_TRANSACTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS DENIED_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS LOST_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS ACCESS_DENIED bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS EMPTY_QUERIES bigint NULL NULL NULL NULL bigint(21)
3.0000 information_schema VIEWS TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema VIEWS TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema VIEWS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
index a61763976f4..a8713293c2a 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result
@@ -7,6 +7,29 @@ NULL information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 NO varchar 32 96 NU
NULL information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
NULL information_schema CHARACTER_SETS DESCRIPTION 3 NO varchar 60 180 NULL NULL utf8 utf8_general_ci varchar(60)
NULL information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(3)
+NULL information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL double
+NULL information_schema CLIENT_STATISTICS BYTES_RECEIVED 7 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS BYTES_SENT 8 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS CLIENT 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
+NULL information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS 18 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL double
+NULL information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_INSERTED 13 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_READ 10 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_SENT 11 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_UPDATED 14 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS SELECT_COMMANDS 15 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS UPDATE_COMMANDS 16 0 NO int NULL NULL 10 0 NULL NULL int(21)
NULL information_schema COLLATIONS CHARACTER_SET_NAME 2 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
NULL information_schema COLLATIONS COLLATION_NAME 1 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
NULL information_schema COLLATIONS ID 3 0 NO bigint NULL NULL 19 0 NULL NULL bigint(11)
@@ -113,6 +136,10 @@ NULL information_schema GLOBAL_STATUS VARIABLE_NAME 1 NO varchar 64 192 NULL NU
NULL information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
NULL information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL utf8 utf8_general_ci varchar(1024)
+NULL information_schema INDEX_STATISTICS INDEX_NAME 3 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
+NULL information_schema INDEX_STATISTICS ROWS_READ 4 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema INDEX_STATISTICS TABLE_NAME 2 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
+NULL information_schema INDEX_STATISTICS TABLE_SCHEMA 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
NULL information_schema INNODB_BUFFER_POOL_PAGES fix_count 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
NULL information_schema INNODB_BUFFER_POOL_PAGES flush_type 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
NULL information_schema INNODB_BUFFER_POOL_PAGES lru_position 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned
@@ -355,6 +382,11 @@ NULL information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE 5 NO varchar 64 192 NUL
NULL information_schema TABLE_PRIVILEGES TABLE_CATALOG 2 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512)
NULL information_schema TABLE_PRIVILEGES TABLE_NAME 4 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema TABLE_PRIVILEGES TABLE_SCHEMA 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED 4 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES 5 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema TABLE_STATISTICS ROWS_READ 3 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema TABLE_STATISTICS TABLE_NAME 2 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
+NULL information_schema TABLE_STATISTICS TABLE_SCHEMA 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192)
NULL information_schema TRIGGERS ACTION_CONDITION 9 NULL YES longtext 4294967295 4294967295 NULL NULL utf8 utf8_general_ci longtext
NULL information_schema TRIGGERS ACTION_ORDER 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(4)
NULL information_schema TRIGGERS ACTION_ORIENTATION 11 NO varchar 9 27 NULL NULL utf8 utf8_general_ci varchar(9)
@@ -381,6 +413,29 @@ NULL information_schema USER_PRIVILEGES GRANTEE 1 NO varchar 81 243 NULL NULL u
NULL information_schema USER_PRIVILEGES IS_GRANTABLE 4 NO varchar 3 9 NULL NULL utf8 utf8_general_ci varchar(3)
NULL information_schema USER_PRIVILEGES PRIVILEGE_TYPE 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64)
NULL information_schema USER_PRIVILEGES TABLE_CATALOG 2 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512)
+NULL information_schema USER_STATISTICS ACCESS_DENIED 22 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL double
+NULL information_schema USER_STATISTICS BYTES_RECEIVED 7 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS BYTES_SENT 8 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS COMMIT_TRANSACTIONS 18 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS CONCURRENT_CONNECTIONS 3 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS CONNECTED_TIME 4 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL NULL NULL double
+NULL information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_DELETED 12 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_INSERTED 13 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_READ 10 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_SENT 11 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_UPDATED 14 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS SELECT_COMMANDS 15 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS TOTAL_CONNECTIONS 2 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS UPDATE_COMMANDS 16 0 NO int NULL NULL 10 0 NULL NULL int(21)
+NULL information_schema USER_STATISTICS USER 1 NO varchar 48 144 NULL NULL utf8 utf8_general_ci varchar(48)
NULL information_schema VIEWS CHARACTER_SET_CLIENT 9 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
NULL information_schema VIEWS CHECK_OPTION 5 NO varchar 8 24 NULL NULL utf8 utf8_general_ci varchar(8)
NULL information_schema VIEWS COLLATION_CONNECTION 10 NO varchar 32 96 NULL NULL utf8 utf8_general_ci varchar(32)
@@ -436,6 +491,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME
NULL bigint NULL NULL
NULL datetime NULL NULL
NULL decimal NULL NULL
+NULL double NULL NULL
NULL int NULL NULL
--> CHAR(0) is allowed (see manual), and here both CHARACHTER_* values
--> are 0, which is intended behavior, and the result of 0 / 0 IS NULL
@@ -458,6 +514,29 @@ COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH C
3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 60 180 utf8 utf8_general_ci varchar(60)
NULL information_schema CHARACTER_SETS MAXLEN bigint NULL NULL NULL NULL bigint(3)
+3.0000 information_schema CLIENT_STATISTICS CLIENT varchar 64 192 utf8 utf8_general_ci varchar(64)
+NULL information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS CONNECTED_TIME int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS BUSY_TIME double NULL NULL NULL NULL double
+NULL information_schema CLIENT_STATISTICS CPU_TIME double NULL NULL NULL NULL double
+NULL information_schema CLIENT_STATISTICS BYTES_RECEIVED int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS BYTES_SENT int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_READ int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_SENT int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_DELETED int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_INSERTED int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROWS_UPDATED int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS SELECT_COMMANDS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS UPDATE_COMMANDS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS OTHER_COMMANDS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS COMMIT_TRANSACTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS DENIED_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS LOST_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS ACCESS_DENIED int NULL NULL NULL NULL int(21)
+NULL information_schema CLIENT_STATISTICS EMPTY_QUERIES int NULL NULL NULL NULL int(21)
3.0000 information_schema COLLATIONS COLLATION_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema COLLATIONS CHARACTER_SET_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
NULL information_schema COLLATIONS ID bigint NULL NULL NULL NULL bigint(11)
@@ -564,6 +643,10 @@ NULL information_schema FILES CHECKSUM bigint NULL NULL NULL NULL bigint(21) uns
3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
+3.0000 information_schema INDEX_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema INDEX_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema INDEX_STATISTICS INDEX_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema INDEX_STATISTICS ROWS_READ int NULL NULL NULL NULL int(21)
3.0000 information_schema INNODB_BUFFER_POOL_PAGES page_type varchar 64 192 utf8 utf8_general_ci varchar(64)
NULL information_schema INNODB_BUFFER_POOL_PAGES space_id bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema INNODB_BUFFER_POOL_PAGES page_no bigint NULL NULL NULL NULL bigint(21) unsigned
@@ -806,6 +889,11 @@ NULL information_schema TABLES CHECKSUM bigint NULL NULL NULL NULL bigint(21) un
3.0000 information_schema TABLE_PRIVILEGES TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema TABLE_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema TABLE_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3)
+3.0000 information_schema TABLE_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192)
+3.0000 information_schema TABLE_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
+NULL information_schema TABLE_STATISTICS ROWS_READ int NULL NULL NULL NULL int(21)
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED int NULL NULL NULL NULL int(21)
+NULL information_schema TABLE_STATISTICS ROWS_CHANGED_X_INDEXES int NULL NULL NULL NULL int(21)
3.0000 information_schema TRIGGERS TRIGGER_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema TRIGGERS TRIGGER_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema TRIGGERS TRIGGER_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
@@ -832,6 +920,29 @@ NULL information_schema TRIGGERS CREATED datetime NULL NULL NULL NULL datetime
3.0000 information_schema USER_PRIVILEGES TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema USER_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema USER_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3)
+3.0000 information_schema USER_STATISTICS USER varchar 48 144 utf8 utf8_general_ci varchar(48)
+NULL information_schema USER_STATISTICS TOTAL_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS CONCURRENT_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS CONNECTED_TIME int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS BUSY_TIME double NULL NULL NULL NULL double
+NULL information_schema USER_STATISTICS CPU_TIME double NULL NULL NULL NULL double
+NULL information_schema USER_STATISTICS BYTES_RECEIVED int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS BYTES_SENT int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS BINLOG_BYTES_WRITTEN int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_READ int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_SENT int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_DELETED int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_INSERTED int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROWS_UPDATED int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS SELECT_COMMANDS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS UPDATE_COMMANDS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS OTHER_COMMANDS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS COMMIT_TRANSACTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS DENIED_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS LOST_CONNECTIONS int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS ACCESS_DENIED int NULL NULL NULL NULL int(21)
+NULL information_schema USER_STATISTICS EMPTY_QUERIES int NULL NULL NULL NULL int(21)
3.0000 information_schema VIEWS TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema VIEWS TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema VIEWS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
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 98eeacdb74c..630baeee74f 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
@@ -49,7 +49,7 @@ NULL mysql event modified 9 0000-00-00 00:00:00 NO timestamp NULL NULL NULL NULL
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned select,insert,update,references
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL 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') select,insert,update,references
+NULL mysql event sql_mode 15 NO set 494 1482 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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') select,insert,update,references
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select,insert,update,references
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references
@@ -124,7 +124,7 @@ NULL mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL 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') select,insert,update,references
+NULL mysql proc sql_mode 15 NO set 494 1482 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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') select,insert,update,references
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI select,insert,update,references
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references
@@ -178,6 +178,7 @@ NULL mysql time_zone_transition_type Time_zone_id 1 NULL NO int NULL NULL 10 0 N
NULL mysql time_zone_transition_type Transition_type_id 2 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned PRI select,insert,update,references
NULL mysql user Alter_priv 17 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Alter_routine_priv 28 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
+NULL mysql user auth_string 41 NULL NO text 65535 65535 NULL NULL utf8 utf8_bin text select,insert,update,references
NULL mysql user Create_priv 8 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Create_routine_priv 27 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL 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
@@ -198,6 +199,7 @@ NULL mysql user max_questions 36 0 NO int NULL NULL 10 0 NULL NULL int(11) unsig
NULL mysql user max_updates 37 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
NULL mysql user max_user_connections 39 0 NO int NULL NULL 10 0 NULL NULL int(11) unsigned select,insert,update,references
NULL mysql user Password 3 NO char 41 41 NULL NULL latin1 latin1_bin char(41) select,insert,update,references
+NULL mysql user plugin 40 NO char 60 60 NULL NULL latin1 latin1_swedish_ci char(60) select,insert,update,references
NULL mysql user Process_priv 12 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user References_priv 15 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
NULL mysql user Reload_priv 10 N NO enum 1 3 NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
@@ -233,6 +235,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
@@ -327,7 +330,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event 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 event sql_mode set 494 1482 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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 event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +405,7 @@ NULL mysql ndb_binlog_index schemaops bigint NULL NULL NULL NULL bigint(20) unsi
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
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 sql_mode set 494 1482 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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)
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)
@@ -497,3 +500,5 @@ NULL mysql user max_questions int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_updates int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_connections int NULL NULL NULL NULL int(11) unsigned
NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) unsigned
+1.0000 mysql user plugin char 60 60 latin1 latin1_swedish_ci char(60)
+1.0000 mysql user auth_string text 65535 65535 utf8 utf8_bin text
diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
index 9c9d3cd26de..104960e4b79 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
@@ -49,7 +49,7 @@ NULL mysql event modified 9 0000-00-00 00:00:00 NO timestamp NULL NULL NULL NULL
NULL mysql event name 2 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI
NULL mysql event on_completion 14 DROP NO enum 8 24 NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE')
NULL mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL int(10) unsigned
-NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL 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')
+NULL mysql event sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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')
NULL mysql event starts 11 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime
NULL mysql event status 13 ENABLED NO enum 18 54 NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
NULL mysql event time_zone 18 SYSTEM NO char 64 64 NULL NULL latin1 latin1_swedish_ci char(64)
@@ -124,7 +124,7 @@ NULL mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL
NULL mysql proc security_type 8 DEFINER NO enum 7 21 NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER')
NULL mysql proc specific_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64)
NULL mysql proc sql_data_access 6 CONTAINS_SQL NO enum 17 51 NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')
-NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL 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')
+NULL mysql proc sql_mode 15 NO set 478 1434 NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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')
NULL mysql proc type 3 NULL NO enum 9 27 NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE') PRI
NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI
NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL
@@ -327,7 +327,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime
NULL mysql event ends datetime NULL NULL NULL NULL datetime
3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE')
-3.0000 mysql event 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 event sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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 event comment char 64 192 utf8 utf8_bin char(64)
NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned
1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64)
@@ -402,7 +402,7 @@ NULL mysql ndb_binlog_index schemaops bigint NULL NULL NULL NULL bigint(20) unsi
3.0000 mysql proc definer char 77 231 utf8 utf8_bin char(77)
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 sql_mode set 478 1434 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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)
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)
diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result
index bcfe138206e..8419bfb7ebb 100644
--- a/mysql-test/suite/funcs_1/r/is_tables_is.result
+++ b/mysql-test/suite/funcs_1/r/is_tables_is.result
@@ -38,6 +38,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME CLIENT_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME COLLATIONS
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -245,6 +268,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME INDEX_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME INNODB_BUFFER_POOL_PAGES
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -590,6 +636,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME KEY_CACHES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -935,6 +1004,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME TABLE_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME TRIGGERS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
@@ -981,6 +1073,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME USER_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME VIEWS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
@@ -1090,6 +1205,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME CLIENT_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME COLLATIONS
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -1297,6 +1435,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME INDEX_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME INNODB_BUFFER_POOL_PAGES
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -1642,6 +1803,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME KEY_CACHES
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
@@ -1987,6 +2171,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME TABLE_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME TRIGGERS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
@@ -2033,6 +2240,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
+TABLE_NAME USER_STATISTICS
+TABLE_TYPE SYSTEM VIEW
+ENGINE MEMORY
+VERSION 10
+ROW_FORMAT Fixed
+TABLE_ROWS #TBLR#
+AVG_ROW_LENGTH #ARL#
+DATA_LENGTH #DL#
+MAX_DATA_LENGTH #MDL#
+INDEX_LENGTH #IL#
+DATA_FREE #DF#
+AUTO_INCREMENT NULL
+CREATE_TIME #CRT#
+UPDATE_TIME #UT#
+CHECK_TIME #CT#
+TABLE_COLLATION utf8_general_ci
+CHECKSUM NULL
+CREATE_OPTIONS #CO#
+TABLE_COMMENT #TC#
+user_comment
+Separator -----------------------------------------------------
+TABLE_CATALOG NULL
+TABLE_SCHEMA information_schema
TABLE_NAME VIEWS
TABLE_TYPE SYSTEM VIEW
ENGINE MYISAM_OR_MARIA
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 03865f59c2c..b9a19f98d65 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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
#
# 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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
# 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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
# 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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
# 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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
# 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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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' NULL 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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
diff --git a/mysql-test/suite/funcs_1/t/is_tables_is.test b/mysql-test/suite/funcs_1/t/is_tables_is.test
index 90da2170281..20ed93ddd07 100644
--- a/mysql-test/suite/funcs_1/t/is_tables_is.test
+++ b/mysql-test/suite/funcs_1/t/is_tables_is.test
@@ -16,4 +16,3 @@
let $my_where = WHERE table_schema = 'information_schema'
AND table_name <> 'profiling';
--source suite/funcs_1/datadict/tables1.inc
-
diff --git a/mysql-test/suite/maria/r/group_commit.result b/mysql-test/suite/maria/r/group_commit.result
new file mode 100644
index 00000000000..75d7318340a
--- /dev/null
+++ b/mysql-test/suite/maria/r/group_commit.result
@@ -0,0 +1,17 @@
+drop table if exists t1;
+create table t1 (a int);
+SET GLOBAL maria_group_commit="NONE";
+SET GLOBAL maria_group_commit_interval= 0;
+SET GLOBAL maria_group_commit="NONE";
+SET GLOBAL maria_group_commit_interval= 100;
+SET GLOBAL maria_group_commit="HARD";
+SET GLOBAL maria_group_commit_interval= 0;
+SET GLOBAL maria_group_commit="HARD";
+SET GLOBAL maria_group_commit_interval= 100;
+SET GLOBAL maria_group_commit="SOFT";
+SET GLOBAL maria_group_commit_interval= 0;
+SET GLOBAL maria_group_commit="SOFT";
+SET GLOBAL maria_group_commit_interval= 100;
+SET GLOBAL maria_group_commit="NONE";
+SET GLOBAL maria_group_commit_interval= 0;
+drop table t1;
diff --git a/mysql-test/suite/maria/r/maria3.result b/mysql-test/suite/maria/r/maria3.result
index e632363346d..4fb08ed192e 100644
--- a/mysql-test/suite/maria/r/maria3.result
+++ b/mysql-test/suite/maria/r/maria3.result
@@ -306,6 +306,8 @@ Variable_name Value
maria_block_size 8192
maria_checkpoint_interval 30
maria_force_start_after_recovery_failures 0
+maria_group_commit none
+maria_group_commit_interval 0
maria_log_file_size 4294959104
maria_log_purge_type immediate
maria_max_sort_file_size 9223372036853727232
@@ -327,6 +329,7 @@ Maria_pagecache_read_requests #
Maria_pagecache_reads #
Maria_pagecache_write_requests #
Maria_pagecache_writes #
+Maria_transaction_log_syncs #
create table t1 (b char(0));
insert into t1 values(NULL),("");
select length(b) from t1;
diff --git a/mysql-test/suite/maria/t/group_commit.test b/mysql-test/suite/maria/t/group_commit.test
new file mode 100644
index 00000000000..e2cace14036
--- /dev/null
+++ b/mysql-test/suite/maria/t/group_commit.test
@@ -0,0 +1,72 @@
+# Test different ways of syncing (mostly syntax)
+--source include/have_maria.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int);
+
+SET GLOBAL maria_group_commit="NONE";
+SET GLOBAL maria_group_commit_interval= 0;
+--disable_query_log
+let $num = 5000;
+while ($num)
+{
+ insert into t1 values (1);
+ dec $num;
+}
+--enable_query_log
+SET GLOBAL maria_group_commit="NONE";
+SET GLOBAL maria_group_commit_interval= 100;
+--disable_query_log
+let $num = 5000;
+while ($num)
+{
+ insert into t1 values (1);
+ dec $num;
+}
+--enable_query_log
+SET GLOBAL maria_group_commit="HARD";
+SET GLOBAL maria_group_commit_interval= 0;
+--disable_query_log
+let $num = 5000;
+while ($num)
+{
+ insert into t1 values (1);
+ dec $num;
+}
+--enable_query_log
+SET GLOBAL maria_group_commit="HARD";
+SET GLOBAL maria_group_commit_interval= 100;
+--disable_query_log
+let $num = 5000;
+while ($num)
+{
+ insert into t1 values (1);
+ dec $num;
+}
+--enable_query_log
+SET GLOBAL maria_group_commit="SOFT";
+SET GLOBAL maria_group_commit_interval= 0;
+--disable_query_log
+let $num = 5000;
+while ($num)
+{
+ insert into t1 values (1);
+ dec $num;
+}
+--enable_query_log
+SET GLOBAL maria_group_commit="SOFT";
+SET GLOBAL maria_group_commit_interval= 100;
+--disable_query_log
+let $num = 5000;
+while ($num)
+{
+ insert into t1 values (1);
+ dec $num;
+}
+--enable_query_log
+SET GLOBAL maria_group_commit="NONE";
+SET GLOBAL maria_group_commit_interval= 0;
+drop table t1;
diff --git a/mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc b/mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc
new file mode 100644
index 00000000000..6fc3c6a0632
--- /dev/null
+++ b/mysql-test/suite/oqgraph/include/have_oqgraph_engine.inc
@@ -0,0 +1,4 @@
+disable_query_log;
+--require r/true.require
+select (PLUGIN_LIBRARY LIKE 'oqgraph_engine%') as `TRUE` from information_schema.plugins where PLUGIN_NAME='OQGRAPH';
+enable_query_log;
diff --git a/mysql-test/suite/oqgraph/r/basic.result b/mysql-test/suite/oqgraph/r/basic.result
new file mode 100644
index 00000000000..e90659c0986
--- /dev/null
+++ b/mysql-test/suite/oqgraph/r/basic.result
@@ -0,0 +1,63 @@
+drop table if exists graph;
+Warnings:
+Note 1051 Unknown table 'graph'
+CREATE TABLE graph (
+latch SMALLINT UNSIGNED NULL,
+origid BIGINT UNSIGNED NULL,
+destid BIGINT UNSIGNED NULL,
+weight DOUBLE NULL,
+seq BIGINT UNSIGNED NULL,
+linkid BIGINT UNSIGNED NULL,
+KEY (latch, origid, destid) USING HASH,
+KEY (latch, destid, origid) USING HASH
+) ENGINE=OQGRAPH;
+delete from graph;
+insert into graph(origid, destid) values (1,2), (2,1);
+insert into graph(origid, destid) values (1,3), (3,1);
+insert into graph(origid, destid) values (3,4), (4,3);
+insert into graph(origid, destid) values (3,5), (5,3);
+insert into graph(origid, destid) values (5,6), (6,5);
+select * from graph where latch = 2 and origid = 1 and weight = 1;
+latch origid destid weight seq linkid
+2 1 NULL 1 3 3
+2 1 NULL 1 2 2
+select * from graph where latch = 2 and origid = 1 and weight = 2;
+latch origid destid weight seq linkid
+2 1 NULL 2 5 5
+2 1 NULL 2 4 4
+select * from graph
+where latch = 2 and origid = 1 and (weight = 1 or weight = 2);
+latch origid destid weight seq linkid
+2 1 NULL 2 5 5
+2 1 NULL 2 4 4
+2 1 NULL 1 3 3
+2 1 NULL 1 2 2
+select * from graph where latch=1 and origid=1 and destid=6;
+latch origid destid weight seq linkid
+1 1 6 NULL 0 1
+1 1 6 1 1 3
+1 1 6 1 2 5
+1 1 6 1 3 6
+select * from graph where latch=1 and origid=1 and destid=4;
+latch origid destid weight seq linkid
+1 1 4 NULL 0 1
+1 1 4 1 1 3
+1 1 4 1 2 4
+select * from graph where latch=1 and origid=4 and destid=1;
+latch origid destid weight seq linkid
+1 4 1 NULL 0 4
+1 4 1 1 1 3
+1 4 1 1 2 1
+insert into graph (origid,destid) values (4,6);
+delete from graph where origid=5;
+delete from graph where origid=3 and destid=5;
+select * from graph where latch=1 and origid=1 and destid=6;
+latch origid destid weight seq linkid
+1 1 6 NULL 0 1
+1 1 6 1 1 3
+1 1 6 1 2 4
+1 1 6 1 3 6
+select * from graph where latch=1 and origid=6 and destid=1;
+latch origid destid weight seq linkid
+truncate table graph;
+drop table graph;
diff --git a/mysql-test/suite/oqgraph/r/binlog.result b/mysql-test/suite/oqgraph/r/binlog.result
new file mode 100644
index 00000000000..ee0a8c081f4
--- /dev/null
+++ b/mysql-test/suite/oqgraph/r/binlog.result
@@ -0,0 +1,18 @@
+drop table if exists graph;
+CREATE TABLE graph (
+latch SMALLINT UNSIGNED NULL,
+origid BIGINT UNSIGNED NULL,
+destid BIGINT UNSIGNED NULL,
+weight DOUBLE NULL,
+seq BIGINT UNSIGNED NULL,
+linkid BIGINT UNSIGNED NULL,
+KEY (latch, origid, destid) USING HASH,
+KEY (latch, destid, origid) USING HASH
+) ENGINE=OQGRAPH;
+SET binlog_format = row;
+insert into graph(origid, destid) values (1,3), (3,1);
+SET binlog_format = statement;
+insert into graph(origid, destid) values (3,4), (4,3);
+SET binlog_format = mixed;
+insert into graph(origid, destid) values (3,5), (5,3);
+drop table graph;
diff --git a/mysql-test/suite/oqgraph/t/basic.test b/mysql-test/suite/oqgraph/t/basic.test
new file mode 100644
index 00000000000..b39341ba3d5
--- /dev/null
+++ b/mysql-test/suite/oqgraph/t/basic.test
@@ -0,0 +1,45 @@
+-- source suite/oqgraph/include/have_oqgraph_engine.inc
+
+drop table if exists graph;
+
+CREATE TABLE graph (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight DOUBLE NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL,
+ KEY (latch, origid, destid) USING HASH,
+ KEY (latch, destid, origid) USING HASH
+ ) ENGINE=OQGRAPH;
+
+delete from graph;
+
+insert into graph(origid, destid) values (1,2), (2,1);
+insert into graph(origid, destid) values (1,3), (3,1);
+insert into graph(origid, destid) values (3,4), (4,3);
+insert into graph(origid, destid) values (3,5), (5,3);
+insert into graph(origid, destid) values (5,6), (6,5);
+
+select * from graph where latch = 2 and origid = 1 and weight = 1;
+
+select * from graph where latch = 2 and origid = 1 and weight = 2;
+
+select * from graph
+where latch = 2 and origid = 1 and (weight = 1 or weight = 2);
+
+select * from graph where latch=1 and origid=1 and destid=6;
+select * from graph where latch=1 and origid=1 and destid=4;
+select * from graph where latch=1 and origid=4 and destid=1;
+
+insert into graph (origid,destid) values (4,6);
+
+delete from graph where origid=5;
+delete from graph where origid=3 and destid=5;
+
+select * from graph where latch=1 and origid=1 and destid=6;
+select * from graph where latch=1 and origid=6 and destid=1;
+
+truncate table graph;
+
+drop table graph;
diff --git a/mysql-test/suite/oqgraph/t/binlog.test b/mysql-test/suite/oqgraph/t/binlog.test
new file mode 100644
index 00000000000..ac7c8867533
--- /dev/null
+++ b/mysql-test/suite/oqgraph/t/binlog.test
@@ -0,0 +1,28 @@
+-- source suite/oqgraph/include/have_oqgraph_engine.inc
+-- source include/have_log_bin.inc
+
+--disable_warnings
+drop table if exists graph;
+--enable_warnings
+
+CREATE TABLE graph (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight DOUBLE NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL,
+ KEY (latch, origid, destid) USING HASH,
+ KEY (latch, destid, origid) USING HASH
+ ) ENGINE=OQGRAPH;
+
+# MBug#524625: OQGraph error with binary logging enabled
+# Test that OQGraph works with different binlogging modes.
+SET binlog_format = row;
+insert into graph(origid, destid) values (1,3), (3,1);
+SET binlog_format = statement;
+insert into graph(origid, destid) values (3,4), (4,3);
+SET binlog_format = mixed;
+insert into graph(origid, destid) values (3,5), (5,3);
+
+drop table graph;
diff --git a/mysql-test/suite/oqgraph/t/suite.opt b/mysql-test/suite/oqgraph/t/suite.opt
new file mode 100644
index 00000000000..05985782664
--- /dev/null
+++ b/mysql-test/suite/oqgraph/t/suite.opt
@@ -0,0 +1 @@
+--plugin-load=$GRAPH_ENGINE_SO
diff --git a/mysql-test/suite/parts/r/partition_debug_sync_innodb.result b/mysql-test/suite/parts/r/partition_debug_sync_innodb.result
index 41c3d1af174..70939691565 100644
--- a/mysql-test/suite/parts/r/partition_debug_sync_innodb.result
+++ b/mysql-test/suite/parts/r/partition_debug_sync_innodb.result
@@ -35,7 +35,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p0 INTO
(PARTITION p0 VALUES LESS THAN (10),
PARTITION p10 VALUES LESS THAN MAXVALUE);
Warnings:
-Warning 1639 debug sync point wait timed out
+Warning 1649 debug sync point wait timed out
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PARTITION_NAME SUBPARTITION_NAME PARTITION_ORDINAL_POSITION SUBPARTITION_ORDINAL_POSITION PARTITION_METHOD SUBPARTITION_METHOD PARTITION_EXPRESSION SUBPARTITION_EXPRESSION PARTITION_DESCRIPTION TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE CREATE_TIME UPDATE_TIME CHECK_TIME CHECKSUM PARTITION_COMMENT NODEGROUP TABLESPACE_NAME
NULL test t1 p0 NULL 1 NULL RANGE NULL a NULL 10 1 16384 16384 NULL 0 0 NULL NULL NULL NULL default NULL
NULL test t1 p10 NULL 2 NULL RANGE NULL a NULL MAXVALUE 3 5461 16384 NULL 0 0 NULL NULL NULL NULL default NULL
diff --git a/mysql-test/suite/pbxt/r/grant.result b/mysql-test/suite/pbxt/r/grant.result
index 74cac3ea4f0..68395661db3 100644
--- a/mysql-test/suite/pbxt/r/grant.result
+++ b/mysql-test/suite/pbxt/r/grant.result
@@ -11,8 +11,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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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'
@@ -42,15 +42,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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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 ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin auth_string
+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
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
@@ -162,6 +162,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
insert into mysql.db (host, db, user, select_priv) values
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
alter table mysql.db order by db asc;
diff --git a/mysql-test/suite/pbxt/r/group_min_max.result b/mysql-test/suite/pbxt/r/group_min_max.result
index 0694a408f55..a591832bc0d 100644
--- a/mysql-test/suite/pbxt/r/group_min_max.result
+++ b/mysql-test/suite/pbxt/r/group_min_max.result
@@ -2199,7 +2199,7 @@ max(b) a
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 15
EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 10 NULL 15 Using index
@@ -2208,7 +2208,7 @@ CREATE TABLE t2 SELECT max(b), a FROM t1 GROUP BY a;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 15
FLUSH STATUS;
SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b;
max(b) a
@@ -2219,7 +2219,7 @@ max(b) a
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 15
FLUSH STATUS;
(SELECT max(b), a FROM t1 GROUP BY a) UNION
(SELECT max(b), a FROM t1 GROUP BY a);
@@ -2231,7 +2231,7 @@ max(b) a
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 30
EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION
(SELECT max(b), a FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
@@ -2282,7 +2282,7 @@ INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 15
DELETE FROM t3;
FLUSH STATUS;
INSERT INTO t3 SELECT 1, (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2)
@@ -2290,13 +2290,13 @@ FROM t1 LIMIT 1;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 15
FLUSH STATUS;
DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 15
FLUSH STATUS;
DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1) > 10000;
@@ -2304,7 +2304,7 @@ ERROR 21000: Subquery returns more than 1 row
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 0
-Handler_read_next 0
+Handler_read_next 16
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (a int, INDEX idx(a));
INSERT INTO t1 VALUES
diff --git a/mysql-test/suite/pbxt/r/mysqlshow.result b/mysql-test/suite/pbxt/r/mysqlshow.result
index 79394980270..8588b332b00 100644
--- a/mysql-test/suite/pbxt/r/mysqlshow.result
+++ b/mysql-test/suite/pbxt/r/mysqlshow.result
@@ -80,6 +80,7 @@ Database: information_schema
| Tables |
+---------------------------------------+
| CHARACTER_SETS |
+| CLIENT_STATISTICS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
@@ -89,6 +90,8 @@ Database: information_schema
| FILES |
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
+| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -104,8 +107,10 @@ Database: information_schema
| TABLES |
| TABLE_CONSTRAINTS |
| TABLE_PRIVILEGES |
+| TABLE_STATISTICS |
| TRIGGERS |
| USER_PRIVILEGES |
+| USER_STATISTICS |
| VIEWS |
| INNODB_BUFFER_POOL_PAGES |
| PBXT_STATISTICS |
@@ -131,6 +136,7 @@ Database: INFORMATION_SCHEMA
| Tables |
+---------------------------------------+
| CHARACTER_SETS |
+| CLIENT_STATISTICS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
@@ -140,6 +146,8 @@ Database: INFORMATION_SCHEMA
| FILES |
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
+| INDEX_STATISTICS |
+| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@@ -155,8 +163,10 @@ Database: INFORMATION_SCHEMA
| TABLES |
| TABLE_CONSTRAINTS |
| TABLE_PRIVILEGES |
+| TABLE_STATISTICS |
| TRIGGERS |
| USER_PRIVILEGES |
+| USER_STATISTICS |
| VIEWS |
| INNODB_BUFFER_POOL_PAGES |
| PBXT_STATISTICS |
diff --git a/mysql-test/suite/pbxt/r/null_key.result b/mysql-test/suite/pbxt/r/null_key.result
index 753ebf31f1c..8a440284c53 100644
--- a/mysql-test/suite/pbxt/r/null_key.result
+++ b/mysql-test/suite/pbxt/r/null_key.result
@@ -423,9 +423,9 @@ FOUND_ROWS()
SHOW STATUS LIKE "handler_read%";
Variable_name Value
Handler_read_first 0
-Handler_read_key 0
-Handler_read_next 0
+Handler_read_key 6
+Handler_read_next 2
Handler_read_prev 0
Handler_read_rnd 0
-Handler_read_rnd_next 0
+Handler_read_rnd_next 5
DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/suite/pbxt/r/partition_pruning.result b/mysql-test/suite/pbxt/r/partition_pruning.result
index 2f43fa6eb86..49fa43916aa 100644
--- a/mysql-test/suite/pbxt/r/partition_pruning.result
+++ b/mysql-test/suite/pbxt/r/partition_pruning.result
@@ -390,7 +390,7 @@ flush status;
update t1 set a=100 where a+1=5+1;
show status like 'Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 0
+Handler_read_rnd_next 10
flush status;
delete from t1 where a=5;
show status like 'Handler_read_rnd_next';
@@ -400,7 +400,7 @@ flush status;
delete from t1 where a+1=5+1;
show status like 'Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 0
+Handler_read_rnd_next 10
create table t2 like t1;
insert into t2 select * from t2;
flush status;
@@ -468,7 +468,7 @@ flush status;
update t2 set b = 100 where b = 6;
show status like 'Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 0
+Handler_read_rnd_next 1015
flush status;
update t2 set a = 1002 where a = 1001;
show status like 'Handler_read_rnd_next';
@@ -478,17 +478,17 @@ flush status;
update t2 set b = 6 where a = 600;
show status like 'Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 0
+Handler_read_rnd_next 201
flush status;
update t2 set b = 6 where a > 600 and a < 800;
show status like 'Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 0
+Handler_read_rnd_next 201
flush status;
delete from t2 where a > 600;
show status like 'Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 0
+Handler_read_rnd_next 402
drop table t2;
CREATE TABLE `t2` (
`a` int(11) default NULL,
@@ -605,7 +605,7 @@ Variable_name Value
Handler_read_rnd_next 0
show status like 'Handler_read_key';
Variable_name Value
-Handler_read_key 0
+Handler_read_key 5
flush status;
update t2 set a = 111 where b in (5,6);
show status like 'Handler_read_rnd_next';
@@ -613,7 +613,7 @@ Variable_name Value
Handler_read_rnd_next 0
show status like 'Handler_read_key';
Variable_name Value
-Handler_read_key 0
+Handler_read_key 10
flush status;
update t2 set a = 222 where b = 7;
show status like 'Handler_read_rnd_next';
@@ -621,7 +621,7 @@ Variable_name Value
Handler_read_rnd_next 0
show status like 'Handler_read_key';
Variable_name Value
-Handler_read_key 0
+Handler_read_key 5
flush status;
delete from t2 where b = 7;
show status like 'Handler_read_rnd_next';
@@ -629,7 +629,7 @@ Variable_name Value
Handler_read_rnd_next 0
show status like 'Handler_read_key';
Variable_name Value
-Handler_read_key 0
+Handler_read_key 5
flush status;
delete from t2 where b > 5;
show status like 'Handler_read_rnd_next';
@@ -637,13 +637,13 @@ Variable_name Value
Handler_read_rnd_next 0
show status like 'Handler_read_key';
Variable_name Value
-Handler_read_key 0
+Handler_read_key 5
show status like 'Handler_read_prev';
Variable_name Value
Handler_read_prev 0
show status like 'Handler_read_next';
Variable_name Value
-Handler_read_next 0
+Handler_read_next 300
flush status;
delete from t2 where b < 5 or b > 3;
show status like 'Handler_read_rnd_next';
@@ -651,13 +651,13 @@ Variable_name Value
Handler_read_rnd_next 0
show status like 'Handler_read_key';
Variable_name Value
-Handler_read_key 0
+Handler_read_key 10
show status like 'Handler_read_prev';
Variable_name Value
Handler_read_prev 0
show status like 'Handler_read_next';
Variable_name Value
-Handler_read_next 0
+Handler_read_next 510
drop table t1, t2;
create table t1 ( f_int1 mediumint, f_int2 integer)
partition by list(mod(f_int1,4)) (
diff --git a/mysql-test/suite/pbxt/r/update.result b/mysql-test/suite/pbxt/r/update.result
index 3a690709c28..9154583fa81 100644
--- a/mysql-test/suite/pbxt/r/update.result
+++ b/mysql-test/suite/pbxt/r/update.result
@@ -271,7 +271,7 @@ a
0
show status like 'handler_read%';
Variable_name Value
-Handler_read_first 0
+Handler_read_first 1
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
@@ -289,8 +289,8 @@ Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
-Handler_read_rnd 0
-Handler_read_rnd_next 0
+Handler_read_rnd 2
+Handler_read_rnd_next 18
flush status;
delete from t1 order by a limit 1;
show status like 'handler_read%';
@@ -299,8 +299,8 @@ Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
-Handler_read_rnd 0
-Handler_read_rnd_next 0
+Handler_read_rnd 1
+Handler_read_rnd_next 9
flush status;
delete from t1 order by a desc limit 1;
show status like 'handler_read%';
@@ -309,8 +309,8 @@ Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
-Handler_read_rnd 0
-Handler_read_rnd_next 0
+Handler_read_rnd 1
+Handler_read_rnd_next 8
alter table t1 disable keys;
Warnings:
Note 1031 Table storage engine for 't1' doesn't have this option
@@ -322,8 +322,8 @@ Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
-Handler_read_rnd 0
-Handler_read_rnd_next 0
+Handler_read_rnd 1
+Handler_read_rnd_next 7
select * from t1;
a b
0 0
@@ -372,10 +372,10 @@ update t2 set a=3 where a=2;
show status like 'handler_read%';
Variable_name Value
Handler_read_first 0
-Handler_read_key 0
-Handler_read_next 0
+Handler_read_key 1
+Handler_read_next 1
Handler_read_prev 0
-Handler_read_rnd 0
+Handler_read_rnd 1
Handler_read_rnd_next 0
drop table t1, t2;
create table t1(f1 int, `*f2` int);
diff --git a/mysql-test/suite/pbxt/t/multi_update.test b/mysql-test/suite/pbxt/t/multi_update.test
index 12e91c79f22..1acd59ea626 100644
--- a/mysql-test/suite/pbxt/t/multi_update.test
+++ b/mysql-test/suite/pbxt/t/multi_update.test
@@ -20,6 +20,7 @@ create table t1(id1 int not null auto_increment primary key, t char(12));
create table t2(id2 int not null, t char(12));
create table t3(id3 int not null, t char(12), index(id3));
disable_query_log;
+begin;
let $1 = 100;
while ($1)
{
@@ -38,6 +39,7 @@ while ($1)
}
dec $1;
}
+commit;
enable_query_log;
select count(*) from t1 where id1 > 95;
@@ -75,6 +77,7 @@ drop table t1,t2,t3;
create table t1(id1 int not null primary key, t varchar(100)) pack_keys = 1;
create table t2(id2 int not null, t varchar(100), index(id2)) pack_keys = 1;
disable_query_log;
+begin;
let $1 = 1000;
while ($1)
{
@@ -87,6 +90,7 @@ while ($1)
}
dec $1;
}
+commit;
enable_query_log;
delete t1 from t1,t2 where t1.id1 = t2.id2 and t1.id1 > 500;
drop table t1,t2;
@@ -328,6 +332,7 @@ drop table t1,t2;
create table t1 ( a int not null, b int not null) ;
--disable_query_log
+begin;
insert into t1 values (1,1),(2,2),(3,3),(4,4);
let $1=19;
set @d=4;
@@ -337,7 +342,7 @@ while ($1)
eval set @d=@d*2;
dec $1;
}
-
+commit;
--enable_query_log
alter table t1 add index i1(a);
delete from t1 where a > 2000000;
diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result
index 0d51f771a90..45c5bcf7ba0 100644
--- a/mysql-test/suite/rpl/r/rpl_do_grant.result
+++ b/mysql-test/suite/rpl/r/rpl_do_grant.result
@@ -162,9 +162,9 @@ SELECT * FROM mysql.procs_priv;
Host Db User Routine_name Routine_type Grantor Proc_priv Timestamp
SELECT upgrade_alter_func();
ERROR HY000: The user specified as a definer ('create_rout_db'@'localhost') does not exist
-USE bug42217_db;
-DROP FUNCTION upgrade_del_func;
-DROP FUNCTION upgrade_alter_func;
+USE test;
+DROP FUNCTION bug42217_db.upgrade_del_func;
+DROP FUNCTION bug42217_db.upgrade_alter_func;
DROP DATABASE bug42217_db;
stop slave;
DROP USER 'create_rout_db'@'localhost';
diff --git a/mysql-test/suite/rpl/r/rpl_ignore_table.result b/mysql-test/suite/rpl/r/rpl_ignore_table.result
index e77be425270..d06dda66267 100644
--- a/mysql-test/suite/rpl/r/rpl_ignore_table.result
+++ b/mysql-test/suite/rpl/r/rpl_ignore_table.result
@@ -34,6 +34,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
GRANT SELECT ON *.* TO mysqltest6@localhost;
GRANT INSERT ON *.* TO mysqltest6@localhost;
GRANT INSERT ON test.* TO mysqltest6@localhost;
diff --git a/mysql-test/suite/rpl/r/rpl_stm_000001.result b/mysql-test/suite/rpl/r/rpl_stm_000001.result
index c2a24cbaa82..2a5e4bdc99f 100644
--- a/mysql-test/suite/rpl/r/rpl_stm_000001.result
+++ b/mysql-test/suite/rpl/r/rpl_stm_000001.result
@@ -66,6 +66,7 @@ Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
+Warning 1364 Field 'auth_string' doesn't have a default value
select select_priv,user from mysql.user where user = _binary'blafasel2';
select_priv user
N blafasel2
diff --git a/mysql-test/suite/rpl/r/rpl_table_options.result b/mysql-test/suite/rpl/r/rpl_table_options.result
new file mode 100644
index 00000000000..9b0511f6494
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_table_options.result
@@ -0,0 +1,25 @@
+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;
+install plugin example soname 'ha_example.so';
+set storage_engine=example;
+create table t1 (a int not null) ull=12340;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ull`=12340
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `ull`=12340
+drop table t1;
+set storage_engine=default;
+select 1;
+1
+1
+uninstall plugin example;
diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test
index b0799b57f6a..457095f8fa6 100644
--- a/mysql-test/suite/rpl/t/rpl_do_grant.test
+++ b/mysql-test/suite/rpl/t/rpl_do_grant.test
@@ -208,9 +208,9 @@ SELECT upgrade_alter_func();
disconnect create_rout_db_master;
disconnect create_rout_db_slave;
connection master;
-USE bug42217_db;
-DROP FUNCTION upgrade_del_func;
-DROP FUNCTION upgrade_alter_func;
+USE test;
+DROP FUNCTION bug42217_db.upgrade_del_func;
+DROP FUNCTION bug42217_db.upgrade_alter_func;
DROP DATABASE bug42217_db;
-- sync_slave_with_master
diff --git a/mysql-test/suite/rpl/t/rpl_table_options.test b/mysql-test/suite/rpl/t/rpl_table_options.test
new file mode 100644
index 00000000000..b3d75bb0f95
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_table_options.test
@@ -0,0 +1,31 @@
+--source include/not_windows_embedded.inc
+--source include/have_example_plugin.inc
+--source include/master-slave.inc
+
+--replace_regex /\.dll/.so/
+eval install plugin example soname '$HA_EXAMPLE_SO';
+set storage_engine=example;
+
+sync_slave_with_master;
+connection master;
+
+#
+# only master has example engine installed,
+# the slave will have the table created in myisam,
+# that does not have ULL table option.
+# but because the table was created by the replication
+# slave thread, the table will be created anyway, even if
+# the option is unknown.
+#
+create table t1 (a int not null) ull=12340;
+show create table t1;
+
+sync_slave_with_master;
+connection slave;
+show create table t1;
+
+connection master;
+drop table t1;
+set storage_engine=default;
+select 1;
+uninstall plugin example;
diff --git a/mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc b/mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
new file mode 100644
index 00000000000..01f939337ed
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
@@ -0,0 +1,344 @@
+################################################################################
+# inc/vcol_blocked_sql_funcs_main.inc #
+# #
+# Purpose: #
+# Tests around sql functions #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: All SQL functions should be rejected, otherwise BUG.
+#
+
+--echo # RAND()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (b double as (rand()));
+
+--echo # LOAD_FILE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(64), b varchar(1024) as (load_file(a)));
+
+--echo # CURDATE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (curdate()));
+
+--echo # CURRENT_DATE(), CURRENT_DATE
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_date));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_date()));
+
+--echo # CURRENT_TIME(), CURRENT_TIME
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_time));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_time()));
+
+--echo # CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_timestamp()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (current_timestamp));
+
+--echo # CURTIME()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime as (curtime()));
+
+--echo # LOCALTIME(), LOCALTIME
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtime()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtime));
+
+--echo # LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6)
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtimestamp()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (localtimestamp));
+
+--echo # NOW()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b varchar(10) as (now()));
+
+--echo # SYSDATE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b varchar(10) as (sysdate()));
+
+--echo # UNIX_TIMESTAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (unix_timestamp()));
+
+--echo # UTC_DATE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (utc_date()));
+
+--echo # UTC_TIME()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (utc_time()));
+
+--echo # UTC_TIMESTAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a datetime, b datetime as (utc_timestamp()));
+
+--echo # MATCH()
+if (!$skip_full_text_checks)
+{
+ -- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+ create table t1 (a varchar(32), b bool as (match a against ('sample text')));
+}
+
+--echo # BENCHMARK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (benchmark(a,3)));
+
+--echo # CONNECTION_ID()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (connection_id()));
+
+--echo # CURRENT_USER(), CURRENT_USER
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (current_user()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (current_user));
+
+--echo # DATABASE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (database()));
+
+--echo # FOUND_ROWS()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (found_rows()));
+
+--echo # GET_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (get_lock(a,10)));
+
+--echo # IS_FREE_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (is_free_lock(a)));
+
+--echo # IS_USED_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (is_used_lock(a)));
+
+--echo # LAST_INSERT_ID()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (last_insert_id()));
+
+--echo # MASTER_POS_WAIT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32), b int as (master_pos_wait(a,0,2)));
+
+--echo # NAME_CONST()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (name_const('test',1)));
+
+--echo # RELEASE_LOCK()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32), b int as (release_lock(a)));
+
+--echo # ROW_COUNT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (row_count()));
+
+--echo # SCHEMA()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (schema()));
+
+--echo # SESSION_USER()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (session_user()));
+
+--echo # SLEEP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (sleep(a)));
+
+--echo # SYSTEM_USER()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32) as (system_user()));
+
+--echo # USER()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (user()));
+
+--echo # UUID_SHORT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024) as (uuid_short()));
+
+--echo # UUID()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024) as (uuid()));
+
+--echo # VALUES()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (values(a)));
+
+--echo # VERSION()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (version()));
+
+--echo # ENCRYPT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (encrypt(a)));
+
+--echo # Stored procedures
+
+delimiter //;
+create procedure p1()
+begin
+ select current_user();
+end //
+
+create function f1()
+returns int
+begin
+ return 1;
+end //
+
+delimiter ;//
+
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (p1()));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (f1()));
+
+drop procedure p1;
+drop function f1;
+
+--echo # Unknown functions
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int as (f1()));
+
+--echo #
+--echo # GROUP BY FUNCTIONS
+--echo #
+
+--echo # AVG()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (avg(a)));
+
+--echo # BIT_AND()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (bit_and(a)));
+
+--echo # BIT_OR()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (bit_or(a)));
+
+--echo # BIT_XOR()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (bit_xor(a)));
+
+--echo # COUNT(DISTINCT)
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (count(distinct a)));
+
+--echo # COUNT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (count(a)));
+
+--echo # GROUP_CONCAT()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(32), b int as (group_concat(a,'')));
+
+--echo # MAX()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (max(a)));
+
+--echo # MIN()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (min(a)));
+
+--echo # STD()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (std(a)));
+
+--echo # STDDEV_POP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (stddev_pop(a)));
+
+--echo # STDDEV_SAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (stddev_samp(a)));
+
+--echo # STDDEV()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (stddev(a)));
+
+--echo # SUM()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (sum(a)));
+
+--echo # VAR_POP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (var_pop(a)));
+
+--echo # VAR_SAMP()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (var_samp(a)));
+
+--echo # VARIANCE()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (variance(a)));
+
+--echo #
+--echo # XML FUNCTIONS
+--echo #
+
+--echo # ExtractValue()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (ExtractValue(a,'//b[$@j]')));
+
+--echo # UpdateXML()
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a varchar(1024), b varchar(1024) as (UpdateXML(a,'/a','<e>fff</e>')));
+
+--echo #
+--echo # Sub-selects
+--echo #
+
+create table t1 (a int);
+-- error ER_PARSE_ERROR
+create table t2 (a int, b int as (select count(*) from t1));
+drop table t1;
+
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as ((select 1)));
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (a+(select 1)));
+
+--echo #
+--echo # SP functions
+--echo #
+
+--disable_warnings
+drop function if exists sub1;
+--enable_warnings
+create function sub1(i int) returns int deterministic
+ return i+1;
+select sub1(1);
+-- error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a int, b int as (a+sub3(1)));
+drop function sub1;
+
+--echo #
+--echo # Long expression
+
+let $tmp_long_string = `SELECT repeat('a',240)`;
+eval create table t1 (a int, b varchar(300) as (concat(a,'$tmp_long_string')));
+drop table t1;
+let $tmp_long_string = `SELECT repeat('a',243)`;
+--error ER_WRONG_STRING_LENGTH
+eval create table t1 (a int, b varchar(300) as (concat(a,'$tmp_long_string')));
+
+--echo #
+--echo # Constant expression
+--error ER_CONST_EXPR_IN_VCOL
+create table t1 (a int as (PI()));
diff --git a/mysql-test/suite/vcol/inc/vcol_cleanup.inc b/mysql-test/suite/vcol/inc/vcol_cleanup.inc
new file mode 100644
index 00000000000..f8adec03b07
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_cleanup.inc
@@ -0,0 +1,25 @@
+################################################################################
+# inc/vcol_cleanup.inc #
+# #
+# Purpose: #
+# Removal of the objects created by the t/<test_name>.test #
+# scripts. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+--disable_warnings
+--disable_query_log
+DROP VIEW IF EXISTS v1,v2;
+DROP TABLE IF EXISTS t1,t2,t3;
+DROP PROCEDURE IF EXISTS p1;
+DROP FUNCTION IF EXISTS f1;
+DROP TRIGGER IF EXISTS trg1;
+DROP TRIGGER IF EXISTS trg2;
+--enable_query_log
+--enable_warnings
diff --git a/mysql-test/suite/vcol/inc/vcol_column_def_options.inc b/mysql-test/suite/vcol/inc/vcol_column_def_options.inc
new file mode 100644
index 00000000000..2f28136ad63
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_column_def_options.inc
@@ -0,0 +1,113 @@
+################################################################################
+# inc/vcol_column_def_options.inc #
+# #
+# Purpose: #
+# Testing different optional parameters specified when defining #
+# a virtual column. #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo #
+--echo # Section 1. Wrong column definition options
+--echo # - NOT NULL
+--echo # - NULL
+--echo # - DEFAULT <value>
+--echo # - AUTO_INCREMENT
+--echo # - [PRIMARY] KEY
+
+--echo # NOT NULL
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) not null);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) not null;
+drop table t1;
+
+--echo # NULL
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) null);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) null;
+drop table t1;
+
+--echo # DEFAULT
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) default 0);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) default 0;
+drop table t1;
+
+--echo # AUTO_INCREMENT
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) AUTO_INCREMENT);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) AUTO_INCREMENT;
+drop table t1;
+
+--echo # [PRIMARY] KEY
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) key);
+--error ER_PARSE_ERROR
+create table t1 (a int, b int as (a+1) primary key);
+create table t1 (a int);
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) key;
+--error ER_PARSE_ERROR
+alter table t1 add column b int as (a+1) primary key;
+drop table t1;
+
+--echo # Section 2. Other column definition options
+--echo # - COMMENT
+--echo # - REFERENCES (only syntax testing here)
+--echo # - STORED (only systax testing here)
+create table t1 (a int, b int as (a % 2) comment 'my comment');
+show create table t1;
+describe t1;
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) comment 'my comment';
+show create table t1;
+describe t1;
+insert into t1 (a) values (1);
+select * from t1;
+insert into t1 values (2,default);
+select a,b from t1;
+create table t2 like t1;
+show create table t2;
+describe t2;
+insert into t2 (a) values (1);
+select * from t2;
+insert into t2 values (2,default);
+select a,b from t2;
+drop table t2;
+drop table t1;
+
+create table t1 (a int, b int as (a % 2) persistent);
+show create table t1;
+describe t1;
+insert into t1 (a) values (1);
+select * from t1;
+insert into t1 values (2,default);
+select a,b from t1;
+drop table t1;
+
+
+create table t2 (a int);
+create table t1 (a int, b int as (a % 2) persistent references t2(a));
+show create table t1;
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+--error ER_PARSE_ERROR
+alter table t1 modify b int as (a % 2) persistent references t2(a);
+show create table t1;
+drop table t1;
diff --git a/mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc b/mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc
new file mode 100644
index 00000000000..91a55013699
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_dependancies_on_vcol.inc
@@ -0,0 +1,43 @@
+################################################################################
+# inc/vcol_dependencies_on_vcol.inc #
+# #
+# Purpose: #
+# Testing scenarios when columns depend on virtual columns, i.e. such as #
+# - a virtual column is based on a virtual column #
+# - a "real" column on which a virtual one is renamed/dropped #
+# - a virtual column involved in partitioning is renamed/dropped #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo # Can't define a virtual column on another virtual column
+--error ER_VCOL_BASED_ON_VCOL
+create table t1 (a int, b int as (a+1), c int as (b+1));
+create table t1 (a int, b int as (a+1));
+--error ER_VCOL_BASED_ON_VCOL
+alter table t1 add column c int as (b+1);
+drop table t1;
+
+--echo # Can't rename or drop a column used in the function of a virtual column
+create table t1 (a int, b int as (a+1));
+--echo # On renaming/dropping a column on which a virtual field is
+--echo # defined the following error is displayed:
+--echo # "Unknown column 'a' in 'virtual column function'"
+--error ER_BAD_FIELD_ERROR
+alter table t1 drop column a;
+--error ER_BAD_FIELD_ERROR
+alter table t1 change a c int;
+drop table t1;
+
+--echo # Can't rename or drop a virtual column used by the paritition function
+create table t1 (a int, b int as (a+1)) partition by hash(b);
+--error ER_BAD_FIELD_ERROR
+alter table t1 drop b;
+--error ER_BAD_FIELD_ERROR
+alter table t1 change b c int as (a+1);
+
diff --git a/mysql-test/suite/vcol/inc/vcol_handler.inc b/mysql-test/suite/vcol/inc/vcol_handler.inc
new file mode 100644
index 00000000000..49e2ddc2973
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_handler.inc
@@ -0,0 +1,77 @@
+################################################################################
+# inc/vcol_handler.inc #
+# #
+# Purpose: #
+# Testing HANDLER. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent,
+ d char(1),
+ index (a),
+ index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+
+--echo # HANDLER tbl_name OPEN
+handler t1 open;
+
+--echo # HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+
+--echo # HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+
+--echo # HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+
+--echo # HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+
+--echo # HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+
+--echo # HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+
+--echo # HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+
+--echo # HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+
+--echo # HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+
+--echo # HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+
+--echo # HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+
+--echo # HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+
+--echo # HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+
+--echo # HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+
+--echo # HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+
+--echo # HANDLER tbl_name CLOSE
+handler t1 close;
+
+drop table t1;
diff --git a/mysql-test/suite/vcol/inc/vcol_init_vars.pre b/mysql-test/suite/vcol/inc/vcol_init_vars.pre
new file mode 100644
index 00000000000..f3c55c22df8
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_init_vars.pre
@@ -0,0 +1,17 @@
+################################################################################
+# inc/vcol_init_vars.pre #
+# #
+# Purpose: #
+# Initialize variables used in t/<name> test cases. #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+let $skip_full_text_check = 0;
+let $skip_spatial_index_check = 0;
diff --git a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
new file mode 100644
index 00000000000..8d0a51f42c0
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc
@@ -0,0 +1,289 @@
+################################################################################
+# inc/vcol_ins_upd.inc #
+# #
+# Purpose: #
+# Testing DDL operations such as INSERT, UPDATE, REPLACE and DELETE. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+let $create1 = create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+let $create2 = create table t1 (a int unique,
+ b int as (-a),
+ c int as (-a) persistent);
+let $create3 = create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent unique);
+let $create4 = create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent unique,
+ d varchar(16));
+eval $create1;
+set sql_warnings = 1;
+
+--echo #
+--echo # *** INSERT ***
+--echo #
+
+--echo # INSERT INTO tbl_name VALUES... DEFAULT is specified against vcols
+insert into t1 values (1,default,default);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name VALUES... NULL is specified against vcols
+insert into t1 values (1,null,null);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name VALUES... a non-NULL value is specified against vcols
+insert into t1 values (1,2,3);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<non_vcol_list>) VALUES...
+insert into t1 (a) values (1), (2);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<normal+vcols>) VALUES... DEFAULT is specified
+--echo # against vcols
+insert into t1 (a,b) values (1,default), (2,default);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<normal+vcols>) VALUES... NULL is specified against vcols
+insert into t1 (a,b) values (1,null), (2,null);
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INSERT INTO tbl_name (<normal+vcols>) VALUES... a non-NULL value is specified
+--echo # against vcols
+insert into t1 (a,b) values (1,3), (2,4);
+select * from t1;
+delete from t1;
+select * from t1;
+drop table t1;
+
+--echo # Table with UNIQUE non-vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+--echo # KEY UPDATE <non_vcol>=expr, <vcol>=expr
+eval $create2;
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+ on duplicate key update a=2, b=default;
+select a,b,c from t1;
+delete from t1 where b in (1,2);
+select * from t1;
+drop table t1;
+
+--echo # Table with UNIQUE vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+--echo # KEY UPDATE <non_vcol>=expr, <vcol>=expr
+eval $create3;
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+ on duplicate key update a=2, b=default;
+select a,b,c from t1;
+
+--echo # CREATE new_table ... LIKE old_table
+--echo # INSERT INTO new_table SELECT * from old_table
+create table t2 like t1;
+insert into t2 select * from t1;
+select * from t1;
+drop table t2;
+
+--echo # CREATE new_table ... LIKE old_table INSERT INTO new_table (<non-vcols>, <vcols>)
+--echo # SELECT <non-vcols>, <vcols> from old_table
+insert into t1 values (1,default,default);
+select * from t1;
+create table t2 like t1;
+insert into t2 (a,b) select a,b from t1;
+select * from t2;
+drop table t2;
+drop table t1;
+
+--echo #
+--echo # *** UPDATE ***
+--echo #
+
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE non-vcol=expr
+eval $create1;
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where a=2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # UPDATE tbl_name SET vcol=expr WHERE non-vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set c=3 where a=2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where b=-2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # UPDATE tbl_name SET vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set c=3 where b=-2;
+select * from t1;
+delete from t1;
+select * from t1;
+drop table t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=const
+eval $create3;
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where c=-2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where c between -3 and -2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # No INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+update t1 set a=3 where b between -3 and -2;
+select * from t1;
+delete from t1;
+select * from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE vcol=between const1 and const2 ORDER BY vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where c between -1 and 0
+ order by c;
+select * from t1;
+delete from t1 where c between -6 and 0;
+select * from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE vcol=between const1 and const2 ORDER BY vcol LIMIT 2
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where c between -1 and 0
+ order by c limit 2;
+select * from t1;
+delete from t1 where c between -2 and 0 order by c;
+select * from t1;
+delete from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where (c between -2 and 0) and (b=-1);
+select * from t1;
+delete from t1;
+
+--echo # INDEX created on vcol
+--echo # UPDATE tbl_name SET non-vcol=expr
+--echo # WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+--echo # ORDER BY indexed vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+update t1 set a=6 where (c between -2 and 0) and (b=-1) order by c;
+select * from t1;
+delete from t1;
+drop table t1;
+
+let $innodb_engine = `SELECT @@session.storage_engine='innodb'`;
+if ($innodb_engine)
+{
+ --echo #
+ --echo # Verify ON UPDATE/DELETE actions of FOREIGN KEYs
+ create table t2 (a int primary key, name varchar(10));
+ create table t1 (a int primary key, b int as (a % 10) persistent);
+ insert into t2 values (1, 'value1'), (2,'value2'), (3,'value3');
+ insert into t1 (a) values (1),(2),(3);
+ select * from t1;
+ select * from t2;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+
+ --echo # - ON UPDATE RESTRICT
+ alter table t1 add foreign key (b) references t2(a) on update restrict;
+ --error ER_NO_REFERENCED_ROW_2
+ insert into t1 (a) values (4);
+ --error ER_ROW_IS_REFERENCED_2
+ update t2 set a=4 where a=3;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+ alter table t1 drop foreign key t1_ibfk_1;
+
+ --echo # - ON DELETE RESTRICT
+ alter table t1 add foreign key (b) references t2(a) on delete restrict;
+ --error ER_ROW_IS_REFERENCED_2
+ delete from t2 where a=3;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+ select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+ alter table t1 drop foreign key t1_ibfk_1;
+
+ --echo # - ON DELETE CASCADE
+ alter table t1 add foreign key (b) references t2(a) on delete cascade;
+ delete from t2 where a=3;
+ select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+ select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+ alter table t1 drop foreign key t1_ibfk_1;
+
+ drop table t1;
+ drop table t2;
+}
+
+--echo #
+--echo # *** REPLACE ***
+--echo #
+
+--echo # UNIQUE INDEX on vcol
+--echo # REPLACE tbl_name (non-vcols) VALUES (non-vcols);
+eval $create4;
+insert into t1 (a,d) values (1,'a'), (2,'b');
+select * from t1;
+replace t1 (a,d) values (1,'c');
+select * from t1;
+delete from t1;
+select * from t1;
+
+
+# *** DELETE
+# All required tests for DELETE are performed as part of the above testing
+# for INSERT, UPDATE and REPLACE.
+
+set sql_warnings = 0;
+drop table t1;
diff --git a/mysql-test/suite/vcol/inc/vcol_keys.inc b/mysql-test/suite/vcol/inc/vcol_keys.inc
new file mode 100644
index 00000000000..68a40afea92
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_keys.inc
@@ -0,0 +1,163 @@
+################################################################################
+# inc/vcol_keys.inc #
+# #
+# Purpose: #
+# Testing keys, indexes defined upon virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+
+--echo # - UNIQUE KEY
+--echo # - INDEX
+--echo # - FULLTEXT INDEX
+--echo # - SPATIAL INDEX (not supported)
+--echo # - FOREIGN INDEX (partially supported)
+--echo # - CHECK (allowed but not used)
+
+--echo # UNIQUE
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2) unique);
+create table t1 (a int, b int as (a*2) persistent unique);
+show create table t1;
+describe t1;
+drop table t1;
+
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2), unique key (b));
+create table t1 (a int, b int as (a*2) persistent, unique (b));
+show create table t1;
+describe t1;
+drop table t1;
+
+create table t1 (a int, b int as (a*2));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add unique key (b);
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add unique key (b);
+drop table t1;
+
+--echo # Testing data manipulation operations involving UNIQUE keys
+--echo # on virtual columns can be found in:
+--echo # - vcol_ins_upd.inc
+--echo # - vcol_select.inc
+
+--echo #
+--echo # INDEX
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2), index (b));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a*2), index (a,b));
+
+create table t1 (a int, b int as (a*2) persistent, index (b));
+show create table t1;
+describe t1;
+drop table t1;
+
+create table t1 (a int, b int as (a*2) persistent, index (a,b));
+show create table t1;
+describe t1;
+drop table t1;
+
+create table t1 (a int, b int as (a*2));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add index (b);
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add index (a,b);
+drop table t1;
+
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (b);
+drop table t1;
+
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (a,b);
+create table t2 like t1;
+drop table t2;
+drop table t1;
+
+--echo # Testing data manipulation operations involving INDEX
+--echo # on virtual columns can be found in:
+--echo # - vcol_select.inc
+
+--echo #
+--echo # TODO: FULLTEXT INDEX
+
+--echo # SPATIAL INDEX
+if (!$skip_spatial_index_check)
+{
+ --echo # Error "All parts of a SPATIAL index must be NOT NULL"
+ --error ER_SPATIAL_CANT_HAVE_NULL
+ create table t1 (a int, b int as (a+1) persistent, spatial index (b));
+ create table t1 (a int, b int as (a+1) persistent);
+ --error ER_SPATIAL_CANT_HAVE_NULL
+ alter table t1 add spatial index (b);
+ drop table t1;
+}
+
+--echo # FOREIGN KEY
+
+--echo # Rejected FK options.
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1) persistent,
+ foreign key (b) references t2(a) on update set null);
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1) persistent,
+ foreign key (b) references t2(a) on update cascade);
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1) persistent,
+ foreign key (b) references t2(a) on delete set null);
+
+create table t1 (a int, b int as (a+1) persistent);
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a) on update set null;
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a) on update cascade;
+--error ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a) on delete set null;
+drop table t1;
+
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1),
+ foreign key (b) references t2(a));
+
+create table t1 (a int, b int as (a+1));
+--error ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+alter table t1 add foreign key (b) references t2(a);
+drop table t1;
+
+--echo # Allowed FK options.
+create table t2 (a int primary key, b char(5));
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on update restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on update no action);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on delete restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on delete cascade);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+ foreign key (b) references t2(a) on delete no action);
+drop table t1;
+
+--echo
+--echo # Testing data manipulation operations involving FOREIGN KEY
+--echo # on virtual columns can be found in:
+--echo # - vcol_ins_upd.inc
+--echo # - vcol_select.inc
+
+--echo #
+--echo # TODO: CHECK
+
diff --git a/mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc b/mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc
new file mode 100644
index 00000000000..c586479618a
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_non_stored_columns.inc
@@ -0,0 +1,162 @@
+################################################################################
+# inc/vcol_non_stored_columns.inc #
+# #
+# Purpose: #
+# Ensure that MySQL behaviour is consistent irrelevant of #
+# - the place of a non-stored column among other columns, #
+# - the total number of non-stored fields. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo # Case 1. All non-stored columns.
+--echo # This scenario is currently impossible due to the fact that virtual columns
+--echo # with a constant expression are not allowed.
+
+--echo # Case 2. CREATE
+--echo # - Column1: "real"
+--echo # - Column 2: virtual non-stored
+create table t1 (a int, b int as (-a));
+insert into t1 values (1,default);
+select * from t1;
+insert into t1 values (2,default);
+select * from t1;
+drop table t1;
+
+--echo # Case 3. CREATE
+--echo # - Column1: "real"
+--echo # - Column 2: virtual stored
+create table t1 (a int, b int as (-a) persistent);
+insert into t1 values (1,default);
+select * from t1;
+insert into t1 values (2,default);
+select * from t1;
+drop table t1;
+
+--echo # Case 4. CREATE
+--echo # - Column1: virtual non-stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b), b int);
+insert into t1 values (default,1);
+select * from t1;
+insert into t1 values (default,2);
+select * from t1;
+drop table t1;
+
+--echo # Case 5. CREATE
+--echo # - Column1: virtual stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b) persistent, b int);
+insert into t1 values (default,1);
+select * from t1;
+insert into t1 values (default,2);
+select * from t1;
+drop table t1;
+
+--echo # Case 6. CREATE
+--echo # - Column1: "real"
+--echo # - Column2: virtual non-stored
+--echo # - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+insert into t1 values (1,default,default);
+select * from t1;
+insert into t1 values (2,default,default);
+select * from t1;
+drop table t1;
+
+--echo # Case 7. ALTER. Modify virtual stored -> virtual non-stored
+create table t1 (a int, b int as (a % 2) persistent);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 modify b int as (a % 2);
+show create table t1;
+drop table t1;
+
+--echo # Case 8. ALTER. Modify virtual non-stored -> virtual stored
+create table t1 (a int, b int as (a % 2));
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 modify b int as (a % 2) persistent;
+show create table t1;
+drop table t1;
+
+--echo # Case 9. CREATE LIKE
+--echo # - Column1: "real"
+--echo # - Column2: virtual non-stored
+--echo # - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+create table t2 like t1;
+insert into t2 values (1,default,default);
+select * from t2;
+insert into t2 values (2,default,default);
+select * from t2;
+drop table t2;
+drop table t1;
+
+--echo # Case 10. ALTER. Dropping a virtual non-stored column.
+--echo # - Column1: virtual non-stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b), b int, c varchar(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+alter table t1 drop column a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 11. ALTER. Dropping a virtual stored column.
+--echo # - Column1: virtual stored
+--echo # - Column2: "real"
+create table t1 (a int as (-b) persistent, b int, c char(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+alter table t1 drop column a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 12. ALTER. Adding a new virtual non-stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+alter table t1 add column c int as (dayofyear(b)) after a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 13. ALTER. Adding a new virtual stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+alter table t1 add column c int as (dayofyear(b)) persistent after a;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 14. ALTER. Changing the expression of a virtual stored column.
+create table t1 (a int, b datetime, c int as (week(b)) persistent);
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+alter table t1 change column c c int as (week(b,1)) persistent;
+select * from t1;
+show create table t1;
+drop table t1;
+
+--echo # Case 15. ALTER. Changing the expression of a virtual non-stored column.
+create table t1 (a int, b datetime, c int as (week(b)));
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+alter table t1 change column c c int as (week(b,1));
+select * from t1;
+show create table t1;
+drop table t1;
+
diff --git a/mysql-test/suite/vcol/inc/vcol_partition.inc b/mysql-test/suite/vcol/inc/vcol_partition.inc
new file mode 100644
index 00000000000..c20dfaaa2a4
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_partition.inc
@@ -0,0 +1,127 @@
+################################################################################
+# inc/vcol_partition.inc #
+# #
+# Purpose: #
+# Testing partitioning tables with virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--source include/have_partition.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+--echo # Case 1. Partitioning by RANGE based on a non-stored virtual column.
+
+CREATE TABLE t1 (
+ a DATE NOT NULL,
+ b int as (year(a))
+)
+PARTITION BY RANGE( b ) (
+ PARTITION p0 VALUES LESS THAN (2006),
+ PARTITION p2 VALUES LESS THAN (2008)
+);
+
+insert into t1 values ('2006-01-01',default);
+insert into t1 values ('2007-01-01',default);
+insert into t1 values ('2005-01-01',default);
+select * from t1;
+
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+
+--echo # Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+
+select * from t1;
+
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+
+drop table t1;
+
+--echo # Case 2. Partitioning by LIST based on a stored virtual column.
+
+CREATE TABLE t1 (a int, b int as (a % 3 ) persistent)
+PARTITION BY LIST (a+1)
+(PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
+
+insert into t1 values (1,default);
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+select * from t1;
+
+#
+# NOTE: The following tests are currently failing due to a
+# [suspected] bug in the existing partition functionality.
+# Here is what was observed when using mysqld compiled prior
+# to adding the virtual column functionality.
+# mysql> create table t1 (a int) partition by list (a)
+# (partition p1 values in (1), partition p2 values in (2));
+# Query OK, 0 rows affected (0.00 sec)
+#
+# mysql> insert into t1 values (1), (1), (2);
+# Query OK, 3 rows affected (0.00 sec)
+# Records: 3 Duplicates: 0 Warnings: 0
+#
+# mysql> select * from t1;
+# +------+
+# | a |
+# +------+
+# | 1 |
+# | 1 |
+# | 2 |
+# +------+
+# 3 rows in set (0.00 sec)
+#
+# mysql> alter table t1 reorganize partition p1 into
+# (partition p1 values in (3));
+# Query OK, 2 rows affected (3.90 sec)
+# Records: 2 Duplicates: 2 Warnings: 0
+#
+# mysql> select * from t1;
+# +------+
+# | a |
+# +------+
+# | 2 | <- Two row have been lost!!!
+# +------+
+# 1 row in set (0.00 sec)
+
+#
+#alter table t1 change b b int as ((a % 3)+1) persistent;
+#--error ER_NO_PARTITION_FOR_GIVEN_VALUE
+#alter table t1 change b b int as (a % 2) persistent;
+#select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+
+select * from t1;
+
+drop table t1;
+
+--echo # Case 3. Partitioning by HASH based on a non-stored virtual column.
+
+CREATE TABLE t1 (
+ a DATE NOT NULL,
+ b int as (year(a))
+)
+PARTITION BY HASH( b % 3 ) PARTITIONS 3;
+
+insert into t1 values ('2005-01-01',default);
+insert into t1 values ('2006-01-01',default);
+select * from t1;
+
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+
+--echo # Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+
+select * from t1;
+
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+
+drop table t1;
diff --git a/mysql-test/suite/vcol/inc/vcol_select.inc b/mysql-test/suite/vcol/inc/vcol_select.inc
new file mode 100644
index 00000000000..28c3416a55a
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_select.inc
@@ -0,0 +1,216 @@
+################################################################################
+# inc/vcol_select.inc #
+# #
+# Purpose: #
+# Testing different SELECTs. #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-18 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+# Table t1 is used below to test:
+# - Join type of ALL (sequential scan of the entire table)
+# - Join type of Index
+# - Join type of Range
+# - Join type of Ref_or_null
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent,
+ index (c));
+insert into t1 (a) values (2), (1), (1), (3), (NULL);
+
+# Table t2 is used below to test:
+# - Join type of system and const
+create table t2 like t1;
+insert into t2 (a) values (1);
+
+# Table t3 is used below to test
+# - Join type of Eq_ref with a unique virtual column
+# - Join type of Const
+create table t3 (a int primary key,
+ b int as (-a),
+ c int as (-a) persistent unique);
+insert into t3 (a) values (2),(1),(3);
+
+
+--echo # select_type=SIMPLE, type=system
+let $s = select * from t2;
+eval $s;
+eval explain $s;
+
+let $s = select * from t2 where c=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=ALL
+let $s = select * from t1 where b=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=const
+let $s = select * from t3 where a=1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=range
+let $s = select * from t3 where c>=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=SIMPLE, type=ref
+let $s = select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+eval $s;
+eval explain $s;
+
+--echo # select_type=PRIMARY, type=index,ALL
+let $s = select * from t1 where b in (select c from t3);
+eval $s;
+eval explain $s;
+
+--echo # select_type=PRIMARY, type=range,ref
+let $s = select * from t1 where c in (select c from t3 where c between -2 and -1);
+eval $s;
+eval explain $s;
+
+--echo # select_type=UNION, type=system
+--echo # select_type=UNION RESULT, type=<union1,2>
+let $s = select * from t1 union select * from t2;
+eval $s;
+eval explain $s;
+
+--echo # select_type=DERIVED, type=system
+let $s = select * from (select a,b,c from t1) as t11;
+eval $s;
+eval explain $s;
+
+--echo ###
+--echo ### Using aggregate functions with/without DISTINCT
+--echo ###
+--echo # SELECT COUNT(*) FROM tbl_name
+let $s = select count(*) from t1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT COUNT(DISTINCT <non-vcol>) FROM tbl_name
+let $s = select count(distinct a) from t1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT COUNT(DISTINCT <non-stored vcol>) FROM tbl_name
+let $s = select count(distinct b) from t1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT COUNT(DISTINCT <stored vcol>) FROM tbl_name
+let $s = select count(distinct c) from t1;
+eval $s;
+eval explain $s;
+
+--echo ###
+--echo ### filesort & range-based utils
+--echo ###
+--echo # SELECT * FROM tbl_name WHERE <vcol expr>
+let $s = select * from t3 where c >= -2;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-vcol expr>
+let $s = select * from t3 where a between 1 and 2;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
+let $s = select * from t3 where b between -2 and -1;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <indexed vcol expr>
+let $s = select * from t3 where c between -2 and -1;
+eval $s;
+eval explain $s;
+
+#### Remove for MyISAM due to a bug
+#### when all the three records are returned (a=1,2,3)
+#### instead of just two (a=1,2).
+#### This bug is presumably in base SQL routines as the same happens
+#### with this table:
+#### create table t4 (a int primary key, b int, c int unique);
+let $myisam_engine = `SELECT @@session.storage_engine='myisam'`;
+if (!$myisam_engine)
+{
+ --echo # SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <non-indexed vcol>
+ let $s = select * from t3 where a between 1 and 2 order by b;
+ eval $s;
+ eval explain $s;
+}
+
+--echo # SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
+let $s = select * from t3 where a between 1 and 2 order by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
+let $s = select * from t3 where b between -2 and -1 order by a;
+eval $s;
+eval explain $s;
+
+#### Remove for MyISAM due to a bug
+#### when all the three records are returned (a=1,2,3)
+#### instead of just two (a=1,2).
+#### This bug is presumably in base SQL routines as the same happens
+#### with this table:
+#### create table t4 (a int primary key, b int, c int unique);
+let $innodb_engine = `SELECT @@session.storage_engine='innodb'`;
+if (!$innodb_engine)
+{
+ --echo # SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-vcol>
+ let $s = select * from t3 where c between -2 and -1 order by a;
+ eval $s;
+ eval explain $s;
+}
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
+let $s = select * from t3 where b between -2 and -1 order by b;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-indexed vcol>
+let $s = select * from t3 where c between -2 and -1 order by b;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
+let $s = select * from t3 where b between -2 and -1 order by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <indexed vcol>
+let $s = select * from t3 where c between -2 and -1 order by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+let $s = select sum(b) from t1 group by b;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+let $s = select sum(c) from t1 group by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+let $s = select sum(b) from t1 group by c;
+eval $s;
+eval explain $s;
+
+--echo # SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+let $s = select sum(c) from t1 group by b;
+eval $s;
+eval explain $s;
+
diff --git a/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc b/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc
new file mode 100644
index 00000000000..f19bec04c7a
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs.inc
@@ -0,0 +1,42 @@
+################################################################################
+# inc/vcol_supported_sql_funcs.inc #
+# #
+# Purpose: #
+# Tests frame for allowed sql functions #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+--enable_warnings
+set sql_warnings = 1;
+eval create table t1 ($cols);
+show create table t1;
+if ($rows)
+{
+ eval insert into t1 values ($values1);
+ dec $rows;
+}
+if ($rows)
+{
+ eval insert into t1 values ($values2);
+ dec $rows;
+}
+if ($rows)
+{
+ eval insert into t1 values ($values3);
+ dec $rows;
+}
+if ($rows)
+{
+ eval insert into t1 values ($values4);
+ dec $rows;
+}
+select * from t1;
+drop table t1;
+set sql_warnings = 0;
diff --git a/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc b/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc
new file mode 100644
index 00000000000..daf59c38a7e
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_supported_sql_funcs_main.inc
@@ -0,0 +1,1229 @@
+################################################################################
+# inc/vcol_supported_sql_funcs_main.inc #
+# #
+# Purpose: #
+# Tests frame for allowed sql functions #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--echo #
+--echo # NUMERIC FUNCTIONS
+--echo #
+
+--echo # ABS()
+let $cols = a int, b int as (abs(a));
+let $values1 = -1, default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ACOS()
+let $cols = a double, b double as (format(acos(a),6));
+let $values1 = 1, default;
+let $values2 = 1.0001,default;
+let $values3 = 0,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ASIN()
+let $cols = a double, b double as (format(asin(a),6));
+let $values1 = 0.2, default;
+let $values2 = 1.0001,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #ATAN
+let $cols = a double, b double, c double as (format(atan(a,b),6));
+let $values1 = -2,2,default;
+let $values2 = format(PI(),6),0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a double, c double as (format(atan(a),6));
+let $values1 = -2,default;
+let $values2 = format(PI(),6),default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ATAN2
+let $cols = a double, b double, c double as (format(atan2(a,b),6));
+let $values1 = -2,2,default;
+let $values2 = format(PI(),6),0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CEIL()
+let $cols = a double, b int as (ceil(a));
+let $values1 = 1.23,default;
+let $values2 = -1.23,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONV()
+let $cols = a varchar(10), b int, c int, d varchar(10) as (conv(a,b,c));
+let $values1 = 'a',16,2,default;
+let $values2 = '6e',18,8,default;
+let $values3 = -17,10,-18,default;
+let $values4 = 10+'10'+'10'+0xa,10,10,default;
+let $rows = 4;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COS()
+let $cols = a double, b double as (format(cos(a),6));
+let $values1 = format(PI(),6),default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COT()
+let $cols = a double, b double as (format(cot(a),6));
+let $values1 = 12,default;
+let $values2 = 0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CRC32()
+let $cols = a varchar(10), b long as (crc32(a));
+let $values1 = 'MySQL',default;
+let $values2 = 'mysql',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DEGREES()
+let $cols = a double, b double as (format(degrees(a),6));
+let $values1 = format(PI(),6),default;
+let $values2 = format(PI()/2,6),default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # /
+let $cols = a double, b double as (a/2);
+let $values1 = 2,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # EXP()
+let $cols = a double, b double as (format(exp(a),6));
+let $values1 = 2,default;
+let $values2 = -2,default;
+let $values3 = 0,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FLOOR()
+let $cols = a double, b long as (floor(a));
+let $values1 = 1.23,default;
+let $values2 = -1.23,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LN()
+let $cols = a double, b double as (format(ln(a),6));
+let $values1 = 2,default;
+let $values2 = -2,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOG()
+let $cols = a double, b double, c double as (format(log(a,b),6));
+let $values1 = 2,65536,default;
+let $values2 = 10,100,default;
+let $values3 = 1,100,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a double, b double as (format(log(a),6));
+let $values1 = 2,default;
+let $values2 = -2,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOG2()
+let $cols = a double, b double as (format(log2(a),6));
+let $values1 = 65536,default;
+let $values2 = -100,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOG10()
+let $cols = a double, b double as (format(log10(a),6));
+let $values1 = 2,default;
+let $values2 = 100,default;
+let $values3 = -100,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # -
+let $cols = a double, b double as (a-1);
+let $values1 = 2,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MOD()
+let $cols = a int, b int as (mod(a,10));
+let $values1 = 1,default;
+let $values2 = 11,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # %
+let $cols = a int, b int as (a % 10);
+let $values1 = 1,default;
+let $values2 = 11,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # OCT()
+let $cols = a double, b varchar(10) as (oct(a));
+let $values1 = 12,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PI()
+let $cols = a double, b double as (format(PI()*a*a,6));
+let $values1 = 1,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # +
+let $cols = a int, b int as (a+1);
+let $values1 = 1,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # POW, POWER
+let $cols = a int, b int as (pow(a,2)), c int as (power(a,2));
+let $values1 = 1,default,default;
+let $values2 = 2,default,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RADIANS()
+let $cols = a double, b double as (format(radians(a),6));
+let $values1 = 90,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ROUND()
+let $cols = a double, b int as (round(a));
+let $values1 = -1.23,default;
+let $values2 = -1.58,default;
+let $values3 = 1.58,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a double, b double, c int as (round(a,b));
+let $values1 = 1.298,1,default;
+let $values2 = 1.298,0,default;
+let $values3 = 23.298,-1,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SIGN()
+let $cols = a double, b int as (sign(a));
+let $values1 = -32,default;
+let $values2 = 0,default;
+let $values3 = 234,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SIN()
+let $cols = a double, b double as (format(sin(a),6));
+let $values1 = format(PI()/2,6),default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SQRT()
+let $cols = a double, b double as (format(sqrt(a),6));
+let $values1 = 4,default;
+let $values2 = 20,default;
+let $values3 = -16,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TAN()
+let $cols = a double, b double as (format(tan(a),6));
+let $values1 = format(PI(),6),default;
+let $values2 = format(PI()+1,6),default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # *
+let $cols = a double, b double as (a*3);
+let $values1 = 0,default;
+let $values2 = 1,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TRUNCATE()
+let $cols = a double, b double as (truncate(a,4));
+let $values1 = 1.223,default;
+let $values2 = 1.999,default;
+let $values3 = 1.999,default;
+let $values4 = 122,default;
+let $rows = 4;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # Unary -
+let $cols = a double, b double as (-a);
+let $values1 = 1,default;
+let $values2 = -1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # STRING FUNCTIONS
+--echo #
+
+--echo # ASCII()
+let $cols = a char(2), b int as (ascii(a));
+let $values1 = '2',default;
+let $values2 = 2,default;
+let $values3 = 'dx',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BIN()
+let $cols = a int, b varchar(10) as (bin(a));
+let $values1 = 12,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BIT_LENGTH()
+let $cols = a varchar(10), b long as (bit_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHAR_LENGTH()
+let $cols = a varchar(10), b long as (char_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHAR()
+let $cols = a int, b int, c varbinary(10) as (char(a,b));
+let $values1 = 77,121,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHARACTER_LENGTH()
+let $cols = a varchar(10), b long as (character_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONCAT_WS()
+let $cols = a varchar(10), b varchar(10), c varchar(20) as (concat_ws(',',a,b));
+let $values1 = 'value1','value2',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONCAT()
+let $cols = a varchar(10), b varchar(10), c varchar(20) as (concat(a,',',b));
+let $values1 = 'value1','value2',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ELT()
+let $cols = a varchar(10), b varchar(10), c int, d varchar(10) as (elt(c,a,b));
+let $values1 = 'value1','value2',1,default;
+let $values2 = 'value1','value2',2,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # EXPORT_SET()
+let $cols = a int, b varchar(10) as (export_set(a,'1','0','',10));
+let $values1 = 6,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FIELD()
+let $cols = a varchar(10), b varchar(10), c int as (field('aa',a,b));
+let $values1 = 'aa','bb',default;
+let $values2 = 'bb','aa',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FIND_IN_SET()
+let $cols = a varchar(10), b varchar(10), c int as (find_in_set(a,b));
+let $values1 = 'aa','aa,bb,cc',default;
+let $values2 = 'aa','bb,aa,cc',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FORMAT()
+let $cols = a double, b varchar(20) as (format(a,2));
+let $values1 = 12332.123456,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # HEX()
+let $cols = a int, b varchar(10) as (hex(a));
+let $values1 = 17,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+let $cols = a varchar(10), b varchar(10) as (hex(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # INSERT()
+let $cols = a varchar(10), b varchar(10), c varchar(20) as (insert(a,length(a),length(b),b));
+let $values1 = 'start,','end',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # INSTR()
+let $cols = a varchar(10), b varchar(10), c int as (instr(a,b));
+let $values1 = 'foobarbar,','bar',default;
+let $values2 = 'xbar,','foobar',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LCASE()
+let $cols = a varchar(10), b varchar(10) as (lcase(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LEFT()
+let $cols = a varchar(10), b varchar(5) as (left(a,5));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LENGTH()
+let $cols = a varchar(10), b int as (length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LIKE
+let $cols = a varchar(10), b bool as (a like 'H%o');
+let $values1 = 'Hello',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOCATE()
+let $cols = a varchar(10), b varchar(10) as (locate('bar',a));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LOWER()
+let $cols = a varchar(10), b varchar(10) as (lower(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LPAD()
+let $cols = a varchar(10), b varchar(10) as (lpad(a,4,' '));
+let $values1 = 'MySQL',default;
+let $values2 = 'M',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LTRIM()
+let $cols = a varchar(10), b varchar(10) as (ltrim(a));
+let $values1 = ' MySQL',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MAKE_SET()
+let $cols = a varchar(10), b varchar(10), c int, d varchar(30) as (make_set(c,a,b));
+let $values1 = 'a','b',1,default;
+let $values2 = 'a','b',3,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MID()
+let $cols = a varchar(10), b varchar(10) as (mid(a,1,2));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NOT LIKE
+let $cols = a varchar(10), b bool as (a not like 'H%o');
+let $values1 = 'Hello',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NOT REGEXP
+let $cols = a varchar(10), b bool as (a not regexp 'H.+o');
+let $values1 = 'Hello',default;
+let $values2 = 'hello',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # OCTET_LENGTH()
+let $cols = a varchar(10), b int as (octet_length(a));
+let $values1 = 'text',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ORD()
+let $cols = a varchar(10), b long as (ord(a));
+let $values1 = '2',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # POSITION()
+let $cols = a varchar(10), b varchar(10) as (position('bar' in a));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # QUOTE()
+let $cols = a varchar(10), b varchar(10) as (quote(a));
+let $values1 = 'Don\'t',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REGEXP()
+let $cols = a varchar(10), b bool as (a regexp 'H.+o');
+let $values1 = 'Hello',default;
+let $values2 = 'hello',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REPEAT()
+let $cols = a varchar(10), b varchar(30) as (repeat(a,3));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REPLACE()
+let $cols = a varchar(10), b varchar(30) as (replace(a,'aa','bb'));
+let $values1 = 'maa',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # REVERSE()
+let $cols = a varchar(10), b varchar(30) as (reverse(a));
+let $values1 = 'maa',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RIGHT()
+let $cols = a varchar(10), b varchar(10) as (right(a,4));
+let $values1 = 'foobarbar',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RLIKE()
+let $cols = a varchar(10), b bool as (a rlike 'H.+o');
+let $values1 = 'Hello',default;
+let $values2 = 'MySQL',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RPAD()
+let $cols = a varchar(10), b varchar(10) as (rpad(a,4,'??'));
+let $values1 = 'He',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # RTRIM();
+let $cols = a varchar(10), b varchar(10) as (rtrim(a));
+let $values1 = 'Hello ',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SOUNDEX()
+let $cols = a varchar(10), b varchar(20) as (soundex(a));
+let $values1 = 'Hello',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SOUNDS LIKE
+let $cols = a varchar(10), b varchar(10), c bool as (a sounds like b);
+let $values1 = 'Hello','Hello',default;
+let $values2 = 'Hello','MySQL',default;
+let $values3 = 'Hello','hello',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SPACE()
+let $cols = a varchar(5), b varchar(10) as (concat(a,space(5)));
+let $values1 = 'Hello', default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # STRCMP()
+let $cols = a varchar(9), b varchar(9), c tinyint(1) as (strcmp(a,b));
+let $values1 = 'Hello','Hello', default;
+let $values2 = 'Hello','Hello1', default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBSTR()
+let $cols = a varchar(5), b varchar(10) as (substr(a,2));
+let $values1 = 'Hello',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBSTRING_INDEX()
+let $cols = a varchar(15), b varchar(10) as (substring_index(a,'.',2));
+let $values1 = 'www.mysql.com',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBSTRING()
+let $cols = a varchar(5), b varchar(10) as (substring(a from 2 for 2));
+let $values1 = 'Hello',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TRIM()
+let $cols = a varchar(15), b varchar(10) as (trim(a));
+let $values1 = ' aa ',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UCASE()
+let $cols = a varchar(5), b varchar(10) as (ucase(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UNHEX()
+let $cols = a varchar(15), b varchar(10) as (unhex(a));
+let $values1 = '4D7953514C',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UPPER()
+let $cols = a varchar(5), b varchar(10) as (upper(a));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # CONTROL FLOW FUNCTIONS
+--echo #
+
+--echo # CASE
+let $cols = a varchar(10), b varchar(16) as (case a when NULL then 'asd' when 'b' then 'B' else a end);
+let $values1 = NULL,default;
+let $values2 = 'b',default;
+let $values3 = 'c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IF
+let $cols = a int, b int, c int as (if(a=1,a,b));
+let $values1 = 1,2,default;
+let $values2 = 3,4,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IFNULL
+let $cols = a varchar(10), b varchar(10), c varchar(10) as (ifnull(a,'DEFAULT'));
+let $values1 = NULL,'adf',default;
+let $values2 = 'a','adf',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NULLIF
+let $cols = a varchar(10), b varchar(10) as (nullif(a,'DEFAULT'));
+let $values1 = 'DEFAULT',default;
+let $values2 = 'a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # OPERATORS
+--echo #
+
+--echo # AND, &&
+let $cols = a int, b bool as (a>0 && a<2);
+let $values1 = -1,default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BETWEEN ... AND ...
+let $cols = a int, b bool as (a between 0 and 2);
+let $values1 = -1,default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BINARY
+let $cols = a varchar(10), b varbinary(10) as (binary a);
+let $values1 = '11',default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # &
+let $cols = a int, b int as (a & 5);
+let $values1 = 1,default;
+let $values2 = 0,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ~
+let $cols = a int, b int as (~a);
+let $values1 = 1,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # |
+let $cols = a int, b int as (a | 5);
+let $values1 = 1,default;
+let $values2 = 0,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ^
+let $cols = a int, b int as (a ^ 5);
+let $values1 = 1,default;
+let $values2 = 0,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DIV
+let $cols = a int, b int as (a div 5);
+let $values1 = 1,default;
+let $values2 = 7,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <=>
+let $cols = a int, b int, c bool as (a <=> b);
+let $values1 = 1,1,default;
+let $values2 = NULL,NULL,default;
+let $values3 = 1,NULL,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # =
+let $cols = a varchar(10), b varchar(10), c bool as (a=b);
+let $values1 = 'a','b',default;
+let $values2 = 'a','a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # >=
+let $cols = a varchar(10), b varchar(10), c bool as (a >= b);
+let $values1 = 'a','b',default;
+let $values2 = 'a','a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # >
+let $cols = a varchar(10), b varchar(10), c bool as (a > b);
+let $values1 = 'a','b',default;
+let $values2 = 'a','a',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IS NOT NULL
+let $cols = a int, b bool as (a is not null);
+let $values1 = 1,default;
+let $values2 = NULL,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # IS NULL
+let $cols = a int, b bool as (a is null);
+let $values1 = 1,default;
+let $values2 = NULL,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <<
+let $cols = a int, b int as (a << 2);
+let $values1 = 1,default;
+let $values2 = 3,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <=
+let $cols = a varchar(10), b varchar(10), c bool as (a <= b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <
+let $cols = a varchar(10), b varchar(10), c bool as (a < b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # NOT BETWEEN ... AND ...
+let $cols = a int, b bool as (a not between 0 and 2);
+let $values1 = -1,default;
+let $values2 = 1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # <>
+let $cols = a varchar(10), b varchar(10), c bool as (a <> b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # !=
+let $cols = a varchar(10), b varchar(10), c bool as (a != b);
+let $values1 = 'b','a',default;
+let $values2 = 'b','b',default;
+let $values3 = 'b','c',default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ||, OR
+let $cols = a int, b int as (a>5 || a<3);
+let $values1 = 1,default;
+let $values2 = 4,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # >>
+let $cols = a int, b int as (a >> 2);
+let $values1 = 8,default;
+let $values2 = 3,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # XOR
+let $cols = a int, b int as (a xor 5);
+let $values1 = 0,default;
+let $values2 = 1,default;
+let $values3 = 2,default;
+let $rows = 3;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # DATE AND TIME FUNCTIONS
+--echo #
+
+--echo # ADDDATE()
+let $cols = a datetime, b datetime as (adddate(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ADDTIME()
+let $cols = a datetime, b datetime as (addtime(a,'02:00:00'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CONVERT_TZ()
+let $cols = a datetime, b datetime as (convert_tz(a,'MET','UTC'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE_ADD()
+let $cols = a datetime, b datetime as (date_add(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE_FORMAT()
+let $cols = a datetime, b varchar(64) as (date_format(a,'%W %M %D'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE_SUB()
+let $cols = a datetime, b datetime as (date_sub(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATE()
+let $cols = a datetime, b datetime as (date(a));
+let $values1 = '2008-08-31 02:00:00',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DATEDIFF()
+let $cols = a datetime, b long as (datediff(a,'2000-01-01'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAY()
+let $cols = a datetime, b int as (day(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYNAME()
+let $cols = a datetime, b varchar(10) as (dayname(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYOFMONTH()
+let $cols = a datetime, b int as (dayofmonth(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYOFWEEK()
+let $cols = a datetime, b int as (dayofweek(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DAYOFYEAR()
+let $cols = a datetime, b int as (dayofyear(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # EXTRACT
+let $cols = a datetime, b int as (extract(year from a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FROM_DAYS()
+let $cols = a long, b datetime as (from_days(a));
+let $values1 = 730669,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # FROM_UNIXTIME()
+let $cols = a long, b datetime as (from_unixtime(a));
+let $values1 = 1196440219,default;
+let $rows = 1;
+set time_zone='UTC';
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # GET_FORMAT()
+let $cols = a datetime, b varchar(32) as (date_format(a,get_format(DATE,'EUR')));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # HOUR()
+let $cols = a time, b long as (hour(a));
+let $values1 = '10:05:03',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # LAST_DAY()
+let $cols = a datetime, b datetime as (last_day(a));
+let $values1 = '2003-02-05',default;
+let $values2 = '2003-02-32',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MAKEDATE()
+let $cols = a int, b datetime as (makedate(a,1));
+let $values1 = 2001,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MAKETIME()
+let $cols = a int, b time as (maketime(a,1,3));
+let $values1 = 12,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MICROSECOND()
+let $cols = a datetime, b long as (microsecond(a));
+let $values1 = '2009-12-31 12:00:00.123456',default;
+let $values2 = '2009-12-31 23:59:59.000010',default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MINUTE()
+let $cols = a datetime, b int as (minute(a));
+let $values1 = '2009-12-31 23:59:59.000010',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MONTH()
+let $cols = a datetime, b int as (month(a));
+let $values1 = '2009-12-31 23:59:59.000010',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MONTHNAME()
+let $cols = a datetime, b varchar(16) as (monthname(a));
+let $values1 = '2009-12-31 23:59:59.000010',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PERIOD_ADD()
+let $cols = a int, b int as (period_add(a,2));
+let $values1 = 200801,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PERIOD_DIFF()
+let $cols = a int, b int, c int as (period_diff(a,b));
+let $values1 = 200802,200703,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # QUARTER()
+let $cols = a datetime, b int as (quarter(a));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SEC_TO_TIME()
+let $cols = a long, b time as (sec_to_time(a));
+let $values1 = 2378,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SECOND()
+let $cols = a datetime, b int as (second(a));
+let $values1 = '10:05:03',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # STR_TO_DATE()
+let $cols = a varchar(64), b datetime as (str_to_date(a,'%m/%d/%Y'));
+let $values1 = '04/30/2004',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBDATE()
+let $cols = a datetime, b datetime as (subdate(a,interval 1 month));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SUBTIME()
+let $cols = a datetime, b datetime as (subtime(a,'02:00:00'));
+let $values1 = '2008-08-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIME_FORMAT()
+let $cols = a datetime, b varchar(32) as (time_format(a,'%r'));
+let $values1 = '2008-08-31 02:03:04',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIME_TO_SEC()
+let $cols = a time, b long as (time_to_sec(a));
+let $values1 = '22:23:00',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIME()
+let $cols = a datetime, b time as (time(a));
+let $values1 = '2008-08-31 02:03:04',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMEDIFF()
+let $cols = a datetime, b datetime, c long as (timediff(a,b));
+let $values1 = '2008-12-31 23:59:59.000001','2008-12-30 01:01:01.000002',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMESTAMP()
+let $cols = a datetime, b timestamp as (timestamp(a));
+let $values1 = '2008-12-31',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMESTAMPADD()
+let $cols = a datetime, b timestamp as (timestampadd(minute,1,a));
+let $values1 = '2003-01-02',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TIMESTAMPDIFF()
+let $cols = a timestamp, b timestamp, c long as (timestampdiff(MONTH, a,b));
+let $values1 = '2003-02-01','2003-05-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # TO_DAYS()
+let $cols = a datetime, b long as (to_days(a));
+let $values1 = '2007-10-07',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # WEEK()
+let $cols = a datetime, b int as (week(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # WEEKDAY()
+let $cols = a datetime, b int as (weekday(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # WEEKOFYEAR()
+let $cols = a datetime, b int as (weekofyear(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # YEAR()
+let $cols = a datetime, b int as (year(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # YEARWEEK()
+let $cols = a datetime, b int as (yearweek(a));
+let $values1 = '2008-09-01',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # FULL TEXT SEARCH FUNCTIONS
+--echo #
+--echo # None.
+
+--echo #
+--echo # CAST FUNCTIONS AND OPERATORS
+--echo #
+
+--echo # CAST()
+let $cols = a int, b long as (cast(a as unsigned));
+let $values1 = 1,default;
+let $values2 = -1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # Convert()
+let $cols = a int, b long as (convert(a,unsigned));
+let $values1 = 1,default;
+let $values2 = -1,default;
+let $rows = 2;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo #
+--echo # XML FUNCTIONS
+--echo #
+--echo # None.
+
+
+--echo #
+--echo # OTHER FUNCTIONS
+--echo #
+
+--echo # AES_DECRYPT(), AES_ENCRYPT()
+let $cols = a varchar(1024), b varchar(1024) as (aes_encrypt(aes_decrypt(a,'adf'),'adf'));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # BIT_COUNT()
+let $cols = a int, b int as (bit_count(a));
+let $values1 = 5,default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # CHARSET()
+let $cols = a varchar(1024), b varchar(1024) as (charset(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COERCIBILITY()
+let $cols = a varchar(1024), b int as (coercibility(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COLLATION()
+let $cols = a varchar(1024), b varchar(1024) as (collation(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # COMPRESS(), UNCOMPRESS()
+let $cols = a varchar(1024), b varchar(1024) as (uncompress(compress(a)));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # ENCODE(), DECODE()
+let $cols = a varchar(1024), b varchar(1024) as (decode(encode(a,'abc'),'abc'));
+let $values1 = 'MySQL',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # DEFAULT()
+let $cols = a varchar(1024) default 'aaa', b varchar(1024) as (ifnull(a,default(a)));
+let $values1 = 'any value',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+#--echo # DES_ENCRYPT(), DES_DECRYPT()
+#--source include/have_ssl.inc
+#let $cols = a varchar(1024), b varchar(1024) as (des_encrypt(des_decrypt(a,'adf'),'adf'));
+#let $values1 = 'MySQL',default;
+#let $rows = 1;
+#--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # INET_ATON(), INET_NTOA()
+let $cols = a varchar(1024), b varchar(1024) as (inet_ntoa(inet_aton(a)));
+let $values1 = '127.0.0.1',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # MD5()
+let $cols = a varchar(1024), b varbinary(32) as (md5(a));
+let $values1 = 'testing',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # OLD_PASSWORD()
+let $cols = a varchar(1024), b varchar(1024) as (old_password(a));
+let $values1 = 'badpwd',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # PASSWORD()
+let $cols = a varchar(1024), b varchar(1024) as (password(a));
+let $values1 = 'badpwd',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SHA1()
+let $cols = a varchar(1024), b varchar(1024) as (sha1(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # SHA()
+let $cols = a varchar(1024), b varchar(1024) as (sha(a));
+let $values1 = 'abc',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
+--echo # UNCOMPRESSED_LENGTH()
+let $cols = a char, b varchar(1024) as (uncompressed_length(compress(repeat(a,30))));
+let $values1 = 'a',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
diff --git a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
new file mode 100644
index 00000000000..ddf13fef6a1
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
@@ -0,0 +1,110 @@
+################################################################################
+# inc/vcol_trigger_sp.inc #
+# #
+# Purpose: #
+# Testing triggers, stored procedures and functions #
+# defined on tables with virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+create table t1 (a int,
+ b int as (a/10),
+ c int as (a/10) persistent);
+
+create table t2 (a timestamp);
+
+delimiter |;
+
+create trigger trg1 before insert on t1 for each row
+begin
+ if (new.b < 10) then
+ set new.a:= 100;
+ set new.b:= 9;
+ set new.c:= 9;
+ end if;
+
+ if (new.c > 50) then
+ set new.a:= 500;
+ end if;
+end|
+
+create trigger trg2 after insert on t1 for each row
+begin
+ if (new.b >= 60) then
+ insert into t2 values (now());
+ end if;
+end|
+
+create function f1()
+returns int
+begin
+ declare sum1 int default '0';
+ declare cur1 cursor for select sum(b) from t1;
+ open cur1;
+ fetch cur1 into sum1;
+ close cur1;
+ return sum1;
+end|
+
+delimiter ;|
+
+set sql_warnings = 1;
+
+insert into t1 (a) values (200);
+select * from t1;
+select * from t2;
+
+insert into t1 (a) values (10);
+select * from t1;
+select * from t2;
+
+insert into t1 (a) values (600);
+select * from t1;
+--replace_column 1 <timestamp>
+select * from t2;
+
+select f1();
+
+set sql_warnings = 0;
+
+drop trigger trg1;
+drop trigger trg2;
+drop table t2;
+
+delimiter |;
+
+create procedure p1()
+begin
+ declare i int default '0';
+ create table t2 like t1;
+ insert into t2 (a) values (100), (200);
+ begin
+ declare cur1 cursor for select sum(c) from t2;
+ open cur1;
+ fetch cur1 into i;
+ close cur1;
+ if (i=30) then
+ insert into t1 values (300,default,default);
+ end if;
+ end;
+end|
+
+delimiter ;|
+
+delete from t1;
+
+call p1();
+
+select * from t2;
+select * from t1;
+
+drop table t1,t2;
+drop procedure p1;
diff --git a/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc b/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc
new file mode 100644
index 00000000000..681ed77fb3c
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc
@@ -0,0 +1,21 @@
+################################################################################
+# inc/vcol_unsupported_storage_engines.inc #
+# #
+# Purpose: #
+# Ensure that defining a virtual column for an unsupported table type #
+# results in a graceful error. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1));
+create table t1 (a int);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 add column b int as (a+1);
+drop table t1;
diff --git a/mysql-test/suite/vcol/inc/vcol_view.inc b/mysql-test/suite/vcol/inc/vcol_view.inc
new file mode 100644
index 00000000000..2bf413e2471
--- /dev/null
+++ b/mysql-test/suite/vcol/inc/vcol_view.inc
@@ -0,0 +1,201 @@
+################################################################################
+# inc/vcol_view.inc #
+# #
+# Purpose: #
+# Testing views defined on tables with virtual columns. #
+# #
+# #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+
+
+create table t1 (a int not null,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1), (1), (2), (2), (3);
+
+# simple view
+create view v1 (d,e) as select abs(b), abs(c) from t1;
+select d,e from v1;
+select is_updatable from information_schema.views where table_name='v1';
+
+# view with different algorithms (explain output differs)
+explain extended select d,e from v1;
+create algorithm=temptable view v2 (d,e) as select abs(b), abs(c) from t1;
+show create view v2;
+select d,e from v2;
+explain extended select d,e from v2;
+
+# VIEW on VIEW test
+create view v3 (d,e) as select d*2, e*2 from v1;
+select * from v3;
+explain extended select * from v3;
+
+drop view v1,v2,v3;
+drop table t1;
+
+#
+# DISTINCT option for VIEW
+#
+create table t1 (a int not null,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct b from t1;
+select * from v1;
+explain select * from v1;
+select * from t1;
+drop view v1;
+create view v1 as select distinct c from t1;
+select * from v1;
+explain select * from v1;
+select * from t1;
+drop view v1;
+drop table t1;
+
+#
+# LIMIT clause test
+#
+create table t1 (a int not null,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (4);
+create view v1 as select b+1 from t1 order by 1 desc limit 2;
+select * from v1;
+explain select * from v1;
+drop view v1;
+create view v1 as select c+1 from t1 order by 1 desc limit 2;
+select * from v1;
+explain select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# simple view + simple update, insert and delete
+#
+create table t1 (a int,
+ b int,
+ c int as (-a),
+ d int as (-a) persistent,
+ primary key(a));
+insert into t1 (a,b) values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,e,f,g) as select a, b+1,c+1,d+1 from t1;
+# updatable field of updateable view
+update v1 set a=a+e;
+select * from v1;
+select * from t1;
+delete from v1;
+select * from v1;
+select * from t1;
+--error ER_NON_INSERTABLE_TABLE
+insert into v1 (a,e) values (60,15);
+drop table t1;
+drop view v1;
+
+#
+# outer join based on VIEW with WHERE clause
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent,
+ primary key(a));
+insert into t1 (a) values (1), (2), (3);
+create view v1 (x,y,z) as select a,b,c from t1 where b < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.b= v1.y);
+drop view v1;
+create view v1 (x,y,z) as select a,b,c from t1 where c < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.c= v1.z);
+drop view v1;
+drop table t1;
+
+#
+# VIEW built over UNION
+#
+create table t1 (a1 int,
+ b1 int as (-a1),
+ c1 int as (-a1) persistent);
+create table t2 (a2 int,
+ b2 int as (-a2),
+ c2 int as (-a2) persistent);
+insert into t1 (a1) values (1), (2);
+insert into t2 (a2) values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+drop view v1;
+drop table t1, t2;
+
+#
+# Showing VIEW with VIEWs in subquery
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+create table t2 like t1;
+create view v1 as select a,b,c from t1;
+create view v2 as select a,b,c from t2 where b in (select b from v1);
+show create view v2;
+drop view v2, v1;
+drop table t1, t2;
+
+#
+# TODO: VIEW with full text
+#
+#CREATE TABLE t1 (c1 int not null auto_increment primary key, c2 varchar(20), fulltext(c2));
+#insert into t1 (c2) VALUES ('real Beer'),('Water'),('Kossu'),('Coca-Cola'),('Vodka'),('Wine'),('almost real Beer');
+#select * from t1 WHERE match (c2) against ('Beer');
+#CREATE VIEW v1 AS SELECT * from t1 WHERE match (c2) against ('Beer');
+#select * from v1;
+#drop view v1;
+#drop table t1;
+
+#
+# distinct in temporary table with a VIEW
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+insert into t1 (a) values (1),(1),(2),(2),(3),(3);
+create view v1 as select b from t1;
+select distinct b from v1;
+select distinct b from v1 limit 2;
+select distinct b from t1 limit 2;
+prepare stmt1 from "select distinct b from v1 limit 2";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v1;
+create view v1 as select c from t1;
+select distinct c from v1;
+select distinct c from v1 limit 2;
+select distinct c from t1 limit 2;
+prepare stmt1 from "select distinct c from v1 limit 2";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+
+#
+# WITH CHECK OPTION insert/update test
+#
+create table t1 (a int,
+ b int as (-a),
+ c int as (-a) persistent);
+create view v1 as select * from t1 where b > -2 && c >-2 with check option;
+# simple insert
+insert into v1 (a) values (1);
+-- error 1369
+insert into v1 (a) values (3);
+# simple insert with ignore
+insert ignore into v1 (a) values (2),(3),(0);
+select * from t1;
+drop view v1;
+drop table t1;
+
diff --git a/mysql-test/suite/vcol/r/rpl_vcol.result b/mysql-test/suite/vcol/r/rpl_vcol.result
new file mode 100644
index 00000000000..f552d16d1c0
--- /dev/null
+++ b/mysql-test/suite/vcol/r/rpl_vcol.result
@@ -0,0 +1,25 @@
+SET @@session.storage_engine = 'InnoDB';
+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;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 2
+2 3
+select * from t1;
+a b
+1 2
+2 3
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_archive.result b/mysql-test/suite/vcol/r/vcol_archive.result
new file mode 100644
index 00000000000..83fb78a5592
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_archive.result
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'archive';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+create table t1 (a int);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_blackhole.result b/mysql-test/suite/vcol/r/vcol_blackhole.result
new file mode 100644
index 00000000000..15e7505aebb
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_blackhole.result
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'blackhole';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+create table t1 (a int);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result
new file mode 100644
index 00000000000..a4099dff381
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_innodb.result
@@ -0,0 +1,243 @@
+SET @@session.storage_engine = 'InnoDB';
+# RAND()
+create table t1 (b double as (rand()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# LOAD_FILE()
+create table t1 (a varchar(64), b varchar(1024) as (load_file(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# CURDATE()
+create table t1 (a datetime as (curdate()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_DATE(), CURRENT_DATE
+create table t1 (a datetime as (current_date));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a datetime as (current_date()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_TIME(), CURRENT_TIME
+create table t1 (a datetime as (current_time));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a datetime as (current_time()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP
+create table t1 (a datetime as (current_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a datetime as (current_timestamp));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURTIME()
+create table t1 (a datetime as (curtime()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# LOCALTIME(), LOCALTIME
+create table t1 (a datetime, b varchar(10) as (localtime()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+create table t1 (a datetime, b varchar(10) as (localtime));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6)
+create table t1 (a datetime, b varchar(10) as (localtimestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+create table t1 (a datetime, b varchar(10) as (localtimestamp));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# NOW()
+create table t1 (a datetime, b varchar(10) as (now()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# SYSDATE()
+create table t1 (a int, b varchar(10) as (sysdate()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UNIX_TIMESTAMP()
+create table t1 (a datetime, b datetime as (unix_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UTC_DATE()
+create table t1 (a datetime, b datetime as (utc_date()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UTC_TIME()
+create table t1 (a datetime, b datetime as (utc_time()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UTC_TIMESTAMP()
+create table t1 (a datetime, b datetime as (utc_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# MATCH()
+# BENCHMARK()
+create table t1 (a varchar(1024), b varchar(1024) as (benchmark(a,3)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# CONNECTION_ID()
+create table t1 (a int as (connection_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_USER(), CURRENT_USER
+create table t1 (a varchar(32) as (current_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a varchar(32) as (current_user));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# DATABASE()
+create table t1 (a varchar(1024), b varchar(1024) as (database()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# FOUND_ROWS()
+create table t1 (a varchar(1024), b varchar(1024) as (found_rows()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# GET_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (get_lock(a,10)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# IS_FREE_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_free_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# IS_USED_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_used_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# LAST_INSERT_ID()
+create table t1 (a int as (last_insert_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# MASTER_POS_WAIT()
+create table t1 (a varchar(32), b int as (master_pos_wait(a,0,2)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# NAME_CONST()
+create table t1 (a varchar(32) as (name_const('test',1)));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# RELEASE_LOCK()
+create table t1 (a varchar(32), b int as (release_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# ROW_COUNT()
+create table t1 (a int as (row_count()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# SCHEMA()
+create table t1 (a varchar(32) as (schema()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# SESSION_USER()
+create table t1 (a varchar(32) as (session_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# SLEEP()
+create table t1 (a int, b int as (sleep(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# SYSTEM_USER()
+create table t1 (a varchar(32) as (system_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# USER()
+create table t1 (a varchar(1024), b varchar(1024) as (user()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UUID_SHORT()
+create table t1 (a varchar(1024) as (uuid_short()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# UUID()
+create table t1 (a varchar(1024) as (uuid()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# VALUES()
+create table t1 (a varchar(1024), b varchar(1024) as (values(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VERSION()
+create table t1 (a varchar(1024), b varchar(1024) as (version()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# ENCRYPT()
+create table t1 (a varchar(1024), b varchar(1024) as (encrypt(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# Stored procedures
+create procedure p1()
+begin
+select current_user();
+end //
+create function f1()
+returns int
+begin
+return 1;
+end //
+create table t1 (a int as (p1()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+drop procedure p1;
+drop function f1;
+# Unknown functions
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+#
+# GROUP BY FUNCTIONS
+#
+# AVG()
+create table t1 (a int, b int as (avg(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BIT_AND()
+create table t1 (a int, b int as (bit_and(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BIT_OR()
+create table t1 (a int, b int as (bit_or(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BIT_XOR()
+create table t1 (a int, b int as (bit_xor(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# COUNT(DISTINCT)
+create table t1 (a int, b int as (count(distinct a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# COUNT()
+create table t1 (a int, b int as (count(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# GROUP_CONCAT()
+create table t1 (a varchar(32), b int as (group_concat(a,'')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# MAX()
+create table t1 (a int, b int as (max(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# MIN()
+create table t1 (a int, b int as (min(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STD()
+create table t1 (a int, b int as (std(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STDDEV_POP()
+create table t1 (a int, b int as (stddev_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STDDEV_SAMP()
+create table t1 (a int, b int as (stddev_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STDDEV()
+create table t1 (a int, b int as (stddev(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# SUM()
+create table t1 (a int, b int as (sum(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VAR_POP()
+create table t1 (a int, b int as (var_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VAR_SAMP()
+create table t1 (a int, b int as (var_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VARIANCE()
+create table t1 (a int, b int as (variance(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+#
+# XML FUNCTIONS
+#
+# ExtractValue()
+create table t1 (a varchar(1024), b varchar(1024) as (ExtractValue(a,'//b[$@j]')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UpdateXML()
+create table t1 (a varchar(1024), b varchar(1024) as (UpdateXML(a,'/a','<e>fff</e>')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+#
+# Sub-selects
+#
+create table t1 (a int);
+create table t2 (a int, b int as (select count(*) from t1));
+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 count(*) from t1))' at line 1
+drop table t1;
+create table t1 (a int, b int as ((select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+create table t1 (a int, b int as (a+(select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+#
+# SP functions
+#
+drop function if exists sub1;
+create function sub1(i int) returns int deterministic
+return i+1;
+select sub1(1);
+sub1(1)
+2
+create table t1 (a int, b int as (a+sub3(1)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+drop function sub1;
+#
+# Long expression
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+drop table t1;
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+ERROR HY000: String 'concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long for VIRTUAL COLUMN EXPRESSION (should be no longer than 252)
+#
+# Constant expression
+create table t1 (a int as (PI()));
+ERROR HY000: Constant expression in computed column function is not allowed
diff --git a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result
new file mode 100644
index 00000000000..dda222f5e8a
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs_myisam.result
@@ -0,0 +1,245 @@
+SET @@session.storage_engine = 'MyISAM';
+# RAND()
+create table t1 (b double as (rand()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# LOAD_FILE()
+create table t1 (a varchar(64), b varchar(1024) as (load_file(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# CURDATE()
+create table t1 (a datetime as (curdate()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_DATE(), CURRENT_DATE
+create table t1 (a datetime as (current_date));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a datetime as (current_date()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_TIME(), CURRENT_TIME
+create table t1 (a datetime as (current_time));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a datetime as (current_time()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP
+create table t1 (a datetime as (current_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a datetime as (current_timestamp));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURTIME()
+create table t1 (a datetime as (curtime()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# LOCALTIME(), LOCALTIME
+create table t1 (a datetime, b varchar(10) as (localtime()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+create table t1 (a datetime, b varchar(10) as (localtime));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# LOCALTIMESTAMP, LOCALTIMESTAMP()(v4.0.6)
+create table t1 (a datetime, b varchar(10) as (localtimestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+create table t1 (a datetime, b varchar(10) as (localtimestamp));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# NOW()
+create table t1 (a datetime, b varchar(10) as (now()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# SYSDATE()
+create table t1 (a int, b varchar(10) as (sysdate()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UNIX_TIMESTAMP()
+create table t1 (a datetime, b datetime as (unix_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UTC_DATE()
+create table t1 (a datetime, b datetime as (utc_date()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UTC_TIME()
+create table t1 (a datetime, b datetime as (utc_time()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UTC_TIMESTAMP()
+create table t1 (a datetime, b datetime as (utc_timestamp()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# MATCH()
+create table t1 (a varchar(32), b bool as (match a against ('sample text')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BENCHMARK()
+create table t1 (a varchar(1024), b varchar(1024) as (benchmark(a,3)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# CONNECTION_ID()
+create table t1 (a int as (connection_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# CURRENT_USER(), CURRENT_USER
+create table t1 (a varchar(32) as (current_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a varchar(32) as (current_user));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# DATABASE()
+create table t1 (a varchar(1024), b varchar(1024) as (database()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# FOUND_ROWS()
+create table t1 (a varchar(1024), b varchar(1024) as (found_rows()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# GET_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (get_lock(a,10)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# IS_FREE_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_free_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# IS_USED_LOCK()
+create table t1 (a varchar(1024), b varchar(1024) as (is_used_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# LAST_INSERT_ID()
+create table t1 (a int as (last_insert_id()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# MASTER_POS_WAIT()
+create table t1 (a varchar(32), b int as (master_pos_wait(a,0,2)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# NAME_CONST()
+create table t1 (a varchar(32) as (name_const('test',1)));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# RELEASE_LOCK()
+create table t1 (a varchar(32), b int as (release_lock(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# ROW_COUNT()
+create table t1 (a int as (row_count()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# SCHEMA()
+create table t1 (a varchar(32) as (schema()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# SESSION_USER()
+create table t1 (a varchar(32) as (session_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# SLEEP()
+create table t1 (a int, b int as (sleep(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# SYSTEM_USER()
+create table t1 (a varchar(32) as (system_user()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# USER()
+create table t1 (a varchar(1024), b varchar(1024) as (user()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UUID_SHORT()
+create table t1 (a varchar(1024) as (uuid_short()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# UUID()
+create table t1 (a varchar(1024) as (uuid()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+# VALUES()
+create table t1 (a varchar(1024), b varchar(1024) as (values(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VERSION()
+create table t1 (a varchar(1024), b varchar(1024) as (version()));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# ENCRYPT()
+create table t1 (a varchar(1024), b varchar(1024) as (encrypt(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# Stored procedures
+create procedure p1()
+begin
+select current_user();
+end //
+create function f1()
+returns int
+begin
+return 1;
+end //
+create table t1 (a int as (p1()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+drop procedure p1;
+drop function f1;
+# Unknown functions
+create table t1 (a int as (f1()));
+ERROR HY000: Function or expression is not allowed for column 'a'
+#
+# GROUP BY FUNCTIONS
+#
+# AVG()
+create table t1 (a int, b int as (avg(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BIT_AND()
+create table t1 (a int, b int as (bit_and(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BIT_OR()
+create table t1 (a int, b int as (bit_or(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# BIT_XOR()
+create table t1 (a int, b int as (bit_xor(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# COUNT(DISTINCT)
+create table t1 (a int, b int as (count(distinct a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# COUNT()
+create table t1 (a int, b int as (count(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# GROUP_CONCAT()
+create table t1 (a varchar(32), b int as (group_concat(a,'')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# MAX()
+create table t1 (a int, b int as (max(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# MIN()
+create table t1 (a int, b int as (min(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STD()
+create table t1 (a int, b int as (std(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STDDEV_POP()
+create table t1 (a int, b int as (stddev_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STDDEV_SAMP()
+create table t1 (a int, b int as (stddev_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# STDDEV()
+create table t1 (a int, b int as (stddev(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# SUM()
+create table t1 (a int, b int as (sum(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VAR_POP()
+create table t1 (a int, b int as (var_pop(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VAR_SAMP()
+create table t1 (a int, b int as (var_samp(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# VARIANCE()
+create table t1 (a int, b int as (variance(a)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+#
+# XML FUNCTIONS
+#
+# ExtractValue()
+create table t1 (a varchar(1024), b varchar(1024) as (ExtractValue(a,'//b[$@j]')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+# UpdateXML()
+create table t1 (a varchar(1024), b varchar(1024) as (UpdateXML(a,'/a','<e>fff</e>')));
+ERROR HY000: Function or expression is not allowed for column 'b'
+#
+# Sub-selects
+#
+create table t1 (a int);
+create table t2 (a int, b int as (select count(*) from t1));
+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 count(*) from t1))' at line 1
+drop table t1;
+create table t1 (a int, b int as ((select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+create table t1 (a int, b int as (a+(select 1)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+#
+# SP functions
+#
+drop function if exists sub1;
+create function sub1(i int) returns int deterministic
+return i+1;
+select sub1(1);
+sub1(1)
+2
+create table t1 (a int, b int as (a+sub3(1)));
+ERROR HY000: Function or expression is not allowed for column 'b'
+drop function sub1;
+#
+# Long expression
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+drop table t1;
+create table t1 (a int, b varchar(300) as (concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
+ERROR HY000: String 'concat(a,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long for VIRTUAL COLUMN EXPRESSION (should be no longer than 252)
+#
+# Constant expression
+create table t1 (a int as (PI()));
+ERROR HY000: Constant expression in computed column function is not allowed
diff --git a/mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result b/mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result
new file mode 100644
index 00000000000..b1f96f8f4d9
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_column_def_options_innodb.result
@@ -0,0 +1,146 @@
+SET @@session.storage_engine = 'InnoDB';
+#
+# Section 1. Wrong column definition options
+# - NOT NULL
+# - NULL
+# - DEFAULT <value>
+# - AUTO_INCREMENT
+# - [PRIMARY] KEY
+# NOT NULL
+create table t1 (a int, b int as (a+1) not null);
+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 'not null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) not null;
+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 'not null' at line 1
+drop table t1;
+# NULL
+create table t1 (a int, b int as (a+1) null);
+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 'null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) null;
+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 'null' at line 1
+drop table t1;
+# DEFAULT
+create table t1 (a int, b int as (a+1) default 0);
+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 'default 0)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) default 0;
+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 'default 0' at line 1
+drop table t1;
+# AUTO_INCREMENT
+create table t1 (a int, b int as (a+1) AUTO_INCREMENT);
+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 'AUTO_INCREMENT)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) AUTO_INCREMENT;
+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 'AUTO_INCREMENT' at line 1
+drop table t1;
+# [PRIMARY] KEY
+create table t1 (a int, b int as (a+1) key);
+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 'key)' at line 1
+create table t1 (a int, b int as (a+1) primary key);
+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 'primary key)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) key;
+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 'key' at line 1
+alter table t1 add column b int as (a+1) primary key;
+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 'primary key' at line 1
+drop table t1;
+# Section 2. Other column definition options
+# - COMMENT
+# - REFERENCES (only syntax testing here)
+# - STORED (only systax testing here)
+create table t1 (a int, b int as (a % 2) comment 'my comment');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) comment 'my comment';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t2;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t2 (a) values (1);
+select * from t2;
+a b
+1 1
+insert into t2 values (2,default);
+select a,b from t2;
+a b
+1 1
+2 0
+drop table t2;
+drop table t1;
+create table t1 (a int, b int as (a % 2) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+drop table t1;
+create table t2 (a int);
+create table t1 (a int, b int as (a % 2) persistent references t2(a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent references t2(a);
+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 'references t2(a)' at line 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result b/mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result
new file mode 100644
index 00000000000..9fde339cb06
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_column_def_options_myisam.result
@@ -0,0 +1,146 @@
+SET @@session.storage_engine = 'MyISAM';
+#
+# Section 1. Wrong column definition options
+# - NOT NULL
+# - NULL
+# - DEFAULT <value>
+# - AUTO_INCREMENT
+# - [PRIMARY] KEY
+# NOT NULL
+create table t1 (a int, b int as (a+1) not null);
+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 'not null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) not null;
+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 'not null' at line 1
+drop table t1;
+# NULL
+create table t1 (a int, b int as (a+1) null);
+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 'null)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) null;
+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 'null' at line 1
+drop table t1;
+# DEFAULT
+create table t1 (a int, b int as (a+1) default 0);
+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 'default 0)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) default 0;
+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 'default 0' at line 1
+drop table t1;
+# AUTO_INCREMENT
+create table t1 (a int, b int as (a+1) AUTO_INCREMENT);
+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 'AUTO_INCREMENT)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) AUTO_INCREMENT;
+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 'AUTO_INCREMENT' at line 1
+drop table t1;
+# [PRIMARY] KEY
+create table t1 (a int, b int as (a+1) key);
+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 'key)' at line 1
+create table t1 (a int, b int as (a+1) primary key);
+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 'primary key)' at line 1
+create table t1 (a int);
+alter table t1 add column b int as (a+1) key;
+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 'key' at line 1
+alter table t1 add column b int as (a+1) primary key;
+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 'primary key' at line 1
+drop table t1;
+# Section 2. Other column definition options
+# - COMMENT
+# - REFERENCES (only syntax testing here)
+# - STORED (only systax testing here)
+create table t1 (a int, b int as (a % 2) comment 'my comment');
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) comment 'my comment';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL COMMENT 'my comment'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t2;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t2 (a) values (1);
+select * from t2;
+a b
+1 1
+insert into t2 values (2,default);
+select a,b from t2;
+a b
+1 1
+2 0
+drop table t2;
+drop table t1;
+create table t1 (a int, b int as (a % 2) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES NULL VIRTUAL
+insert into t1 (a) values (1);
+select * from t1;
+a b
+1 1
+insert into t1 values (2,default);
+select a,b from t1;
+a b
+1 1
+2 0
+drop table t1;
+create table t2 (a int);
+create table t1 (a int, b int as (a % 2) persistent references t2(a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent references t2(a);
+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 'references t2(a)' at line 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_csv.result b/mysql-test/suite/vcol/r/vcol_csv.result
new file mode 100644
index 00000000000..97977505696
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_csv.result
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'CSV';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+create table t1 (a int not null);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_handler_innodb.result b/mysql-test/suite/vcol/r/vcol_handler_innodb.result
new file mode 100644
index 00000000000..f7576299e9a
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_handler_innodb.result
@@ -0,0 +1,76 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+d char(1),
+index (a),
+index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+a b c d
+4 -4 -4 a
+2 -2 -2 b
+1 -1 -1 c
+3 -3 -3 d
+# HANDLER tbl_name OPEN
+handler t1 open;
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+a b c d
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+a b c d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+a b c d
+# HANDLER tbl_name CLOSE
+handler t1 close;
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_handler_maria.result b/mysql-test/suite/vcol/r/vcol_handler_maria.result
new file mode 100644
index 00000000000..df36d0fbbf3
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_handler_maria.result
@@ -0,0 +1,76 @@
+SET @@session.storage_engine = 'maria';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+d char(1),
+index (a),
+index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+a b c d
+4 -4 -4 a
+2 -2 -2 b
+1 -1 -1 c
+3 -3 -3 d
+# HANDLER tbl_name OPEN
+handler t1 open;
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+a b c d
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+a b c d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+a b c d
+# HANDLER tbl_name CLOSE
+handler t1 close;
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_handler_myisam.result b/mysql-test/suite/vcol/r/vcol_handler_myisam.result
new file mode 100644
index 00000000000..ff93756adc5
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_handler_myisam.result
@@ -0,0 +1,76 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+d char(1),
+index (a),
+index (c));
+insert into t1 (a,d) values (4,'a'), (2,'b'), (1,'c'), (3,'d');
+select * from t1;
+a b c d
+4 -4 -4 a
+2 -2 -2 b
+1 -1 -1 c
+3 -3 -3 d
+# HANDLER tbl_name OPEN
+handler t1 open;
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...)
+handler t1 read a > (2);
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read a > (2) where d='c';
+a b c d
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...)
+handler t1 read c = (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name = (value1,value2,...) WHERE non-vcol_field=expr
+handler t1 read c = (-2) where d='c';
+a b c d
+# HANDLER tbl_name READ non-vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read a > (2) where b=-3 && c=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name <= (value1,value2,...)
+handler t1 read c <= (-2);
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ vcol_index_name > (value1,value2,...) WHERE vcol_field=expr
+handler t1 read c <= (-2) where b=-3;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name FIRST
+handler t1 read c first;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name NEXT
+handler t1 read c next;
+a b c d
+3 -3 -3 d
+# HANDLER tbl_name READ vcol_index_name PREV
+handler t1 read c prev;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ vcol_index_name LAST
+handler t1 read c last;
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ FIRST where non-vcol=expr
+handler t1 read FIRST where a >= 2;
+a b c d
+4 -4 -4 a
+# HANDLER tbl_name READ FIRST where vcol=expr
+handler t1 read FIRST where b >= -2;
+a b c d
+2 -2 -2 b
+# HANDLER tbl_name READ NEXT where non-vcol=expr
+handler t1 read NEXT where d='c';
+a b c d
+1 -1 -1 c
+# HANDLER tbl_name READ NEXT where vcol=expr
+handler t1 read NEXT where b<=-4;
+a b c d
+# HANDLER tbl_name CLOSE
+handler t1 close;
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
new file mode 100644
index 00000000000..b996a0108e3
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result
@@ -0,0 +1,427 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+set sql_warnings = 1;
+#
+# *** INSERT ***
+#
+# INSERT INTO tbl_name VALUES... DEFAULT is specified against vcols
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... NULL is specified against vcols
+insert into t1 values (1,null,null);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... a non-NULL value is specified against vcols
+insert into t1 values (1,2,3);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<non_vcol_list>) VALUES...
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... DEFAULT is specified
+# against vcols
+insert into t1 (a,b) values (1,default), (2,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... NULL is specified against vcols
+insert into t1 (a,b) values (1,null), (2,null);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... a non-NULL value is specified
+# against vcols
+insert into t1 (a,b) values (1,3), (2,4);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# Table with UNIQUE non-vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int unique,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+delete from t1 where b in (1,2);
+select * from t1;
+a b c
+2 -2 -2
+drop table t1;
+# Table with UNIQUE vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+# CREATE new_table ... LIKE old_table
+# INSERT INTO new_table SELECT * from old_table
+create table t2 like t1;
+insert into t2 select * from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored
+Warning 1645 The value specified for computed column 'c' in table 't2' ignored
+select * from t1;
+a b c
+2 -2 -2
+drop table t2;
+# CREATE new_table ... LIKE old_table INSERT INTO new_table (<non-vcols>, <vcols>)
+# SELECT <non-vcols>, <vcols> from old_table
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+2 -2 -2
+1 -1 -1
+create table t2 like t1;
+insert into t2 (a,b) select a,b from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored
+select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+drop table t2;
+drop table t1;
+#
+# *** UPDATE ***
+#
+# UPDATE tbl_name SET non-vcol=expr WHERE non-vcol=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where a=2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE non-vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where a=2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where b=-2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=const
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# No INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where c between -1 and 0
+order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1 where c between -6 and 0;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol LIMIT 2
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where c between -1 and 0
+order by c limit 2;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1 where c between -2 and 0 order by c;
+select * from t1;
+a b c
+6 -6 -6
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1);
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+# ORDER BY indexed vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1) order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+drop table t1;
+#
+# Verify ON UPDATE/DELETE actions of FOREIGN KEYs
+create table t2 (a int primary key, name varchar(10));
+create table t1 (a int primary key, b int as (a % 10) persistent);
+insert into t2 values (1, 'value1'), (2,'value2'), (3,'value3');
+insert into t1 (a) values (1),(2),(3);
+select * from t1;
+a b
+1 1
+2 2
+3 3
+select * from t2;
+a name
+1 value1
+2 value2
+3 value3
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+# - ON UPDATE RESTRICT
+alter table t1 add foreign key (b) references t2(a) on update restrict;
+insert into t1 (a) values (4);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+update t2 set a=4 where a=3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+alter table t1 drop foreign key t1_ibfk_1;
+# - ON DELETE RESTRICT
+alter table t1 add foreign key (b) references t2(a) on delete restrict;
+delete from t2 where a=3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t2` (`a`))
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+a b name
+1 1 value1
+2 2 value2
+3 3 value3
+alter table t1 drop foreign key t1_ibfk_1;
+# - ON DELETE CASCADE
+alter table t1 add foreign key (b) references t2(a) on delete cascade;
+delete from t2 where a=3;
+select t1.a, t1.b, t2.name from t1,t2 where t1.b=t2.a;
+a b name
+1 1 value1
+2 2 value2
+select t1.a, t1.b, t2.name from t1 left outer join t2 on (t1.b=t2.a);
+a b name
+1 1 value1
+2 2 value2
+alter table t1 drop foreign key t1_ibfk_1;
+drop table t1;
+drop table t2;
+#
+# *** REPLACE ***
+#
+# UNIQUE INDEX on vcol
+# REPLACE tbl_name (non-vcols) VALUES (non-vcols);
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique,
+d varchar(16));
+insert into t1 (a,d) values (1,'a'), (2,'b');
+select * from t1;
+a b c d
+1 -1 -1 a
+2 -2 -2 b
+replace t1 (a,d) values (1,'c');
+select * from t1;
+a b c d
+1 -1 -1 c
+2 -2 -2 b
+delete from t1;
+select * from t1;
+a b c d
+set sql_warnings = 0;
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result
new file mode 100644
index 00000000000..fa636597536
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result
@@ -0,0 +1,365 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+set sql_warnings = 1;
+#
+# *** INSERT ***
+#
+# INSERT INTO tbl_name VALUES... DEFAULT is specified against vcols
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... NULL is specified against vcols
+insert into t1 values (1,null,null);
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name VALUES... a non-NULL value is specified against vcols
+insert into t1 values (1,2,3);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<non_vcol_list>) VALUES...
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... DEFAULT is specified
+# against vcols
+insert into t1 (a,b) values (1,default), (2,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... NULL is specified against vcols
+insert into t1 (a,b) values (1,null), (2,null);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# INSERT INTO tbl_name (<normal+vcols>) VALUES... a non-NULL value is specified
+# against vcols
+insert into t1 (a,b) values (1,3), (2,4);
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored
+Warning 1645 The value specified for computed column 'b' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# Table with UNIQUE non-vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int unique,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+delete from t1 where b in (1,2);
+select * from t1;
+a b c
+2 -2 -2
+drop table t1;
+# Table with UNIQUE vcol field. INSERT INTO tbl_name VALUES... ON DUPLICATE
+# KEY UPDATE <non_vcol>=expr, <vcol>=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 values (1,default,default);
+insert into t1 values (1,default,default)
+on duplicate key update a=2, b=default;
+select a,b,c from t1;
+a b c
+2 -2 -2
+# CREATE new_table ... LIKE old_table
+# INSERT INTO new_table SELECT * from old_table
+create table t2 like t1;
+insert into t2 select * from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored
+Warning 1645 The value specified for computed column 'c' in table 't2' ignored
+select * from t1;
+a b c
+2 -2 -2
+drop table t2;
+# CREATE new_table ... LIKE old_table INSERT INTO new_table (<non-vcols>, <vcols>)
+# SELECT <non-vcols>, <vcols> from old_table
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+2 -2 -2
+1 -1 -1
+create table t2 like t1;
+insert into t2 (a,b) select a,b from t1;
+Warnings:
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored
+Warning 1645 The value specified for computed column 'b' in table 't2' ignored
+select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+drop table t2;
+drop table t1;
+#
+# *** UPDATE ***
+#
+# UPDATE tbl_name SET non-vcol=expr WHERE non-vcol=expr
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where a=2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE non-vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where a=2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# UPDATE tbl_name SET vcol=expr WHERE vcol=expr
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set c=3 where b=-2;
+Warnings:
+Warning 1645 The value specified for computed column 'c' in table 't1' ignored
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+delete from t1;
+select * from t1;
+a b c
+drop table t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=const
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c=-2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where c between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# No INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr WHERE vcol=between const1 and const2
+insert into t1 (a) values (1), (2);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+update t1 set a=3 where b between -3 and -2;
+select * from t1;
+a b c
+1 -1 -1
+3 -3 -3
+delete from t1;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where c between -1 and 0
+order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1 where c between -6 and 0;
+select * from t1;
+a b c
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE vcol=between const1 and const2 ORDER BY vcol LIMIT 2
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+5 -5 -5
+4 -4 -4
+3 -3 -3
+2 -2 -2
+1 -1 -1
+update t1 set a=6 where c between -1 and 0
+order by c limit 2;
+select * from t1;
+a b c
+5 -5 -5
+4 -4 -4
+3 -3 -3
+2 -2 -2
+6 -6 -6
+delete from t1 where c between -2 and 0 order by c;
+select * from t1;
+a b c
+5 -5 -5
+4 -4 -4
+3 -3 -3
+6 -6 -6
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1);
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+# INDEX created on vcol
+# UPDATE tbl_name SET non-vcol=expr
+# WHERE indexed vcol=between const1 and const2 and non-indexed vcol=const3
+# ORDER BY indexed vcol
+insert into t1 (a) values (1), (2), (3), (4), (5);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+update t1 set a=6 where (c between -2 and 0) and (b=-1) order by c;
+select * from t1;
+a b c
+6 -6 -6
+2 -2 -2
+3 -3 -3
+4 -4 -4
+5 -5 -5
+delete from t1;
+drop table t1;
+#
+# *** REPLACE ***
+#
+# UNIQUE INDEX on vcol
+# REPLACE tbl_name (non-vcols) VALUES (non-vcols);
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent unique,
+d varchar(16));
+insert into t1 (a,d) values (1,'a'), (2,'b');
+select * from t1;
+a b c d
+1 -1 -1 a
+2 -2 -2 b
+replace t1 (a,d) values (1,'c');
+select * from t1;
+a b c d
+1 -1 -1 c
+2 -2 -2 b
+delete from t1;
+select * from t1;
+a b c d
+set sql_warnings = 0;
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result
new file mode 100644
index 00000000000..857dcb8423f
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result
@@ -0,0 +1,151 @@
+SET @@session.storage_engine = 'InnoDB';
+# - UNIQUE KEY
+# - INDEX
+# - FULLTEXT INDEX
+# - SPATIAL INDEX (not supported)
+# - FOREIGN INDEX (partially supported)
+# - CHECK (allowed but not used)
+# UNIQUE
+create table t1 (a int, b int as (a*2) unique);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2) persistent unique);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2), unique key (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2) persistent, unique (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add unique key (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add unique key (b);
+drop table t1;
+# Testing data manipulation operations involving UNIQUE keys
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# INDEX
+create table t1 (a int, b int as (a*2), index (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2), index (a,b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2) persistent, index (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `b` (`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES MUL NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent, index (a,b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `a` (`a`,`b`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES MUL NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add index (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+alter table t1 add index (a,b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (b);
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (a,b);
+create table t2 like t1;
+drop table t2;
+drop table t1;
+# Testing data manipulation operations involving INDEX
+# on virtual columns can be found in:
+# - vcol_select.inc
+#
+# TODO: FULLTEXT INDEX
+# SPATIAL INDEX
+# FOREIGN KEY
+# Rejected FK options.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update set null);
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update cascade);
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on delete set null);
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column
+create table t1 (a int, b int as (a+1) persistent);
+alter table t1 add foreign key (b) references t2(a) on update set null;
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column
+alter table t1 add foreign key (b) references t2(a) on update cascade;
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column
+alter table t1 add foreign key (b) references t2(a) on delete set null;
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column
+drop table t1;
+create table t1 (a int, b int as (a+1),
+foreign key (b) references t2(a));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a+1));
+alter table t1 add foreign key (b) references t2(a);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+drop table t1;
+# Allowed FK options.
+create table t2 (a int primary key, b char(5));
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update no action);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete cascade);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete no action);
+drop table t1;
+
+# Testing data manipulation operations involving FOREIGN KEY
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# TODO: CHECK
diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result
new file mode 100644
index 00000000000..af0935affbc
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result
@@ -0,0 +1,158 @@
+SET @@session.storage_engine = 'MyISAM';
+# - UNIQUE KEY
+# - INDEX
+# - FULLTEXT INDEX
+# - SPATIAL INDEX (not supported)
+# - FOREIGN INDEX (partially supported)
+# - CHECK (allowed but not used)
+# UNIQUE
+create table t1 (a int, b int as (a*2) unique);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2) persistent unique);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2), unique key (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2) persistent, unique (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES UNI NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add unique key (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add unique key (b);
+drop table t1;
+# Testing data manipulation operations involving UNIQUE keys
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# INDEX
+create table t1 (a int, b int as (a*2), index (b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2), index (a,b));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a*2) persistent, index (b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b int(11) YES MUL NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent, index (a,b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a*2) PERSISTENT,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+describe t1;
+Field Type Null Key Default Extra
+a int(11) YES MUL NULL
+b int(11) YES NULL VIRTUAL
+drop table t1;
+create table t1 (a int, b int as (a*2));
+alter table t1 add index (b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+alter table t1 add index (a,b);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (b);
+drop table t1;
+create table t1 (a int, b int as (a*2) persistent);
+alter table t1 add index (a,b);
+create table t2 like t1;
+drop table t2;
+drop table t1;
+# Testing data manipulation operations involving INDEX
+# on virtual columns can be found in:
+# - vcol_select.inc
+#
+# TODO: FULLTEXT INDEX
+# SPATIAL INDEX
+# Error "All parts of a SPATIAL index must be NOT NULL"
+create table t1 (a int, b int as (a+1) persistent, spatial index (b));
+ERROR 42000: All parts of a SPATIAL index must be NOT NULL
+create table t1 (a int, b int as (a+1) persistent);
+alter table t1 add spatial index (b);
+ERROR 42000: All parts of a SPATIAL index must be NOT NULL
+drop table t1;
+# FOREIGN KEY
+# Rejected FK options.
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update set null);
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on update cascade);
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column
+create table t1 (a int, b int as (a+1) persistent,
+foreign key (b) references t2(a) on delete set null);
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column
+create table t1 (a int, b int as (a+1) persistent);
+alter table t1 add foreign key (b) references t2(a) on update set null;
+ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a computed column
+alter table t1 add foreign key (b) references t2(a) on update cascade;
+ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a computed column
+alter table t1 add foreign key (b) references t2(a) on delete set null;
+ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a computed column
+drop table t1;
+create table t1 (a int, b int as (a+1),
+foreign key (b) references t2(a));
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+create table t1 (a int, b int as (a+1));
+alter table t1 add foreign key (b) references t2(a);
+ERROR HY000: Key/Index cannot be defined on a non-stored computed column
+drop table t1;
+# Allowed FK options.
+create table t2 (a int primary key, b char(5));
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on update no action);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete restrict);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete cascade);
+drop table t1;
+create table t1 (a int, b int as (a % 10) persistent,
+foreign key (b) references t2(a) on delete no action);
+drop table t1;
+
+# Testing data manipulation operations involving FOREIGN KEY
+# on virtual columns can be found in:
+# - vcol_ins_upd.inc
+# - vcol_select.inc
+#
+# TODO: CHECK
diff --git a/mysql-test/suite/vcol/r/vcol_memory.result b/mysql-test/suite/vcol/r/vcol_memory.result
new file mode 100644
index 00000000000..30b6bd4a4bf
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_memory.result
@@ -0,0 +1,7 @@
+SET @@session.storage_engine = 'memory';
+create table t1 (a int, b int as (a+1));
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+create table t1 (a int);
+alter table t1 add column b int as (a+1);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_merge.result b/mysql-test/suite/vcol/r/vcol_merge.result
new file mode 100644
index 00000000000..03a1e151c2e
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_merge.result
@@ -0,0 +1,8 @@
+drop table if exists t1, t2, t3;
+create table t1 (a int, b int as (a % 10));
+create table t2 (a int, b int as (a % 10));
+insert into t1 values (1,default);
+insert into t2 values (2,default);
+create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2);
+ERROR HY000: 'Specified storage engine' is not yet supported for computed columns
+drop table t1,t2;
diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result
new file mode 100644
index 00000000000..dee34cb4860
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_misc.result
@@ -0,0 +1,135 @@
+drop table if exists t1,t2;
+create table t1 (a int, b int, v int as (a+1), index idx(b));
+insert into t1(a, b) values
+(4, 40), (3, 30), (5, 50), (7, 70), (8, 80), (2, 20), (1, 10);
+select * from t1 order by b;
+a b v
+1 10 2
+2 20 3
+3 30 4
+4 40 5
+5 50 6
+7 70 8
+8 80 9
+delete from t1 where v > 6 order by b limit 1;
+select * from t1 order by b;
+a b v
+1 10 2
+2 20 3
+3 30 4
+4 40 5
+5 50 6
+8 80 9
+update t1 set a=v order by b limit 1;
+select * from t1 order by b;
+a b v
+2 10 3
+2 20 3
+3 30 4
+4 40 5
+5 50 6
+8 80 9
+drop table t1;
+CREATE TABLE t1 (
+a int NOT NULL DEFAULT '0',
+v double AS ((1, a)) VIRTUAL
+);
+ERROR HY000: Expression for computed column cannot return a row
+CREATE TABLE t1 (
+a CHAR(255) BINARY NOT NULL DEFAULT 0,
+b CHAR(255) BINARY NOT NULL DEFAULT 0,
+v CHAR(255) BINARY AS (CONCAT(a,b)) VIRTUAL );
+INSERT INTO t1(a,b) VALUES ('4','7'), ('4','6');
+SELECT 1 AS C FROM t1 ORDER BY v;
+C
+1
+1
+DROP TABLE t1;
+CREATE TABLE t1(a int, b int DEFAULT 0, v INT AS (b+10) PERSISTENT);
+INSERT INTO t1(a) VALUES (1);
+SELECT b, v FROM t1;
+b v
+0 10
+DROP TABLE t1;
+CREATE TABLE t1(a int DEFAULT 100, v int AS (a+1) PERSISTENT);
+INSERT INTO t1 () VALUES ();
+CREATE TABLE t2(a int DEFAULT 100 , v int AS (a+1));
+INSERT INTO t2 () VALUES ();
+SELECT a, v FROM t1;
+a v
+100 101
+SELECT a, v FROM t2;
+a v
+100 101
+DROP TABLE t1,t2;
+CREATE TABLE t1 (
+a datetime NOT NULL DEFAULT '2000-01-01',
+v boolean AS (a < '2001-01-01')
+);
+INSERT INTO t1(a) VALUES ('2002-02-15');
+INSERT INTO t1(a) VALUES ('2000-10-15');
+SELECT a, v FROM t1;
+a v
+2002-02-15 00:00:00 0
+2000-10-15 00:00:00 1
+SELECT a, v FROM t1;
+a v
+2002-02-15 00:00:00 0
+2000-10-15 00:00:00 1
+CREATE TABLE t2 (
+a datetime NOT NULL DEFAULT '2000-01-01',
+v boolean AS (a < '2001-01-01') PERSISTENT
+);
+INSERT INTO t2(a) VALUES ('2002-02-15');
+INSERT INTO t2(a) VALUES ('2000-10-15');
+SELECT * FROM t2;
+a v
+2002-02-15 00:00:00 0
+2000-10-15 00:00:00 1
+DROP TABLE t1, t2;
+CREATE TABLE t1 (
+a char(255), b char(255), c char(255), d char(255),
+v char(255) AS (CONCAT(c,d) ) VIRTUAL
+);
+INSERT INTO t1(a,b,c,d) VALUES ('w','x','y','z'), ('W','X','Y','Z');
+SELECT v FROM t1 ORDER BY CONCAT(a,b);
+v
+yz
+YZ
+DROP TABLE t1;
+CREATE TABLE t1 (f1 INTEGER, v1 INTEGER AS (f1) VIRTUAL);
+CREATE TABLE t2 AS SELECT v1 FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1,t2;
+CREATE TABLE t1 (p int, a double NOT NULL, v double AS (ROUND(a,p)) VIRTUAL);
+INSERT INTO t1 VALUES (0,1,0);
+Warnings:
+Warning 1645 The value specified for computed column 'v' in table 't1' ignored
+INSERT INTO t1 VALUES (NULL,0,0);
+Warnings:
+Warning 1645 The value specified for computed column 'v' in table 't1' ignored
+SELECT a, p, v, ROUND(a,p), ROUND(a,p+NULL) FROM t1;
+a p v ROUND(a,p) ROUND(a,p+NULL)
+1 0 1 1 NULL
+0 NULL NULL NULL NULL
+DROP TABLE t1;
+CREATE TABLE t1 (p int, a double NOT NULL);
+INSERT INTO t1(p,a) VALUES (0,1);
+INSERT INTO t1(p,a) VALUES (NULL,0);
+SELECT a, p, ROUND(a,p), ROUND(a,p+NULL) FROM t1;
+a p ROUND(a,p) ROUND(a,p+NULL)
+1 0 1 NULL
+0 NULL NULL NULL
+DROP TABLE t1;
+CREATE TABLE t1 (a char(32), v char(32) CHARACTER SET ucs2 AS (a) VIRTUAL);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(32) DEFAULT NULL,
+ `v` char(32) CHARACTER SET ucs2 AS (a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result b/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result
new file mode 100644
index 00000000000..c638ced4f41
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result
@@ -0,0 +1,242 @@
+SET @@session.storage_engine = 'InnoDB';
+# Case 1. All non-stored columns.
+# This scenario is currently impossible due to the fact that virtual columns
+# with a constant expression are not allowed.
+# Case 2. CREATE
+# - Column1: "real"
+# - Column 2: virtual non-stored
+create table t1 (a int, b int as (-a));
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 3. CREATE
+# - Column1: "real"
+# - Column 2: virtual stored
+create table t1 (a int, b int as (-a) persistent);
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 4. CREATE
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 5. CREATE
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 6. CREATE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t1;
+# Case 7. ALTER. Modify virtual stored -> virtual non-stored
+create table t1 (a int, b int as (a % 2) persistent);
+alter table t1 modify b int as (a % 2);
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 8. ALTER. Modify virtual non-stored -> virtual stored
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent;
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 9. CREATE LIKE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+create table t2 like t1;
+insert into t2 values (1,default,default);
+select * from t2;
+a b c
+1 -1 -1
+insert into t2 values (2,default,default);
+select * from t2;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t2;
+drop table t1;
+# Case 10. ALTER. Dropping a virtual non-stored column.
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int, c varchar(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(5) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 11. ALTER. Dropping a virtual stored column.
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int, c char(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` char(5) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 12. ALTER. Adding a new virtual non-stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) VIRTUAL,
+ `b` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 13. ALTER. Adding a new virtual stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) persistent after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) PERSISTENT,
+ `b` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 14. ALTER. Changing the expression of a virtual stored column.
+create table t1 (a int, b datetime, c int as (week(b)) persistent);
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1)) persistent;
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) PERSISTENT
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+# Case 15. ALTER. Changing the expression of a virtual non-stored column.
+create table t1 (a int, b datetime, c int as (week(b)));
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1));
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result b/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result
new file mode 100644
index 00000000000..be42b8b76c4
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result
@@ -0,0 +1,242 @@
+SET @@session.storage_engine = 'MyISAM';
+# Case 1. All non-stored columns.
+# This scenario is currently impossible due to the fact that virtual columns
+# with a constant expression are not allowed.
+# Case 2. CREATE
+# - Column1: "real"
+# - Column 2: virtual non-stored
+create table t1 (a int, b int as (-a));
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 3. CREATE
+# - Column1: "real"
+# - Column 2: virtual stored
+create table t1 (a int, b int as (-a) persistent);
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 -1
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 -1
+2 -2
+drop table t1;
+# Case 4. CREATE
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 5. CREATE
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int);
+insert into t1 values (default,1);
+select * from t1;
+a b
+-1 1
+insert into t1 values (default,2);
+select * from t1;
+a b
+-1 1
+-2 2
+drop table t1;
+# Case 6. CREATE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+insert into t1 values (1,default,default);
+select * from t1;
+a b c
+1 -1 -1
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t1;
+# Case 7. ALTER. Modify virtual stored -> virtual non-stored
+create table t1 (a int, b int as (a % 2) persistent);
+alter table t1 modify b int as (a % 2);
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 8. ALTER. Modify virtual non-stored -> virtual stored
+create table t1 (a int, b int as (a % 2));
+alter table t1 modify b int as (a % 2) persistent;
+ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 9. CREATE LIKE
+# - Column1: "real"
+# - Column2: virtual non-stored
+# - Column3: virtual stored
+create table t1 (a int, b int as (-a), c int as (-a) persistent);
+create table t2 like t1;
+insert into t2 values (1,default,default);
+select * from t2;
+a b c
+1 -1 -1
+insert into t2 values (2,default,default);
+select * from t2;
+a b c
+1 -1 -1
+2 -2 -2
+drop table t2;
+drop table t1;
+# Case 10. ALTER. Dropping a virtual non-stored column.
+# - Column1: virtual non-stored
+# - Column2: "real"
+create table t1 (a int as (-b), b int, c varchar(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` varchar(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 11. ALTER. Dropping a virtual stored column.
+# - Column1: virtual stored
+# - Column2: "real"
+create table t1 (a int as (-b) persistent, b int, c char(5));
+insert into t1 values (default,1,'v1');
+insert into t1 values (default,2,'v2');
+select * from t1;
+a b c
+-1 1 v1
+-2 2 v2
+alter table t1 drop column a;
+select * from t1;
+b c
+1 v1
+2 v2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` char(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 12. ALTER. Adding a new virtual non-stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) VIRTUAL,
+ `b` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 13. ALTER. Adding a new virtual stored column.
+create table t1 (a int, b datetime);
+insert into t1 values (1,'2008-09-04');
+insert into t1 values (2,'2008-09-05');
+select * from t1;
+a b
+1 2008-09-04 00:00:00
+2 2008-09-05 00:00:00
+alter table t1 add column c int as (dayofyear(b)) persistent after a;
+select * from t1;
+a c b
+1 248 2008-09-04 00:00:00
+2 249 2008-09-05 00:00:00
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `c` int(11) AS (dayofyear(b)) PERSISTENT,
+ `b` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 14. ALTER. Changing the expression of a virtual stored column.
+create table t1 (a int, b datetime, c int as (week(b)) persistent);
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1)) persistent;
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+# Case 15. ALTER. Changing the expression of a virtual non-stored column.
+create table t1 (a int, b datetime, c int as (week(b)));
+insert into t1 values (1,'2008-09-04',default);
+insert into t1 values (2,'2008-09-05',default);
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 35
+2 2008-09-05 00:00:00 35
+alter table t1 change column c c int as (week(b,1));
+select * from t1;
+a b c
+1 2008-09-04 00:00:00 36
+2 2008-09-05 00:00:00 36
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` int(11) AS (week(b,1)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_partition_innodb.result b/mysql-test/suite/vcol/r/vcol_partition_innodb.result
new file mode 100644
index 00000000000..466c1851800
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_partition_innodb.result
@@ -0,0 +1,80 @@
+SET @@session.storage_engine = 'InnoDB';
+drop table if exists t1;
+# Case 1. Partitioning by RANGE based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY RANGE( b ) (
+PARTITION p0 VALUES LESS THAN (2006),
+PARTITION p2 VALUES LESS THAN (2008)
+);
+insert into t1 values ('2006-01-01',default);
+insert into t1 values ('2007-01-01',default);
+insert into t1 values ('2005-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+2007-01-01 2007
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 1 16384
+p2 2 16384
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+2007-01-01 2006
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 2 16384
+p2 1 16384
+drop table t1;
+# Case 2. Partitioning by LIST based on a stored virtual column.
+CREATE TABLE t1 (a int, b int as (a % 3 ) persistent)
+PARTITION BY LIST (a+1)
+(PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
+insert into t1 values (1,default);
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p1 0 16384
+p2 1 16384
+select * from t1;
+a b
+1 1
+select * from t1;
+a b
+1 1
+drop table t1;
+# Case 3. Partitioning by HASH based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY HASH( b % 3 ) PARTITIONS 3;
+insert into t1 values ('2005-01-01',default);
+insert into t1 values ('2006-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 0 16384
+p1 1 16384
+p2 1 16384
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 1 16384
+p1 1 16384
+p2 0 16384
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_partition_myisam.result b/mysql-test/suite/vcol/r/vcol_partition_myisam.result
new file mode 100644
index 00000000000..9a92f308c45
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_partition_myisam.result
@@ -0,0 +1,80 @@
+SET @@session.storage_engine = 'MyISAM';
+drop table if exists t1;
+# Case 1. Partitioning by RANGE based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY RANGE( b ) (
+PARTITION p0 VALUES LESS THAN (2006),
+PARTITION p2 VALUES LESS THAN (2008)
+);
+insert into t1 values ('2006-01-01',default);
+insert into t1 values ('2007-01-01',default);
+insert into t1 values ('2005-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+2007-01-01 2007
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 1 7
+p2 2 14
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+2007-01-01 2006
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 2 14
+p2 1 7
+drop table t1;
+# Case 2. Partitioning by LIST based on a stored virtual column.
+CREATE TABLE t1 (a int, b int as (a % 3 ) persistent)
+PARTITION BY LIST (a+1)
+(PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
+insert into t1 values (1,default);
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p1 0 0
+p2 1 9
+select * from t1;
+a b
+1 1
+select * from t1;
+a b
+1 1
+drop table t1;
+# Case 3. Partitioning by HASH based on a non-stored virtual column.
+CREATE TABLE t1 (
+a DATE NOT NULL,
+b int as (year(a))
+)
+PARTITION BY HASH( b % 3 ) PARTITIONS 3;
+insert into t1 values ('2005-01-01',default);
+insert into t1 values ('2006-01-01',default);
+select * from t1;
+a b
+2005-01-01 2005
+2006-01-01 2006
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 0 0
+p1 1 7
+p2 1 7
+# Modify the expression of virtual column b
+ALTER TABLE t1 modify b int as (year(a)-1);
+select * from t1;
+a b
+2005-01-01 2004
+2006-01-01 2005
+select partition_name,table_rows,data_length from information_schema.partitions where table_name = 't1';
+partition_name table_rows data_length
+p0 1 7
+p1 1 7
+p2 0 0
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_select_innodb.result b/mysql-test/suite/vcol/r/vcol_select_innodb.result
new file mode 100644
index 00000000000..f5b430fe233
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_select_innodb.result
@@ -0,0 +1,264 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+index (c));
+insert into t1 (a) values (2), (1), (1), (3), (NULL);
+create table t2 like t1;
+insert into t2 (a) values (1);
+create table t3 (a int primary key,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t3 (a) values (2),(1),(3);
+# select_type=SIMPLE, type=system
+select * from t2;
+a b c
+1 -1 -1
+explain select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1
+select * from t2 where c=-1;
+a b c
+1 -1 -1
+explain select * from t2 where c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c c 5 const 1 Using where
+# select_type=SIMPLE, type=ALL
+select * from t1 where b=-1;
+a b c
+1 -1 -1
+1 -1 -1
+explain select * from t1 where b=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+# select_type=SIMPLE, type=const
+select * from t3 where a=1;
+a b c
+1 -1 -1
+explain select * from t3 where a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1
+# select_type=SIMPLE, type=range
+select * from t3 where c>=-1;
+a b c
+1 -1 -1
+explain select * from t3 where c>=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# select_type=SIMPLE, type=ref
+select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+a b c a b c
+1 -1 -1 1 -1 -1
+1 -1 -1 1 -1 -1
+explain select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const c c 5 const 1
+1 SIMPLE t1 ref c c 5 const 2 Using where
+# select_type=PRIMARY, type=index,ALL
+select * from t1 where b in (select c from t3);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+explain select * from t1 where b in (select c from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 1 Using index; Using where
+# select_type=PRIMARY, type=range,ref
+select * from t1 where c in (select c from t3 where c between -2 and -1);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+explain select * from t1 where c in (select c from t3 where c between -2 and -1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 1 Using index; Using where
+# select_type=UNION, type=system
+# select_type=UNION RESULT, type=<union1,2>
+select * from t1 union select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from t1 union select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+2 UNION t2 ALL NULL NULL NULL NULL 1
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
+# select_type=DERIVED, type=system
+select * from (select a,b,c from t1) as t11;
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from (select a,b,c from t1) as t11;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED t1 ALL NULL NULL NULL NULL 5
+###
+### Using aggregate functions with/without DISTINCT
+###
+# SELECT COUNT(*) FROM tbl_name
+select count(*) from t1;
+count(*)
+5
+explain select count(*) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+# SELECT COUNT(DISTINCT <non-vcol>) FROM tbl_name
+select count(distinct a) from t1;
+count(distinct a)
+3
+explain select count(distinct a) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <non-stored vcol>) FROM tbl_name
+select count(distinct b) from t1;
+count(distinct b)
+3
+explain select count(distinct b) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <stored vcol>) FROM tbl_name
+select count(distinct c) from t1;
+count(distinct c)
+3
+explain select count(distinct c) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+###
+### filesort & range-based utils
+###
+# SELECT * FROM tbl_name WHERE <vcol expr>
+select * from t3 where c >= -2;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c >= -2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr>
+select * from t3 where a between 1 and 2;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where a between 1 and 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
+select * from t3 where b between -2 and -1;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where b between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where
+# SELECT * FROM tbl_name WHERE <indexed vcol expr>
+select * from t3 where c between -2 and -1;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where a between 1 and 2 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where a between 1 and 2 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
+select * from t3 where a between 1 and 2 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where a between 1 and 2 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
+select * from t3 where b between -2 and -1 order by a;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where b between -2 and -1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index NULL PRIMARY 4 NULL 3 Using where
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where b between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where c between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where b between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where c between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(b) from t1 group by b;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(c) from t1 group by c;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(b) from t1 group by c;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(c) from t1 group by b;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
diff --git a/mysql-test/suite/vcol/r/vcol_select_myisam.result b/mysql-test/suite/vcol/r/vcol_select_myisam.result
new file mode 100644
index 00000000000..45e4defd315
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_select_myisam.result
@@ -0,0 +1,264 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+index (c));
+insert into t1 (a) values (2), (1), (1), (3), (NULL);
+create table t2 like t1;
+insert into t2 (a) values (1);
+create table t3 (a int primary key,
+b int as (-a),
+c int as (-a) persistent unique);
+insert into t3 (a) values (2),(1),(3);
+# select_type=SIMPLE, type=system
+select * from t2;
+a b c
+1 -1 -1
+explain select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+select * from t2 where c=-1;
+a b c
+1 -1 -1
+explain select * from t2 where c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system c NULL NULL NULL 1
+# select_type=SIMPLE, type=ALL
+select * from t1 where b=-1;
+a b c
+1 -1 -1
+1 -1 -1
+explain select * from t1 where b=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+# select_type=SIMPLE, type=const
+select * from t3 where a=1;
+a b c
+1 -1 -1
+explain select * from t3 where a=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const PRIMARY PRIMARY 4 const 1
+# select_type=SIMPLE, type=range
+select * from t3 where c>=-1;
+a b c
+1 -1 -1
+explain select * from t3 where c>=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 2 Using where
+# select_type=SIMPLE, type=ref
+select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+a b c a b c
+1 -1 -1 1 -1 -1
+1 -1 -1 1 -1 -1
+explain select * from t1,t3 where t1.c=t3.c and t3.c=-1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 const c c 5 const 1
+1 SIMPLE t1 ref c c 5 const 2 Using where
+# select_type=PRIMARY, type=index,ALL
+select * from t1 where b in (select c from t3);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+explain select * from t1 where b in (select c from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 2 Using index; Using where
+# select_type=PRIMARY, type=range,ref
+select * from t1 where c in (select c from t3 where c between -2 and -1);
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+explain select * from t1 where c in (select c from t3 where c between -2 and -1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t3 index_subquery c c 5 func 2 Using index; Using where
+# select_type=UNION, type=system
+# select_type=UNION RESULT, type=<union1,2>
+select * from t1 union select * from t2;
+a b c
+2 -2 -2
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from t1 union select * from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+2 UNION t2 system NULL NULL NULL NULL 1
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
+# select_type=DERIVED, type=system
+select * from (select a,b,c from t1) as t11;
+a b c
+2 -2 -2
+1 -1 -1
+1 -1 -1
+3 -3 -3
+NULL NULL NULL
+explain select * from (select a,b,c from t1) as t11;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
+2 DERIVED t1 ALL NULL NULL NULL NULL 5
+###
+### Using aggregate functions with/without DISTINCT
+###
+# SELECT COUNT(*) FROM tbl_name
+select count(*) from t1;
+count(*)
+5
+explain select count(*) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+# SELECT COUNT(DISTINCT <non-vcol>) FROM tbl_name
+select count(distinct a) from t1;
+count(distinct a)
+3
+explain select count(distinct a) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <non-stored vcol>) FROM tbl_name
+select count(distinct b) from t1;
+count(distinct b)
+3
+explain select count(distinct b) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
+# SELECT COUNT(DISTINCT <stored vcol>) FROM tbl_name
+select count(distinct c) from t1;
+count(distinct c)
+3
+explain select count(distinct c) from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+###
+### filesort & range-based utils
+###
+# SELECT * FROM tbl_name WHERE <vcol expr>
+select * from t3 where c >= -2;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c >= -2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 2 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr>
+select * from t3 where a between 1 and 2;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where a between 1 and 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
+select * from t3 where b between -2 and -1;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where
+# SELECT * FROM tbl_name WHERE <indexed vcol expr>
+select * from t3 where c between -2 and -1;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
+select * from t3 where a between 1 and 2 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where a between 1 and 2 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
+select * from t3 where b between -2 and -1 order by a;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where b between -2 and -1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-vcol>
+select * from t3 where c between -2 and -1 order by a;
+a b c
+1 -1 -1
+2 -2 -2
+explain select * from t3 where c between -2 and -1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where b between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <non-indexed vcol>
+select * from t3 where c between -2 and -1 order by b;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where b between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where b between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
+# SELECT * FROM tbl_name WHERE <indexed vcol expr> ORDER BY <indexed vcol>
+select * from t3 where c between -2 and -1 order by c;
+a b c
+2 -2 -2
+1 -1 -1
+explain select * from t3 where c between -2 and -1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 range c c 5 NULL 1 Using where
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(b) from t1 group by b;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(c) from t1 group by c;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL c 5 NULL 5 Using index
+# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <indexed vcol>
+select sum(b) from t1 group by c;
+sum(b)
+NULL
+-3
+-2
+-2
+explain select sum(b) from t1 group by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+# SELECT sum(<indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
+select sum(c) from t1 group by b;
+sum(c)
+NULL
+-3
+-2
+-2
+explain select sum(c) from t1 group by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
diff --git a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result
new file mode 100644
index 00000000000..2bc652a7da2
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result
@@ -0,0 +1,2943 @@
+SET @@session.storage_engine = 'InnoDB';
+#
+# NUMERIC FUNCTIONS
+#
+# ABS()
+set sql_warnings = 1;
+create table t1 (a int, b int as (abs(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (abs(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1, default);
+select * from t1;
+a b
+-1 1
+drop table t1;
+set sql_warnings = 0;
+# ACOS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(acos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(acos(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1, default);
+insert into t1 values (1.0001,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 0
+1.0001 NULL
+0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ASIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(asin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(asin(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (0.2, default);
+insert into t1 values (1.0001,default);
+select * from t1;
+a b
+0.2 0.201358
+1.0001 NULL
+drop table t1;
+set sql_warnings = 0;
+#ATAN
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan(a,b),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, c double as (format(atan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `c` double AS (format(atan(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-2,default);
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a c
+-2 -1.107149
+3.141593 1.262627
+drop table t1;
+set sql_warnings = 0;
+# ATAN2
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan2(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan2(a,b),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# CEIL()
+set sql_warnings = 1;
+create table t1 (a double, b int as (ceil(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (ceil(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 2
+-1.23 -1
+drop table t1;
+set sql_warnings = 0;
+# CONV()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int, c int, d varchar(10) as (conv(a,b,c)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (conv(a,b,c)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a',16,2,default);
+insert into t1 values ('6e',18,8,default);
+insert into t1 values (-17,10,-18,default);
+insert into t1 values (10+'10'+'10'+0xa,10,10,default);
+select * from t1;
+a b c d
+a 16 2 1010
+6e 18 8 172
+-17 10 -18 -H
+40 10 10 40
+drop table t1;
+set sql_warnings = 0;
+# COS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cos(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a b
+3.141593 -1
+drop table t1;
+set sql_warnings = 0;
+# COT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cot(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cot(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+12 -1.572673
+0 NULL
+drop table t1;
+set sql_warnings = 0;
+# CRC32()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (crc32(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (crc32(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('mysql',default);
+select * from t1;
+a b
+MySQL 3259397556
+mysql 2501908538
+drop table t1;
+set sql_warnings = 0;
+# DEGREES()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(degrees(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(degrees(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+3.141593 180.00002
+1.570796 89.999981
+drop table t1;
+set sql_warnings = 0;
+# /
+set sql_warnings = 1;
+create table t1 (a double, b double as (a/2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a/2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# EXP()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(exp(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(exp(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+2 7.389056
+-2 0.135335
+0 1
+drop table t1;
+set sql_warnings = 0;
+# FLOOR()
+set sql_warnings = 1;
+create table t1 (a double, b long as (floor(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` mediumtext AS (floor(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 1
+-1.23 -2
+drop table t1;
+set sql_warnings = 0;
+# LN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(ln(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(ln(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG()
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(log(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(log(a,b),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,65536,default);
+insert into t1 values (10,100,default);
+insert into t1 values (1,100,default);
+select * from t1;
+a b c
+2 65536 16
+10 100 2
+1 100 NULL
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG2()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log2(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log2(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (65536,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+65536 16
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG10()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log10(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log10(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (100,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+2 0.30103
+100 2
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# -
+set sql_warnings = 1;
+create table t1 (a double, b double as (a-1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a-1) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# MOD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (mod(a,10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (mod(a,10)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# %
+set sql_warnings = 1;
+create table t1 (a int, b int as (a % 10));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 10) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# OCT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(10) as (oct(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(10) AS (oct(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 14
+drop table t1;
+set sql_warnings = 0;
+# PI()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(PI()*a*a,6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(PI()*a*a,6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 3.141593
+drop table t1;
+set sql_warnings = 0;
+# +
+set sql_warnings = 1;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 2
+drop table t1;
+set sql_warnings = 0;
+# POW, POWER
+set sql_warnings = 1;
+create table t1 (a int, b int as (pow(a,2)), c int as (power(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (pow(a,2)) VIRTUAL,
+ `c` int(11) AS (power(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default,default);
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 1 1
+2 4 4
+drop table t1;
+set sql_warnings = 0;
+# RADIANS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(radians(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(radians(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (90,default);
+select * from t1;
+a b
+90 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ROUND()
+set sql_warnings = 1;
+create table t1 (a double, b int as (round(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (round(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1.23,default);
+insert into t1 values (-1.58,default);
+insert into t1 values (1.58,default);
+select * from t1;
+a b
+-1.23 -1
+-1.58 -2
+1.58 2
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double, c int as (round(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` int(11) AS (round(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.298,1,default);
+insert into t1 values (1.298,0,default);
+insert into t1 values (23.298,-1,default);
+select * from t1;
+a b c
+1.298 1 1
+1.298 0 1
+23.298 -1 20
+drop table t1;
+set sql_warnings = 0;
+# SIGN()
+set sql_warnings = 1;
+create table t1 (a double, b int as (sign(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (sign(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-32,default);
+insert into t1 values (0,default);
+insert into t1 values (234,default);
+select * from t1;
+a b
+-32 -1
+0 0
+234 1
+drop table t1;
+set sql_warnings = 0;
+# SIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sin(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+1.570796 1
+drop table t1;
+set sql_warnings = 0;
+# SQRT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sqrt(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sqrt(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (4,default);
+insert into t1 values (20,default);
+insert into t1 values (-16,default);
+select * from t1;
+a b
+4 2
+20 4.472136
+-16 NULL
+drop table t1;
+set sql_warnings = 0;
+# TAN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(tan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(tan(a),6)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()+1,6),default);
+select * from t1;
+a b
+3.141593 0
+4.141593 1.557409
+drop table t1;
+set sql_warnings = 0;
+# *
+set sql_warnings = 1;
+create table t1 (a double, b double as (a*3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a*3) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 0
+1 3
+2 6
+drop table t1;
+set sql_warnings = 0;
+# TRUNCATE()
+set sql_warnings = 1;
+create table t1 (a double, b double as (truncate(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (truncate(a,4)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1.223,default);
+insert into t1 values (1.999,default);
+insert into t1 values (1.999,default);
+insert into t1 values (122,default);
+select * from t1;
+a b
+1.223 1.223
+1.999 1.999
+1.999 1.999
+122 122
+drop table t1;
+set sql_warnings = 0;
+# Unary -
+set sql_warnings = 1;
+create table t1 (a double, b double as (-a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (-a) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 -1
+-1 1
+drop table t1;
+set sql_warnings = 0;
+#
+# STRING FUNCTIONS
+#
+# ASCII()
+set sql_warnings = 1;
+create table t1 (a char(2), b int as (ascii(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(2) DEFAULT NULL,
+ `b` int(11) AS (ascii(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+insert into t1 values (2,default);
+insert into t1 values ('dx',default);
+select * from t1;
+a b
+2 50
+2 50
+dx 100
+drop table t1;
+set sql_warnings = 0;
+# BIN()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (bin(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (bin(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 1100
+drop table t1;
+set sql_warnings = 0;
+# BIT_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (bit_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (bit_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 32
+drop table t1;
+set sql_warnings = 0;
+# CHAR_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (char_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (char_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CHAR()
+set sql_warnings = 1;
+create table t1 (a int, b int, c varbinary(10) as (char(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` varbinary(10) AS (char(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (77,121,default);
+select * from t1;
+a b c
+77 121 My
+drop table t1;
+set sql_warnings = 0;
+# CHARACTER_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (character_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (character_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CONCAT_WS()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat_ws(',',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat_ws(',',a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# CONCAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat(a,',',b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat(a,',',b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# ELT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(10) as (elt(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (elt(c,a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',1,default);
+insert into t1 values ('value1','value2',2,default);
+select * from t1;
+a b c d
+value1 value2 1 value1
+value1 value2 2 value2
+drop table t1;
+set sql_warnings = 0;
+# EXPORT_SET()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (export_set(a,'1','0','',10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (export_set(a,'1','0','',10)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (6,default);
+select * from t1;
+a b
+6 0110000000
+drop table t1;
+set sql_warnings = 0;
+# FIELD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (field('aa',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (field('aa',a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('aa','bb',default);
+insert into t1 values ('bb','aa',default);
+select * from t1;
+a b c
+aa bb 1
+bb aa 2
+drop table t1;
+set sql_warnings = 0;
+# FIND_IN_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (find_in_set(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (find_in_set(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('aa','aa,bb,cc',default);
+insert into t1 values ('aa','bb,aa,cc',default);
+select * from t1;
+a b c
+aa aa,bb,cc 1
+aa bb,aa,cc 2
+drop table t1;
+set sql_warnings = 0;
+# FORMAT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(20) as (format(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(20) AS (format(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12332.123456,default);
+select * from t1;
+a b
+12332.123456 12,332.12
+drop table t1;
+set sql_warnings = 0;
+# HEX()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (17,default);
+select * from t1;
+a b
+17 11
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 616263
+drop table t1;
+set sql_warnings = 0;
+# INSERT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (insert(a,length(a),length(b),b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (insert(a,length(a),length(b),b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('start,','end',default);
+select * from t1;
+a b c
+start, end startend
+drop table t1;
+set sql_warnings = 0;
+# INSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (instr(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (instr(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar,','bar',default);
+insert into t1 values ('xbar,','foobar',default);
+select * from t1;
+a b c
+foobarbar, bar 4
+xbar, foobar 0
+drop table t1;
+set sql_warnings = 0;
+# LCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lcase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lcase(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LEFT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(5) as (left(a,5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(5) AS (left(a,5)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fooba
+drop table t1;
+set sql_warnings = 0;
+# LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a like 'H%o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# LOCATE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (locate('bar',a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (locate('bar',a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# LOWER()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lower(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lower(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lpad(a,4,' ')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lpad(a,4,' ')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('M',default);
+select * from t1;
+a b
+MySQL MySQ
+M M
+drop table t1;
+set sql_warnings = 0;
+# LTRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (ltrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (ltrim(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (' MySQL',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+ MySQL MySQL
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# MAKE_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(30) as (make_set(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(30) AS (make_set(c,a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',1,default);
+insert into t1 values ('a','b',3,default);
+select * from t1;
+a b c d
+a b 1 a
+a b 3 a,b
+drop table t1;
+set sql_warnings = 0;
+# MID()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (mid(a,1,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (mid(a,1,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fo
+drop table t1;
+set sql_warnings = 0;
+# NOT LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not like 'H%o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 0
+MySQL 1
+drop table t1;
+set sql_warnings = 0;
+# NOT REGEXP
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not regexp 'H.+o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 0
+hello 0
+drop table t1;
+set sql_warnings = 0;
+# OCTET_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (octet_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (octet_length(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# ORD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (ord(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (ord(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+select * from t1;
+a b
+2 50
+drop table t1;
+set sql_warnings = 0;
+# POSITION()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (position('bar' in a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (position('bar' in a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# QUOTE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (quote(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (quote(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Don\'t',default);
+select * from t1;
+a b
+Don't 'Don\'t'
+drop table t1;
+set sql_warnings = 0;
+# REGEXP()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a regexp 'H.+o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 1
+hello 1
+drop table t1;
+set sql_warnings = 0;
+# REPEAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (repeat(a,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (repeat(a,3)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQLMySQLMySQL
+drop table t1;
+set sql_warnings = 0;
+# REPLACE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (replace(a,'aa','bb')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (replace(a,'aa','bb')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa mbb
+drop table t1;
+set sql_warnings = 0;
+# REVERSE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (reverse(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (reverse(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa aam
+drop table t1;
+set sql_warnings = 0;
+# RIGHT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (right(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (right(a,4)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar rbar
+drop table t1;
+set sql_warnings = 0;
+# RLIKE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a rlike 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a rlike 'H.+o') VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# RPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rpad(a,4,'??')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rpad(a,4,'??')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('He',default);
+select * from t1;
+a b
+He He??
+drop table t1;
+set sql_warnings = 0;
+# RTRIM();
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rtrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rtrim(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello ',default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# SOUNDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(20) as (soundex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(20) AS (soundex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello H400
+drop table t1;
+set sql_warnings = 0;
+# SOUNDS LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a sounds like b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a sounds like b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello',default);
+insert into t1 values ('Hello','MySQL',default);
+insert into t1 values ('Hello','hello',default);
+select * from t1;
+a b c
+Hello Hello 1
+Hello MySQL 0
+Hello hello 1
+drop table t1;
+set sql_warnings = 0;
+# SPACE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (concat(a,space(5))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (concat(a,space(5))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello', default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# STRCMP()
+set sql_warnings = 1;
+create table t1 (a varchar(9), b varchar(9), c tinyint(1) as (strcmp(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(9) DEFAULT NULL,
+ `b` varchar(9) DEFAULT NULL,
+ `c` tinyint(1) AS (strcmp(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello', default);
+insert into t1 values ('Hello','Hello1', default);
+select * from t1;
+a b c
+Hello Hello 0
+Hello Hello1 -1
+drop table t1;
+set sql_warnings = 0;
+# SUBSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substr(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substr(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello ello
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING_INDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (substring_index(a,'.',2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (substring_index(a,'.',2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('www.mysql.com',default);
+select * from t1;
+a b
+www.mysql.com www.mysql
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substring(a from 2 for 2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substring(a from 2 for 2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello el
+drop table t1;
+set sql_warnings = 0;
+# TRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (trim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (trim(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (' aa ',default);
+select * from t1;
+a b
+ aa aa
+drop table t1;
+set sql_warnings = 0;
+# UCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (ucase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (ucase(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+# UNHEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (unhex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (unhex(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('4D7953514C',default);
+select * from t1;
+a b
+4D7953514C MySQL
+drop table t1;
+set sql_warnings = 0;
+# UPPER()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (upper(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (upper(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+#
+# CONTROL FLOW FUNCTIONS
+#
+# CASE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(16) as (case a when NULL then 'asd' when 'b' then 'B' else a end));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(16) AS (case a when NULL then 'asd' when 'b' then 'B' else a end) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (NULL,default);
+insert into t1 values ('b',default);
+insert into t1 values ('c',default);
+select * from t1;
+a b
+NULL NULL
+b B
+c c
+drop table t1;
+set sql_warnings = 0;
+# IF
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (if(a=1,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (if(a=1,a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,2,default);
+insert into t1 values (3,4,default);
+select * from t1;
+a b c
+1 2 1
+3 4 4
+drop table t1;
+set sql_warnings = 0;
+# IFNULL
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(10) as (ifnull(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(10) AS (ifnull(a,'DEFAULT')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (NULL,'adf',default);
+insert into t1 values ('a','adf',default);
+select * from t1;
+a b c
+NULL adf DEFAULT
+a adf a
+drop table t1;
+set sql_warnings = 0;
+# NULLIF
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (nullif(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (nullif(a,'DEFAULT')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('DEFAULT',default);
+insert into t1 values ('a',default);
+select * from t1;
+a b
+DEFAULT NULL
+a a
+drop table t1;
+set sql_warnings = 0;
+#
+# OPERATORS
+#
+# AND, &&
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a>0 && a<2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a>0 && a<2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a between 0 and 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BINARY
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varbinary(10) as (binary a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varbinary(10) AS (binary a) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('11',default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+11 11
+1 1
+drop table t1;
+set sql_warnings = 0;
+# &
+set sql_warnings = 1;
+create table t1 (a int, b int as (a & 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a & 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 1
+0 0
+drop table t1;
+set sql_warnings = 0;
+# ~
+set sql_warnings = 1;
+create table t1 (a int, b int as (~a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (~a) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+Warnings:
+Warning 1264 Out of range value for column 'b' at row 1
+select * from t1;
+a b
+1 2147483647
+drop table t1;
+set sql_warnings = 0;
+# |
+set sql_warnings = 1;
+create table t1 (a int, b int as (a | 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a | 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 5
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# ^
+set sql_warnings = 1;
+create table t1 (a int, b int as (a ^ 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a ^ 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 4
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# DIV
+set sql_warnings = 1;
+create table t1 (a int, b int as (a div 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a div 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (7,default);
+select * from t1;
+a b
+1 0
+7 1
+drop table t1;
+set sql_warnings = 0;
+# <=>
+set sql_warnings = 1;
+create table t1 (a int, b int, c bool as (a <=> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` tinyint(1) AS (a <=> b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,1,default);
+insert into t1 values (NULL,NULL,default);
+insert into t1 values (1,NULL,default);
+select * from t1;
+a b c
+1 1 1
+NULL NULL 1
+1 NULL 0
+drop table t1;
+set sql_warnings = 0;
+# =
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a=b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a=b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a >= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a >= b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a > b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a > b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 0
+drop table t1;
+set sql_warnings = 0;
+# IS NOT NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is not null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is not null) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 1
+NULL 0
+drop table t1;
+set sql_warnings = 0;
+# IS NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is null) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 0
+NULL 1
+drop table t1;
+set sql_warnings = 0;
+# <<
+set sql_warnings = 1;
+create table t1 (a int, b int as (a << 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a << 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+1 4
+3 12
+drop table t1;
+set sql_warnings = 0;
+# <=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <= b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 1
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# <
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a < b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a < b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# NOT BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a not between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a not between 0 and 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 1
+1 0
+drop table t1;
+set sql_warnings = 0;
+# <>
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <> b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# !=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a != b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a != b) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# ||, OR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a>5 || a<3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a>5 || a<3) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (4,default);
+select * from t1;
+a b
+1 1
+4 0
+drop table t1;
+set sql_warnings = 0;
+# >>
+set sql_warnings = 1;
+create table t1 (a int, b int as (a >> 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a >> 2) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (8,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+8 2
+3 0
+drop table t1;
+set sql_warnings = 0;
+# XOR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a xor 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a xor 5) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 1
+1 0
+2 0
+drop table t1;
+set sql_warnings = 0;
+#
+# DATE AND TIME FUNCTIONS
+#
+# ADDDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (adddate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (adddate(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# ADDTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (addtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (addtime(a,'02:00:00')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-31 02:00:00
+drop table t1;
+set sql_warnings = 0;
+# CONVERT_TZ()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (convert_tz(a,'MET','UTC')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (convert_tz(a,'MET','UTC')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_ADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_add(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_add(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(64) as (date_format(a,'%W %M %D')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(64) AS (date_format(a,'%W %M %D')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday August 31st
+drop table t1;
+set sql_warnings = 0;
+# DATE_SUB()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_sub(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_sub(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:00:00',default);
+select * from t1;
+a b
+2008-08-31 02:00:00 2008-08-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (datediff(a,'2000-01-01')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (datediff(a,'2000-01-01')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3165
+drop table t1;
+set sql_warnings = 0;
+# DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (day(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(10) as (dayname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(10) AS (dayname(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday
+drop table t1;
+set sql_warnings = 0;
+# DAYOFMONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofmonth(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofmonth(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYOFWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofweek(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 1
+drop table t1;
+set sql_warnings = 0;
+# DAYOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofyear(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 244
+drop table t1;
+set sql_warnings = 0;
+# EXTRACT
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (extract(year from a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (extract(year from a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# FROM_DAYS()
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_days(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (730669,default);
+select * from t1;
+a b
+730669 2000-07-03 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# FROM_UNIXTIME()
+set time_zone='UTC';
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_unixtime(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_unixtime(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1196440219,default);
+select * from t1;
+a b
+1196440219 2007-11-30 16:30:19
+drop table t1;
+set sql_warnings = 0;
+# GET_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (date_format(a,get_format(DATE,'EUR'))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (date_format(a,get_format(DATE,'EUR'))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31.08.2008
+drop table t1;
+set sql_warnings = 0;
+# HOUR()
+set sql_warnings = 1;
+create table t1 (a time, b long as (hour(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (hour(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+10:05:03 10
+drop table t1;
+set sql_warnings = 0;
+# LAST_DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (last_day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (last_day(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-05',default);
+insert into t1 values ('2003-02-32',default);
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+select * from t1;
+a b
+2003-02-05 00:00:00 2003-02-28 00:00:00
+0000-00-00 00:00:00 NULL
+drop table t1;
+set sql_warnings = 0;
+# MAKEDATE()
+set sql_warnings = 1;
+create table t1 (a int, b datetime as (makedate(a,1)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime AS (makedate(a,1)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2001,default);
+select * from t1;
+a b
+2001 2001-01-01 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# MAKETIME()
+set sql_warnings = 1;
+create table t1 (a int, b time as (maketime(a,1,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` time AS (maketime(a,1,3)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 12:01:03
+drop table t1;
+set sql_warnings = 0;
+# MICROSECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (microsecond(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (microsecond(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 12:00:00.123456',default);
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 12:00:00 0
+2009-12-31 23:59:59 0
+drop table t1;
+set sql_warnings = 0;
+# MINUTE()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (minute(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (minute(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 59
+drop table t1;
+set sql_warnings = 0;
+# MONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (month(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (month(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 12
+drop table t1;
+set sql_warnings = 0;
+# MONTHNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(16) as (monthname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(16) AS (monthname(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 December
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_ADD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (period_add(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (period_add(a,2)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (200801,default);
+select * from t1;
+a b
+200801 200803
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_DIFF()
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (period_diff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (period_diff(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (200802,200703,default);
+select * from t1;
+a b c
+200802 200703 11
+drop table t1;
+set sql_warnings = 0;
+# QUARTER()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (quarter(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (quarter(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# SEC_TO_TIME()
+set sql_warnings = 1;
+create table t1 (a long, b time as (sec_to_time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` time AS (sec_to_time(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (2378,default);
+select * from t1;
+a b
+2378 00:39:38
+drop table t1;
+set sql_warnings = 0;
+# SECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (second(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (second(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+2010-05-03 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# STR_TO_DATE()
+set sql_warnings = 1;
+create table t1 (a varchar(64), b datetime as (str_to_date(a,'%m/%d/%Y')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(64) DEFAULT NULL,
+ `b` datetime AS (str_to_date(a,'%m/%d/%Y')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('04/30/2004',default);
+select * from t1;
+a b
+04/30/2004 2004-04-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subdate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subdate(a,interval 1 month)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subtime(a,'02:00:00')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIME_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (time_format(a,'%r')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (time_format(a,'%r')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04 AM
+drop table t1;
+set sql_warnings = 0;
+# TIME_TO_SEC()
+set sql_warnings = 1;
+create table t1 (a time, b long as (time_to_sec(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (time_to_sec(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('22:23:00',default);
+select * from t1;
+a b
+22:23:00 80580
+drop table t1;
+set sql_warnings = 0;
+# TIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b time as (time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` time AS (time(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04
+drop table t1;
+set sql_warnings = 0;
+# TIMEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime, c long as (timediff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` mediumtext AS (timediff(a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31 23:59:59.000001','2008-12-30 01:01:01.000002',default);
+select * from t1;
+a b c
+2008-12-31 23:59:59 2008-12-30 01:01:01 46:58:58
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMP()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestamp(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestamp(a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31',default);
+select * from t1;
+a b
+2008-12-31 00:00:00 2008-12-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestampadd(minute,1,a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2003-01-02',default);
+select * from t1;
+a b
+2003-01-02 00:00:00 2003-01-02 00:01:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPDIFF()
+set sql_warnings = 1;
+create table t1 (a timestamp, b timestamp, c long as (timestampdiff(MONTH, a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `c` mediumtext AS (timestampdiff(MONTH, a,b)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-01','2003-05-01',default);
+select * from t1;
+a b c
+2003-02-01 00:00:00 2003-05-01 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# TO_DAYS()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (to_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (to_days(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2007-10-07',default);
+select * from t1;
+a b
+2007-10-07 00:00:00 733321
+drop table t1;
+set sql_warnings = 0;
+# WEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (week(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (week(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 35
+drop table t1;
+set sql_warnings = 0;
+# WEEKDAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekday(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekday(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# WEEKOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekofyear(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 36
+drop table t1;
+set sql_warnings = 0;
+# YEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (year(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (year(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# YEARWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (yearweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (yearweek(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 200835
+drop table t1;
+set sql_warnings = 0;
+#
+# FULL TEXT SEARCH FUNCTIONS
+#
+# None.
+#
+# CAST FUNCTIONS AND OPERATORS
+#
+# CAST()
+set sql_warnings = 1;
+create table t1 (a int, b long as (cast(a as unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (cast(a as unsigned)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+# Convert()
+set sql_warnings = 1;
+create table t1 (a int, b long as (convert(a,unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (convert(a,unsigned)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+#
+# XML FUNCTIONS
+#
+# None.
+#
+# OTHER FUNCTIONS
+#
+# AES_DECRYPT(), AES_ENCRYPT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (aes_encrypt(aes_decrypt(a,'adf'),'adf')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (aes_encrypt(aes_decrypt(a,'adf'),'adf')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL NULL
+drop table t1;
+set sql_warnings = 0;
+# BIT_COUNT()
+set sql_warnings = 1;
+create table t1 (a int, b int as (bit_count(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (bit_count(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values (5,default);
+select * from t1;
+a b
+5 2
+drop table t1;
+set sql_warnings = 0;
+# CHARSET()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (charset(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (charset(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1
+drop table t1;
+set sql_warnings = 0;
+# COERCIBILITY()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b int as (coercibility(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` int(11) AS (coercibility(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 2
+drop table t1;
+set sql_warnings = 0;
+# COLLATION()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (collation(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (collation(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1_swedish_ci
+drop table t1;
+set sql_warnings = 0;
+# COMPRESS(), UNCOMPRESS()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (uncompress(compress(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompress(compress(a))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# ENCODE(), DECODE()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (decode(encode(a,'abc'),'abc')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (decode(encode(a,'abc'),'abc')) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# DEFAULT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024) default 'aaa', b varchar(1024) as (ifnull(a,default(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT 'aaa',
+ `b` varchar(1024) AS (ifnull(a,default(a))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('any value',default);
+select * from t1;
+a b
+any value any value
+drop table t1;
+set sql_warnings = 0;
+# INET_ATON(), INET_NTOA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (inet_ntoa(inet_aton(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (inet_ntoa(inet_aton(a))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('127.0.0.1',default);
+select * from t1;
+a b
+127.0.0.1 127.0.0.1
+drop table t1;
+set sql_warnings = 0;
+# MD5()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varbinary(32) as (md5(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varbinary(32) AS (md5(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('testing',default);
+select * from t1;
+a b
+testing ae2b1fca515949e5d54fb22b8ed95575
+drop table t1;
+set sql_warnings = 0;
+# OLD_PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (old_password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (old_password(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd 7f84554057dd964b
+drop table t1;
+set sql_warnings = 0;
+# PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (password(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd *AAB3E285149C0135D51A520E1940DD3263DC008C
+drop table t1;
+set sql_warnings = 0;
+# SHA1()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha1(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha1(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# SHA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha(a)) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# UNCOMPRESSED_LENGTH()
+set sql_warnings = 1;
+create table t1 (a char, b varchar(1024) as (uncompressed_length(compress(repeat(a,30)))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompressed_length(compress(repeat(a,30)))) VIRTUAL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+insert into t1 values ('a',default);
+select * from t1;
+a b
+a 30
+drop table t1;
+set sql_warnings = 0;
diff --git a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result
new file mode 100644
index 00000000000..a94e220180c
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result
@@ -0,0 +1,2943 @@
+SET @@session.storage_engine = 'MyISAM';
+#
+# NUMERIC FUNCTIONS
+#
+# ABS()
+set sql_warnings = 1;
+create table t1 (a int, b int as (abs(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (abs(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1, default);
+select * from t1;
+a b
+-1 1
+drop table t1;
+set sql_warnings = 0;
+# ACOS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(acos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(acos(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1, default);
+insert into t1 values (1.0001,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 0
+1.0001 NULL
+0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ASIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(asin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(asin(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (0.2, default);
+insert into t1 values (1.0001,default);
+select * from t1;
+a b
+0.2 0.201358
+1.0001 NULL
+drop table t1;
+set sql_warnings = 0;
+#ATAN
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan(a,b),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, c double as (format(atan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `c` double AS (format(atan(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-2,default);
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a c
+-2 -1.107149
+3.141593 1.262627
+drop table t1;
+set sql_warnings = 0;
+# ATAN2
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(atan2(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(atan2(a,b),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-2,2,default);
+insert into t1 values (format(PI(),6),0,default);
+select * from t1;
+a b c
+-2 2 -0.785398
+3.141593 0 1.570796
+drop table t1;
+set sql_warnings = 0;
+# CEIL()
+set sql_warnings = 1;
+create table t1 (a double, b int as (ceil(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (ceil(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 2
+-1.23 -1
+drop table t1;
+set sql_warnings = 0;
+# CONV()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int, c int, d varchar(10) as (conv(a,b,c)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (conv(a,b,c)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a',16,2,default);
+insert into t1 values ('6e',18,8,default);
+insert into t1 values (-17,10,-18,default);
+insert into t1 values (10+'10'+'10'+0xa,10,10,default);
+select * from t1;
+a b c d
+a 16 2 1010
+6e 18 8 172
+-17 10 -18 -H
+40 10 10 40
+drop table t1;
+set sql_warnings = 0;
+# COS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cos(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cos(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+select * from t1;
+a b
+3.141593 -1
+drop table t1;
+set sql_warnings = 0;
+# COT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(cot(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(cot(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+12 -1.572673
+0 NULL
+drop table t1;
+set sql_warnings = 0;
+# CRC32()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (crc32(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (crc32(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('mysql',default);
+select * from t1;
+a b
+MySQL 3259397556
+mysql 2501908538
+drop table t1;
+set sql_warnings = 0;
+# DEGREES()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(degrees(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(degrees(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+3.141593 180.00002
+1.570796 89.999981
+drop table t1;
+set sql_warnings = 0;
+# /
+set sql_warnings = 1;
+create table t1 (a double, b double as (a/2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a/2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# EXP()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(exp(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(exp(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+2 7.389056
+-2 0.135335
+0 1
+drop table t1;
+set sql_warnings = 0;
+# FLOOR()
+set sql_warnings = 1;
+create table t1 (a double, b long as (floor(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` mediumtext AS (floor(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.23,default);
+insert into t1 values (-1.23,default);
+select * from t1;
+a b
+1.23 1
+-1.23 -2
+drop table t1;
+set sql_warnings = 0;
+# LN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(ln(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(ln(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG()
+set sql_warnings = 1;
+create table t1 (a double, b double, c double as (format(log(a,b),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` double AS (format(log(a,b),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,65536,default);
+insert into t1 values (10,100,default);
+insert into t1 values (1,100,default);
+select * from t1;
+a b c
+2 65536 16
+10 100 2
+1 100 NULL
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (-2,default);
+select * from t1;
+a b
+2 0.693147
+-2 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG2()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log2(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log2(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (65536,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+65536 16
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# LOG10()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(log10(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(log10(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+insert into t1 values (100,default);
+insert into t1 values (-100,default);
+select * from t1;
+a b
+2 0.30103
+100 2
+-100 NULL
+drop table t1;
+set sql_warnings = 0;
+# -
+set sql_warnings = 1;
+create table t1 (a double, b double as (a-1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a-1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2,default);
+select * from t1;
+a b
+2 1
+drop table t1;
+set sql_warnings = 0;
+# MOD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (mod(a,10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (mod(a,10)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# %
+set sql_warnings = 1;
+create table t1 (a int, b int as (a % 10));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a % 10) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (11,default);
+select * from t1;
+a b
+1 1
+11 1
+drop table t1;
+set sql_warnings = 0;
+# OCT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(10) as (oct(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(10) AS (oct(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 14
+drop table t1;
+set sql_warnings = 0;
+# PI()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(PI()*a*a,6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(PI()*a*a,6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 3.141593
+drop table t1;
+set sql_warnings = 0;
+# +
+set sql_warnings = 1;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+select * from t1;
+a b
+1 2
+drop table t1;
+set sql_warnings = 0;
+# POW, POWER
+set sql_warnings = 1;
+create table t1 (a int, b int as (pow(a,2)), c int as (power(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (pow(a,2)) VIRTUAL,
+ `c` int(11) AS (power(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default,default);
+insert into t1 values (2,default,default);
+select * from t1;
+a b c
+1 1 1
+2 4 4
+drop table t1;
+set sql_warnings = 0;
+# RADIANS()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(radians(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(radians(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (90,default);
+select * from t1;
+a b
+90 1.570796
+drop table t1;
+set sql_warnings = 0;
+# ROUND()
+set sql_warnings = 1;
+create table t1 (a double, b int as (round(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (round(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1.23,default);
+insert into t1 values (-1.58,default);
+insert into t1 values (1.58,default);
+select * from t1;
+a b
+-1.23 -1
+-1.58 -2
+1.58 2
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a double, b double, c int as (round(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double DEFAULT NULL,
+ `c` int(11) AS (round(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.298,1,default);
+insert into t1 values (1.298,0,default);
+insert into t1 values (23.298,-1,default);
+select * from t1;
+a b c
+1.298 1 1
+1.298 0 1
+23.298 -1 20
+drop table t1;
+set sql_warnings = 0;
+# SIGN()
+set sql_warnings = 1;
+create table t1 (a double, b int as (sign(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` int(11) AS (sign(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-32,default);
+insert into t1 values (0,default);
+insert into t1 values (234,default);
+select * from t1;
+a b
+-32 -1
+0 0
+234 1
+drop table t1;
+set sql_warnings = 0;
+# SIN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sin(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sin(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI()/2,6),default);
+select * from t1;
+a b
+1.570796 1
+drop table t1;
+set sql_warnings = 0;
+# SQRT()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(sqrt(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(sqrt(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (4,default);
+insert into t1 values (20,default);
+insert into t1 values (-16,default);
+select * from t1;
+a b
+4 2
+20 4.472136
+-16 NULL
+drop table t1;
+set sql_warnings = 0;
+# TAN()
+set sql_warnings = 1;
+create table t1 (a double, b double as (format(tan(a),6)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (format(tan(a),6)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (format(PI(),6),default);
+insert into t1 values (format(PI()+1,6),default);
+select * from t1;
+a b
+3.141593 0
+4.141593 1.557409
+drop table t1;
+set sql_warnings = 0;
+# *
+set sql_warnings = 1;
+create table t1 (a double, b double as (a*3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (a*3) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 0
+1 3
+2 6
+drop table t1;
+set sql_warnings = 0;
+# TRUNCATE()
+set sql_warnings = 1;
+create table t1 (a double, b double as (truncate(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (truncate(a,4)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1.223,default);
+insert into t1 values (1.999,default);
+insert into t1 values (1.999,default);
+insert into t1 values (122,default);
+select * from t1;
+a b
+1.223 1.223
+1.999 1.999
+1.999 1.999
+122 122
+drop table t1;
+set sql_warnings = 0;
+# Unary -
+set sql_warnings = 1;
+create table t1 (a double, b double as (-a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` double AS (-a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 -1
+-1 1
+drop table t1;
+set sql_warnings = 0;
+#
+# STRING FUNCTIONS
+#
+# ASCII()
+set sql_warnings = 1;
+create table t1 (a char(2), b int as (ascii(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(2) DEFAULT NULL,
+ `b` int(11) AS (ascii(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+insert into t1 values (2,default);
+insert into t1 values ('dx',default);
+select * from t1;
+a b
+2 50
+2 50
+dx 100
+drop table t1;
+set sql_warnings = 0;
+# BIN()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (bin(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (bin(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 1100
+drop table t1;
+set sql_warnings = 0;
+# BIT_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (bit_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (bit_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 32
+drop table t1;
+set sql_warnings = 0;
+# CHAR_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (char_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (char_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CHAR()
+set sql_warnings = 1;
+create table t1 (a int, b int, c varbinary(10) as (char(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` varbinary(10) AS (char(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (77,121,default);
+select * from t1;
+a b c
+77 121 My
+drop table t1;
+set sql_warnings = 0;
+# CHARACTER_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (character_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (character_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# CONCAT_WS()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat_ws(',',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat_ws(',',a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# CONCAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (concat(a,',',b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (concat(a,',',b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',default);
+select * from t1;
+a b c
+value1 value2 value1,value2
+drop table t1;
+set sql_warnings = 0;
+# ELT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(10) as (elt(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(10) AS (elt(c,a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('value1','value2',1,default);
+insert into t1 values ('value1','value2',2,default);
+select * from t1;
+a b c d
+value1 value2 1 value1
+value1 value2 2 value2
+drop table t1;
+set sql_warnings = 0;
+# EXPORT_SET()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (export_set(a,'1','0','',10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (export_set(a,'1','0','',10)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (6,default);
+select * from t1;
+a b
+6 0110000000
+drop table t1;
+set sql_warnings = 0;
+# FIELD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (field('aa',a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (field('aa',a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('aa','bb',default);
+insert into t1 values ('bb','aa',default);
+select * from t1;
+a b c
+aa bb 1
+bb aa 2
+drop table t1;
+set sql_warnings = 0;
+# FIND_IN_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (find_in_set(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (find_in_set(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('aa','aa,bb,cc',default);
+insert into t1 values ('aa','bb,aa,cc',default);
+select * from t1;
+a b c
+aa aa,bb,cc 1
+aa bb,aa,cc 2
+drop table t1;
+set sql_warnings = 0;
+# FORMAT()
+set sql_warnings = 1;
+create table t1 (a double, b varchar(20) as (format(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` double DEFAULT NULL,
+ `b` varchar(20) AS (format(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12332.123456,default);
+select * from t1;
+a b
+12332.123456 12,332.12
+drop table t1;
+set sql_warnings = 0;
+# HEX()
+set sql_warnings = 1;
+create table t1 (a int, b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (17,default);
+select * from t1;
+a b
+17 11
+drop table t1;
+set sql_warnings = 0;
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (hex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (hex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 616263
+drop table t1;
+set sql_warnings = 0;
+# INSERT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(20) as (insert(a,length(a),length(b),b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(20) AS (insert(a,length(a),length(b),b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('start,','end',default);
+select * from t1;
+a b c
+start, end startend
+drop table t1;
+set sql_warnings = 0;
+# INSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int as (instr(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) AS (instr(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar,','bar',default);
+insert into t1 values ('xbar,','foobar',default);
+select * from t1;
+a b c
+foobarbar, bar 4
+xbar, foobar 0
+drop table t1;
+set sql_warnings = 0;
+# LCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lcase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lcase(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LEFT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(5) as (left(a,5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(5) AS (left(a,5)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fooba
+drop table t1;
+set sql_warnings = 0;
+# LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a like 'H%o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# LOCATE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (locate('bar',a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (locate('bar',a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# LOWER()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lower(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lower(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL mysql
+drop table t1;
+set sql_warnings = 0;
+# LPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (lpad(a,4,' ')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (lpad(a,4,' ')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+insert into t1 values ('M',default);
+select * from t1;
+a b
+MySQL MySQ
+M M
+drop table t1;
+set sql_warnings = 0;
+# LTRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (ltrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (ltrim(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (' MySQL',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+ MySQL MySQL
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# MAKE_SET()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c int, d varchar(30) as (make_set(c,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(30) AS (make_set(c,a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',1,default);
+insert into t1 values ('a','b',3,default);
+select * from t1;
+a b c d
+a b 1 a
+a b 3 a,b
+drop table t1;
+set sql_warnings = 0;
+# MID()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (mid(a,1,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (mid(a,1,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar fo
+drop table t1;
+set sql_warnings = 0;
+# NOT LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not like 'H%o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not like 'H%o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 0
+MySQL 1
+drop table t1;
+set sql_warnings = 0;
+# NOT REGEXP
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a not regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a not regexp 'H.+o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 0
+hello 0
+drop table t1;
+set sql_warnings = 0;
+# OCTET_LENGTH()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b int as (octet_length(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` int(11) AS (octet_length(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('text',default);
+select * from t1;
+a b
+text 4
+drop table t1;
+set sql_warnings = 0;
+# ORD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b long as (ord(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` mediumtext AS (ord(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2',default);
+select * from t1;
+a b
+2 50
+drop table t1;
+set sql_warnings = 0;
+# POSITION()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (position('bar' in a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (position('bar' in a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar 4
+drop table t1;
+set sql_warnings = 0;
+# QUOTE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (quote(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (quote(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Don\'t',default);
+select * from t1;
+a b
+Don't 'Don\'t'
+drop table t1;
+set sql_warnings = 0;
+# REGEXP()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a regexp 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a regexp 'H.+o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('hello',default);
+select * from t1;
+a b
+Hello 1
+hello 1
+drop table t1;
+set sql_warnings = 0;
+# REPEAT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (repeat(a,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (repeat(a,3)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQLMySQLMySQL
+drop table t1;
+set sql_warnings = 0;
+# REPLACE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (replace(a,'aa','bb')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (replace(a,'aa','bb')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa mbb
+drop table t1;
+set sql_warnings = 0;
+# REVERSE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(30) as (reverse(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(30) AS (reverse(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('maa',default);
+select * from t1;
+a b
+maa aam
+drop table t1;
+set sql_warnings = 0;
+# RIGHT()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (right(a,4)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (right(a,4)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('foobarbar',default);
+select * from t1;
+a b
+foobarbar rbar
+drop table t1;
+set sql_warnings = 0;
+# RLIKE()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b bool as (a rlike 'H.+o'));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` tinyint(1) AS (a rlike 'H.+o') VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+Hello 1
+MySQL 0
+drop table t1;
+set sql_warnings = 0;
+# RPAD()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rpad(a,4,'??')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rpad(a,4,'??')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('He',default);
+select * from t1;
+a b
+He He??
+drop table t1;
+set sql_warnings = 0;
+# RTRIM();
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (rtrim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (rtrim(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello ',default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# SOUNDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(20) as (soundex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(20) AS (soundex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello H400
+drop table t1;
+set sql_warnings = 0;
+# SOUNDS LIKE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a sounds like b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a sounds like b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello',default);
+insert into t1 values ('Hello','MySQL',default);
+insert into t1 values ('Hello','hello',default);
+select * from t1;
+a b c
+Hello Hello 1
+Hello MySQL 0
+Hello hello 1
+drop table t1;
+set sql_warnings = 0;
+# SPACE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (concat(a,space(5))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (concat(a,space(5))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello', default);
+select * from t1;
+a b
+Hello Hello
+drop table t1;
+set sql_warnings = 0;
+# STRCMP()
+set sql_warnings = 1;
+create table t1 (a varchar(9), b varchar(9), c tinyint(1) as (strcmp(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(9) DEFAULT NULL,
+ `b` varchar(9) DEFAULT NULL,
+ `c` tinyint(1) AS (strcmp(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello','Hello', default);
+insert into t1 values ('Hello','Hello1', default);
+select * from t1;
+a b c
+Hello Hello 0
+Hello Hello1 -1
+drop table t1;
+set sql_warnings = 0;
+# SUBSTR()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substr(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substr(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello ello
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING_INDEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (substring_index(a,'.',2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (substring_index(a,'.',2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('www.mysql.com',default);
+select * from t1;
+a b
+www.mysql.com www.mysql
+drop table t1;
+set sql_warnings = 0;
+# SUBSTRING()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (substring(a from 2 for 2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (substring(a from 2 for 2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('Hello',default);
+select * from t1;
+a b
+Hello el
+drop table t1;
+set sql_warnings = 0;
+# TRIM()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (trim(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (trim(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (' aa ',default);
+select * from t1;
+a b
+ aa aa
+drop table t1;
+set sql_warnings = 0;
+# UCASE()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (ucase(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (ucase(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+# UNHEX()
+set sql_warnings = 1;
+create table t1 (a varchar(15), b varchar(10) as (unhex(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(15) DEFAULT NULL,
+ `b` varchar(10) AS (unhex(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('4D7953514C',default);
+select * from t1;
+a b
+4D7953514C MySQL
+drop table t1;
+set sql_warnings = 0;
+# UPPER()
+set sql_warnings = 1;
+create table t1 (a varchar(5), b varchar(10) as (upper(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(5) DEFAULT NULL,
+ `b` varchar(10) AS (upper(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MYSQL
+drop table t1;
+set sql_warnings = 0;
+#
+# CONTROL FLOW FUNCTIONS
+#
+# CASE
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(16) as (case a when NULL then 'asd' when 'b' then 'B' else a end));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(16) AS (case a when NULL then 'asd' when 'b' then 'B' else a end) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (NULL,default);
+insert into t1 values ('b',default);
+insert into t1 values ('c',default);
+select * from t1;
+a b
+NULL NULL
+b B
+c c
+drop table t1;
+set sql_warnings = 0;
+# IF
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (if(a=1,a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (if(a=1,a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,2,default);
+insert into t1 values (3,4,default);
+select * from t1;
+a b c
+1 2 1
+3 4 4
+drop table t1;
+set sql_warnings = 0;
+# IFNULL
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c varchar(10) as (ifnull(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` varchar(10) AS (ifnull(a,'DEFAULT')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (NULL,'adf',default);
+insert into t1 values ('a','adf',default);
+select * from t1;
+a b c
+NULL adf DEFAULT
+a adf a
+drop table t1;
+set sql_warnings = 0;
+# NULLIF
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10) as (nullif(a,'DEFAULT')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) AS (nullif(a,'DEFAULT')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('DEFAULT',default);
+insert into t1 values ('a',default);
+select * from t1;
+a b
+DEFAULT NULL
+a a
+drop table t1;
+set sql_warnings = 0;
+#
+# OPERATORS
+#
+# AND, &&
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a>0 && a<2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a>0 && a<2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a between 0 and 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 0
+1 1
+drop table t1;
+set sql_warnings = 0;
+# BINARY
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varbinary(10) as (binary a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varbinary(10) AS (binary a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('11',default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+11 11
+1 1
+drop table t1;
+set sql_warnings = 0;
+# &
+set sql_warnings = 1;
+create table t1 (a int, b int as (a & 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a & 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+select * from t1;
+a b
+1 1
+0 0
+drop table t1;
+set sql_warnings = 0;
+# ~
+set sql_warnings = 1;
+create table t1 (a int, b int as (~a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (~a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+Warnings:
+Warning 1264 Out of range value for column 'b' at row 1
+select * from t1;
+a b
+1 2147483647
+drop table t1;
+set sql_warnings = 0;
+# |
+set sql_warnings = 1;
+create table t1 (a int, b int as (a | 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a | 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 5
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# ^
+set sql_warnings = 1;
+create table t1 (a int, b int as (a ^ 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a ^ 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (0,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+1 4
+0 5
+2 7
+drop table t1;
+set sql_warnings = 0;
+# DIV
+set sql_warnings = 1;
+create table t1 (a int, b int as (a div 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a div 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (7,default);
+select * from t1;
+a b
+1 0
+7 1
+drop table t1;
+set sql_warnings = 0;
+# <=>
+set sql_warnings = 1;
+create table t1 (a int, b int, c bool as (a <=> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` tinyint(1) AS (a <=> b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,1,default);
+insert into t1 values (NULL,NULL,default);
+insert into t1 values (1,NULL,default);
+select * from t1;
+a b c
+1 1 1
+NULL NULL 1
+1 NULL 0
+drop table t1;
+set sql_warnings = 0;
+# =
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a=b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a=b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a >= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a >= b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 1
+drop table t1;
+set sql_warnings = 0;
+# >
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a > b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a > b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a','b',default);
+insert into t1 values ('a','a',default);
+select * from t1;
+a b c
+a b 0
+a a 0
+drop table t1;
+set sql_warnings = 0;
+# IS NOT NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is not null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is not null) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 1
+NULL 0
+drop table t1;
+set sql_warnings = 0;
+# IS NULL
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a is null));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a is null) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (NULL,default);
+select * from t1;
+a b
+1 0
+NULL 1
+drop table t1;
+set sql_warnings = 0;
+# <<
+set sql_warnings = 1;
+create table t1 (a int, b int as (a << 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a << 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+1 4
+3 12
+drop table t1;
+set sql_warnings = 0;
+# <=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <= b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <= b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 1
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# <
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a < b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a < b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 0
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# NOT BETWEEN ... AND ...
+set sql_warnings = 1;
+create table t1 (a int, b bool as (a not between 0 and 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` tinyint(1) AS (a not between 0 and 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (-1,default);
+insert into t1 values (1,default);
+select * from t1;
+a b
+-1 1
+1 0
+drop table t1;
+set sql_warnings = 0;
+# <>
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a <> b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a <> b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# !=
+set sql_warnings = 1;
+create table t1 (a varchar(10), b varchar(10), c bool as (a != b));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL,
+ `c` tinyint(1) AS (a != b) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('b','a',default);
+insert into t1 values ('b','b',default);
+insert into t1 values ('b','c',default);
+select * from t1;
+a b c
+b a 1
+b b 0
+b c 1
+drop table t1;
+set sql_warnings = 0;
+# ||, OR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a>5 || a<3));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a>5 || a<3) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (4,default);
+select * from t1;
+a b
+1 1
+4 0
+drop table t1;
+set sql_warnings = 0;
+# >>
+set sql_warnings = 1;
+create table t1 (a int, b int as (a >> 2));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a >> 2) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (8,default);
+insert into t1 values (3,default);
+select * from t1;
+a b
+8 2
+3 0
+drop table t1;
+set sql_warnings = 0;
+# XOR
+set sql_warnings = 1;
+create table t1 (a int, b int as (a xor 5));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a xor 5) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (0,default);
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+a b
+0 1
+1 0
+2 0
+drop table t1;
+set sql_warnings = 0;
+#
+# DATE AND TIME FUNCTIONS
+#
+# ADDDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (adddate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (adddate(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# ADDTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (addtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (addtime(a,'02:00:00')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-31 02:00:00
+drop table t1;
+set sql_warnings = 0;
+# CONVERT_TZ()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (convert_tz(a,'MET','UTC')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (convert_tz(a,'MET','UTC')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_ADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_add(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_add(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-09-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(64) as (date_format(a,'%W %M %D')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(64) AS (date_format(a,'%W %M %D')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday August 31st
+drop table t1;
+set sql_warnings = 0;
+# DATE_SUB()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date_sub(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date_sub(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (date(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (date(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:00:00',default);
+select * from t1;
+a b
+2008-08-31 02:00:00 2008-08-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# DATEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (datediff(a,'2000-01-01')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (datediff(a,'2000-01-01')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3165
+drop table t1;
+set sql_warnings = 0;
+# DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (day(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(10) as (dayname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(10) AS (dayname(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 Sunday
+drop table t1;
+set sql_warnings = 0;
+# DAYOFMONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofmonth(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofmonth(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31
+drop table t1;
+set sql_warnings = 0;
+# DAYOFWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofweek(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 1
+drop table t1;
+set sql_warnings = 0;
+# DAYOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (dayofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (dayofyear(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 244
+drop table t1;
+set sql_warnings = 0;
+# EXTRACT
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (extract(year from a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (extract(year from a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# FROM_DAYS()
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_days(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (730669,default);
+select * from t1;
+a b
+730669 2000-07-03 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# FROM_UNIXTIME()
+set time_zone='UTC';
+set sql_warnings = 1;
+create table t1 (a long, b datetime as (from_unixtime(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` datetime AS (from_unixtime(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1196440219,default);
+select * from t1;
+a b
+1196440219 2007-11-30 16:30:19
+drop table t1;
+set sql_warnings = 0;
+# GET_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (date_format(a,get_format(DATE,'EUR'))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (date_format(a,get_format(DATE,'EUR'))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 31.08.2008
+drop table t1;
+set sql_warnings = 0;
+# HOUR()
+set sql_warnings = 1;
+create table t1 (a time, b long as (hour(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (hour(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+10:05:03 10
+drop table t1;
+set sql_warnings = 0;
+# LAST_DAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (last_day(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (last_day(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-05',default);
+insert into t1 values ('2003-02-32',default);
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+select * from t1;
+a b
+2003-02-05 00:00:00 2003-02-28 00:00:00
+0000-00-00 00:00:00 NULL
+drop table t1;
+set sql_warnings = 0;
+# MAKEDATE()
+set sql_warnings = 1;
+create table t1 (a int, b datetime as (makedate(a,1)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` datetime AS (makedate(a,1)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2001,default);
+select * from t1;
+a b
+2001 2001-01-01 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# MAKETIME()
+set sql_warnings = 1;
+create table t1 (a int, b time as (maketime(a,1,3)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` time AS (maketime(a,1,3)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (12,default);
+select * from t1;
+a b
+12 12:01:03
+drop table t1;
+set sql_warnings = 0;
+# MICROSECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (microsecond(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (microsecond(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 12:00:00.123456',default);
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 12:00:00 0
+2009-12-31 23:59:59 0
+drop table t1;
+set sql_warnings = 0;
+# MINUTE()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (minute(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (minute(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 59
+drop table t1;
+set sql_warnings = 0;
+# MONTH()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (month(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (month(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 12
+drop table t1;
+set sql_warnings = 0;
+# MONTHNAME()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(16) as (monthname(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(16) AS (monthname(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2009-12-31 23:59:59.000010',default);
+select * from t1;
+a b
+2009-12-31 23:59:59 December
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_ADD()
+set sql_warnings = 1;
+create table t1 (a int, b int as (period_add(a,2)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (period_add(a,2)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (200801,default);
+select * from t1;
+a b
+200801 200803
+drop table t1;
+set sql_warnings = 0;
+# PERIOD_DIFF()
+set sql_warnings = 1;
+create table t1 (a int, b int, c int as (period_diff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) AS (period_diff(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (200802,200703,default);
+select * from t1;
+a b c
+200802 200703 11
+drop table t1;
+set sql_warnings = 0;
+# QUARTER()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (quarter(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (quarter(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# SEC_TO_TIME()
+set sql_warnings = 1;
+create table t1 (a long, b time as (sec_to_time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` mediumtext,
+ `b` time AS (sec_to_time(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (2378,default);
+select * from t1;
+a b
+2378 00:39:38
+drop table t1;
+set sql_warnings = 0;
+# SECOND()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (second(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (second(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('10:05:03',default);
+select * from t1;
+a b
+2010-05-03 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# STR_TO_DATE()
+set sql_warnings = 1;
+create table t1 (a varchar(64), b datetime as (str_to_date(a,'%m/%d/%Y')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(64) DEFAULT NULL,
+ `b` datetime AS (str_to_date(a,'%m/%d/%Y')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('04/30/2004',default);
+select * from t1;
+a b
+04/30/2004 2004-04-30 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBDATE()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subdate(a,interval 1 month)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subdate(a,interval 1 month)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-07-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# SUBTIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime as (subtime(a,'02:00:00')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime AS (subtime(a,'02:00:00')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31',default);
+select * from t1;
+a b
+2008-08-31 00:00:00 2008-08-30 22:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIME_FORMAT()
+set sql_warnings = 1;
+create table t1 (a datetime, b varchar(32) as (time_format(a,'%r')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` varchar(32) AS (time_format(a,'%r')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04 AM
+drop table t1;
+set sql_warnings = 0;
+# TIME_TO_SEC()
+set sql_warnings = 1;
+create table t1 (a time, b long as (time_to_sec(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` time DEFAULT NULL,
+ `b` mediumtext AS (time_to_sec(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('22:23:00',default);
+select * from t1;
+a b
+22:23:00 80580
+drop table t1;
+set sql_warnings = 0;
+# TIME()
+set sql_warnings = 1;
+create table t1 (a datetime, b time as (time(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` time AS (time(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-08-31 02:03:04',default);
+select * from t1;
+a b
+2008-08-31 02:03:04 02:03:04
+drop table t1;
+set sql_warnings = 0;
+# TIMEDIFF()
+set sql_warnings = 1;
+create table t1 (a datetime, b datetime, c long as (timediff(a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` datetime DEFAULT NULL,
+ `c` mediumtext AS (timediff(a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31 23:59:59.000001','2008-12-30 01:01:01.000002',default);
+select * from t1;
+a b c
+2008-12-31 23:59:59 2008-12-30 01:01:01 46:58:58
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMP()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestamp(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestamp(a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-12-31',default);
+select * from t1;
+a b
+2008-12-31 00:00:00 2008-12-31 00:00:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPADD()
+set sql_warnings = 1;
+create table t1 (a datetime, b timestamp as (timestampadd(minute,1,a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2003-01-02',default);
+select * from t1;
+a b
+2003-01-02 00:00:00 2003-01-02 00:01:00
+drop table t1;
+set sql_warnings = 0;
+# TIMESTAMPDIFF()
+set sql_warnings = 1;
+create table t1 (a timestamp, b timestamp, c long as (timestampdiff(MONTH, a,b)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `b` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `c` mediumtext AS (timestampdiff(MONTH, a,b)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2003-02-01','2003-05-01',default);
+select * from t1;
+a b c
+2003-02-01 00:00:00 2003-05-01 00:00:00 3
+drop table t1;
+set sql_warnings = 0;
+# TO_DAYS()
+set sql_warnings = 1;
+create table t1 (a datetime, b long as (to_days(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` mediumtext AS (to_days(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2007-10-07',default);
+select * from t1;
+a b
+2007-10-07 00:00:00 733321
+drop table t1;
+set sql_warnings = 0;
+# WEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (week(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (week(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 35
+drop table t1;
+set sql_warnings = 0;
+# WEEKDAY()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekday(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekday(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 0
+drop table t1;
+set sql_warnings = 0;
+# WEEKOFYEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (weekofyear(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (weekofyear(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 36
+drop table t1;
+set sql_warnings = 0;
+# YEAR()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (year(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (year(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 2008
+drop table t1;
+set sql_warnings = 0;
+# YEARWEEK()
+set sql_warnings = 1;
+create table t1 (a datetime, b int as (yearweek(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` datetime DEFAULT NULL,
+ `b` int(11) AS (yearweek(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2008-09-01',default);
+select * from t1;
+a b
+2008-09-01 00:00:00 200835
+drop table t1;
+set sql_warnings = 0;
+#
+# FULL TEXT SEARCH FUNCTIONS
+#
+# None.
+#
+# CAST FUNCTIONS AND OPERATORS
+#
+# CAST()
+set sql_warnings = 1;
+create table t1 (a int, b long as (cast(a as unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (cast(a as unsigned)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+# Convert()
+set sql_warnings = 1;
+create table t1 (a int, b long as (convert(a,unsigned)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` mediumtext AS (convert(a,unsigned)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (1,default);
+insert into t1 values (-1,default);
+select * from t1;
+a b
+1 1
+-1 18446744073709551615
+drop table t1;
+set sql_warnings = 0;
+#
+# XML FUNCTIONS
+#
+# None.
+#
+# OTHER FUNCTIONS
+#
+# AES_DECRYPT(), AES_ENCRYPT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (aes_encrypt(aes_decrypt(a,'adf'),'adf')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (aes_encrypt(aes_decrypt(a,'adf'),'adf')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL NULL
+drop table t1;
+set sql_warnings = 0;
+# BIT_COUNT()
+set sql_warnings = 1;
+create table t1 (a int, b int as (bit_count(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (bit_count(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values (5,default);
+select * from t1;
+a b
+5 2
+drop table t1;
+set sql_warnings = 0;
+# CHARSET()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (charset(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (charset(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1
+drop table t1;
+set sql_warnings = 0;
+# COERCIBILITY()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b int as (coercibility(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` int(11) AS (coercibility(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc 2
+drop table t1;
+set sql_warnings = 0;
+# COLLATION()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (collation(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (collation(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc latin1_swedish_ci
+drop table t1;
+set sql_warnings = 0;
+# COMPRESS(), UNCOMPRESS()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (uncompress(compress(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompress(compress(a))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# ENCODE(), DECODE()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (decode(encode(a,'abc'),'abc')));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (decode(encode(a,'abc'),'abc')) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('MySQL',default);
+select * from t1;
+a b
+MySQL MySQL
+drop table t1;
+set sql_warnings = 0;
+# DEFAULT()
+set sql_warnings = 1;
+create table t1 (a varchar(1024) default 'aaa', b varchar(1024) as (ifnull(a,default(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT 'aaa',
+ `b` varchar(1024) AS (ifnull(a,default(a))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('any value',default);
+select * from t1;
+a b
+any value any value
+drop table t1;
+set sql_warnings = 0;
+# INET_ATON(), INET_NTOA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (inet_ntoa(inet_aton(a))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (inet_ntoa(inet_aton(a))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('127.0.0.1',default);
+select * from t1;
+a b
+127.0.0.1 127.0.0.1
+drop table t1;
+set sql_warnings = 0;
+# MD5()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varbinary(32) as (md5(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varbinary(32) AS (md5(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('testing',default);
+select * from t1;
+a b
+testing ae2b1fca515949e5d54fb22b8ed95575
+drop table t1;
+set sql_warnings = 0;
+# OLD_PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (old_password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (old_password(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd 7f84554057dd964b
+drop table t1;
+set sql_warnings = 0;
+# PASSWORD()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (password(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (password(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('badpwd',default);
+select * from t1;
+a b
+badpwd *AAB3E285149C0135D51A520E1940DD3263DC008C
+drop table t1;
+set sql_warnings = 0;
+# SHA1()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha1(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha1(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# SHA()
+set sql_warnings = 1;
+create table t1 (a varchar(1024), b varchar(1024) as (sha(a)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1024) DEFAULT NULL,
+ `b` varchar(1024) AS (sha(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc',default);
+select * from t1;
+a b
+abc a9993e364706816aba3e25717850c26c9cd0d89d
+drop table t1;
+set sql_warnings = 0;
+# UNCOMPRESSED_LENGTH()
+set sql_warnings = 1;
+create table t1 (a char, b varchar(1024) as (uncompressed_length(compress(repeat(a,30)))));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(1) DEFAULT NULL,
+ `b` varchar(1024) AS (uncompressed_length(compress(repeat(a,30)))) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('a',default);
+select * from t1;
+a b
+a 30
+drop table t1;
+set sql_warnings = 0;
diff --git a/mysql-test/suite/vcol/r/vcol_syntax.result b/mysql-test/suite/vcol/r/vcol_syntax.result
new file mode 100644
index 00000000000..8515d790359
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_syntax.result
@@ -0,0 +1,52 @@
+drop table if exists t1;
+set @OLD_SQL_MODE=@@SESSION.SQL_MODE;
+create table t1 (a int, b int generated always as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int as (a+1) virtual);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) AS (a+1) PERSISTENT
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set session sql_mode='ORACLE';
+create table t1 (a int, b int as (a+1));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) DEFAULT NULL,
+ "b" int(11) AS (a+1) VIRTUAL
+)
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) virtual);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) DEFAULT NULL,
+ "b" int(11) AS (a+1) VIRTUAL
+)
+drop table t1;
+create table t1 (a int, b int as (a+1) persistent);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" int(11) DEFAULT NULL,
+ "b" int(11) AS (a+1) PERSISTENT
+)
+drop table t1;
+set session sql_mode=@OLD_SQL_MODE;
diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
new file mode 100644
index 00000000000..e903bc4eafd
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
@@ -0,0 +1,87 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int,
+b int as (a/10),
+c int as (a/10) persistent);
+create table t2 (a timestamp);
+create trigger trg1 before insert on t1 for each row
+begin
+if (new.b < 10) then
+set new.a:= 100;
+set new.b:= 9;
+set new.c:= 9;
+end if;
+if (new.c > 50) then
+set new.a:= 500;
+end if;
+end|
+create trigger trg2 after insert on t1 for each row
+begin
+if (new.b >= 60) then
+insert into t2 values (now());
+end if;
+end|
+create function f1()
+returns int
+begin
+declare sum1 int default '0';
+declare cur1 cursor for select sum(b) from t1;
+open cur1;
+fetch cur1 into sum1;
+close cur1;
+return sum1;
+end|
+set sql_warnings = 1;
+insert into t1 (a) values (200);
+select * from t1;
+a b c
+200 20 20
+select * from t2;
+a
+insert into t1 (a) values (10);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+select * from t2;
+a
+insert into t1 (a) values (600);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+500 50 50
+select * from t2;
+a
+select f1();
+f1()
+80
+set sql_warnings = 0;
+drop trigger trg1;
+drop trigger trg2;
+drop table t2;
+create procedure p1()
+begin
+declare i int default '0';
+create table t2 like t1;
+insert into t2 (a) values (100), (200);
+begin
+declare cur1 cursor for select sum(c) from t2;
+open cur1;
+fetch cur1 into i;
+close cur1;
+if (i=30) then
+insert into t1 values (300,default,default);
+end if;
+end;
+end|
+delete from t1;
+call p1();
+select * from t2;
+a b c
+100 10 10
+200 20 20
+select * from t1;
+a b c
+300 30 30
+drop table t1,t2;
+drop procedure p1;
diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
new file mode 100644
index 00000000000..c2a66d656b5
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
@@ -0,0 +1,87 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int,
+b int as (a/10),
+c int as (a/10) persistent);
+create table t2 (a timestamp);
+create trigger trg1 before insert on t1 for each row
+begin
+if (new.b < 10) then
+set new.a:= 100;
+set new.b:= 9;
+set new.c:= 9;
+end if;
+if (new.c > 50) then
+set new.a:= 500;
+end if;
+end|
+create trigger trg2 after insert on t1 for each row
+begin
+if (new.b >= 60) then
+insert into t2 values (now());
+end if;
+end|
+create function f1()
+returns int
+begin
+declare sum1 int default '0';
+declare cur1 cursor for select sum(b) from t1;
+open cur1;
+fetch cur1 into sum1;
+close cur1;
+return sum1;
+end|
+set sql_warnings = 1;
+insert into t1 (a) values (200);
+select * from t1;
+a b c
+200 20 20
+select * from t2;
+a
+insert into t1 (a) values (10);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+select * from t2;
+a
+insert into t1 (a) values (600);
+select * from t1;
+a b c
+200 20 20
+100 10 10
+500 50 50
+select * from t2;
+a
+select f1();
+f1()
+80
+set sql_warnings = 0;
+drop trigger trg1;
+drop trigger trg2;
+drop table t2;
+create procedure p1()
+begin
+declare i int default '0';
+create table t2 like t1;
+insert into t2 (a) values (100), (200);
+begin
+declare cur1 cursor for select sum(c) from t2;
+open cur1;
+fetch cur1 into i;
+close cur1;
+if (i=30) then
+insert into t1 values (300,default,default);
+end if;
+end;
+end|
+delete from t1;
+call p1();
+select * from t2;
+a b c
+100 10 10
+200 20 20
+select * from t1;
+a b c
+300 30 30
+drop table t1,t2;
+drop procedure p1;
diff --git a/mysql-test/suite/vcol/r/vcol_view_innodb.result b/mysql-test/suite/vcol/r/vcol_view_innodb.result
new file mode 100644
index 00000000000..ae834722606
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_view_innodb.result
@@ -0,0 +1,276 @@
+SET @@session.storage_engine = 'InnoDB';
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (1), (2), (2), (3);
+create view v1 (d,e) as select abs(b), abs(c) from t1;
+select d,e from v1;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+select is_updatable from information_schema.views where table_name='v1';
+is_updatable
+NO
+explain extended select d,e from v1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select abs(`test`.`t1`.`b`) AS `d`,abs(`test`.`t1`.`c`) AS `e` from `test`.`t1`
+create algorithm=temptable view v2 (d,e) as select abs(b), abs(c) from t1;
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select abs(`t1`.`b`) AS `d`,abs(`t1`.`c`) AS `e` from `t1` latin1 latin1_swedish_ci
+select d,e from v2;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+explain extended select d,e from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
+create view v3 (d,e) as select d*2, e*2 from v1;
+select * from v3;
+d e
+2 2
+2 2
+4 4
+4 4
+6 6
+explain extended select * from v3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select (abs(`test`.`t1`.`b`) * 2) AS `d`,(abs(`test`.`t1`.`c`) * 2) AS `e` from `test`.`t1`
+drop view v1,v2,v3;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct b from t1;
+select * from v1;
+b
+-1
+-2
+-3
+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 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+create view v1 as select distinct c from t1;
+select * from v1;
+c
+-1
+-2
+-3
+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 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (4);
+create view v1 as select b+1 from t1 order by 1 desc limit 2;
+select * from v1;
+b+1
+0
+-1
+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 4 Using filesort
+drop view v1;
+create view v1 as select c+1 from t1 order by 1 desc limit 2;
+select * from v1;
+c+1
+0
+-1
+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 4 Using filesort
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int,
+c int as (-a),
+d int as (-a) persistent,
+primary key(a));
+insert into t1 (a,b) values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,e,f,g) as select a, b+1,c+1,d+1 from t1;
+update v1 set a=a+e;
+select * from v1;
+a e f g
+13 3 -12 -12
+24 4 -23 -23
+35 5 -34 -34
+46 6 -45 -45
+61 11 -60 -60
+select * from t1;
+a b c d
+13 2 -13 -13
+24 3 -24 -24
+35 4 -35 -35
+46 5 -46 -46
+61 10 -61 -61
+delete from v1;
+select * from v1;
+a e f g
+select * from t1;
+a b c d
+insert into v1 (a,e) values (60,15);
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
+drop table t1;
+drop view v1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+primary key(a));
+insert into t1 (a) values (1), (2), (3);
+create view v1 (x,y,z) as select a,b,c from t1 where b < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.b= v1.y);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+create view v1 (x,y,z) as select a,b,c from t1 where c < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.c= v1.z);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a1 int,
+b1 int as (-a1),
+c1 int as (-a1) persistent);
+create table t2 (a2 int,
+b2 int as (-a2),
+c2 int as (-a2) persistent);
+insert into t1 (a1) values (1), (2);
+insert into t2 (a2) values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+a1 b1 c1 a2 b2 c2
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+drop view v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create table t2 like t1;
+create view v1 as select a,b,c from t1;
+create view v2 as select a,b,c from t2 where b in (select b from v1);
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t2` where `t2`.`b` in (select `v1`.`b` from `v1`) latin1 latin1_swedish_ci
+drop view v2, v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1),(1),(2),(2),(3),(3);
+create view v1 as select b from t1;
+select distinct b from v1;
+b
+-1
+-2
+-3
+select distinct b from v1 limit 2;
+b
+-1
+-2
+select distinct b from t1 limit 2;
+b
+-1
+-2
+prepare stmt1 from "select distinct b from v1 limit 2";
+execute stmt1;
+b
+-1
+-2
+execute stmt1;
+b
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+create view v1 as select c from t1;
+select distinct c from v1;
+c
+-1
+-2
+-3
+select distinct c from v1 limit 2;
+c
+-1
+-2
+select distinct c from t1 limit 2;
+c
+-1
+-2
+prepare stmt1 from "select distinct c from v1 limit 2";
+execute stmt1;
+c
+-1
+-2
+execute stmt1;
+c
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create view v1 as select * from t1 where b > -2 && c >-2 with check option;
+insert into v1 (a) values (1);
+insert into v1 (a) values (3);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 (a) values (2),(3),(0);
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a b c
+1 -1 -1
+0 0 0
+drop view v1;
+drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_view_myisam.result b/mysql-test/suite/vcol/r/vcol_view_myisam.result
new file mode 100644
index 00000000000..bd5999792ff
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_view_myisam.result
@@ -0,0 +1,276 @@
+SET @@session.storage_engine = 'MyISAM';
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (1), (2), (2), (3);
+create view v1 (d,e) as select abs(b), abs(c) from t1;
+select d,e from v1;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+select is_updatable from information_schema.views where table_name='v1';
+is_updatable
+NO
+explain extended select d,e from v1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select abs(`test`.`t1`.`b`) AS `d`,abs(`test`.`t1`.`c`) AS `e` from `test`.`t1`
+create algorithm=temptable view v2 (d,e) as select abs(b), abs(c) from t1;
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select abs(`t1`.`b`) AS `d`,abs(`t1`.`c`) AS `e` from `t1` latin1 latin1_swedish_ci
+select d,e from v2;
+d e
+1 1
+1 1
+2 2
+2 2
+3 3
+explain extended select d,e from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
+create view v3 (d,e) as select d*2, e*2 from v1;
+select * from v3;
+d e
+2 2
+2 2
+4 4
+4 4
+6 6
+explain extended select * from v3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00
+Warnings:
+Note 1003 select (abs(`test`.`t1`.`b`) * 2) AS `d`,(abs(`test`.`t1`.`c`) * 2) AS `e` from `test`.`t1`
+drop view v1,v2,v3;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (1), (2), (3);
+create view v1 as select distinct b from t1;
+select * from v1;
+b
+-1
+-2
+-3
+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 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+create view v1 as select distinct c from t1;
+select * from v1;
+c
+-1
+-2
+-3
+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 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
+select * from t1;
+a b c
+1 -1 -1
+2 -2 -2
+3 -3 -3
+1 -1 -1
+2 -2 -2
+3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a int not null,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1), (2), (3), (4);
+create view v1 as select b+1 from t1 order by 1 desc limit 2;
+select * from v1;
+b+1
+0
+-1
+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 4 Using filesort
+drop view v1;
+create view v1 as select c+1 from t1 order by 1 desc limit 2;
+select * from v1;
+c+1
+0
+-1
+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 4 Using filesort
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int,
+c int as (-a),
+d int as (-a) persistent,
+primary key(a));
+insert into t1 (a,b) values (10,2), (20,3), (30,4), (40,5), (50,10);
+create view v1 (a,e,f,g) as select a, b+1,c+1,d+1 from t1;
+update v1 set a=a+e;
+select * from v1;
+a e f g
+13 3 -12 -12
+24 4 -23 -23
+35 5 -34 -34
+46 6 -45 -45
+61 11 -60 -60
+select * from t1;
+a b c d
+13 2 -13 -13
+24 3 -24 -24
+35 4 -35 -35
+46 5 -46 -46
+61 10 -61 -61
+delete from v1;
+select * from v1;
+a e f g
+select * from t1;
+a b c d
+insert into v1 (a,e) values (60,15);
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
+drop table t1;
+drop view v1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent,
+primary key(a));
+insert into t1 (a) values (1), (2), (3);
+create view v1 (x,y,z) as select a,b,c from t1 where b < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.b= v1.y);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+create view v1 (x,y,z) as select a,b,c from t1 where c < -1;
+select t1.a, v1.x, v1.y, v1.z from t1 left join v1 on (t1.c= v1.z);
+a x y z
+1 NULL NULL NULL
+2 2 -2 -2
+3 3 -3 -3
+drop view v1;
+drop table t1;
+create table t1 (a1 int,
+b1 int as (-a1),
+c1 int as (-a1) persistent);
+create table t2 (a2 int,
+b2 int as (-a2),
+c2 int as (-a2) persistent);
+insert into t1 (a1) values (1), (2);
+insert into t2 (a2) values (2), (3);
+create view v1 as select * from t1,t2 union all select * from t1,t2;
+select * from v1;
+a1 b1 c1 a2 b2 c2
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+1 -1 -1 2 -2 -2
+2 -2 -2 2 -2 -2
+1 -1 -1 3 -3 -3
+2 -2 -2 3 -3 -3
+drop view v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create table t2 like t1;
+create view v1 as select a,b,c from t1;
+create view v2 as select a,b,c from t2 where b in (select b from v1);
+show create view v2;
+View Create View character_set_client collation_connection
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t2` where `t2`.`b` in (select `v1`.`b` from `v1`) latin1 latin1_swedish_ci
+drop view v2, v1;
+drop table t1, t2;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+insert into t1 (a) values (1),(1),(2),(2),(3),(3);
+create view v1 as select b from t1;
+select distinct b from v1;
+b
+-1
+-2
+-3
+select distinct b from v1 limit 2;
+b
+-1
+-2
+select distinct b from t1 limit 2;
+b
+-1
+-2
+prepare stmt1 from "select distinct b from v1 limit 2";
+execute stmt1;
+b
+-1
+-2
+execute stmt1;
+b
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+create view v1 as select c from t1;
+select distinct c from v1;
+c
+-1
+-2
+-3
+select distinct c from v1 limit 2;
+c
+-1
+-2
+select distinct c from t1 limit 2;
+c
+-1
+-2
+prepare stmt1 from "select distinct c from v1 limit 2";
+execute stmt1;
+c
+-1
+-2
+execute stmt1;
+c
+-1
+-2
+deallocate prepare stmt1;
+drop view v1;
+drop table t1;
+create table t1 (a int,
+b int as (-a),
+c int as (-a) persistent);
+create view v1 as select * from t1 where b > -2 && c >-2 with check option;
+insert into v1 (a) values (1);
+insert into v1 (a) values (3);
+ERROR HY000: CHECK OPTION failed 'test.v1'
+insert ignore into v1 (a) values (2),(3),(0);
+Warnings:
+Error 1369 CHECK OPTION failed 'test.v1'
+Error 1369 CHECK OPTION failed 'test.v1'
+select * from t1;
+a b c
+1 -1 -1
+0 0 0
+drop view v1;
+drop table t1;
diff --git a/mysql-test/suite/vcol/t/rpl_vcol.test b/mysql-test/suite/vcol/t/rpl_vcol.test
new file mode 100644
index 00000000000..2ac31f5ba35
--- /dev/null
+++ b/mysql-test/suite/vcol/t/rpl_vcol.test
@@ -0,0 +1,69 @@
+################################################################################
+# t/vcol_rpl.test #
+# #
+# Purpose: #
+# Test replication of tables with virtual columns. #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+SET @@session.storage_engine = 'InnoDB';
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source include/master-slave.inc
+
+connection master;
+create table t1 (a int, b int as (a+1));
+show create table t1;
+insert into t1 values (1,default);
+insert into t1 values (2,default);
+select * from t1;
+save_master_pos;
+
+connection slave;
+sync_with_master;
+select * from t1;
+
+connection master;
+drop table t1;
+save_master_pos;
+
+connection slave;
+sync_with_master;
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_archive.test b/mysql-test/suite/vcol/t/vcol_archive.test
new file mode 100644
index 00000000000..c0c9ecc445d
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_archive.test
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_archive.test #
+# #
+# Purpose: #
+# ARCHIVE branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_archive.inc
+SET @@session.storage_engine = 'archive';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--source suite/vcol/inc/vcol_unsupported_storage_engines.inc
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_blackhole.test b/mysql-test/suite/vcol/t/vcol_blackhole.test
new file mode 100644
index 00000000000..eac074d9595
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_blackhole.test
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_blackhole.test #
+# #
+# Purpose: #
+# BLACKHOLE branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_blackhole.inc
+SET @@session.storage_engine = 'blackhole';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--source suite/vcol/inc/vcol_unsupported_storage_engines.inc
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test
new file mode 100644
index 00000000000..516e121a2aa
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions not allowed for virtual columns #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+let $skip_full_text_checks = 1;
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test
new file mode 100644
index 00000000000..d8eddb4ef15
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_myisam.test
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions not allowed for virtual columns #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_blocked_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test b/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test
new file mode 100644
index 00000000000..38baa2b3024
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_column_def_options_innodb.test #
+# #
+# Purpose: #
+# Testing different optional parameters of virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_column_def_options.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test b/mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test
new file mode 100644
index 00000000000..5c3a4619834
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_column_def_options_myisam.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_column_def_options_myisam.test #
+# #
+# Purpose: #
+# Testing different optional parameters of virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_column_def_options.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_csv.test b/mysql-test/suite/vcol/t/vcol_csv.test
new file mode 100644
index 00000000000..b8342e24e07
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_csv.test
@@ -0,0 +1,54 @@
+################################################################################
+# t/vcol_csv.test #
+# #
+# Purpose: #
+# CSV branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_csv.inc
+SET @@session.storage_engine = 'CSV';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+create table t1 (a int, b int as (a+1));
+create table t1 (a int not null);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+alter table t1 add column b int as (a+1);
+drop table t1;
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_handler_innodb.test b/mysql-test/suite/vcol/t/vcol_handler_innodb.test
new file mode 100644
index 00000000000..bf443c6bbd3
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_handler_innodb.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_handler_innodb.test #
+# #
+# Purpose: #
+# Testing HANDLER.
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_handler.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_handler_maria.test b/mysql-test/suite/vcol/t/vcol_handler_maria.test
new file mode 100644
index 00000000000..9b69e600767
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_handler_maria.test
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_handler_maria.test #
+# #
+# Purpose: #
+# Testing HANDLER.
+# #
+# Maria branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+--source include/have_maria.inc
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MARIA SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'maria';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_handler.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_handler_myisam.test b/mysql-test/suite/vcol/t/vcol_handler_myisam.test
new file mode 100644
index 00000000000..5aa16da180a
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_handler_myisam.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_handler_myisam.test #
+# #
+# Purpose: #
+# Testing HANDLER.
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_handler.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test b/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test
new file mode 100644
index 00000000000..5d9ac12e930
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_ins_upd_innodb.test #
+# #
+# Purpose: #
+# Testing DDL operations such as INSERT, UPDATE, REPLACE and DELETE. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_ins_upd.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test b/mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test
new file mode 100644
index 00000000000..7840c191194
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_ins_upd_myisam.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_ins_upd_myisam.test #
+# #
+# Purpose: #
+# Testing DDL operations such as INSERT, UPDATE, REPLACE and DELETE. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_ins_upd.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_keys_innodb.test b/mysql-test/suite/vcol/t/vcol_keys_innodb.test
new file mode 100644
index 00000000000..e408672ac07
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_keys_innodb.test
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_keys_innodb.test #
+# #
+# Purpose: #
+# Testing keys, indexes defined upon virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+let $skip_spatial_index_check = 1;
+--source suite/vcol/inc/vcol_keys.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_keys_myisam.test b/mysql-test/suite/vcol/t/vcol_keys_myisam.test
new file mode 100644
index 00000000000..87d7b79aa1c
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_keys_myisam.test #
+# #
+# Purpose: #
+# Testing keys, indexes defined upon virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_keys.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_memory.test b/mysql-test/suite/vcol/t/vcol_memory.test
new file mode 100644
index 00000000000..f481427fa93
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_memory.test
@@ -0,0 +1,48 @@
+################################################################################
+# t/vcol_memory.test #
+# #
+# Purpose: #
+# MEMORY branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-02 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+SET @@session.storage_engine = 'memory';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--source suite/vcol/inc/vcol_unsupported_storage_engines.inc
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_merge.test b/mysql-test/suite/vcol/t/vcol_merge.test
new file mode 100644
index 00000000000..7ba72441bf5
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_merge.test
@@ -0,0 +1,57 @@
+################################################################################
+# t/vcol_merge.test #
+# #
+# Purpose: #
+# MERGE branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-03 #
+# Change Author: Oleksandr Byelkin (Monty program Ab)
+# Date: 2009-03-24
+# Change: Syntax changed
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+
+create table t1 (a int, b int as (a % 10));
+create table t2 (a int, b int as (a % 10));
+insert into t1 values (1,default);
+insert into t2 values (2,default);
+--error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2);
+drop table t1,t2;
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test
new file mode 100644
index 00000000000..8ae507a8f17
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_misc.test
@@ -0,0 +1,140 @@
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+#
+# Bug#601164: DELETE/UPDATE with ORDER BY index and LIMIT
+#
+
+create table t1 (a int, b int, v int as (a+1), index idx(b));
+insert into t1(a, b) values
+ (4, 40), (3, 30), (5, 50), (7, 70), (8, 80), (2, 20), (1, 10);
+
+select * from t1 order by b;
+
+delete from t1 where v > 6 order by b limit 1;
+select * from t1 order by b;
+
+update t1 set a=v order by b limit 1;
+select * from t1 order by b;
+
+drop table t1;
+
+#
+# Bug#604549: Expression for virtual column returns row
+#
+
+-- error ER_ROW_EXPR_FOR_VCOL
+CREATE TABLE t1 (
+ a int NOT NULL DEFAULT '0',
+ v double AS ((1, a)) VIRTUAL
+);
+
+#
+# Bug#603654: Virtual column in ORDER BY, no other references of table columns
+#
+
+CREATE TABLE t1 (
+ a CHAR(255) BINARY NOT NULL DEFAULT 0,
+ b CHAR(255) BINARY NOT NULL DEFAULT 0,
+ v CHAR(255) BINARY AS (CONCAT(a,b)) VIRTUAL );
+INSERT INTO t1(a,b) VALUES ('4','7'), ('4','6');
+SELECT 1 AS C FROM t1 ORDER BY v;
+
+DROP TABLE t1;
+
+#
+# Bug#603186: Insert into a table with stored vurtual columns
+#
+
+CREATE TABLE t1(a int, b int DEFAULT 0, v INT AS (b+10) PERSISTENT);
+INSERT INTO t1(a) VALUES (1);
+SELECT b, v FROM t1;
+
+DROP TABLE t1;
+
+CREATE TABLE t1(a int DEFAULT 100, v int AS (a+1) PERSISTENT);
+INSERT INTO t1 () VALUES ();
+CREATE TABLE t2(a int DEFAULT 100 , v int AS (a+1));
+INSERT INTO t2 () VALUES ();
+
+SELECT a, v FROM t1;
+SELECT a, v FROM t2;
+
+DROP TABLE t1,t2;
+
+#
+# Bug#604503: Virtual column expression with datetime comparison
+#
+
+CREATE TABLE t1 (
+ a datetime NOT NULL DEFAULT '2000-01-01',
+ v boolean AS (a < '2001-01-01')
+);
+INSERT INTO t1(a) VALUES ('2002-02-15');
+INSERT INTO t1(a) VALUES ('2000-10-15');
+
+SELECT a, v FROM t1;
+SELECT a, v FROM t1;
+
+CREATE TABLE t2 (
+ a datetime NOT NULL DEFAULT '2000-01-01',
+ v boolean AS (a < '2001-01-01') PERSISTENT
+);
+INSERT INTO t2(a) VALUES ('2002-02-15');
+INSERT INTO t2(a) VALUES ('2000-10-15');
+
+SELECT * FROM t2;
+
+DROP TABLE t1, t2;
+
+#
+# Bug#607566: Virtual column in the select list of SELECT with ORDER BY
+#
+
+CREATE TABLE t1 (
+ a char(255), b char(255), c char(255), d char(255),
+ v char(255) AS (CONCAT(c,d) ) VIRTUAL
+);
+
+INSERT INTO t1(a,b,c,d) VALUES ('w','x','y','z'), ('W','X','Y','Z');
+
+SELECT v FROM t1 ORDER BY CONCAT(a,b);
+
+DROP TABLE t1;
+
+#
+# Bug#607168: CREATE TABLE AS SELECT that returns virtual columns
+#
+
+CREATE TABLE t1 (f1 INTEGER, v1 INTEGER AS (f1) VIRTUAL);
+CREATE TABLE t2 AS SELECT v1 FROM t1;
+SHOW CREATE TABLE t2;
+
+DROP TABLE t1,t2;
+
+#
+# Bug#607177: ROUND function in the expression for a virtual function
+#
+
+CREATE TABLE t1 (p int, a double NOT NULL, v double AS (ROUND(a,p)) VIRTUAL);
+INSERT INTO t1 VALUES (0,1,0);
+INSERT INTO t1 VALUES (NULL,0,0);
+SELECT a, p, v, ROUND(a,p), ROUND(a,p+NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (p int, a double NOT NULL);
+INSERT INTO t1(p,a) VALUES (0,1);
+INSERT INTO t1(p,a) VALUES (NULL,0);
+SELECT a, p, ROUND(a,p), ROUND(a,p+NULL) FROM t1;
+DROP TABLE t1;
+
+#
+# Bug#610890: SHOW CREATE TABLE with a virtual column
+#
+
+CREATE TABLE t1 (a char(32), v char(32) CHARACTER SET ucs2 AS (a) VIRTUAL);
+
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test b/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test
new file mode 100644
index 00000000000..88ed6157294
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test
@@ -0,0 +1,53 @@
+################################################################################
+# t/vcol_non_stored_columns_innodb.test #
+# #
+# Purpose: #
+# Ensure that MySQL behaviour is consistent irrelevant of #
+# - the place of a non-stored column among other columns, #
+# - the total number of non-stored fields. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_non_stored_columns.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test b/mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test
new file mode 100644
index 00000000000..32481e792ec
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_non_stored_columns_myisam.test
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_non_stored_columns_myisam.test #
+# #
+# Purpose: #
+# Ensure that MySQL behaviour is consistent irrelevant of #
+# - the place of a non-stored column among other columns, #
+# - the total number of non-stored fields. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_non_stored_columns.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_partition_innodb.test b/mysql-test/suite/vcol/t/vcol_partition_innodb.test
new file mode 100644
index 00000000000..01230120ef9
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_partition_innodb.test
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_partition_innodb.test #
+# #
+# Purpose: #
+# Testing partitioning tables with virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+--source include/have_partition.inc
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_partition.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_partition_myisam.test b/mysql-test/suite/vcol/t/vcol_partition_myisam.test
new file mode 100644
index 00000000000..25f0d42c300
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_partition_myisam.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_partition_myisam.test #
+# #
+# Purpose: #
+# Testing partitioning tables with virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+--source include/have_partition.inc
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_partition.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_select_innodb.test b/mysql-test/suite/vcol/t/vcol_select_innodb.test
new file mode 100644
index 00000000000..314aecb75b9
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_select_innodb.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_select_innodb.test #
+# #
+# Purpose: #
+# Testing different SELECTs. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-18 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_select.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_select_myisam.test b/mysql-test/suite/vcol/t/vcol_select_myisam.test
new file mode 100644
index 00000000000..855e02ac113
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_select_myisam.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_select.test #
+# #
+# Purpose: #
+# Testing different SELECTs. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-18 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_select.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test
new file mode 100644
index 00000000000..53826a460a7
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions allowed for virtual columns #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_supported_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test
new file mode 100644
index 00000000000..aa5833451c6
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_myisam.test
@@ -0,0 +1,49 @@
+################################################################################
+# t/vcol_supported_sql_funcs.test #
+# #
+# Purpose: #
+# Test SQL functions allowed for virtual columns #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-08-31 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_supported_sql_funcs_main.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_syntax.test b/mysql-test/suite/vcol/t/vcol_syntax.test
new file mode 100644
index 00000000000..6dc3cf43317
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_syntax.test
@@ -0,0 +1,30 @@
+#
+# test syntax
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+set @OLD_SQL_MODE=@@SESSION.SQL_MODE;
+create table t1 (a int, b int generated always as (a+1));
+show create table t1;
+drop table t1;
+create table t1 (a int, b int as (a+1) virtual);
+show create table t1;
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) persistent);
+show create table t1;
+drop table t1;
+
+set session sql_mode='ORACLE';
+create table t1 (a int, b int as (a+1));
+show create table t1;
+drop table t1;
+create table t1 (a int, b int generated always as (a+1) virtual);
+show create table t1;
+drop table t1;
+create table t1 (a int, b int as (a+1) persistent);
+show create table t1;
+drop table t1;
+set session sql_mode=@OLD_SQL_MODE;
+
diff --git a/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test b/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test
new file mode 100644
index 00000000000..5a36fb1c06d
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test
@@ -0,0 +1,52 @@
+################################################################################
+# t/vcol_trigger_sp_innodb.test #
+# #
+# Purpose: #
+# Testing triggers, stored procedures and functions #
+# defined on tables with virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_trigger_sp.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test b/mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test
new file mode 100644
index 00000000000..c475a31eaa6
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_trigger_sp_myisam.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_trigger_sp_myisam.test #
+# #
+# Purpose: #
+# Testing triggers, stored procedures and functions #
+# defined on tables with virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_trigger_sp.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_view_innodb.test b/mysql-test/suite/vcol/t/vcol_view_innodb.test
new file mode 100644
index 00000000000..01fced8e4c3
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_view_innodb.test
@@ -0,0 +1,51 @@
+################################################################################
+# t/vcol_view_innodb.test #
+# #
+# Purpose: #
+# Testing views defined on tables with virtual columns. #
+# #
+# InnoDB branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+--source include/have_innodb.inc
+eval SET @@session.storage_engine = 'InnoDB';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_view.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/suite/vcol/t/vcol_view_myisam.test b/mysql-test/suite/vcol/t/vcol_view_myisam.test
new file mode 100644
index 00000000000..2ebd36431bc
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_view_myisam.test
@@ -0,0 +1,50 @@
+################################################################################
+# t/vcol_view_myisam.test #
+# #
+# Purpose: #
+# Testing views defined on tables with virtual columns. #
+# #
+# MyISAM branch #
+# #
+#------------------------------------------------------------------------------#
+# Original Author: Andrey Zhakov #
+# Original Date: 2008-09-04 #
+# Change Author: #
+# Change Date: #
+# Change: #
+################################################################################
+
+#
+# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE !
+# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN
+# THE SOURCED FILES ONLY.
+#
+
+#------------------------------------------------------------------------------#
+# General not engine specific settings and requirements
+--source suite/vcol/inc/vcol_init_vars.pre
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
+
+#------------------------------------------------------------------------------#
+# Engine specific settings and requirements
+
+##### Storage engine to be tested
+# Set the session storage engine
+eval SET @@session.storage_engine = 'MyISAM';
+
+##### Workarounds for known open engine specific bugs
+# none
+
+#------------------------------------------------------------------------------#
+# Execute the tests to be applied to all storage engines
+--source suite/vcol/inc/vcol_view.inc
+
+#------------------------------------------------------------------------------#
+# Execute storage engine specific tests
+
+#------------------------------------------------------------------------------#
+# Cleanup
+--source suite/vcol/inc/vcol_cleanup.inc
diff --git a/mysql-test/t/change_user.test b/mysql-test/t/change_user.test
index 46bf1d2a92c..5639e013de8 100644
--- a/mysql-test/t/change_user.test
+++ b/mysql-test/t/change_user.test
@@ -1,4 +1,61 @@
#
+# functional change user tests
+#
+
+grant select on test.* to test_nopw;
+grant select on test.* to test_oldpw identified by password "09301740536db389";
+grant select on test.* to test_newpw identified by "newpw";
+
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+#
+# massaging the data for tests to pass in the embedded server,
+# that has authentication completely disabled or, if enabled, can
+# only do new auth (20-byte scramble).
+#
+
+change_user test_nopw;
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+#
+# embedded with enabled privilege control cannot do plugin negotiation.
+# that is, it cannot try to authenticate with a new scramble, receive a request
+# to switch to an old scramble, and retry with an old scramble.
+# As a result, it cannot change to a user that has old scramble and
+# and it stays logged as a previous user - test_nopw in this test file.
+# For the embedded with auth we replace nopw with oldpw in the results.
+#
+let $repl = `select if(version() like '%embedded%' and user() like '%nopw%', 'nopw', 'oldpw')`;
+
+change_user test_oldpw, oldpw;
+--replace_result <@> <test_oldpw@%> @> @localhost> $repl oldpw
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_newpw, newpw;
+--replace_result <@> <test_newpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user root;
+--replace_result <@> <root@localhost> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+change_user test_nopw,,test;
+--replace_result <@> <test_nopw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_oldpw,oldpw,test;
+--replace_result <@> <test_oldpw@%> @> @localhost> $repl oldpw
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user test_newpw,newpw,test;
+--replace_result <@> <test_newpw@%> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+change_user root,,test;
+--replace_result <@> <root@localhost> @> @localhost>
+select concat('<', user(), '>'), concat('<', current_user(), '>'), database();
+
+drop user test_nopw;
+drop user test_oldpw;
+drop user test_newpw;
+
+#
# Bug#20023 mysql_change_user() resets the value of SQL_BIG_SELECTS
# The replace's are here to fix things for 32 bit systems
#
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index 255a4634bca..a8c8b659c3c 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -328,6 +328,34 @@ if ($error)
--disconnect extracon2
--connection default
+#
+# A couple of plugin tests - for builtin plugins only
+#
+CREATE USER mysqltest_up1 IDENTIFIED VIA mysql_native_password using '*E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB';
+CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db389';
+
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect(pcon1,localhost,mysqltest_up1,foo,,$MASTER_MYPORT,);
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+connect(pcon2,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,);
+connection pcon2;
+select user(), current_user();
+disconnect pcon2;
+
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect(pcon3,localhost,mysqltest_up2,newpw,,$MASTER_MYPORT,);
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+connect(pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,);
+connection pcon4;
+select user(), current_user();
+disconnect pcon4;
+
+connection default;
+DROP USER mysqltest_up1@'%';
+DROP USER mysqltest_up2@'%';
+
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test
index 81397b333f9..f2a82f40cff 100644
--- a/mysql-test/t/events_bugs.test
+++ b/mysql-test/t/events_bugs.test
@@ -1204,7 +1204,6 @@ create event e1 on schedule every 1 day do select 1;
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.event where name = 'p' and sql_mode = @full_mode;
drop event e1;
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index 4c14dc96aaa..d77ce243e32 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -1,11 +1,13 @@
#
-# Test of multiple key caches
+# Test of multiple key caches, simple and segmented
#
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
-SET @save_key_buffer=@@key_buffer_size;
+SET @save_key_buffer_size=@@key_buffer_size;
+SET @save_key_cache_block_size=@@key_cache_block_size;
+SET @save_key_cache_segments=@@key_cache_segments;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@ -33,7 +35,7 @@ SELECT @@`default`.key_buffer_size;
SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size;
-SET @@global.key_buffer_size=@save_key_buffer;
+SET @@global.key_buffer_size=@save_key_buffer_size;
#
# Errors
@@ -247,3 +249,272 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
# End of 4.1 tests
+
+# End of 5.1 tests
+
+#
+# Test cases for segmented key caches
+#
+
+# Test usage of the KEY_CACHE table from information schema
+# for a simple key cache
+
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_block_size=@save_key_cache_block_size;
+select @@key_buffer_size;
+select @@key_cache_block_size;
+select @@key_cache_segments;
+
+create table t1 (
+ p int not null auto_increment primary key,
+ a char(10));
+create table t2 (
+ p int not null auto_increment primary key,
+ i int, a char(10), key k1(i), key k2(a));
+
+select @@key_cache_segments;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED 1789 KEY_BLOCKS_UNUSED
+show status like 'key_%';
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+delete from t2 where a='zzzz';
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+delete from t1;
+delete from t2;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+# For the key cache with 2 segments execute the same sequence of
+# statements as for the simple cache above.
+# The statistical information on the number of i/o requests and
+# the number of is expected to be the same.
+
+set global key_cache_segments=2;
+select @@key_cache_segments;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED 1788 KEY_BLOCKS_UNUSED
+show status like 'key_%';
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+delete from t1;
+delete from t2;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+# Check that we can work with one segment with the same results
+
+set global key_cache_segments=1;
+select @@key_cache_segments;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED 1789 KEY_BLOCKS_UNUSED
+show status like 'key_%';
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+delete from t1;
+delete from t2;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+flush tables; flush status;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+# Switch back to 2 segments
+
+set global key_buffer_size=32*1024;
+select @@key_buffer_size;
+set global key_cache_segments=2;
+select @@key_cache_segments;
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+insert into t1 values (1, 'qqqq'), (2, 'yyyy');
+insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
+ (3, 1, 'yyyy'), (4, 3, 'zzzz');
+select * from t1;
+select * from t2;
+update t1 set p=3 where p=1;
+update t2 set i=2 where i=1;
+
+--replace_column 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+# Add more rows to tables t1 and t2
+
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+insert into t1(a) select a from t1;
+
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+insert into t2(i,a) select i,a from t2;
+
+--replace_column 6 # 7 # 10 #
+select * from information_schema.key_caches where segment_number is null;
+
+select * from t1 where p between 1010 and 1020 ;
+select * from t2 where p between 1010 and 1020 ;
+--replace_column 6 # 7 # 10 #
+select * from information_schema.key_caches where segment_number is null;
+
+flush tables; flush status;
+update t1 set a='zzzz' where a='qqqq';
+update t2 set i=1 where i=2;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+# Now test how we can work with 7 segments
+
+set global keycache1.key_buffer_size=256*1024;
+select @@keycache1.key_buffer_size;
+set global keycache1.key_cache_segments=7;
+select @@keycache1.key_cache_segments;
+
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+
+cache index t1 key (`primary`) in keycache1;
+
+explain select p from t1 where p between 1010 and 1020;
+select p from t1 where p between 1010 and 1020;
+explain select i from t2 where p between 1010 and 1020;
+select i from t2 where p between 1010 and 1020;
+explain select count(*) from t1, t2 where t1.p = t2.i;
+select count(*) from t1, t2 where t1.p = t2.i;
+
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+
+cache index t2 in keycache1;
+update t2 set p=p+3000, i=2 where a='qqqq';
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+
+set global keycache2.key_buffer_size=1024*1024;
+cache index t2 in keycache2;
+insert into t2 values (2000, 3, 'yyyy');
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "keycache2"
+ and segment_number is null;
+--replace_column 7 #
+select * from information_schema.key_caches where key_cache_name like "key%"
+ and segment_number is null;
+
+cache index t2 in keycache1;
+update t2 set p=p+5000 where a='zzzz';
+select * from t2 where p between 1010 and 1020;
+explain select p from t2 where p between 1010 and 1020;
+select p from t2 where p between 1010 and 1020;
+explain select i from t2 where a='yyyy' and i=3;
+select i from t2 where a='yyyy' and i=3;
+explain select a from t2 where a='yyyy' and i=3;
+select a from t2 where a='yyyy' and i=3 ;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_cache_block_size=2*1024;
+insert into t2 values (7000, 3, 'yyyy');
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+insert into t2 values (8000, 3, 'yyyy');
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_buffer_size=64*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_cache_block_size=2*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_buffer_size=0;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_cache_block_size=8*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_buffer_size=0;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_buffer_size=128*1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+set global keycache1.key_cache_block_size=1024;
+--replace_column 6 # 7 #
+select * from information_schema.key_caches where segment_number is null;
+
+drop table t1,t2;
+
+set global keycache1.key_buffer_size=0;
+set global keycache2.key_buffer_size=0;
+
+set global key_buffer_size=@save_key_buffer_size;
+set global key_cache_segments=@save_key_cache_segments;
+
+# End of 5.2 tests
diff --git a/mysql-test/t/log_slow.test b/mysql-test/t/log_slow.test
index 303d5bf8deb..d624e9f2520 100644
--- a/mysql-test/t/log_slow.test
+++ b/mysql-test/t/log_slow.test
@@ -36,6 +36,12 @@ select @@log_slow_verbosity;
show fields from mysql.slow_log;
+#
+# Check flush command
+#
+
+flush slow query logs;
+
# Reset used variables
set @@log_slow_filter=default;
diff --git a/mysql-test/t/partition_example.test b/mysql-test/t/partition_example.test
new file mode 100644
index 00000000000..8c1b92b2e33
--- /dev/null
+++ b/mysql-test/t/partition_example.test
@@ -0,0 +1,23 @@
+--source include/not_windows_embedded.inc
+--source include/have_example_plugin.inc
+--source include/have_partition.inc
+
+--replace_regex /\.dll/.so/
+eval install plugin example soname '$HA_EXAMPLE_SO';
+
+create table t1 (a int not null)
+engine=example
+partition by list (a)
+(partition p0 values in (1), partition p1 values in (2));
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null)
+engine=example ull=12340
+partition by list (a)
+(partition p0 values in (1), partition p1 values in (2));
+show create table t1;
+drop table t1;
+
+select 1;
+uninstall plugin example;
diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test
index 9a1a750378c..55250b73ae5 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;
@@ -78,4 +84,55 @@ set session sql_mode=@old_sql_mode;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set session old=bla;
+###############################################################
+# engine-specific clauses in the CREATE TABLE:
+
+--echo #legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+drop table t1;
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
+
+--echo #illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+show create table t1;
+
+--echo #alter table
+alter table t1 ULL=10000000;
+show create table t1;
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+drop table t1;
+
+--echo #illegal value error
+SET SQL_MODE='';
+--error ER_BAD_OPTION_VALUE
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+
+--error ER_PARSE_ERROR
+CREATE TABLE t1 (a int) ENGINE=example ULL=10.00;
+
+--error ER_PARSE_ERROR
+CREATE TABLE t1 (a int) ENGINE=example ULL=1e2;
+
+CREATE TABLE t1 (a int) ENGINE=example ULL=0x1234;
+SHOW CREATE TABLE t1;
+
+ALTER TABLE t1 ULL=DEFAULT;
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
+
+#
+# The only preparable statement above was CREATE TABLE.
+# We need to prepare another statement here to force the
+# previous one to be deallocated (mysqltest reuses the same handle)
+# and to unlock all thread-local plugin locks. Otherwise the plugin won't
+# uninstall.
+#
+select 1;
UNINSTALL PLUGIN example;
diff --git a/mysql-test/t/plugin_maturity-master.opt b/mysql-test/t/plugin_maturity-master.opt
new file mode 100644
index 00000000000..70ba6280117
--- /dev/null
+++ b/mysql-test/t/plugin_maturity-master.opt
@@ -0,0 +1 @@
+--plugin-maturity=stable
diff --git a/mysql-test/t/plugin_maturity.test b/mysql-test/t/plugin_maturity.test
new file mode 100644
index 00000000000..fe95f19b803
--- /dev/null
+++ b/mysql-test/t/plugin_maturity.test
@@ -0,0 +1,6 @@
+--source include/have_example_plugin.inc
+
+# test for --plugin_maturity
+--replace_regex /\.dll/.so/
+--error 1126
+eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO';
diff --git a/mysql-test/t/select_pkeycache-master.opt b/mysql-test/t/select_pkeycache-master.opt
new file mode 100644
index 00000000000..a6c0f247334
--- /dev/null
+++ b/mysql-test/t/select_pkeycache-master.opt
@@ -0,0 +1 @@
+--key_cache_segments=7
diff --git a/mysql-test/t/select_pkeycache.test b/mysql-test/t/select_pkeycache.test
new file mode 100644
index 00000000000..e0ee96e937a
--- /dev/null
+++ b/mysql-test/t/select_pkeycache.test
@@ -0,0 +1,8 @@
+
+#
+# Run select.test with the segmented default key cache (with 7 segments)
+# (see setting the number of segments in select_pkecache-master.opt)
+# The result is expected the same as for select.test
+#
+
+--source t/select.test
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 5cf050146dd..db8077bbbef 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -8210,7 +8210,6 @@ call p();
select @@sql_mode;
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
drop procedure p;
diff --git a/mysql-test/t/status_user-master.opt b/mysql-test/t/status_user-master.opt
new file mode 100644
index 00000000000..cef79bc8585
--- /dev/null
+++ b/mysql-test/t/status_user-master.opt
@@ -0,0 +1 @@
+--force-restart
diff --git a/mysql-test/t/status_user.test b/mysql-test/t/status_user.test
new file mode 100644
index 00000000000..d42f81b20e5
--- /dev/null
+++ b/mysql-test/t/status_user.test
@@ -0,0 +1,89 @@
+#
+# Testing of user status (the userstat variable).
+# Note that this test requires a fresh restart to not problems with
+# old status
+
+-- source include/have_innodb.inc
+-- source include/have_log_bin.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+select variable_value from information_schema.global_status where variable_name="handler_read_key" into @global_read_key;
+show columns from information_schema.client_statistics;
+show columns from information_schema.user_statistics;
+show columns from information_schema.index_statistics;
+show columns from information_schema.table_statistics;
+
+# Disable logging to get right number of writes into the tables.
+set @save_general_log=@@global.general_log;
+set @@global.general_log=0;
+set @@global.userstat=1;
+flush status;
+
+create table t1 (a int, primary key (a), b int default 0) engine=innodb;
+insert into t1 (a) values (1),(2),(3),(4);
+update t1 set b=1;
+update t1 set b=5 where a=2;
+delete from t1 where a=3;
+
+/* Empty query */
+select * from t1 where a=999;
+
+drop table t1;
+
+#
+# Test the commit and rollback are counted
+#
+
+create table t1 (a int, primary key (a), b int default 0) engine=innodb;
+begin;
+insert into t1 values(1,1);
+commit;
+begin;
+insert into t1 values(2,2);
+commit;
+begin;
+insert into t1 values(3,3);
+rollback;
+drop table t1;
+
+select sleep(1);
+
+show status like "rows%";
+show status like "ha%";
+select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key";
+
+# Ensure that the following commands doesn't change statistics
+
+set @@global.userstat=0;
+
+#
+# Check that we got right statistics
+#
+select * from information_schema.index_statistics;
+select * from information_schema.table_statistics;
+show table_statistics;
+show index_statistics;
+--query_vertical select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, ACCESS_DENIED, EMPTY_QUERIES from information_schema.client_statistics;
+--query_vertical select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, ACCESS_DENIED, EMPTY_QUERIES from information_schema.user_statistics;
+flush table_statistics;
+flush index_statistics;
+select * from information_schema.index_statistics;
+select * from information_schema.table_statistics;
+show status like "%statistics%";
+
+#
+# Test that some variables are not 0
+#
+
+select connected_time <> 0, busy_time <> 0, bytes_received <> 0,
+ bytes_sent <> 0, binlog_bytes_written <> 0
+ from information_schema.user_statistics;
+select connected_time <> 0, busy_time <> 0, bytes_received <> 0,
+ bytes_sent <> 0, binlog_bytes_written <> 0
+ from information_schema.client_statistics;
+
+# Cleanup
+set @@global.general_log=@save_general_log;
diff --git a/mysql-test/t/table_options.test b/mysql-test/t/table_options.test
new file mode 100644
index 00000000000..533e6829c00
--- /dev/null
+++ b/mysql-test/t/table_options.test
@@ -0,0 +1,68 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
+
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1='1v1';
+show create table t1;
+drop table t1;
+
+--echo #reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+show create table t1;
+
+-- echo #add option
+alter table t1 tkey4=4v1;
+show create table t1;
+
+--echo #remove options
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+show create table t1;
+
+drop table t1;
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+show create table t1;
+
+--echo #change field with option with the same value
+alter table t1 change a a int `FKEY1`='v1';
+show create table t1;
+--echo #change field with option with a different value
+alter table t1 change a a int fkey1=v2;
+show create table t1;
+--echo #new column no options
+alter table t1 add column b int;
+show create table t1;
+--echo #new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+show create table t1;
+--echo #new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+show create table t1;
+--echo #new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+--echo #drop column
+alter table t1 drop b;
+show create table t1;
+--echo #add column with options after delete
+alter table t1 add column b int fkey2=v1;
+show create table t1;
+--echo #add key
+alter table t1 add key bkey (b) kkey2=v2;
+show create table t1;
+drop table t1;
+
+#numeric (unquoted) value
+create table t1 (a int) tkey1=100;
+show create table t1;
+drop table t1;
+
+--echo #error on unknown option
+SET SQL_MODE='';
+--error ER_UNKNOWN_OPTION
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index 67179571953..1919b79461d 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -539,6 +539,13 @@
fun:_Unwind_ForcedUnwind
}
+{
+ dlsym memory loss from plugin
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_signal_error
+}
+
#
# Reading wrong addresses on SuSe Linux 10.3 32 bit
#
@@ -1000,6 +1007,27 @@
fun:nptl_pthread_exit_hack_handler
}
+{
+ Invalid read within nptl_pthread_exit_hack_handler
+ Memcheck:Addr8
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/ld-*.so
+ obj:*/libc-*.so
+ obj:*/ld-*.so
+ obj:*/libc-*.so
+ fun:__libc_dlopen_mode
+ fun:pthread_cancel_init
+ fun:_Unwind_ForcedUnwind
+ fun:__pthread_unwind
+ fun:pthread_exit
+ fun:nptl_pthread_exit_hack_handler
+}
+
#
# Pthread doesn't free all thread specific memory before program exists
#
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 5137566c158..337fc86c12e 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -74,13 +74,13 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
# charset2html_DEPENDENCIES= $(LIBRARIES)
-DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+DEFS = -DDEFAULT_BASEDIR='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
+ -DSHAREDIR'="$(MYSQLSHAREdir)"' \
-DDEFAULT_HOME_ENV=MYSQL_HOME \
-DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
+ -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
@DEFS@
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index 5c68258ada1..db10000e174 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -24,49 +24,49 @@
#ifdef HAVE_UCA_COLLATIONS
#ifdef HAVE_CHARSET_ucs2
-extern CHARSET_INFO my_charset_ucs2_icelandic_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_latvian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_romanian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_slovenian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_polish_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_estonian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_spanish_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_swedish_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_turkish_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_czech_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_danish_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_slovak_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_roman_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_persian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_hungarian_uca_ci;
-extern CHARSET_INFO my_charset_ucs2_croatian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_icelandic_uca_ci;
+extern struct charset_info_st my_charset_ucs2_latvian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_romanian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_slovenian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_polish_uca_ci;
+extern struct charset_info_st my_charset_ucs2_estonian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_spanish_uca_ci;
+extern struct charset_info_st my_charset_ucs2_swedish_uca_ci;
+extern struct charset_info_st my_charset_ucs2_turkish_uca_ci;
+extern struct charset_info_st my_charset_ucs2_czech_uca_ci;
+extern struct charset_info_st my_charset_ucs2_danish_uca_ci;
+extern struct charset_info_st my_charset_ucs2_lithuanian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_slovak_uca_ci;
+extern struct charset_info_st my_charset_ucs2_spanish2_uca_ci;
+extern struct charset_info_st my_charset_ucs2_roman_uca_ci;
+extern struct charset_info_st my_charset_ucs2_persian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_esperanto_uca_ci;
+extern struct charset_info_st my_charset_ucs2_hungarian_uca_ci;
+extern struct charset_info_st my_charset_ucs2_croatian_uca_ci;
#endif
#ifdef HAVE_CHARSET_utf8
-extern CHARSET_INFO my_charset_utf8_icelandic_uca_ci;
-extern CHARSET_INFO my_charset_utf8_latvian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_romanian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_slovenian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_polish_uca_ci;
-extern CHARSET_INFO my_charset_utf8_estonian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_spanish_uca_ci;
-extern CHARSET_INFO my_charset_utf8_swedish_uca_ci;
-extern CHARSET_INFO my_charset_utf8_turkish_uca_ci;
-extern CHARSET_INFO my_charset_utf8_czech_uca_ci;
-extern CHARSET_INFO my_charset_utf8_danish_uca_ci;
-extern CHARSET_INFO my_charset_utf8_lithuanian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_slovak_uca_ci;
-extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci;
-extern CHARSET_INFO my_charset_utf8_roman_uca_ci;
-extern CHARSET_INFO my_charset_utf8_persian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci;
-extern CHARSET_INFO my_charset_utf8_hungarian_uca_ci;
-extern CHARSET_INFO my_charset_utf8_croatian_uca_ci;
+extern struct charset_info_st my_charset_utf8_icelandic_uca_ci;
+extern struct charset_info_st my_charset_utf8_latvian_uca_ci;
+extern struct charset_info_st my_charset_utf8_romanian_uca_ci;
+extern struct charset_info_st my_charset_utf8_slovenian_uca_ci;
+extern struct charset_info_st my_charset_utf8_polish_uca_ci;
+extern struct charset_info_st my_charset_utf8_estonian_uca_ci;
+extern struct charset_info_st my_charset_utf8_spanish_uca_ci;
+extern struct charset_info_st my_charset_utf8_swedish_uca_ci;
+extern struct charset_info_st my_charset_utf8_turkish_uca_ci;
+extern struct charset_info_st my_charset_utf8_czech_uca_ci;
+extern struct charset_info_st my_charset_utf8_danish_uca_ci;
+extern struct charset_info_st my_charset_utf8_lithuanian_uca_ci;
+extern struct charset_info_st my_charset_utf8_slovak_uca_ci;
+extern struct charset_info_st my_charset_utf8_spanish2_uca_ci;
+extern struct charset_info_st my_charset_utf8_roman_uca_ci;
+extern struct charset_info_st my_charset_utf8_persian_uca_ci;
+extern struct charset_info_st my_charset_utf8_esperanto_uca_ci;
+extern struct charset_info_st my_charset_utf8_hungarian_uca_ci;
+extern struct charset_info_st my_charset_utf8_croatian_uca_ci;
#ifdef HAVE_UTF8_GENERAL_CS
-extern CHARSET_INFO my_charset_utf8_general_cs;
+extern struct charset_info_st my_charset_utf8_general_cs;
#endif
#endif
@@ -195,7 +195,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
/* Copy compiled charsets */
for (cs=compiled_charsets; cs->name; cs++)
- add_compiled_collation(cs);
+ add_compiled_collation((struct charset_info_st *) cs);
return FALSE;
}
diff --git a/mysys/charset.c b/mysys/charset.c
index 8d2f68b7bbf..7cf8a8b828d 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -53,21 +53,18 @@ get_collation_number_internal(const char *name)
}
-static my_bool init_state_maps(CHARSET_INFO *cs)
+static my_bool init_state_maps(struct charset_info_st *cs)
{
uint i;
uchar *state_map;
uchar *ident_map;
- if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
+ if (!(cs->state_map= state_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
return 1;
- if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
+ if (!(cs->ident_map= ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME))))
return 1;
- state_map= cs->state_map;
- ident_map= cs->ident_map;
-
/* Fill state_map with states to get a faster parser */
for (i=0; i < 256 ; i++)
{
@@ -118,7 +115,7 @@ static my_bool init_state_maps(CHARSET_INFO *cs)
}
-static void simple_cs_init_functions(CHARSET_INFO *cs)
+static void simple_cs_init_functions(struct charset_info_st *cs)
{
if (cs->state & MY_CS_BINSORT)
cs->coll= &my_collation_8bit_bin_handler;
@@ -130,7 +127,7 @@ static void simple_cs_init_functions(CHARSET_INFO *cs)
-static int cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
+static int cs_copy_data(struct charset_info_st *to, CHARSET_INFO *from)
{
to->number= from->number ? from->number : to->number;
@@ -203,7 +200,7 @@ static my_bool simple_cs_is_full(CHARSET_INFO *cs)
static void
-copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from)
+copy_uca_collation(struct charset_info_st *to, CHARSET_INFO *from)
{
to->cset= from->cset;
to->coll= from->coll;
@@ -217,18 +214,19 @@ copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from)
}
-static int add_collation(CHARSET_INFO *cs)
+static int add_collation(struct charset_info_st *cs)
{
if (cs->name && (cs->number ||
(cs->number=get_collation_number_internal(cs->name))) &&
cs->number < array_elements(all_charsets))
{
- if (!all_charsets[cs->number])
+ struct charset_info_st *newcs;
+ if (!(newcs= (struct charset_info_st*) all_charsets[cs->number]))
{
- if (!(all_charsets[cs->number]=
- (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
+ if (!(all_charsets[cs->number]= newcs=
+ (struct charset_info_st*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
return MY_XML_ERROR;
- bzero((void*)all_charsets[cs->number],sizeof(CHARSET_INFO));
+ bzero(newcs,sizeof(CHARSET_INFO));
}
if (cs->primary_number == cs->number)
@@ -237,12 +235,11 @@ static int add_collation(CHARSET_INFO *cs)
if (cs->binary_number == cs->number)
cs->state |= MY_CS_BINSORT;
- all_charsets[cs->number]->state|= cs->state;
+ newcs->state|= cs->state;
- if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
+ if (!(newcs->state & MY_CS_COMPILED))
{
- CHARSET_INFO *newcs= all_charsets[cs->number];
- if (cs_copy_data(all_charsets[cs->number],cs))
+ if (cs_copy_data(newcs,cs))
return MY_XML_ERROR;
newcs->caseup_multiply= newcs->casedn_multiply= 1;
@@ -262,15 +259,15 @@ static int add_collation(CHARSET_INFO *cs)
}
else
{
- uchar *sort_order= all_charsets[cs->number]->sort_order;
- simple_cs_init_functions(all_charsets[cs->number]);
+ const uchar *sort_order= newcs->sort_order;
+ simple_cs_init_functions(newcs);
newcs->mbminlen= 1;
newcs->mbmaxlen= 1;
- if (simple_cs_is_full(all_charsets[cs->number]))
+ if (simple_cs_is_full(newcs))
{
- all_charsets[cs->number]->state |= MY_CS_LOADED;
+ newcs->state |= MY_CS_LOADED;
}
- all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
+ newcs->state|= MY_CS_AVAILABLE;
/*
Check if case sensitive sort order: A < a < B.
@@ -280,12 +277,12 @@ static int add_collation(CHARSET_INFO *cs)
*/
if (sort_order && sort_order['A'] < sort_order['a'] &&
sort_order['a'] < sort_order['B'])
- all_charsets[cs->number]->state|= MY_CS_CSSORT;
+ newcs->state|= MY_CS_CSSORT;
- if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number]))
- all_charsets[cs->number]->state|= MY_CS_PUREASCII;
+ if (my_charset_is_8bit_pure_ascii(newcs))
+ newcs->state|= MY_CS_PUREASCII;
if (!my_charset_is_ascii_compatible(cs))
- all_charsets[cs->number]->state|= MY_CS_NONASCII;
+ newcs->state|= MY_CS_NONASCII;
}
}
else
@@ -299,16 +296,15 @@ static int add_collation(CHARSET_INFO *cs)
If a character set was compiled, this information
will get lost and overwritten in add_compiled_collation().
*/
- CHARSET_INFO *dst= all_charsets[cs->number];
- dst->number= cs->number;
+ newcs->number= cs->number;
if (cs->comment)
- if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME))))
+ if (!(newcs->comment= my_once_strdup(cs->comment,MYF(MY_WME))))
return MY_XML_ERROR;
if (cs->csname)
- if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME))))
+ if (!(newcs->csname= my_once_strdup(cs->csname,MYF(MY_WME))))
return MY_XML_ERROR;
if (cs->name)
- if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME))))
+ if (!(newcs->name= my_once_strdup(cs->name,MYF(MY_WME))))
return MY_XML_ERROR;
}
cs->number= 0;
@@ -392,7 +388,7 @@ char *get_charsets_dir(char *buf)
CHARSET_INFO *all_charsets[256]={NULL};
CHARSET_INFO *default_charset_info = &my_charset_latin1;
-void add_compiled_collation(CHARSET_INFO *cs)
+void add_compiled_collation(struct charset_info_st *cs)
{
all_charsets[cs->number]= cs;
cs->state|= MY_CS_AVAILABLE;
@@ -410,14 +406,15 @@ static my_pthread_once_t charsets_template= MY_PTHREAD_ONCE_INIT;
static void init_available_charsets(void)
{
char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)];
- CHARSET_INFO **cs;
+ struct charset_info_st **cs;
bzero(&all_charsets,sizeof(all_charsets));
init_compiled_charsets(MYF(0));
/* Copy compiled charsets */
- for (cs=all_charsets;
- cs < all_charsets+array_elements(all_charsets)-1 ;
+ for (cs= (struct charset_info_st**) all_charsets;
+ cs < (struct charset_info_st**) all_charsets +
+ array_elements(all_charsets)-1 ;
cs++)
{
if (*cs)
@@ -478,9 +475,9 @@ const char *get_charset_name(uint charset_number)
static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
{
char buf[FN_REFLEN];
- CHARSET_INFO *cs;
+ struct charset_info_st *cs;
- if ((cs= all_charsets[cs_number]))
+ if ((cs= (struct charset_info_st*) all_charsets[cs_number]))
{
if (cs->state & MY_CS_READY) /* if CS is already initialized */
return cs;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index f7b420c3bf2..08c160910c7 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -13,12 +13,43 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
/**
- @file
+ @file
+ The file contains the following modules:
+
+ Simple Key Cache Module
+
+ Partitioned Key Cache Module
+
+ Key Cache Interface Module
+
+*/
+
+#include "mysys_priv.h"
+#include "mysys_err.h"
+#include <keycache.h>
+#include "my_static.h"
+#include <m_string.h>
+#include <my_bit.h>
+#include <errno.h>
+#include <stdarg.h>
+
+/******************************************************************************
+ Simple Key Cache Module
+
+ The module contains implementations of all key cache interface functions
+ employed by partitioned key caches.
+
+******************************************************************************/
+
+/*
These functions handle keyblock cacheing for ISAM and MyISAM tables.
One cache can handle many files.
It must contain buffers of the same blocksize.
+
init_key_cache() should be used to init cache handler.
The free list (free_block_list) is a stack like structure.
@@ -37,9 +68,7 @@
blocks_unused is the sum of never used blocks in the pool and of currently
free blocks. blocks_used is the number of blocks fetched from the pool and
as such gives the maximum number of in-use blocks at any time.
-*/
-/*
Key Cache Locking
=================
@@ -104,14 +133,77 @@
I/O finished.
*/
-#include "mysys_priv.h"
-#include "mysys_err.h"
-#include <keycache.h>
-#include "my_static.h"
-#include <m_string.h>
-#include <my_bit.h>
-#include <errno.h>
-#include <stdarg.h>
+/* declare structures that is used by st_key_cache */
+
+struct st_block_link;
+typedef struct st_block_link BLOCK_LINK;
+struct st_keycache_page;
+typedef struct st_keycache_page KEYCACHE_PAGE;
+struct st_hash_link;
+typedef struct st_hash_link HASH_LINK;
+
+/* info about requests in a waiting queue */
+typedef struct st_keycache_wqueue
+{
+ struct st_my_thread_var *last_thread; /* circular list of waiting threads */
+} KEYCACHE_WQUEUE;
+
+#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
+
+/* Control block for a simple (non-partitioned) key cache */
+
+typedef struct st_simple_key_cache_cb
+{
+ my_bool key_cache_inited; /* <=> control block is allocated */
+ my_bool in_resize; /* true during resize operation */
+ my_bool resize_in_flush; /* true during flush of resize operation */
+ my_bool can_be_used; /* usage of cache for read/write is allowed */
+ size_t key_cache_mem_size; /* specified size of the cache memory */
+ uint key_cache_block_size; /* size of the page buffer of a cache block */
+ ulong min_warm_blocks; /* min number of warm blocks; */
+ ulong age_threshold; /* age threshold for hot blocks */
+ ulonglong keycache_time; /* total number of block link operations */
+ uint hash_entries; /* max number of entries in the hash table */
+ int hash_links; /* max number of hash links */
+ int hash_links_used; /* number of hash links currently used */
+ int disk_blocks; /* max number of blocks in the cache */
+ ulong blocks_used; /* maximum number of concurrently used blocks */
+ ulong blocks_unused; /* number of currently unused blocks */
+ ulong blocks_changed; /* number of currently dirty blocks */
+ ulong warm_blocks; /* number of blocks in warm sub-chain */
+ ulong cnt_for_resize_op; /* counter to block resize operation */
+ long blocks_available; /* number of blocks available in the LRU chain */
+ HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
+ HASH_LINK *hash_link_root; /* memory for hash table links */
+ HASH_LINK *free_hash_list; /* list of free hash links */
+ BLOCK_LINK *free_block_list; /* list of free blocks */
+ BLOCK_LINK *block_root; /* memory for block links */
+ uchar HUGE_PTR *block_mem; /* memory for block buffers */
+ BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */
+ BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */
+ pthread_mutex_t cache_lock; /* to lock access to the cache structure */
+ KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
+ /*
+ Waiting for a zero resize count. Using a queue for symmetry though
+ only one thread can wait here.
+ */
+ KEYCACHE_WQUEUE waiting_for_resize_cnt;
+ KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */
+ KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
+ BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/
+ BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/
+
+ /* Statistics variables. These are reset in reset_key_cache_counters(). */
+ ulong global_blocks_changed; /* number of currently dirty blocks */
+ ulonglong global_cache_w_requests;/* number of write requests (write hits) */
+ ulonglong global_cache_write; /* number of writes from cache to files */
+ ulonglong global_cache_r_requests;/* number of read requests (read hits) */
+ ulonglong global_cache_read; /* number of reads from files to cache */
+
+ int blocks; /* max number of blocks in the cache */
+ uint hash_factor; /* factor used to calculate hash function */
+ my_bool in_init; /* Set to 1 in MySQL during init/resize */
+} SIMPLE_KEY_CACHE_CB;
/*
Some compilation flags have been added specifically for this module
@@ -223,7 +315,8 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cache_var;
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
-static int flush_all_key_blocks(KEY_CACHE *keycache);
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache);
+static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup);
#ifdef THREAD
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
pthread_mutex_t *mutex);
@@ -232,15 +325,16 @@ static void release_whole_queue(KEYCACHE_WQUEUE *wqueue);
#define wait_on_queue(wqueue, mutex) do {} while (0)
#define release_whole_queue(wqueue) do {} while (0)
#endif
-static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block);
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
#if !defined(DBUG_OFF)
-static void test_key_cache(KEY_CACHE *keycache,
+static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
const char *where, my_bool lock);
#endif
-
+#define KEYCACHE_BASE_EXPR(f, pos) \
+ ((ulong) ((pos) / keycache->key_cache_block_size) + (ulong) (f))
#define KEYCACHE_HASH(f, pos) \
-(((ulong) ((pos) / keycache->key_cache_block_size) + \
- (ulong) (f)) & (keycache->hash_entries-1))
+ ((KEYCACHE_BASE_EXPR(f, pos) / keycache->hash_factor) & \
+ (keycache->hash_entries-1))
#define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
#define DEFAULT_KEYCACHE_DEBUG_LOG "keycache_debug.log"
@@ -336,9 +430,10 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond);
#define inline /* disabled inline for easier debugging */
static int fail_block(BLOCK_LINK *block);
static int fail_hlink(HASH_LINK *hlink);
-static int cache_empty(KEY_CACHE *keycache);
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache);
#endif
+
static inline uint next_power(uint value)
{
return (uint) my_round_up_to_next_power((uint32) value) << 1;
@@ -346,19 +441,32 @@ static inline uint next_power(uint value)
/*
- Initialize a key cache
+ Initialize a simple key cache
SYNOPSIS
- init_key_cache()
- keycache pointer to a key cache data structure
- key_cache_block_size size of blocks to keep cached data
- use_mem total memory to use for the key cache
- division_limit division limit (may be zero)
- age_threshold age threshold (may be zero)
+ init_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem memory to use for the key cache buferrs/structures
+ division_limit division limit (may be zero)
+ age_threshold age threshold (may be zero)
+
+ DESCRIPTION
+ This function is the implementation of the init_key_cache interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function builds a simple key cache and initializes the control block
+ structure of the type SIMPLE_KEY_CACHE_CB that is used for this key cache.
+ The parameter keycache is supposed to point to this structure.
+ The parameter key_cache_block_size specifies the size of the blocks in
+ the key cache to be built. The parameters division_limit and age_threshhold
+ determine the initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for key cache blocks
+ and auxiliary structures.
RETURN VALUE
number of blocks in the key cache, if successful,
- 0 - otherwise.
+ <= 0 - otherwise.
NOTES.
if keycache->key_cache_inited != 0 we assume that the key cache
@@ -367,17 +475,17 @@ static inline uint next_power(uint value)
It's assumed that no two threads call this function simultaneously
referring to the same key cache handle.
-
*/
-int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+static
+int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
{
ulong blocks, hash_links;
size_t length;
int error;
- DBUG_ENTER("init_key_cache");
+ DBUG_ENTER("init_simple_key_cache");
DBUG_ASSERT(key_cache_block_size >= 512);
KEYCACHE_DEBUG_OPEN;
@@ -387,12 +495,15 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
DBUG_RETURN(0);
}
+ keycache->blocks_used= keycache->blocks_unused= 0;
+ keycache->global_blocks_changed= 0;
keycache->global_cache_w_requests= keycache->global_cache_r_requests= 0;
keycache->global_cache_read= keycache->global_cache_write= 0;
keycache->disk_blocks= -1;
if (! keycache->key_cache_inited)
{
keycache->key_cache_inited= 1;
+ keycache->hash_factor= 1;
/*
Initialize these variables once only.
Their value must survive re-initialization during resizing.
@@ -534,51 +645,42 @@ err:
/*
- Resize a key cache
+ Prepare for resizing a simple key cache
SYNOPSIS
- resize_key_cache()
- keycache pointer to a key cache data structure
- key_cache_block_size size of blocks to keep cached data
- use_mem total memory to use for the new key cache
- division_limit new division limit (if not zero)
- age_threshold new age threshold (if not zero)
-
- RETURN VALUE
- number of blocks in the key cache, if successful,
- 0 - otherwise.
+ prepare_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ with_resize_queue <=> resize queue is used
+ release_lock <=> release the key cache lock before return
- NOTES.
- The function first compares the memory size and the block size parameters
- with the key cache values.
+ DESCRIPTION
+ This function flushes all dirty pages from a simple key cache and after
+ this it destroys the key cache calling end_simple_key_cache. The function
+ takes the parameter keycache as a pointer to the control block
+ structure of the type SIMPLE_KEY_CACHE_CB for this key cache.
+ The parameter with_resize_queue determines weather the resize queue is
+ involved (MySQL server never uses this queue). The parameter release_lock
+ says weather the key cache lock must be released before return from
+ the function.
- If they differ the function free the the memory allocated for the
- old key cache blocks by calling the end_key_cache function and
- then rebuilds the key cache with new blocks by calling
- init_key_cache.
+ RETURN VALUE
+ 0 - on success,
+ 1 - otherwise.
- The function starts the operation only when all other threads
- performing operations with the key cache let her to proceed
- (when cnt_for_resize=0).
+ NOTES
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
*/
-int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
- size_t use_mem, uint division_limit,
- uint age_threshold)
+static
+int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool release_lock)
{
- int blocks;
- DBUG_ENTER("resize_key_cache");
-
- if (!keycache->key_cache_inited)
- DBUG_RETURN(keycache->disk_blocks);
-
- if(key_cache_block_size == keycache->key_cache_block_size &&
- use_mem == keycache->key_cache_mem_size)
- {
- change_key_cache_param(keycache, division_limit, age_threshold);
- DBUG_RETURN(keycache->disk_blocks);
- }
-
+ int res= 0;
+ DBUG_ENTER("prepare_resize_simple_key_cache");
+
keycache_pthread_mutex_lock(&keycache->cache_lock);
#ifdef THREAD
@@ -588,7 +690,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
one resizer only. In set_var.cc keycache->in_init is used to block
multiple attempts.
*/
- while (keycache->in_resize)
+ while (with_resize_queue && keycache->in_resize)
{
/* purecov: begin inspected */
wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
@@ -613,8 +715,8 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
{
/* TODO: if this happens, we should write a warning in the log file ! */
keycache->resize_in_flush= 0;
- blocks= 0;
keycache->can_be_used= 0;
+ res= 1;
goto finish;
}
DBUG_ASSERT(cache_empty(keycache));
@@ -640,29 +742,144 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
#else
KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0);
#endif
-
- /*
- Free old cache structures, allocate new structures, and initialize
- them. Note that the cache_lock mutex and the resize_queue are left
- untouched. We do not lose the cache_lock and will release it only at
- the end of this function.
- */
- end_key_cache(keycache, 0); /* Don't free mutex */
- /* The following will work even if use_mem is 0 */
- blocks= init_key_cache(keycache, key_cache_block_size, use_mem,
- division_limit, age_threshold);
+
+ end_simple_key_cache(keycache, 0);
finish:
+ if (release_lock)
+ keycache_pthread_mutex_unlock(&keycache->cache_lock);
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Finalize resizing a simple key cache
+
+ SYNOPSIS
+ finish_resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ with_resize_queue <=> resize queue is used
+ acquire_lock <=> acquire the key cache lock at start
+
+ DESCRIPTION
+ This function performs finalizing actions for the operation of
+ resizing a simple key cache. The function takes the parameter
+ keycache as a pointer to the control block structure of the type
+ SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
+ in_resize in this structure to FALSE.
+ The parameter with_resize_queue determines weather the resize queue
+ is involved (MySQL server never uses this queue).
+ The parameter acquire_lock says weather the key cache lock must be
+ acquired at the start of the function.
+
+ RETURN VALUE
+ none
+
+ NOTES
+ This function is the called by resize_simple_key_cache and
+ resize_partitioned_key_cache that resize simple and partitioned key caches
+ respectively.
+*/
+
+static
+void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
+ my_bool with_resize_queue,
+ my_bool acquire_lock)
+{
+ DBUG_ENTER("finish_resize_simple_key_cache");
+
+ if (acquire_lock)
+ keycache_pthread_mutex_lock(&keycache->cache_lock);
+
+ safe_mutex_assert_owner(&keycache->cache_lock);
+
/*
Mark the resize finished. This allows other threads to start a
resize or to request new cache blocks.
*/
keycache->in_resize= 0;
-
- /* Signal waiting threads. */
- release_whole_queue(&keycache->resize_queue);
+
+ if (with_resize_queue)
+ {
+ /* Signal waiting threads. */
+ release_whole_queue(&keycache->resize_queue);
+ }
keycache_pthread_mutex_unlock(&keycache->cache_lock);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Resize a simple key cache
+
+ SYNOPSIS
+ resize_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem memory to use for the key cache buffers/structures
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the resize_key_cache interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
+ cache to be resized.
+ The parameter key_cache_block_size specifies the new size of the blocks in
+ the key cache. The parameters division_limit and age_threshold
+ determine the new initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for key cache blocks
+ and auxiliary structures in the new key cache.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES.
+ The function first calls the function prepare_resize_simple_key_cache
+ to flush all dirty blocks from key cache, to free memory used
+ for key cache blocks and auxiliary structures. After this the
+ function builds a new key cache with new parameters.
+
+ This implementation doesn't block the calls and executions of other
+ functions from the key cache interface. However it assumes that the
+ calls of resize_simple_key_cache itself are serialized.
+
+ The function starts the operation only when all other threads
+ performing operations with the key cache let her to proceed
+ (when cnt_for_resize=0).
+*/
+
+static
+int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
+{
+ int blocks= 0;
+ DBUG_ENTER("resize_simple_key_cache");
+
+ if (!keycache->key_cache_inited)
+ DBUG_RETURN(blocks);
+
+ /*
+ Note that the cache_lock mutex and the resize_queue are left untouched.
+ We do not lose the cache_lock and will release it only at the end of
+ this function.
+ */
+ if (prepare_resize_simple_key_cache(keycache, 1, 0))
+ goto finish;
+
+ /* The following will work even if use_mem is 0 */
+ blocks= init_simple_key_cache(keycache, key_cache_block_size, use_mem,
+ division_limit, age_threshold);
+
+finish:
+ finish_resize_simple_key_cache(keycache, 1, 0);
+
DBUG_RETURN(blocks);
}
@@ -670,7 +887,7 @@ finish:
/*
Increment counter blocking resize key cache operation
*/
-static inline void inc_counter_for_resize_op(KEY_CACHE *keycache)
+static inline void inc_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
keycache->cnt_for_resize_op++;
}
@@ -680,35 +897,47 @@ static inline void inc_counter_for_resize_op(KEY_CACHE *keycache)
Decrement counter blocking resize key cache operation;
Signal the operation to proceed when counter becomes equal zero
*/
-static inline void dec_counter_for_resize_op(KEY_CACHE *keycache)
+static inline void dec_counter_for_resize_op(SIMPLE_KEY_CACHE_CB *keycache)
{
if (!--keycache->cnt_for_resize_op)
release_whole_queue(&keycache->waiting_for_resize_cnt);
}
+
/*
- Change the key cache parameters
+ Change key cache parameters of a simple key cache
SYNOPSIS
- change_key_cache_param()
- keycache pointer to a key cache data structure
- division_limit new division limit (if not zero)
- age_threshold new age threshold (if not zero)
+ change_simple_key_cache_param()
+ keycache pointer to the control block of a simple key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the change_key_cache_param interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
+ cache where new values of the division limit and the age threshold used
+ for midpoint insertion strategy are to be set. The parameters
+ division_limit and age_threshold provide these new values.
RETURN VALUE
none
NOTES.
- Presently the function resets the key cache parameters
- concerning midpoint insertion strategy - division_limit and
- age_threshold.
+ Presently the function resets the key cache parameters concerning
+ midpoint insertion strategy - division_limit and age_threshold.
+ This function changes some parameters of a given key cache without
+ reformatting it. The function does not touch the contents the key
+ cache blocks.
*/
-void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
- uint age_threshold)
+static
+void change_simple_key_cache_param(SIMPLE_KEY_CACHE_CB *keycache, uint division_limit,
+ uint age_threshold)
{
- DBUG_ENTER("change_key_cache_param");
-
+ DBUG_ENTER("change_simple_key_cache_param");
keycache_pthread_mutex_lock(&keycache->cache_lock);
if (division_limit)
keycache->min_warm_blocks= (keycache->disk_blocks *
@@ -722,20 +951,31 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
/*
- Remove key_cache from memory
+ Destroy a simple key cache
SYNOPSIS
- end_key_cache()
- keycache key cache handle
- cleanup Complete free (Free also mutex for key cache)
+ end_simple_key_cache()
+ keycache pointer to the control block of a simple key cache
+ cleanup <=> complete free (free also mutex for key cache)
+
+ DESCRIPTION
+ This function is the implementation of the end_key_cache interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for the simple key
+ cache to be destroyed.
+ The function frees the memory allocated for the key cache blocks and
+ auxiliary structures. If the value of the parameter cleanup is TRUE
+ then even the key cache mutex is freed.
RETURN VALUE
none
*/
-void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
+static
+void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup)
{
- DBUG_ENTER("end_key_cache");
+ DBUG_ENTER("end_simple_key_cache");
DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
if (!keycache->key_cache_inited)
@@ -1026,7 +1266,7 @@ static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
void
*/
-static void link_to_file_list(KEY_CACHE *keycache,
+static void link_to_file_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int file,
my_bool unlink_block)
{
@@ -1067,7 +1307,7 @@ static void link_to_file_list(KEY_CACHE *keycache,
void
*/
-static void link_to_changed_list(KEY_CACHE *keycache,
+static void link_to_changed_list(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
@@ -1122,8 +1362,8 @@ static void link_to_changed_list(KEY_CACHE *keycache,
not linked in the LRU ring.
*/
-static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
- my_bool at_end)
+static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block,
+ my_bool hot, my_bool at_end)
{
BLOCK_LINK *ins;
BLOCK_LINK **pins;
@@ -1243,7 +1483,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
See NOTES for link_block
*/
-static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
+static void unlink_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE));
DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/
@@ -1301,7 +1541,8 @@ static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
RETURN
void
*/
-static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
+static void reg_requests(SIMPLE_KEY_CACHE_CB *keycache,
+ BLOCK_LINK *block, int count)
{
DBUG_ASSERT(block->status & BLOCK_IN_USE);
DBUG_ASSERT(block->hash_link);
@@ -1344,7 +1585,7 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
not linked in the LRU ring.
*/
-static void unreg_request(KEY_CACHE *keycache,
+static void unreg_request(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, int at_end)
{
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
@@ -1433,7 +1674,7 @@ static void remove_reader(BLOCK_LINK *block)
signals on its termination
*/
-static void wait_for_readers(KEY_CACHE *keycache,
+static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
#ifdef THREAD
@@ -1482,7 +1723,7 @@ static inline void link_hash(HASH_LINK **start, HASH_LINK *hash_link)
Remove a hash link from the hash table
*/
-static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
+static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
{
KEYCACHE_DBUG_PRINT("unlink_hash", ("fd: %u pos_ %lu #requests=%u",
(uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests));
@@ -1538,7 +1779,7 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
Get the hash link for a page
*/
-static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
+static HASH_LINK *get_hash_link(SIMPLE_KEY_CACHE_CB *keycache,
int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
@@ -1659,7 +1900,7 @@ restart:
waits until first of this operations links any block back.
*/
-static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
+static BLOCK_LINK *find_key_block(SIMPLE_KEY_CACHE_CB *keycache,
File file, my_off_t filepos,
int init_hits_left,
int wrmode, int *page_st)
@@ -2419,7 +2660,7 @@ restart:
portion is less than read_length, but not less than min_length.
*/
-static void read_block(KEY_CACHE *keycache,
+static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block, uint read_length,
uint min_length, my_bool primary)
{
@@ -2507,43 +2748,60 @@ static void read_block(KEY_CACHE *keycache,
/*
- Read a block of data from a cached file into a buffer;
+ Read a block of data from a simple key cache into a buffer
SYNOPSIS
- key_cache_read()
- keycache pointer to a key cache data structure
- file handler for the file for the block of data to be read
- filepos position of the block of data in the file
- level determines the weight of the data
- buff buffer to where the data must be placed
- length length of the buffer
- block_length length of the block in the key cache buffer
- return_buffer return pointer to the key cache buffer with the data
+ simple_key_cache_read()
+ keycache pointer to the control block of a simple key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ level determines the weight of the data
+ buff buffer to where the data must be placed
+ length length of the buffer
+ block_length length of the read data from a key cache block
+ return_buffer return pointer to the key cache buffer with the data
+ DESCRIPTION
+ This function is the implementation of the key_cache_read interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache.
+ In a general case the function reads a block of data from the key cache
+ into the buffer buff of the size specified by the parameter length. The
+ beginning of the block of data to be read is specified by the parameters
+ file and filepos. The length of the read data is the same as the length
+ of the buffer. The data is read into the buffer in key_cache_block_size
+ increments. If the next portion of the data is not found in any key cache
+ block, first it is read from file into the key cache.
+ If the parameter return_buffer is not ignored and its value is TRUE, and
+ the data to be read of the specified size block_length can be read from one
+ key cache buffer, then the function returns a pointer to the data in the
+ key cache buffer.
+ The function takse into account parameters block_length and return buffer
+ only in a single-threaded environment.
+ The parameter 'level' is used only by the midpoint insertion strategy
+ when the data or its portion cannot be found in the key cache.
+
RETURN VALUE
- Returns address from where the data is placed if sucessful, 0 - otherwise.
+ Returns address from where the data is placed if successful, 0 - otherwise.
- NOTES.
- The function ensures that a block of data of size length from file
- positioned at filepos is in the buffers for some key cache blocks.
- Then the function either copies the data into the buffer buff, or,
- if return_buffer is TRUE, it just returns the pointer to the key cache
- buffer with the data.
+ NOTES
Filepos must be a multiple of 'block_length', but it doesn't
have to be a multiple of key_cache_block_size;
*/
-uchar *key_cache_read(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int return_buffer __attribute__((unused)))
+uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
{
my_bool locked_and_incremented= FALSE;
int error=0;
uchar *start= buff;
- DBUG_ENTER("key_cache_read");
+ DBUG_ENTER("simple_key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
@@ -2738,28 +2996,47 @@ end:
/*
- Insert a block of file data from a buffer into key cache
+ Insert a block of file data from a buffer into a simple key cache
SYNOPSIS
- key_cache_insert()
- keycache pointer to a key cache data structure
+ simple_key_cache_insert()
+ keycache pointer to the control block of a simple key cache
file handler for the file to insert data from
filepos position of the block of data in the file to insert
level determines the weight of the data
buff buffer to read data from
length length of the data in the buffer
- NOTES
- This is used by MyISAM to move all blocks from a index file to the key
- cache
-
+ DESCRIPTION
+ This function is the implementation of the key_cache_insert interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache.
+ The function writes a block of file data from a buffer into the key cache.
+ The buffer is specified with the parameters buff and length - the pointer
+ to the beginning of the buffer and its size respectively. It's assumed
+ the buffer contains the data from 'file' allocated from the position
+ filepos. The data is copied from the buffer in key_cache_block_size
+ increments.
+ The parameter level is used to set one characteristic for the key buffers
+ loaded with the data from buff. The characteristic is used only by the
+ midpoint insertion strategy.
+
RETURN VALUE
0 if a success, 1 - otherwise.
+
+ NOTES
+ The function is used by MyISAM to move all blocks from a index file to
+ the key cache. It can be performed in parallel with reading the file data
+ from the key buffers by other threads.
+
*/
-int key_cache_insert(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length)
+static
+int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
{
int error= 0;
DBUG_ENTER("key_cache_insert");
@@ -2979,43 +3256,64 @@ int key_cache_insert(KEY_CACHE *keycache,
/*
- Write a buffer into a cached file.
+ Write a buffer into a simple key cache
SYNOPSIS
- key_cache_write()
- keycache pointer to a key cache data structure
- file handler for the file to write data to
- filepos position in the file to write data to
- level determines the weight of the data
- buff buffer with the data
- length length of the buffer
- dont_write if is 0 then all dirty pages involved in writing
- should have been flushed from key cache
+ simple_key_cache_write()
+ keycache pointer to the control block of a simple key cache
+ file handler for the file to write data to
+ file_extra maps of key cache partitions containing
+ dirty pages from file
+ filepos position in the file to write data to
+ level determines the weight of the data
+ buff buffer with the data
+ length length of the buffer
+ dont_write if is 0 then all dirty pages involved in writing
+ should have been flushed from key cache
+ DESCRIPTION
+ This function is the implementation of the key_cache_write interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache.
+ In a general case the function copies data from a buffer into the key
+ cache. The buffer is specified with the parameters buff and length -
+ the pointer to the beginning of the buffer and its size respectively.
+ It's assumed the buffer contains the data to be written into 'file'
+ starting from the position filepos. The data is copied from the buffer
+ in key_cache_block_size increments.
+ If the value of the parameter dont_write is FALSE then the function
+ also writes the data into file.
+ The parameter level is used to set one characteristic for the key buffers
+ filled with the data from buff. The characteristic is employed only by
+ the midpoint insertion strategy.
+ The parameter file_extra currently makes sense only for simple key caches
+ that are elements of a partitioned key cache. It provides a pointer to the
+ shared bitmap of the partitions that may contains dirty pages for the file.
+ This bitmap is used to optimize the function
+ flush_partitioned_key_cache_blocks.
+
RETURN VALUE
0 if a success, 1 - otherwise.
- NOTES.
- The function copies the data of size length from buff into buffers
- for key cache blocks that are assigned to contain the portion of
- the file starting with position filepos.
- It ensures that this data is flushed to the file if dont_write is FALSE.
- Filepos must be a multiple of 'block_length', but it doesn't
- have to be a multiple of key_cache_block_size;
-
- dont_write is always TRUE in the server (info->lock_type is never F_UNLCK).
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
*/
-int key_cache_write(KEY_CACHE *keycache,
- File file, my_off_t filepos, int level,
- uchar *buff, uint length,
- uint block_length __attribute__((unused)),
- int dont_write)
+static
+int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
+ File file, void *file_extra __attribute__((unused)),
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
{
my_bool locked_and_incremented= FALSE;
int error=0;
- DBUG_ENTER("key_cache_write");
+ DBUG_ENTER("simple_key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu length: %u block_length: %u"
" key_block_length: %u",
@@ -3330,7 +3628,7 @@ end:
Block must have a request registered on it.
*/
-static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block)
+static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
{
KEYCACHE_THREAD_TRACE("free block");
KEYCACHE_DBUG_PRINT("free_block",
@@ -3470,7 +3768,7 @@ static int cmp_sec_link(BLOCK_LINK **a, BLOCK_LINK **b)
free used blocks if requested
*/
-static int flush_cached_blocks(KEY_CACHE *keycache,
+static int flush_cached_blocks(SIMPLE_KEY_CACHE_CB *keycache,
File file, BLOCK_LINK **cache,
BLOCK_LINK **end,
enum flush_type type)
@@ -3514,9 +3812,9 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
(BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE));
block->status|= BLOCK_IN_FLUSHWRITE;
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- error= my_pwrite(file, block->buffer+block->offset,
+ error= my_pwrite(file, block->buffer + block->offset,
block->length - block->offset,
- block->hash_link->diskpos+ block->offset,
+ block->hash_link->diskpos + block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&keycache->cache_lock);
keycache->global_cache_write++;
@@ -3576,7 +3874,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
/*
- Flush all key blocks for a file to disk, but don't do any mutex locks.
+ Flush all key blocks for a file to disk, but don't do any mutex locks
SYNOPSIS
flush_key_blocks_int()
@@ -3598,7 +3896,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
1 error
*/
-static int flush_key_blocks_int(KEY_CACHE *keycache,
+static int flush_key_blocks_int(SIMPLE_KEY_CACHE_CB *keycache,
File file, enum flush_type type)
{
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
@@ -4040,22 +4338,46 @@ err:
/*
- Flush all blocks for a file to disk
+ Flush all blocks for a file from key buffers of a simple key cache
SYNOPSIS
- flush_key_blocks()
- keycache pointer to a key cache data structure
- file handler for the file to flush to
- flush_type type of the flush
+ flush_simple_key_blocks()
+ keycache pointer to the control block of a simple key cache
+ file handler for the file to flush to
+ file_extra maps of key cache partitions containing
+ dirty pages from file (not used)
+ flush_type type of the flush operation
+ DESCRIPTION
+ This function is the implementation of the flush_key_blocks interface
+ function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type S_KEY_CACHE_CB for a simple key
+ cache.
+ In a general case the function flushes the data from all dirty key
+ buffers related to the file 'file' into this file. The function does
+ exactly this if the value of the parameter type is FLUSH_KEEP. If the
+ value of this parameter is FLUSH_RELEASE, the function additionally
+ releases the key buffers containing data from 'file' for new usage.
+ If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
+ just releases the key buffers containing data from 'file'.
+ The parameter file_extra currently is not used by this function.
+
RETURN
0 ok
1 error
+
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
*/
-int flush_key_blocks(KEY_CACHE *keycache,
- File file, enum flush_type type)
+static
+int flush_simple_key_cache_blocks(SIMPLE_KEY_CACHE_CB *keycache,
+ File file,
+ void *file_extra __attribute__((unused)),
+ enum flush_type type)
{
int res= 0;
DBUG_ENTER("flush_key_blocks");
@@ -4109,7 +4431,7 @@ int flush_key_blocks(KEY_CACHE *keycache,
!= 0 Error
*/
-static int flush_all_key_blocks(KEY_CACHE *keycache)
+static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache)
{
BLOCK_LINK *block;
uint total_found;
@@ -4212,37 +4534,43 @@ static int flush_all_key_blocks(KEY_CACHE *keycache)
/*
- Reset the counters of a key cache.
+ Reset the counters of a simple key cache
SYNOPSIS
- reset_key_cache_counters()
- name the name of a key cache
- key_cache pointer to the key kache to be reset
+ reset_simple_key_cache_counters()
+ name the name of a key cache
+ keycache pointer to the control block of a simple key cache
DESCRIPTION
- This procedure is used by process_key_caches() to reset the counters of all
- currently used key caches, both the default one and the named ones.
+ This function is the implementation of the reset_key_cache_counters
+ interface function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type S_KEY_CACHE_CB for a simple key cache.
+ This function resets the values of all statistical counters for the key
+ cache to 0.
+ The parameter name is currently not used.
RETURN
0 on success (always because it can't fail)
*/
-int reset_key_cache_counters(const char *name __attribute__((unused)),
- KEY_CACHE *key_cache)
+static
+int reset_simple_key_cache_counters(const char *name __attribute__((unused)),
+ SIMPLE_KEY_CACHE_CB *keycache)
{
- DBUG_ENTER("reset_key_cache_counters");
- if (!key_cache->key_cache_inited)
+ DBUG_ENTER("reset_simple_key_cache_counters");
+ if (!keycache->key_cache_inited)
{
DBUG_PRINT("info", ("Key cache %s not initialized.", name));
DBUG_RETURN(0);
}
DBUG_PRINT("info", ("Resetting counters for key cache %s.", name));
- key_cache->global_blocks_changed= 0; /* Key_blocks_not_flushed */
- key_cache->global_cache_r_requests= 0; /* Key_read_requests */
- key_cache->global_cache_read= 0; /* Key_reads */
- key_cache->global_cache_w_requests= 0; /* Key_write_requests */
- key_cache->global_cache_write= 0; /* Key_writes */
+ keycache->global_blocks_changed= 0; /* Key_blocks_not_flushed */
+ keycache->global_cache_r_requests= 0; /* Key_read_requests */
+ keycache->global_cache_read= 0; /* Key_reads */
+ keycache->global_cache_w_requests= 0; /* Key_write_requests */
+ keycache->global_cache_write= 0; /* Key_writes */
DBUG_RETURN(0);
}
@@ -4251,9 +4579,10 @@ int reset_key_cache_counters(const char *name __attribute__((unused)),
/*
Test if disk-cache is ok
*/
-static void test_key_cache(KEY_CACHE *keycache __attribute__((unused)),
- const char *where __attribute__((unused)),
- my_bool lock __attribute__((unused)))
+static
+void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache __attribute__((unused)),
+ const char *where __attribute__((unused)),
+ my_bool lock __attribute__((unused)))
{
/* TODO */
}
@@ -4265,7 +4594,7 @@ static void test_key_cache(KEY_CACHE *keycache __attribute__((unused)),
#define MAX_QUEUE_LEN 100
-static void keycache_dump(KEY_CACHE *keycache)
+static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache)
{
FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
struct st_my_thread_var *last;
@@ -4505,7 +4834,7 @@ static int fail_hlink(HASH_LINK *hlink)
return 0; /* Let the assert fail. */
}
-static int cache_empty(KEY_CACHE *keycache)
+static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache)
{
int errcnt= 0;
int idx;
@@ -4543,3 +4872,1702 @@ static int cache_empty(KEY_CACHE *keycache)
}
#endif
+
+/*
+ Get statistics for a simple key cache
+
+ SYNOPSIS
+ get_simple_key_cache_statistics()
+ keycache pointer to the control block of a simple key cache
+ partition_no partition number (not used)
+ key_cache_stats OUT pointer to the structure for the returned statistics
+
+ DESCRIPTION
+ This function is the implementation of the get_key_cache_statistics
+ interface function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the statistical data for the key cache.
+ The parameter partition_no is not used by this function.
+
+ RETURN
+ none
+*/
+
+static
+void get_simple_key_cache_statistics(SIMPLE_KEY_CACHE_CB *keycache,
+ uint partition_no __attribute__((unused)),
+ KEY_CACHE_STATISTICS *keycache_stats)
+{
+ DBUG_ENTER("simple_get_key_cache_statistics");
+
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ keycache_stats->blocks_used= keycache->blocks_used;
+ keycache_stats->blocks_unused= keycache->blocks_unused;
+ keycache_stats->blocks_changed= keycache->global_blocks_changed;
+ keycache_stats->read_requests= keycache->global_cache_r_requests;
+ keycache_stats->reads= keycache->global_cache_read;
+ keycache_stats->write_requests= keycache->global_cache_w_requests;
+ keycache_stats->writes= keycache->global_cache_write;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Offsets of the statistical values in the control block for a simple key cache
+ The first NO_LONG_KEY_CACHE_STAT_VARIABLES=3 are of the ulong type while the
+ remaining are of the ulonglong type.
+ */
+static size_t simple_key_cache_stat_var_offsets[]=
+{
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_used),
+ offsetof(SIMPLE_KEY_CACHE_CB, blocks_unused),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_blocks_changed),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_w_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_write),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_r_requests),
+ offsetof(SIMPLE_KEY_CACHE_CB, global_cache_read)
+};
+
+
+/*
+ Get the value of a statistical variable for a simple key cache
+
+ SYNOPSIS
+ get_simple_key_cache_stat_value()
+ keycache pointer to the control block of a simple key cache
+ var_no the ordered number of a statistical variable
+
+ DESCRIPTION
+ This function is the implementation of the get_simple_key_cache_stat_value
+ interface function that is employed by simple (non-partitioned) key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type SIMPLE_KEY_CACHE_CB for a simple key
+ cache. This function returns the value of the statistical variable var_no
+ for this key cache. The variables are numbered starting from 0 to 6.
+
+ RETURN
+ The value of the specified statistical variable
+
+*/
+
+static
+ulonglong get_simple_key_cache_stat_value(SIMPLE_KEY_CACHE_CB *keycache,
+ uint var_no)
+{
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
+ ulonglong res= 0;
+ DBUG_ENTER("get_simple_key_cache_stat_value");
+
+ if (var_no < 3)
+ res= (ulonglong) (*(long *) ((char *) keycache + var_ofs));
+ else
+ res= *(ulonglong *) ((char *) keycache + var_ofs);
+
+ DBUG_RETURN(res);
+}
+
+
+/*
+ The array of pointer to the key cache interface functions used for simple
+ key caches. Any simple key cache objects including those incorporated into
+ partitioned keys caches exploit this array.
+
+ The current implementation of these functions allows to call them from
+ the MySQL server code directly. We don't do it though.
+*/
+
+static KEY_CACHE_FUNCS simple_key_cache_funcs =
+{
+ (INIT_KEY_CACHE) init_simple_key_cache,
+ (RESIZE_KEY_CACHE) resize_simple_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_simple_key_cache_param,
+ (KEY_CACHE_READ) simple_key_cache_read,
+ (KEY_CACHE_INSERT) simple_key_cache_insert,
+ (KEY_CACHE_WRITE) simple_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_simple_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_simple_key_cache_counters,
+ (END_KEY_CACHE) end_simple_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_simple_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_simple_key_cache_stat_value
+};
+
+
+/******************************************************************************
+ Partitioned Key Cache Module
+
+ The module contains implementations of all key cache interface functions
+ employed by partitioned key caches.
+
+ A partitioned key cache is a collection of structures for simple key caches
+ called key cache partitions. Any page from a file can be placed into a buffer
+ of only one partition. The number of the partition is calculated from
+ the file number and the position of the page in the file, and it's always the
+ same for the page. The function that maps pages into partitions takes care
+ of even distribution of pages among partitions.
+
+ Partition key cache mitigate one of the major problem of simple key cache:
+ thread contention for key cache lock (mutex). Every call of a key cache
+ interface function must acquire this lock. So threads compete for this lock
+ even in the case when they have acquired shared locks for the file and
+ pages they want read from are in the key cache buffers.
+ When working with a partitioned key cache any key cache interface function
+ that needs only one page has to acquire the key cache lock only for the
+ partition the page is ascribed to. This makes the chances for threads not
+ compete for the same key cache lock better. Unfortunately if we use a
+ partitioned key cache with N partitions for B-tree indexes we can't say
+ that the chances becomes N times less. The fact is that any index lookup
+ operation requires reading from the root page that, for any index, is always
+ ascribed to the same partition. To resolve this problem we should have
+ employed more sophisticated mechanisms of working with root pages.
+
+ Currently the number of partitions in a partitioned key cache is limited
+ by 64. We could increase this limit. Simultaneously we would have to increase
+ accordingly the size of the bitmap dirty_part_map from the MYISAM_SHARE
+ structure.
+
+******************************************************************************/
+
+/* Control block for a partitioned key cache */
+
+typedef struct st_partitioned_key_cache_cb
+{
+ my_bool key_cache_inited; /*<=> control block is allocated */
+ SIMPLE_KEY_CACHE_CB **partition_array; /* the key cache partitions */
+ size_t key_cache_mem_size; /* specified size of the cache memory */
+ uint key_cache_block_size; /* size of the page buffer of a cache block */
+ uint partitions; /* number of partitions in the key cache */
+} PARTITIONED_KEY_CACHE_CB;
+
+static
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup);
+
+static int
+reset_partitioned_key_cache_counters(const char *name,
+ PARTITIONED_KEY_CACHE_CB *keycache);
+
+/*
+ Determine the partition to which the index block to read is ascribed
+
+ SYNOPSIS
+ get_key_cache_partition()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+
+ DESCRIPTION
+ The function determines the number of the partition in whose buffer the
+ block from 'file' at the position filepos has to be placed for reading.
+ The function returns the control block of the simple key cache for this
+ partition to the caller.
+
+ RETURN VALUE
+ The pointer to the control block of the partition to which the specified
+ file block is ascribed.
+*/
+
+static
+SIMPLE_KEY_CACHE_CB *
+get_key_cache_partition(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos)
+{
+ uint i= KEYCACHE_BASE_EXPR(file, filepos) % keycache->partitions;
+ return keycache->partition_array[i];
+}
+
+
+/*
+ Determine the partition to which the index block to write is ascribed
+
+ SYNOPSIS
+ get_key_cache_partition()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ dirty_part_map pointer to the bitmap of dirty partitions for the file
+
+ DESCRIPTION
+ The function determines the number of the partition in whose buffer the
+ block from 'file' at the position filepos has to be placed for writing and
+ marks the partition as dirty in the dirty_part_map bitmap.
+ The function returns the control block of the simple key cache for this
+ partition to the caller.
+
+ RETURN VALUE
+ The pointer to the control block of the partition to which the specified
+ file block is ascribed.
+*/
+
+static SIMPLE_KEY_CACHE_CB
+*get_key_cache_partition_for_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos,
+ ulonglong* dirty_part_map)
+{
+ uint i= KEYCACHE_BASE_EXPR( file, filepos) % keycache->partitions;
+ *dirty_part_map|= 1ULL << i;
+ return keycache->partition_array[i];
+}
+
+
+/*
+ Initialize a partitioned key cache
+
+ SYNOPSIS
+ init_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for all key cache partitions
+ division_limit division limit (may be zero)
+ age_threshold age threshold (may be zero)
+
+ DESCRIPTION
+ This function is the implementation of the init_key_cache interface function
+ that is employed by partitioned key caches.
+ The function builds and initializes an array of simple key caches, and then
+ initializes the control block structure of the type PARTITIONED_KEY_CACHE_CB
+ that is used for a partitioned key cache. The parameter keycache is
+ supposed to point to this structure. The number of partitions in the
+ partitioned key cache to be built must be passed through the field
+ 'partitions' of this structure. The parameter key_cache_block_size specifies
+ the size of the blocks in the the simple key caches to be built.
+ The parameters division_limit and age_threshold determine the initial
+ values of those characteristics of the simple key caches that are used for
+ midpoint insertion strategy. The parameter use_mem specifies the total
+ amount of memory to be allocated for the key cache blocks in all simple key
+ caches and for all auxiliary structures.
+
+ RETURN VALUE
+ total number of blocks in key cache partitions, if successful,
+ <= 0 - otherwise.
+
+ NOTES
+ If keycache->key_cache_inited != 0 then we assume that the memory for
+ the array of partitions has been already allocated.
+
+ It's assumed that no two threads call this function simultaneously
+ referring to the same key cache handle.
+*/
+
+static
+int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
+{
+ int i;
+ size_t mem_per_cache;
+ size_t mem_decr;
+ int cnt;
+ SIMPLE_KEY_CACHE_CB *partition;
+ SIMPLE_KEY_CACHE_CB **partition_ptr;
+ uint partitions= keycache->partitions;
+ int blocks= 0;
+ DBUG_ENTER("partitioned_init_key_cache");
+
+ keycache->key_cache_block_size = key_cache_block_size;
+
+ if (keycache->key_cache_inited)
+ partition_ptr= keycache->partition_array;
+ else
+ {
+ if(!(partition_ptr=
+ (SIMPLE_KEY_CACHE_CB **) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB *) *
+ partitions, MYF(MY_WME))))
+ DBUG_RETURN(-1);
+ bzero(partition_ptr, sizeof(SIMPLE_KEY_CACHE_CB *) * partitions);
+ keycache->partition_array= partition_ptr;
+ }
+
+ mem_per_cache = use_mem / partitions;
+ mem_decr= mem_per_cache / 5;
+
+ for (i= 0; i < (int) partitions; i++)
+ {
+ my_bool key_cache_inited= keycache->key_cache_inited;
+ if (key_cache_inited)
+ partition= *partition_ptr;
+ else
+ {
+ if (!(partition=
+ (SIMPLE_KEY_CACHE_CB *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(MY_WME))))
+ continue;
+ partition->key_cache_inited= 0;
+ }
+
+ cnt= init_simple_key_cache(partition, key_cache_block_size, mem_per_cache,
+ division_limit, age_threshold);
+ if (cnt <= 0)
+ {
+ end_simple_key_cache(partition, 1);
+ if (!key_cache_inited)
+ {
+ my_free(partition, MYF(0));
+ partition= 0;
+ }
+ if ((i == 0 && cnt < 0) || i > 0)
+ {
+ /*
+ Here we have two cases:
+ 1. i == 0 and cnt < 0
+ cnt < 0 => mem_per_cache is not big enough to allocate minimal
+ number of key blocks in the key cache of the partition.
+ Decrease the the number of the partitions by 1 and start again.
+ 2. i > 0
+ There is not enough memory for one of the succeeding partitions.
+ Just skip this partition decreasing the number of partitions in
+ the key cache by one.
+ Do not change the value of mem_per_cache in both cases.
+ */
+ if (key_cache_inited)
+ {
+ my_free(partition, MYF(0));
+ partition= 0;
+ if(key_cache_inited)
+ memmove(partition_ptr, partition_ptr+1,
+ sizeof(partition_ptr)*(partitions-i-1));
+ }
+ if (!--partitions)
+ break;
+ }
+ else
+ {
+ /*
+ We come here when i == 0 && cnt == 0.
+ cnt == 0 => the memory allocator fails to allocate a block of
+ memory of the size mem_per_cache. Decrease the value of
+ mem_per_cache without changing the current number of partitions
+ and start again. Make sure that such a decrease may happen not
+ more than 5 times in total.
+ */
+ if (use_mem <= mem_decr)
+ break;
+ use_mem-= mem_decr;
+ }
+ i--;
+ mem_per_cache= use_mem/partitions;
+ continue;
+ }
+ else
+ {
+ blocks+= cnt;
+ *partition_ptr++= partition;
+ }
+ }
+
+ keycache->partitions= partitions= partition_ptr-keycache->partition_array;
+ keycache->key_cache_mem_size= mem_per_cache * partitions;
+ for (i= 0; i < (int) partitions; i++)
+ keycache->partition_array[i]->hash_factor= partitions;
+
+ keycache->key_cache_inited= 1;
+
+ if (!partitions)
+ blocks= -1;
+
+ DBUG_RETURN(blocks);
+}
+
+
+/*
+ Resize a partitioned key cache
+
+ SYNOPSIS
+ resize_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for the new key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the resize_key_cache interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be resized.
+ The parameter key_cache_block_size specifies the new size of the blocks in
+ the simple key caches that comprise the partitioned key cache.
+ The parameters division_limit and age_threshold determine the new initial
+ values of those characteristics of the simple key cache that are used for
+ midpoint insertion strategy. The parameter use-mem specifies the total
+ amount of memory to be allocated for the key cache blocks in all new
+ simple key caches and for all auxiliary structures.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES.
+ The function first calls prepare_resize_simple_key_cache for each simple
+ key cache effectively flushing all dirty pages from it and destroying
+ the key cache. Then init_partitioned_key_cache is called. This call builds
+ a new array of simple key caches containing the same number of elements
+ as the old one. After this the function calls the function
+ finish_resize_simple_key_cache for each simple key cache from this array.
+
+ This implementation doesn't block the calls and executions of other
+ functions from the key cache interface. However it assumes that the
+ calls of resize_partitioned_key_cache itself are serialized.
+*/
+
+static
+int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ my_bool cleanup= use_mem == 0;
+ int blocks= -1;
+ int err= 0;
+ DBUG_ENTER("partitioned_resize_key_cache");
+ if (cleanup)
+ {
+ end_partitioned_key_cache(keycache, 0);
+ DBUG_RETURN(-1);
+ }
+ for (i= 0; i < partitions; i++)
+ {
+ err|= prepare_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
+ }
+ if (!err)
+ blocks= init_partitioned_key_cache(keycache, key_cache_block_size,
+ use_mem, division_limit, age_threshold);
+ if (blocks > 0)
+ {
+ for (i= 0; i < partitions; i++)
+ {
+ finish_resize_simple_key_cache(keycache->partition_array[i], 0, 1);
+ }
+ }
+ DBUG_RETURN(blocks);
+}
+
+
+/*
+ Change key cache parameters of a partitioned key cache
+
+ SYNOPSIS
+ partitioned_change_key_cache_param()
+ keycache pointer to the control block of a partitioned key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ This function is the implementation of the change_key_cache_param interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the simple
+ key cache where new values of the division limit and the age threshold used
+ for midpoint insertion strategy are to be set. The parameters
+ division_limit and age_threshold provide these new values.
+
+ RETURN VALUE
+ none
+
+ NOTES
+ The function just calls change_simple_key_cache_param for each element from
+ the array of simple caches that comprise the partitioned key cache.
+*/
+
+static
+void change_partitioned_key_cache_param(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint division_limit,
+ uint age_threshold)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("partitioned_change_key_cache_param");
+ for (i= 0; i < partitions; i++)
+ {
+ change_simple_key_cache_param(keycache->partition_array[i], division_limit,
+ age_threshold);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Destroy a partitioned key cache
+
+ SYNOPSIS
+ end_partitioned_key_cache()
+ keycache pointer to the control block of a partitioned key cache
+ cleanup <=> complete free (free also control block structures
+ for all simple key caches)
+
+ DESCRIPTION
+ This function is the implementation of the end_key_cache interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for the
+ partitioned key cache to be destroyed.
+ The function frees the memory allocated for the cache blocks and
+ auxiliary structures used by simple key caches that comprise the
+ partitioned key cache. If the value of the parameter cleanup is TRUE
+ then even the memory used for control blocks of the simple key caches
+ and the array of pointers to them are freed.
+
+ RETURN VALUE
+ none
+*/
+
+static
+void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
+ my_bool cleanup)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("partitioned_end_key_cache");
+ DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
+
+ for (i= 0; i < partitions; i++)
+ {
+ end_simple_key_cache(keycache->partition_array[i], cleanup);
+ }
+ if (cleanup)
+ {
+ for (i= 0; i < partitions; i++)
+ my_free((uchar*) keycache->partition_array[i], MYF(0));
+ my_free((uchar*) keycache->partition_array, MYF(0));
+ keycache->key_cache_inited= 0;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Read a block of data from a partitioned key cache into a buffer
+
+ SYNOPSIS
+
+ partitioned_key_cache_read()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ level determines the weight of the data
+ buff buffer to where the data must be placed
+ length length of the buffer
+ block_length length of the read data from a key cache block
+ return_buffer return pointer to the key cache buffer with the data
+
+ DESCRIPTION
+ This function is the implementation of the key_cache_read interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ In a general case the function reads a block of data from the key cache
+ into the buffer buff of the size specified by the parameter length. The
+ beginning of the block of data to be read is specified by the parameters
+ file and filepos. The length of the read data is the same as the length
+ of the buffer. The data is read into the buffer in key_cache_block_size
+ increments. To read each portion the function first finds out in what
+ partition of the key cache this portion(page) is to be saved, and calls
+ simple_key_cache_read with the pointer to the corresponding simple key as
+ its first parameter.
+ If the parameter return_buffer is not ignored and its value is TRUE, and
+ the data to be read of the specified size block_length can be read from one
+ key cache buffer, then the function returns a pointer to the data in the
+ key cache buffer.
+ The function takes into account parameters block_length and return buffer
+ only in a single-threaded environment.
+ The parameter 'level' is used only by the midpoint insertion strategy
+ when the data or its portion cannot be found in the key cache.
+
+ RETURN VALUE
+ Returns address from where the data is placed if successful, 0 - otherwise.
+*/
+
+static
+uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int return_buffer __attribute__((unused)))
+{
+ uint r_length;
+ uint offset= (uint) (filepos % keycache->key_cache_block_size);
+ uchar *start= buff;
+ DBUG_ENTER("partitioned_key_cache_read");
+ DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
+ (uint) file, (ulong) filepos, length));
+
+#ifndef THREAD
+ if (block_length > keycache->key_cache_block_size || offset)
+ return_buffer=0;
+#endif
+
+ /* Read data in key_cache_block_size increments */
+ do
+ {
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
+ uchar *ret_buff= 0;
+ r_length= length;
+ set_if_smaller(r_length, keycache->key_cache_block_size - offset);
+ ret_buff= simple_key_cache_read((void *) partition,
+ file, filepos, level,
+ buff, r_length,
+ block_length, return_buffer);
+ if (ret_buff == 0)
+ DBUG_RETURN(0);
+#ifndef THREAD
+ /* This is only true if we were able to read everything in one block */
+ if (return_buffer)
+ DBUG_RETURN(ret_buff);
+#endif
+ filepos+= r_length;
+ buff+= r_length;
+ offset= 0;
+ } while ((length-= r_length));
+
+ DBUG_RETURN(start);
+}
+
+
+/*
+ Insert a block of file data from a buffer into a partitioned key cache
+
+ SYNOPSIS
+ partitioned_key_cache_insert()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file to insert data from
+ filepos position of the block of data in the file to insert
+ level determines the weight of the data
+ buff buffer to read data from
+ length length of the data in the buffer
+
+ DESCRIPTION
+ This function is the implementation of the key_cache_insert interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ The function writes a block of file data from a buffer into the key cache.
+ The buffer is specified with the parameters buff and length - the pointer
+ to the beginning of the buffer and its size respectively. It's assumed
+ that the buffer contains the data from 'file' allocated from the position
+ filepos. The data is copied from the buffer in key_cache_block_size
+ increments. For every portion of data the function finds out in what simple
+ key cache from the array of partitions the data must be stored, and after
+ this calls simple_key_cache_insert to copy the data into a key buffer of
+ this simple key cache.
+ The parameter level is used to set one characteristic for the key buffers
+ loaded with the data from buff. The characteristic is used only by the
+ midpoint insertion strategy.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ The function is used by MyISAM to move all blocks from a index file to
+ the key cache. It can be performed in parallel with reading the file data
+ from the key buffers by other threads.
+*/
+
+static
+int partitioned_key_cache_insert(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
+{
+ uint w_length;
+ uint offset= (uint) (filepos % keycache->key_cache_block_size);
+ DBUG_ENTER("partitioned_key_cache_insert");
+ DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
+ (uint) file,(ulong) filepos, length));
+
+
+ /* Write data in key_cache_block_size increments */
+ do
+ {
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition(keycache,
+ file, filepos);
+ w_length= length;
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset);
+ if (simple_key_cache_insert((void *) partition,
+ file, filepos, level,
+ buff, w_length))
+ DBUG_RETURN(1);
+
+ filepos+= w_length;
+ buff+= w_length;
+ offset = 0;
+ } while ((length-= w_length));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Write data from a buffer into a partitioned key cache
+
+ SYNOPSIS
+
+ partitioned_key_cache_write()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file to write data to
+ filepos position in the file to write data to
+ level determines the weight of the data
+ buff buffer with the data
+ length length of the buffer
+ dont_write if is 0 then all dirty pages involved in writing
+ should have been flushed from key cache
+ file_extra maps of key cache partitions containing
+ dirty pages from file
+
+ DESCRIPTION
+ This function is the implementation of the key_cache_write interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ In a general case the function copies data from a buffer into the key
+ cache. The buffer is specified with the parameters buff and length -
+ the pointer to the beginning of the buffer and its size respectively.
+ It's assumed the buffer contains the data to be written into 'file'
+ starting from the position filepos. The data is copied from the buffer
+ in key_cache_block_size increments. For every portion of data the
+ function finds out in what simple key cache from the array of partitions
+ the data must be stored, and after this calls simple_key_cache_write to
+ copy the data into a key buffer of this simple key cache.
+ If the value of the parameter dont_write is FALSE then the function
+ also writes the data into file.
+ The parameter level is used to set one characteristic for the key buffers
+ filled with the data from buff. The characteristic is employed only by
+ the midpoint insertion strategy.
+ The parameter file_expra provides a pointer to the shared bitmap of
+ the partitions that may contains dirty pages for the file. This bitmap
+ is used to optimize the function flush_partitioned_key_cache_blocks.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
+*/
+
+static
+int partitioned_key_cache_write(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length __attribute__((unused)),
+ int dont_write)
+{
+ uint w_length;
+ ulonglong *part_map= (ulonglong *) file_extra;
+ uint offset= (uint) (filepos % keycache->key_cache_block_size);
+ DBUG_ENTER("partitioned_key_cache_write");
+ DBUG_PRINT("enter",
+ ("fd: %u pos: %lu length: %u block_length: %u"
+ " key_block_length: %u",
+ (uint) file, (ulong) filepos, length, block_length,
+ keycache ? keycache->key_cache_block_size : 0));
+
+
+ /* Write data in key_cache_block_size increments */
+ do
+ {
+ SIMPLE_KEY_CACHE_CB *partition= get_key_cache_partition_for_write(keycache,
+ file,
+ filepos,
+ part_map);
+ w_length = length;
+ set_if_smaller(w_length, keycache->key_cache_block_size - offset );
+ if (simple_key_cache_write(partition,
+ file, 0, filepos, level,
+ buff, w_length, block_length,
+ dont_write))
+ DBUG_RETURN(1);
+
+ filepos+= w_length;
+ buff+= w_length;
+ offset= 0;
+ } while ((length-= w_length));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Flush all blocks for a file from key buffers of a partitioned key cache
+
+ SYNOPSIS
+
+ flush_partitioned_key_cache_blocks()
+ keycache pointer to the control block of a partitioned key cache
+ file handler for the file to flush to
+ file_extra maps of key cache partitions containing
+ dirty pages from file (not used)
+ flush_type type of the flush operation
+
+ DESCRIPTION
+ This function is the implementation of the flush_key_blocks interface
+ function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ In a general case the function flushes the data from all dirty key
+ buffers related to the file 'file' into this file. The function does
+ exactly this if the value of the parameter type is FLUSH_KEEP. If the
+ value of this parameter is FLUSH_RELEASE, the function additionally
+ releases the key buffers containing data from 'file' for new usage.
+ If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
+ just releases the key buffers containing data from 'file'.
+ The function performs the operation by calling the function
+ flush_simple_key_cache_blocks for the elements of the array of the
+ simple key caches that comprise the partitioned key_cache. If the value
+ of the parameter type is FLUSH_KEEP s_flush_key_blocks is called only
+ for the partitions with possibly dirty pages marked in the bitmap
+ pointed to by the parameter file_extra.
+
+ RETURN
+ 0 ok
+ 1 error
+
+ NOTES
+ This implementation exploits the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
+*/
+
+static
+int flush_partitioned_key_cache_blocks(PARTITIONED_KEY_CACHE_CB *keycache,
+ File file, void *file_extra,
+ enum flush_type type)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ int err= 0;
+ ulonglong *dirty_part_map= (ulonglong *) file_extra;
+ DBUG_ENTER("partitioned_flush_key_blocks");
+ DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
+
+ for (i= 0; i < partitions; i++)
+ {
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ if ((type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) &&
+ !((*dirty_part_map) & ((ulonglong) 1 << i)))
+ continue;
+ err|= test(flush_simple_key_cache_blocks(partition, file, 0, type));
+ }
+ *dirty_part_map= 0;
+
+ DBUG_RETURN(err);
+}
+
+
+/*
+ Reset the counters of a partitioned key cache
+
+ SYNOPSIS
+ reset_partitioned_key_cache_counters()
+ name the name of a key cache
+ keycache pointer to the control block of a partitioned key cache
+
+ DESCRIPTION
+ This function is the implementation of the reset_key_cache_counters
+ interface function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a partitioned
+ key cache.
+ This function resets the values of the statistical counters of the simple
+ key caches comprising partitioned key cache to 0. It does it by calling
+ reset_simple_key_cache_counters for each key cache partition.
+ The parameter name is currently not used.
+
+ RETURN
+ 0 on success (always because it can't fail)
+*/
+
+static int
+reset_partitioned_key_cache_counters(const char *name __attribute__((unused)),
+ PARTITIONED_KEY_CACHE_CB *keycache)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("partitioned_reset_key_cache_counters");
+
+ for (i = 0; i < partitions; i++)
+ {
+ reset_simple_key_cache_counters(name, keycache->partition_array[i]);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Get statistics for a partition key cache
+
+ SYNOPSIS
+ get_partitioned_key_cache_statistics()
+ keycache pointer to the control block of a partitioned key cache
+ partition_no partition number to get statistics for
+ key_cache_stats OUT pointer to the structure for the returned statistics
+
+ DESCRIPTION
+ This function is the implementation of the get_key_cache_statistics
+ interface function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for
+ a partitioned key cache.
+ If the value of the parameter partition_no is equal to 0 then aggregated
+ statistics for all partitions is returned in the fields of the
+ structure key_cache_stat of the type KEY_CACHE_STATISTICS . Otherwise
+ the function returns data for the partition number partition_no of the
+ key cache in the structure key_cache_stat. (Here partitions are numbered
+ starting from 1.)
+
+ RETURN
+ none
+*/
+
+static
+void
+get_partitioned_key_cache_statistics(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint partition_no,
+ KEY_CACHE_STATISTICS *keycache_stats)
+{
+ uint i;
+ SIMPLE_KEY_CACHE_CB *partition;
+ uint partitions= keycache->partitions;
+ DBUG_ENTER("get_partitioned_key_cache_statistics");
+
+ if (partition_no != 0)
+ {
+ partition= keycache->partition_array[partition_no-1];
+ get_simple_key_cache_statistics((void *) partition, 0, keycache_stats);
+ DBUG_VOID_RETURN;
+ }
+ bzero(keycache_stats, sizeof(KEY_CACHE_STATISTICS));
+ keycache_stats->mem_size= (longlong) keycache->key_cache_mem_size;
+ keycache_stats->block_size= (longlong) keycache->key_cache_block_size;
+ for (i = 0; i < partitions; i++)
+ {
+ partition= keycache->partition_array[i];
+ keycache_stats->blocks_used+= partition->blocks_used;
+ keycache_stats->blocks_unused+= partition->blocks_unused;
+ keycache_stats->blocks_changed+= partition->global_blocks_changed;
+ keycache_stats->read_requests+= partition->global_cache_r_requests;
+ keycache_stats->reads+= partition->global_cache_read;
+ keycache_stats->write_requests+= partition->global_cache_w_requests;
+ keycache_stats->writes+= partition->global_cache_write;
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Get the value of a statistical variable for a partitioned key cache
+
+ SYNOPSIS
+ get_partitioned_key_cache_stat_value()
+ keycache pointer to the control block of a partitioned key cache
+ var_no the ordered number of a statistical variable
+
+ DESCRIPTION
+ This function is the implementation of the get_key_cache_stat_value
+ interface function that is employed by partitioned key caches.
+ The function takes the parameter keycache as a pointer to the
+ control block structure of the type PARTITIONED_KEY_CACHE_CB for a
+ partitioned key cache.
+ This function returns the value of the statistical variable var_no
+ for this key cache. The variables are numbered starting from 0 to 6.
+ The returned value is calculated as the sum of the values of the
+ statistical variable with number var_no for all simple key caches that
+ comprise the partitioned key cache.
+
+ RETURN
+ The value of the specified statistical variable
+*/
+
+static
+ulonglong
+get_partitioned_key_cache_stat_value(PARTITIONED_KEY_CACHE_CB *keycache,
+ uint var_no)
+{
+ uint i;
+ uint partitions= keycache->partitions;
+ size_t var_ofs= simple_key_cache_stat_var_offsets[var_no];
+ ulonglong res= 0;
+ DBUG_ENTER("get_partitioned_key_cache_stat_value");
+
+ if (var_no < NUM_LONG_KEY_CACHE_STAT_VARIABLES)
+ {
+ for (i = 0; i < partitions; i++)
+ {
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ res+= (ulonglong) (*(long *) ((char *) partition + var_ofs));
+ }
+ }
+ else
+ {
+ for (i = 0; i < partitions; i++)
+ {
+ SIMPLE_KEY_CACHE_CB *partition= keycache->partition_array[i];
+ res+= *(ulonglong *) ((char *) partition + var_ofs);
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+/*
+ The array of pointers to the key cache interface functions used by
+ partitioned key caches. Any partitioned key cache object caches exploits
+ this array.
+
+ The current implementation of these functions does not allow to call
+ them from the MySQL server code directly. The key cache interface
+ wrappers must be used for this purpose.
+*/
+
+static KEY_CACHE_FUNCS partitioned_key_cache_funcs =
+{
+ (INIT_KEY_CACHE) init_partitioned_key_cache,
+ (RESIZE_KEY_CACHE) resize_partitioned_key_cache,
+ (CHANGE_KEY_CACHE_PARAM) change_partitioned_key_cache_param,
+ (KEY_CACHE_READ) partitioned_key_cache_read,
+ (KEY_CACHE_INSERT) partitioned_key_cache_insert,
+ (KEY_CACHE_WRITE) partitioned_key_cache_write,
+ (FLUSH_KEY_BLOCKS) flush_partitioned_key_cache_blocks,
+ (RESET_KEY_CACHE_COUNTERS) reset_partitioned_key_cache_counters,
+ (END_KEY_CACHE) end_partitioned_key_cache,
+ (GET_KEY_CACHE_STATISTICS) get_partitioned_key_cache_statistics,
+ (GET_KEY_CACHE_STAT_VALUE) get_partitioned_key_cache_stat_value
+};
+
+
+/******************************************************************************
+ Key Cache Interface Module
+
+ The module contains wrappers for all key cache interface functions.
+
+ Currently there are key caches of two types: simple key caches and
+ partitioned key caches. Each type (class) has its own implementation of the
+ basic key cache operations used the MyISAM storage engine. The pointers
+ to the implementation functions are stored in two static structures of the
+ type KEY_CACHE_FUNC: simple_key_cache_funcs - for simple key caches, and
+ partitioned_key_cache_funcs - for partitioned key caches. When a key cache
+ object is created the constructor procedure init_key_cache places a pointer
+ to the corresponding table into one of its fields. The procedure also
+ initializes a control block for the key cache oject and saves the pointer
+ to this block in another field of the key cache object.
+ When a key cache wrapper function is invoked for a key cache object to
+ perform a basic key cache operation it looks into the interface table
+ associated with the key cache oject and calls the corresponding
+ implementation of the operation. It passes the saved key cache control
+ block to this implementation. If, for some reasons, the control block
+ has not been fully initialized yet, the wrapper function either does not
+ do anything or, in the case when it perform a read/write operation, the
+ function do it directly through the system i/o functions.
+
+ As we can see the model with which the key cache interface is supported
+ as quite conventional for interfaces in general.
+
+******************************************************************************/
+
+
+/*
+ Initialize a key cache
+
+ SYNOPSIS
+ init_key_cache()
+ keycache pointer to the key cache to be initialized
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for cache buffers/structures
+ division_limit division limit (may be zero)
+ age_threshold age threshold (may be zero)
+ partitions number of partitions in the key cache
+
+ DESCRIPTION
+ The function creates a control block structure for a key cache and
+ places the pointer to this block in the structure keycache.
+ If the value of the parameter 'partitions' is 0 then a simple key cache
+ is created. Otherwise a partitioned key cache with the specified number
+ of partitions is created.
+ The parameter key_cache_block_size specifies the size of the blocks in
+ the key cache to be created. The parameters division_limit and
+ age_threshold determine the initial values of those characteristics of
+ the key cache that are used for midpoint insertion strategy. The parameter
+ use_mem specifies the total amount of memory to be allocated for the
+ key cache buffers and for all auxiliary structures.
+
+ RETURN VALUE
+ total number of blocks in key cache partitions, if successful,
+ <= 0 - otherwise.
+
+ NOTES
+ if keycache->key_cache_inited != 0 we assume that the memory
+ for the control block of the key cache has been already allocated.
+
+ It's assumed that no two threads call this function simultaneously
+ referring to the same key cache handle.
+*/
+
+int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold, uint partitions)
+{
+ void *keycache_cb;
+ int blocks;
+ if (keycache->key_cache_inited)
+ keycache_cb= keycache->keycache_cb;
+ else
+ {
+ if (partitions == 0)
+ {
+ if (!(keycache_cb= (void *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB),
+ MYF(0))))
+ return 0;
+ ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ keycache->key_cache_type= SIMPLE_KEY_CACHE;
+ keycache->interface_funcs= &simple_key_cache_funcs;
+ }
+ else
+ {
+ if (!(keycache_cb= (void *) my_malloc(sizeof(PARTITIONED_KEY_CACHE_CB),
+ MYF(0))))
+ return 0;
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0;
+ keycache->key_cache_type= PARTITIONED_KEY_CACHE;
+ keycache->interface_funcs= &partitioned_key_cache_funcs;
+ }
+ keycache->keycache_cb= keycache_cb;
+ keycache->key_cache_inited= 1;
+ }
+
+ if (partitions != 0)
+ {
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions= partitions;
+ }
+ keycache->can_be_used= 0;
+ blocks= keycache->interface_funcs->init(keycache_cb, key_cache_block_size,
+ use_mem, division_limit,
+ age_threshold);
+ keycache->partitions= partitions ?
+ ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions :
+ 0;
+ DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
+ if (blocks > 0)
+ keycache->can_be_used= 1;
+ return blocks;
+}
+
+
+/*
+ Resize a key cache
+
+ SYNOPSIS
+ resize_key_cache()
+ keycache pointer to the key cache to be resized
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for the new key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ The function operates over the key cache key cache.
+ The parameter key_cache_block_size specifies the new size of the block
+ buffers in the key cache. The parameters division_limit and age_threshold
+ determine the new initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for the key cache
+ buffers and for all auxiliary structures.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES
+ The function does not block the calls and executions of other functions
+ from the key cache interface. However it assumes that the calls of
+ resize_key_cache itself are serialized.
+
+ Currently the function is called when the values of the variables
+ key_buffer_size and/or key_cache_block_size are being reset for
+ the key cache keycache.
+*/
+
+int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit, uint age_threshold)
+{
+ int blocks= -1;
+ if (keycache->key_cache_inited)
+ {
+ if ((uint) keycache->param_partitions != keycache->partitions && use_mem)
+ blocks= repartition_key_cache(keycache,
+ key_cache_block_size, use_mem,
+ division_limit, age_threshold,
+ (uint) keycache->param_partitions);
+ else
+ {
+ blocks= keycache->interface_funcs->resize(keycache->keycache_cb,
+ key_cache_block_size,
+ use_mem, division_limit,
+ age_threshold);
+
+ if (keycache->partitions)
+ keycache->partitions=
+ ((PARTITIONED_KEY_CACHE_CB *)(keycache->keycache_cb))->partitions;
+ }
+
+ keycache->can_be_used= (blocks >= 0);
+ }
+ return blocks;
+}
+
+
+/*
+ Change key cache parameters of a key cache
+
+ SYNOPSIS
+ change_key_cache_param()
+ keycache pointer to the key cache to change parameters for
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+
+ DESCRIPTION
+ The function sets new values of the division limit and the age threshold
+ used when the key cache keycach employs midpoint insertion strategy.
+ The parameters division_limit and age_threshold provide these new values.
+
+ RETURN VALUE
+ none
+
+ NOTES
+ Currently the function is called when the values of the variables
+ key_cache_division_limit and/or key_cache_age_threshold are being reset
+ for the key cache keycache.
+*/
+
+void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
+ uint age_threshold)
+{
+ if (keycache->key_cache_inited)
+ {
+
+ keycache->interface_funcs->change_param(keycache->keycache_cb,
+ division_limit,
+ age_threshold);
+ }
+}
+
+
+/*
+ Destroy a key cache
+
+ SYNOPSIS
+ end_key_cache()
+ keycache pointer to the key cache to be destroyed
+ cleanup <=> complete free
+
+ DESCRIPTION
+ The function frees the memory allocated for the cache blocks and
+ auxiliary structures used by the key cache keycache. If the value
+ of the parameter cleanup is TRUE then all resources used by the key
+ cache are to be freed.
+
+ RETURN VALUE
+ none
+*/
+
+void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
+{
+ if (keycache->key_cache_inited)
+ {
+ keycache->interface_funcs->end(keycache->keycache_cb, cleanup);
+ if (cleanup)
+ {
+ if (keycache->keycache_cb)
+ {
+ my_free((uchar *) keycache->keycache_cb, MYF(0));
+ keycache->keycache_cb= 0;
+ }
+ keycache->key_cache_inited= 0;
+ }
+ keycache->can_be_used= 0;
+ }
+}
+
+
+/*
+ Read a block of data from a key cache into a buffer
+
+ SYNOPSIS
+
+ key_cache_read()
+ keycache pointer to the key cache to read data from
+ file handler for the file for the block of data to be read
+ filepos position of the block of data in the file
+ level determines the weight of the data
+ buff buffer to where the data must be placed
+ length length of the buffer
+ block_length length of the data read from a key cache block
+ return_buffer return pointer to the key cache buffer with the data
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ In a general case the function reads a block of data from the key cache
+ into the buffer buff of the size specified by the parameter length. The
+ beginning of the block of data to be read is specified by the parameters
+ file and filepos. The length of the read data is the same as the length
+ of the buffer.
+ If the parameter return_buffer is not ignored and its value is TRUE, and
+ the data to be read of the specified size block_length can be read from one
+ key cache buffer, then the function returns a pointer to the data in the
+ key cache buffer.
+ The parameter 'level' is used only by the midpoint insertion strategy
+ when the data or its portion cannot be found in the key cache.
+ The function reads data into the buffer directly from file if the control
+ block of the key cache has not been initialized yet.
+
+ RETURN VALUE
+ Returns address from where the data is placed if successful, 0 - otherwise.
+
+ NOTES.
+ Filepos must be a multiple of 'block_length', but it doesn't
+ have to be a multiple of key_cache_block_size;
+*/
+
+uchar *key_cache_read(KEY_CACHE *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int return_buffer)
+{
+ if (keycache->key_cache_inited && keycache->can_be_used)
+ return keycache->interface_funcs->read(keycache->keycache_cb,
+ file, filepos, level,
+ buff, length,
+ block_length, return_buffer);
+
+ /* We can't use mutex here as the key cache may not be initialized */
+ keycache->global_cache_r_requests++;
+ keycache->global_cache_read++;
+
+ if (my_pread(file, (uchar*) buff, length, filepos, MYF(MY_NABP)))
+ return (uchar *) 0;
+
+ return buff;
+}
+
+
+/*
+ Insert a block of file data from a buffer into a key cache
+
+ SYNOPSIS
+ key_cache_insert()
+ keycache pointer to the key cache to insert data into
+ file handler for the file to insert data from
+ filepos position of the block of data in the file to insert
+ level determines the weight of the data
+ buff buffer to read data from
+ length length of the data in the buffer
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ The function writes a block of file data from a buffer into the key cache.
+ The buffer is specified with the parameters buff and length - the pointer
+ to the beginning of the buffer and its size respectively. It's assumed
+ that the buffer contains the data from 'file' allocated from the position
+ filepos.
+ The parameter level is used to set one characteristic for the key buffers
+ loaded with the data from buff. The characteristic is used only by the
+ midpoint insertion strategy.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ The function is used by MyISAM to move all blocks from a index file to
+ the key cache.
+ It is assumed that it may be performed in parallel with reading the file
+ data from the key buffers by other threads.
+*/
+
+int key_cache_insert(KEY_CACHE *keycache,
+ File file, my_off_t filepos, int level,
+ uchar *buff, uint length)
+{
+ if (keycache->key_cache_inited && keycache->can_be_used)
+ return keycache->interface_funcs->insert(keycache->keycache_cb,
+ file, filepos, level,
+ buff, length);
+ return 0;
+}
+
+
+/*
+ Write data from a buffer into a key cache
+
+ SYNOPSIS
+
+ key_cache_write()
+ keycache pointer to the key cache to write data to
+ file handler for the file to write data to
+ filepos position in the file to write data to
+ level determines the weight of the data
+ buff buffer with the data
+ length length of the buffer
+ dont_write if is 0 then all dirty pages involved in writing
+ should have been flushed from key cache
+ file_extra pointer to optional file attributes
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ In a general case the function writes data from a buffer into the key
+ cache. The buffer is specified with the parameters buff and length -
+ the pointer to the beginning of the buffer and its size respectively.
+ It's assumed the buffer contains the data to be written into 'file'
+ starting from the position filepos.
+ If the value of the parameter dont_write is FALSE then the function
+ also writes the data into file.
+ The parameter level is used to set one characteristic for the key buffers
+ filled with the data from buff. The characteristic is employed only by
+ the midpoint insertion strategy.
+ The parameter file_expra may point to additional file attributes used
+ for optimization or other purposes.
+ The function writes data from the buffer directly into file if the control
+ block of the key cache has not been initialized yet.
+
+ RETURN VALUE
+ 0 if a success, 1 - otherwise.
+
+ NOTES
+ This implementation may exploit the fact that the function is called only
+ when a thread has got an exclusive lock for the key file.
+*/
+
+int key_cache_write(KEY_CACHE *keycache,
+ File file, void *file_extra,
+ my_off_t filepos, int level,
+ uchar *buff, uint length,
+ uint block_length, int force_write)
+{
+ if (keycache->key_cache_inited && keycache->can_be_used)
+ return keycache->interface_funcs->write(keycache->keycache_cb,
+ file, file_extra,
+ filepos, level,
+ buff, length,
+ block_length, force_write);
+
+ /* We can't use mutex here as the key cache may not be initialized */
+ keycache->global_cache_w_requests++;
+ keycache->global_cache_write++;
+ if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL)))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+ Flush all blocks for a file from key buffers of a key cache
+
+ SYNOPSIS
+
+ flush_key_blocks()
+ keycache pointer to the key cache whose blocks are to be flushed
+ file handler for the file to flush to
+ file_extra maps of key cache (used for partitioned key caches)
+ flush_type type of the flush operation
+
+ DESCRIPTION
+ The function operates over buffers of the key cache keycache.
+ In a general case the function flushes the data from all dirty key
+ buffers related to the file 'file' into this file. The function does
+ exactly this if the value of the parameter type is FLUSH_KEEP. If the
+ value of this parameter is FLUSH_RELEASE, the function additionally
+ releases the key buffers containing data from 'file' for new usage.
+ If the value of the parameter type is FLUSH_IGNORE_CHANGED the function
+ just releases the key buffers containing data from 'file'.
+ If the value of the parameter type is FLUSH_KEEP the function may use
+ the value of the parameter file_extra pointing to possibly dirty
+ partitions to optimize the operation for partitioned key caches.
+
+ RETURN
+ 0 ok
+ 1 error
+
+ NOTES
+ Any implementation of the function may exploit the fact that the function
+ is called only when a thread has got an exclusive lock for the key file.
+*/
+
+int flush_key_blocks(KEY_CACHE *keycache,
+ int file, void *file_extra,
+ enum flush_type type)
+{
+ if (keycache->key_cache_inited)
+ return keycache->interface_funcs->flush(keycache->keycache_cb,
+ file, file_extra, type);
+ return 0;
+}
+
+
+/*
+ Reset the counters of a key cache
+
+ SYNOPSIS
+ reset_key_cache_counters()
+ name the name of a key cache (unused)
+ keycache pointer to the key cache for which to reset counters
+
+ DESCRIPTION
+ This function resets the values of the statistical counters for the key
+ cache keycache.
+ The parameter name is currently not used.
+
+ RETURN
+ 0 on success (always because it can't fail)
+
+ NOTES
+ This procedure is used by process_key_caches() to reset the counters of all
+ currently used key caches, both the default one and the named ones.
+*/
+
+int reset_key_cache_counters(const char *name __attribute__((unused)),
+ KEY_CACHE *keycache)
+{
+ if (keycache->key_cache_inited)
+ {
+
+ return keycache->interface_funcs->reset_counters(name,
+ keycache->keycache_cb);
+ }
+ return 0;
+}
+
+
+/*
+ Get statistics for a key cache
+
+ SYNOPSIS
+ get_key_cache_statistics()
+ keycache pointer to the key cache to get statistics for
+ partition_no partition number to get statistics for
+ key_cache_stats OUT pointer to the structure for the returned statistics
+
+ DESCRIPTION
+ If the value of the parameter partition_no is equal to 0 then statistics
+ for the whole key cache keycache (aggregated statistics) is returned in the
+ fields of the structure key_cache_stat of the type KEY_CACHE_STATISTICS.
+ Otherwise the value of the parameter partition_no makes sense only for
+ a partitioned key cache. In this case the function returns statistics
+ for the partition with the specified number partition_no.
+
+ RETURN
+ none
+*/
+
+void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no,
+ KEY_CACHE_STATISTICS *key_cache_stats)
+{
+ if (keycache->key_cache_inited)
+ {
+ keycache->interface_funcs->get_stats(keycache->keycache_cb,
+ partition_no, key_cache_stats);
+ }
+}
+
+
+/*
+ Get the value of a statistical variable for a key cache
+
+ SYNOPSIS
+ get_key_cache_stat_value()
+ keycache pointer to the key cache to get statistics for
+ var_no the ordered number of a statistical variable
+
+ DESCRIPTION
+ This function returns the value of the statistical variable var_no for
+ the key cache keycache. The variables are numbered starting from 0 to 6.
+
+ RETURN
+ The value of the specified statistical variable.
+
+ NOTES
+ Currently for any key cache the function can return values for the
+ following 7 statistical variables:
+
+ Name Number
+
+ blocks_used 0
+ blocks_unused 1
+ blocks_changed 2
+ read_requests 3
+ reads 4
+ write_requests 5
+ writes 6
+*/
+
+ulonglong get_key_cache_stat_value(KEY_CACHE *keycache, uint var_no)
+{
+ if (keycache->key_cache_inited)
+ {
+ return keycache->interface_funcs->get_stat_val(keycache->keycache_cb,
+ var_no);
+ }
+ else
+ return 0;
+}
+
+
+/*
+ Repartition a key cache
+
+ SYNOPSIS
+ repartition_key_cache()
+ keycache pointer to the key cache to be repartitioned
+ key_cache_block_size size of blocks to keep cached data
+ use_mem total memory to use for the new key cache
+ division_limit new division limit (if not zero)
+ age_threshold new age threshold (if not zero)
+ partitions new number of partitions in the key cache
+
+ DESCRIPTION
+ The function operates over the key cache keycache.
+ The parameter partitions specifies the number of partitions in the key
+ cache after repartitioning. If the value of this parameter is 0 then
+ a simple key cache must be created instead of the old one.
+ The parameter key_cache_block_size specifies the new size of the block
+ buffers in the key cache. The parameters division_limit and age_threshold
+ determine the new initial values of those characteristics of the key cache
+ that are used for midpoint insertion strategy. The parameter use_mem
+ specifies the total amount of memory to be allocated for the new key
+ cache buffers and for all auxiliary structures.
+
+ RETURN VALUE
+ number of blocks in the key cache, if successful,
+ 0 - otherwise.
+
+ NOTES
+ The function does not block the calls and executions of other functions
+ from the key cache interface. However it assumes that the calls of
+ resize_key_cache itself are serialized.
+
+ Currently the function is called when the value of the variable
+ key_cache_partitions is being reset for the key cache keycache.
+*/
+
+int repartition_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
+ size_t use_mem, uint division_limit,
+ uint age_threshold, uint partitions)
+{
+ uint blocks= -1;
+ if (keycache->key_cache_inited)
+ {
+ keycache->interface_funcs->resize(keycache->keycache_cb,
+ key_cache_block_size, 0,
+ division_limit, age_threshold);
+ end_key_cache(keycache, 1);
+ blocks= init_key_cache(keycache, key_cache_block_size, use_mem,
+ division_limit, age_threshold, partitions);
+ }
+ return blocks;
+}
+
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
index 64480c4aa7a..336d005d7d5 100644
--- a/mysys/my_getsystime.c
+++ b/mysys/my_getsystime.c
@@ -28,6 +28,10 @@
#ifdef __NETWARE__
#include <nks/time.h>
#endif
+#ifdef HAVE_LINUX_UNISTD_H
+#include <linux/unistd.h>
+#endif
+
ulonglong my_getsystime()
{
@@ -222,3 +226,25 @@ time_t my_time_possible_from_micro(ulonglong microtime __attribute__((unused)))
return (time_t) (microtime / 1000000);
#endif /* defined(__WIN__) */
}
+
+
+/*
+ Return cpu time in milliseconds * 10
+*/
+
+ulonglong my_getcputime()
+{
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec tp;
+ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp))
+ return 0;
+ return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100;
+#elif defined(__NR_clock_gettime)
+ struct timespec tp;
+ if (syscall(__NR_clock_gettime, CLOCK_THREAD_CPUTIME_ID, &tp))
+ return 0;
+ return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100;
+#else
+ return 0;
+#endif /* HAVE_CLOCK_GETTIME */
+}
diff --git a/plugin/auth/Makefile.am b/plugin/auth/Makefile.am
new file mode 100644
index 00000000000..acca98e26f8
--- /dev/null
+++ b/plugin/auth/Makefile.am
@@ -0,0 +1,15 @@
+pkgplugindir=$(pkglibdir)/plugin
+
+AM_LDFLAGS=-module -rpath $(pkgplugindir)
+AM_CPPFLAGS=-DMYSQL_DYNAMIC_PLUGIN -I$(top_srcdir)/include
+
+pkgplugin_LTLIBRARIES= dialog.la
+dialog_la_SOURCES= dialog.c
+
+if HAVE_PEERCRED
+pkgplugin_LTLIBRARIES+= auth_socket.la
+auth_socket_la_SOURCES= auth_socket.c
+endif
+
+EXTRA_DIST= plug.in
+
diff --git a/plugin/auth/auth_socket.c b/plugin/auth/auth_socket.c
new file mode 100644
index 00000000000..cc406dac331
--- /dev/null
+++ b/plugin/auth/auth_socket.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program 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 */
+
+/**
+ @file
+
+ socket_peercred authentication plugin.
+
+ Authentication is successful if the connection is done via a unix socket and
+ the owner of the client process matches the user name that was used when
+ connecting to mysqld.
+*/
+#define _GNU_SOURCE /* for struct ucred */
+
+#include <mysql/plugin_auth.h>
+#include <sys/socket.h>
+#include <pwd.h>
+#include <string.h>
+
+/**
+ perform the unix socket based authentication
+
+ This authentication callback performs a unix socket based authentication -
+ it gets the uid of the client process and considers the user authenticated
+ if it uses username of this uid. That is - if the user is already
+ authenticated to the OS (if she is logged in) - she can use MySQL as herself
+*/
+
+static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ MYSQL_PLUGIN_VIO_INFO vio_info;
+ struct ucred cred;
+ socklen_t cred_len= sizeof(cred);
+ struct passwd pwd_buf, *pwd;
+ char buf[1024];
+
+ /* no user name yet ? read the client handshake packet with the user name */
+ if (info->user_name == 0)
+ {
+ if (vio->read_packet(vio, &pkt) < 0)
+ return CR_ERROR;
+ }
+
+ info->password_used = 0;
+
+ vio->info(vio, &vio_info);
+ if (vio_info.protocol != MYSQL_VIO_SOCKET)
+ return CR_ERROR;
+
+ /* get the UID of the client process */
+ if (getsockopt(vio_info.socket, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len))
+ return CR_ERROR;
+
+ if (cred_len != sizeof(cred))
+ return CR_ERROR;
+
+ /* and find the username for this uid */
+ getpwuid_r(cred.uid, &pwd_buf, buf, sizeof(buf), &pwd);
+ if (pwd == NULL)
+ return CR_ERROR;
+
+ /* now it's simple as that */
+ return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK;
+}
+
+static struct st_mysql_auth socket_auth_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ 0,
+ socket_auth
+};
+
+mysql_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+maria_declare_plugin(socket_auth)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &socket_auth_handler,
+ "socket_peercred",
+ "Sergei Golubchik",
+ "Unix Socket based authentication",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+maria_declare_plugin_end;
+
diff --git a/plugin/auth/dialog.c b/plugin/auth/dialog.c
new file mode 100644
index 00000000000..72c6364f49a
--- /dev/null
+++ b/plugin/auth/dialog.c
@@ -0,0 +1,346 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program 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 */
+
+/**
+ @file
+
+ dialog client authentication plugin with examples
+
+ dialog is a general purpose client authentication plugin, it simply
+ asks the user the question, as provided by the server and reports
+ the answer back to the server. No encryption is involved,
+ the answers are sent in clear text.
+
+ Two examples are provided: two_questions server plugin, that asks
+ the password and an "Are you sure?" question with a reply "yes, of course".
+ It demonstrates the usage of "password" (input is hidden) and "ordinary"
+ (input can be echoed) questions, and how to mark the last question,
+ to avoid an extra roundtrip.
+
+ And three_attempts plugin that gives the user three attempts to enter
+ a correct password. It shows the situation when a number of questions
+ is not known in advance.
+*/
+#define _GNU_SOURCE /* for RTLD_DEFAULT */
+
+#include <mysql/plugin_auth.h>
+#include <mysql/client_plugin.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/**
+ first byte of the question string is the question "type".
+ It can be a "ordinary" or a "password" question.
+ The last bit set marks a last question in the authentication exchange.
+*/
+#define ORDINARY_QUESTION "\2"
+#define LAST_QUESTION "\3"
+#define PASSWORD_QUESTION "\4"
+#define LAST_PASSWORD "\5"
+
+typedef unsigned char uchar;
+
+/********************* SERVER SIDE ****************************************/
+
+/**
+ dialog demo with two questions, one password and one ordinary.
+*/
+
+static int two_questions(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len;
+
+ /* send a password question */
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"),
+ 18))
+ return CR_ERROR;
+
+ /* read the answer */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ /* fail if the password is wrong */
+ if (strcmp((char*) pkt, info->auth_string))
+ return CR_ERROR;
+
+ /* send the last, ordinary, question */
+ if (vio->write_packet(vio,
+ (const uchar*) (LAST_QUESTION "Are you sure ?"), 15))
+ return CR_ERROR;
+
+ /* read the answer */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ /* check the reply */
+ return strcmp((char*) pkt, "yes, of course") ? CR_ERROR : CR_OK;
+}
+
+static struct st_mysql_auth two_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog", /* requires dialog client plugin */
+ two_questions
+};
+
+
+/**
+ dialog demo where the number of questions is not known in advance
+*/
+
+static int three_attempts(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ unsigned char *pkt;
+ int pkt_len, i;
+
+ for (i= 0; i < 3; i++)
+ {
+ /* send the prompt */
+ if (vio->write_packet(vio,
+ (const uchar*) (PASSWORD_QUESTION "Password, please:"), 18))
+ return CR_ERROR;
+
+ /* read the password */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ /*
+ finish, if the password is correct.
+ note, that we did not mark the prompt packet as "last"
+ */
+ if (strcmp((char*) pkt, info->auth_string) == 0)
+ return CR_OK;
+ }
+
+ return CR_ERROR;
+}
+
+static struct st_mysql_auth three_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog", /* requires dialog client plugin */
+ three_attempts
+};
+
+mysql_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+maria_declare_plugin(dialog)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &two_handler,
+ "two_questions",
+ "Sergei Golubchik",
+ "Dialog plugin demo 1",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &three_handler,
+ "three_attempts",
+ "Sergei Golubchik",
+ "Dialog plugin demo 2",
+ PLUGIN_LICENSE_GPL,
+ NULL,
+ NULL,
+ 0x0100,
+ NULL,
+ NULL,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+maria_declare_plugin_end;
+
+/********************* CLIENT SIDE ***************************************/
+/*
+ This plugin performs a dialog with the user, asking questions and
+ reading answers. Depending on the client it may be desirable to do it
+ using GUI, or console, with or without curses, or read answers
+ from a smardcard, for example.
+
+ To support all this variety, the dialog plugin has a callback function
+ "authentication_dialog_ask". If the client has a function of this name
+ dialog plugin will use it for communication with the user. Otherwise
+ a default gets() based implementation will be used.
+*/
+#include <mysql.h>
+#include <dlfcn.h>
+
+static mysql_authentication_dialog_ask_t ask;
+
+static char *builtin_ask(MYSQL *mysql __attribute__((unused)),
+ int type __attribute__((unused)),
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ int len;
+
+ fputs(prompt, stdout);
+ fputc(' ', stdout);
+ if (fgets(buf, buf_len, stdin) == 0)
+ return 0;
+
+ len= strlen(buf);
+ if (len && buf[len-1]=='\n')
+ buf[len-1]=0;
+
+ return buf;
+}
+
+
+/**
+ The main function of the dialog plugin.
+
+ Read the prompt, ask the question, send the reply, repeat until
+ the server is satisfied.
+
+ @note
+ 1. this plugin shows how a client authentication plugin
+ may read a MySQL protocol OK packet internally - which is important
+ where a number of packets is not known in advance.
+ 2. the first byte of the prompt is special. it is not
+ shown to the user, but signals whether it is the last question
+ (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0),
+ and whether the input is a password (not echoed).
+ 3. the prompt is expected to be sent zero-terminated
+*/
+
+static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ unsigned char *pkt, cmd= 0;
+ int pkt_len, res;
+ char reply_buf[1024], *reply;
+
+ do
+ {
+ /* read the prompt */
+ pkt_len= vio->read_packet(vio, &pkt);
+ if (pkt_len < 0)
+ return CR_ERROR;
+
+ if (pkt == 0)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet, so
+ the first vio->read_packet() does nothing (pkt == 0).
+
+ We send the "password", assuming the client knows what its doing.
+ (in other words, the dialog plugin should be only set as a default
+ authentication plugin on the client if the first question
+ asks for a password - which will be sent in clear text, by the way)
+ */
+ reply= mysql->passwd;
+ }
+ else
+ {
+ cmd= *pkt++;
+
+ /* is it MySQL protocol packet ? */
+ if (cmd == 0 || cmd == 254)
+ return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */
+
+ /*
+ asking for a password with an empty prompt means mysql->password
+ otherwise we ask the user and read the reply
+ */
+ if ((cmd >> 1) == 2 && *pkt == 0)
+ reply= mysql->passwd;
+ else
+ reply= ask(mysql, cmd >> 1, (char*) pkt, reply_buf, sizeof(reply_buf));
+ if (!reply)
+ return CR_ERROR;
+ }
+ /* send the reply to the server */
+ res= vio->write_packet(vio, (uchar*) reply, strlen(reply)+1);
+
+ if (reply != mysql->passwd && reply != reply_buf)
+ free(reply);
+
+ if (res)
+ return CR_ERROR;
+
+ /* repeat unless it was the last question */
+ } while ((cmd & 1) != 1);
+
+ /* the job of reading the ok/error packet is left to the server */
+ return CR_OK;
+}
+
+
+/**
+ initialization function of the dialog plugin
+
+ Pick up the client's authentication_dialog_ask() function, if exists,
+ or fall back to the default implementation.
+*/
+
+static int init_dialog()
+{
+ void *sym= dlsym(RTLD_DEFAULT, "mysql_authentication_dialog_ask");
+ ask= sym ? (mysql_authentication_dialog_ask_t)sym : builtin_ask;
+ return 0;
+}
+
+mysql_declare_client_plugin(AUTHENTICATION)
+ "dialog",
+ "Sergei Golubchik",
+ "Dialog Client Authentication Plugin",
+ {0,1,0},
+ init_dialog,
+ NULL,
+ perform_dialog
+mysql_end_client_plugin;
+
diff --git a/plugin/auth/plug.in b/plugin/auth/plug.in
new file mode 100644
index 00000000000..ce31465b056
--- /dev/null
+++ b/plugin/auth/plug.in
@@ -0,0 +1,15 @@
+MYSQL_PLUGIN(auth, [Collection of Authentication Plugins],
+ [Collection of Authentication Plugins])
+MYSQL_PLUGIN_DYNAMIC(auth, [dialog.la])
+MYSQL_PLUGIN_ACTIONS(auth,[
+AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#define _GNU_SOURCE
+#include <sys/socket.h>
+]],[[
+ struct ucred cred;
+ getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0);
+]])],have_peercred=yes)
+AM_CONDITIONAL(HAVE_PEERCRED, test x$have_peercred = xyes)
+])
+AM_CONDITIONAL(HAVE_PEERCRED, false)
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/plugin/daemon_example/daemon_example.cc b/plugin/daemon_example/daemon_example.cc
index e683bf7ab7a..38c1f2f3181 100644
--- a/plugin/daemon_example/daemon_example.cc
+++ b/plugin/daemon_example/daemon_example.cc
@@ -200,3 +200,20 @@ mysql_declare_plugin(daemon_example)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(daemon_example)
+{
+ MYSQL_DAEMON_PLUGIN,
+ &daemon_example_plugin,
+ "daemon_example",
+ "Brian Aker",
+ "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log",
+ PLUGIN_LICENSE_GPL,
+ daemon_example_plugin_init, /* Plugin Init */
+ daemon_example_plugin_deinit, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c
index 87eb7f3e150..f39ff6a78fd 100644
--- a/plugin/fulltext/plugin_example.c
+++ b/plugin/fulltext/plugin_example.c
@@ -270,4 +270,21 @@ mysql_declare_plugin(ftexample)
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(ftexample)
+{
+ MYSQL_FTPARSER_PLUGIN, /* type */
+ &simple_parser_descriptor, /* descriptor */
+ "simple_parser", /* name */
+ "MySQL AB", /* author */
+ "Simple Full-Text Parser", /* description */
+ PLUGIN_LICENSE_GPL,
+ simple_parser_plugin_init, /* init function (when loaded) */
+ simple_parser_plugin_deinit,/* deinit function (when unloaded) */
+ 0x0001, /* version */
+ simple_status, /* status variables */
+ simple_system_variables, /* system variables */
+ "0.01", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/randgen/conf/maria_group_commit.yy b/randgen/conf/maria_group_commit.yy
new file mode 100644
index 00000000000..e136cbf7b07
--- /dev/null
+++ b/randgen/conf/maria_group_commit.yy
@@ -0,0 +1,181 @@
+# test of group commit switching
+
+query:
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ select | insert | update| delete |
+ change_group_commit | change_interval;
+
+
+select:
+ SELECT select_item FROM join where order_by limit;
+
+select_item:
+ * | X . _field ;
+
+join:
+ _table AS X |
+ _table AS X LEFT JOIN _table AS Y ON ( X . _field = Y . _field ) ;
+
+where:
+ |
+ WHERE X . _field < value |
+ WHERE X . _field > value |
+ WHERE X . _field = value ;
+
+where_delete:
+ |
+ WHERE _field < value |
+ WHERE _field > value |
+ WHERE _field = value ;
+
+order_by:
+ | ORDER BY X . _field ;
+
+limit:
+ | LIMIT _digit ;
+
+insert:
+ INSERT INTO _table ( _field , _field ) VALUES ( value , value ) ;
+
+update:
+ UPDATE _table AS X SET _field = value where order_by limit ;
+
+delete:
+ DELETE FROM _table where_delete LIMIT _digit ;
+
+value:
+ ' _letter ' | _digit | _date | _datetime | _time | _english ;
+
+change_group_commit:
+ SET GLOBAL MARIA_GROUP_COMMIT=none_soft_hard;
+
+none_soft_hard:
+ NONE | SOFT | HARD;
+
+change_interval:
+ set_interval | set_interval | set_interval | set_interval |
+ drop_interval;
+
+set_interval:
+ SET GLOBAL MARIA_GROUP_COMMIT_INTERVAL=_tinyint_unsigned;
+
+drop_interval:
+ SET GLOBAL MARIA_GROUP_COMMIT_INTERVAL=0;
diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist
index aa252ed2b7b..bdaa07a907f 100755
--- a/scripts/make_win_bin_dist
+++ b/scripts/make_win_bin_dist
@@ -163,7 +163,7 @@ if [ -f "storage/pbxt/bin/xtstat.exe" ] ; then
cp storage/pbxt/bin/xtstat.{exe,pdb} $DESTDIR/bin
fi
-cp server-tools/instance-manager/$TARGET/*.{exe,map} $DESTDIR/bin/
+cp server-tools/instance-manager/$TARGET/*.exe $DESTDIR/bin/
if [ x"$TARGET" != x"release" ] ; then
cp server-tools/instance-manager/$TARGET/*.pdb $DESTDIR/bin/
cp client/$TARGET/mysql.pdb $DESTDIR/bin/
@@ -361,7 +361,7 @@ cp -R mysql-test/{t,r,include,suite,std_data,lib,collections} $DESTDIR/mysql-tes
rm -rf $DESTDIR/mysql-test/lib/My/SafeProcess/my_safe_kill.{dir,vcproj}
rm -rf $DESTDIR/mysql-test/lib/My/SafeProcess/my_safe_process.{dir,vcproj}
-rm -rf $DESTDIR/mysql-test/lib/My/SafeProcess/{Debug,RelWithDebInfo}/*.{ilk,idb,map}
+rm -rf $DESTDIR/mysql-test/lib/My/SafeProcess/{Debug,RelWithDebInfo}/*.{ilk,idb}
# Note that this will not copy "extra" if a soft link
diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
index 923497b0ab2..aabb1fdb4b7 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, 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, plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, auth_string TEXT 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,7 +60,7 @@ 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', 'IGNORE_BAD_TABLE_OPTIONS', '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 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';
@@ -80,7 +80,7 @@ PREPARE stmt FROM @str;
EXECUTE stmt;
DROP PREPARE stmt;
-CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', 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) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', 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) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
+CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', 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) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;
diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql
index 9a3a3f7bb84..b8726e68276 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','','','','',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 (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 deeb4d4de82..69fc1b8a052 100644
--- a/scripts/mysql_system_tables_fix.sql
+++ b/scripts/mysql_system_tables_fix.sql
@@ -385,7 +385,7 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL,
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'IGNORE_BAD_TABLE_OPTIONS',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -499,14 +499,14 @@ ALTER TABLE db MODIFY Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NO
ALTER TABLE event DROP PRIMARY KEY;
ALTER TABLE event ADD PRIMARY KEY(db, name);
# Add sql_mode column just in case.
-ALTER TABLE event ADD sql_mode set ('NOT_USED') AFTER on_completion;
+ALTER TABLE event ADD sql_mode set ('IGNORE_BAD_TABLE_OPTIONS') AFTER on_completion;
# Update list of sql_mode values.
ALTER TABLE event MODIFY sql_mode
set('REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'IGNORE_BAD_TABLE_OPTIONS',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
@@ -588,6 +588,9 @@ ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete
UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0;
+ALTER TABLE user ADD plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL, ADD auth_string TEXT NOT NULL;
+ALTER TABLE user MODIFY plugin char(60) CHARACTER SET latin1 DEFAULT '' NOT NULL;
+
# 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/server-tools/CMakeLists.txt b/server-tools/CMakeLists.txt
index 3f02ba88f1d..9cfeb4e80f9 100644
--- a/server-tools/CMakeLists.txt
+++ b/server-tools/CMakeLists.txt
@@ -27,7 +27,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instanc
user_management_commands.cc
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
- ../../libmysql/errmsg.c)
+ ../../libmysql/errmsg.c ../../sql-common/client_plugin.c)
ADD_DEPENDENCIES(mysqlmanager GenError)
TARGET_LINK_LIBRARIES(mysqlmanager dbug mysys strings taocrypt vio yassl zlib wsock32)
diff --git a/server-tools/instance-manager/CMakeLists.txt b/server-tools/instance-manager/CMakeLists.txt
index c988a03912e..2d04e522a6d 100755
--- a/server-tools/instance-manager/CMakeLists.txt
+++ b/server-tools/instance-manager/CMakeLists.txt
@@ -20,8 +20,6 @@ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS(-DMYSQL_SERVER -DMYSQL_INSTANCE_MANAGER)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/sql
${PROJECT_SOURCE_DIR}/extra/yassl/include)
-
-SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MAP /MAPINFO:EXPORTS")
ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instance.cc instance_map.cc
instance_options.cc listener.cc log.cc manager.cc messages.cc mysql_connection.cc
@@ -30,7 +28,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instanc
user_management_commands.cc ../../mysys/my_rnd.c
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
- ../../libmysql/errmsg.c)
+ ../../libmysql/errmsg.c ../../sql-common/client_plugin.c)
ADD_DEPENDENCIES(mysqlmanager GenError)
TARGET_LINK_LIBRARIES(mysqlmanager debug dbug mysys strings taocrypt vio yassl zlib wsock32)
diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am
index 19c4ac8de19..5c5af3377eb 100644
--- a/server-tools/instance-manager/Makefile.am
+++ b/server-tools/instance-manager/Makefile.am
@@ -46,7 +46,8 @@ libnet_a_LIBADD= $(top_builddir)/sql/password.$(OBJEXT) \
$(top_builddir)/sql/pack.$(OBJEXT) \
$(top_builddir)/sql/sql_state.$(OBJEXT) \
$(top_builddir)/sql/mini_client_errors.$(OBJEXT)\
- $(top_builddir)/sql/client.$(OBJEXT)
+ $(top_builddir)/sql/client.$(OBJEXT) \
+ $(top_builddir)/sql/client_plugin.$(OBJEXT)
CLEANFILES= net_serv.cc client_settings.h
@@ -91,7 +92,7 @@ mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
$(top_builddir)/dbug/libdbug.a \
- @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@
+ @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@ @LIBDL@
EXTRA_DIST = WindowsService.cpp WindowsService.h IMService.cpp \
IMService.h CMakeLists.txt
diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc
index 85e3f4a2cac..b7a32f1d047 100644
--- a/server-tools/instance-manager/user_map.cc
+++ b/server-tools/instance-manager/user_map.cc
@@ -368,7 +368,7 @@ int User_map::authenticate(const LEX_STRING *user_name,
const char *scramble) const
{
const User *user= find_user(user_name);
- return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
+ return user ? check_scramble((uchar*)scrambled_password, scramble, user->salt) : 2;
}
diff --git a/sql-common/Makefile.am b/sql-common/Makefile.am
index 614ccffde9d..7b883ec2457 100644
--- a/sql-common/Makefile.am
+++ b/sql-common/Makefile.am
@@ -14,7 +14,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## Process this file with automake to create Makefile.in
-EXTRA_DIST = client.c pack.c my_time.c my_user.c
+EXTRA_DIST = client.c pack.c my_time.c my_user.c client_plugin.c
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql-common/client.c b/sql-common/client.c
index 05b5f820138..2cad8df1f9b 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -107,6 +107,10 @@ my_bool net_flush(NET *net);
#include "client_settings.h"
#include <sql_common.h>
+#include <mysql/client_plugin.h>
+
+#define native_password_plugin_name "mysql_native_password"
+#define old_password_plugin_name "mysql_old_password"
uint mysql_port=0;
char *mysql_unix_port= 0;
@@ -332,7 +336,7 @@ void net_clear_error(NET *net)
@param ... variable number of arguments
*/
-static void set_mysql_extended_error(MYSQL *mysql, int errcode,
+void set_mysql_extended_error(MYSQL *mysql, int errcode,
const char *sqlstate,
const char *format, ...)
{
@@ -1002,9 +1006,20 @@ static const char *default_options[]=
"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",
+ "report-data-truncation", "plugin-dir", "default-auth",
NullS
};
+enum option_id {
+ OPT_port=1, OPT_socket, OPT_compress, OPT_password, OPT_pipe, OPT_timeout, OPT_user,
+ OPT_init_command, OPT_host, OPT_database, OPT_debug, OPT_return_found_rows,
+ OPT_ssl_key, OPT_ssl_cert, OPT_ssl_ca, OPT_ssl_capath,
+ OPT_character_sets_dir, OPT_default_character_set, OPT_interactive_timeout,
+ OPT_connect_timeout, OPT_local_infile, OPT_disable_local_infile,
+ OPT_replication_probe, OPT_enable_reads_from_master, OPT_repl_parse_query,
+ OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
+ OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
+ OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
+};
static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options, NULL};
@@ -1035,6 +1050,15 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
return 0;
}
+#define extension_set_string(OPTS, X, STR) \
+ if ((OPTS)->extension) \
+ my_free((OPTS)->extension->X, MYF(MY_ALLOW_ZERO_PTR)); \
+ else \
+ (OPTS)->extension= (struct st_mysql_options_extention *) \
+ my_malloc(sizeof(struct st_mysql_options_extention), \
+ MYF(MY_WME | MY_ZEROFILL)); \
+ (OPTS)->extension->X= my_strdup((STR), MYF(MY_WME));
+
void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
{
@@ -1067,134 +1091,134 @@ void mysql_read_default_options(struct st_mysql_options *options,
for (end= *option ; *(end= strcend(end,'_')) ; )
*end= '-';
switch (find_type(*option+2,&option_types,2)) {
- case 1: /* port */
+ case OPT_port:
if (opt_arg)
options->port=atoi(opt_arg);
break;
- case 2: /* socket */
+ case OPT_socket:
if (opt_arg)
{
my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 3: /* compress */
+ case OPT_compress:
options->compress=1;
options->client_flag|= CLIENT_COMPRESS;
break;
- case 4: /* password */
+ case OPT_password:
if (opt_arg)
{
my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
options->password=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 5:
+ case OPT_pipe:
options->protocol = MYSQL_PROTOCOL_PIPE;
- case 20: /* connect_timeout */
- case 6: /* timeout */
+ case OPT_connect_timeout:
+ case OPT_timeout:
if (opt_arg)
options->connect_timeout=atoi(opt_arg);
break;
- case 7: /* user */
+ case OPT_user:
if (opt_arg)
{
my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
options->user=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 8: /* init-command */
+ case OPT_init_command:
add_init_command(options,opt_arg);
break;
- case 9: /* host */
+ case OPT_host:
if (opt_arg)
{
my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
options->host=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 10: /* database */
+ case OPT_database:
if (opt_arg)
{
my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
options->db=my_strdup(opt_arg,MYF(MY_WME));
}
break;
- case 11: /* debug */
+ case OPT_debug:
#ifdef MYSQL_CLIENT
mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
break;
#endif
- case 12: /* return-found-rows */
+ case OPT_return_found_rows:
options->client_flag|=CLIENT_FOUND_ROWS;
break;
#ifdef HAVE_OPENSSL
- case 13: /* ssl_key */
+ case OPT_ssl_key:
my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 14: /* ssl_cert */
+ case OPT_ssl_cert:
my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 15: /* ssl_ca */
+ case OPT_ssl_ca:
my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 16: /* ssl_capath */
+ case OPT_ssl_capath:
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 OPT_ssl_cipher:
my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
break;
#else
- case 13: /* Ignore SSL options */
- case 14:
- case 15:
- case 16:
- case 26:
+ case OPT_ssl_key:
+ case OPT_ssl_cert:
+ case OPT_ssl_ca:
+ case OPT_ssl_capath:
+ case OPT_ssl_cipher:
break;
#endif /* HAVE_OPENSSL */
- case 17: /* charset-lib */
+ case OPT_character_sets_dir:
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 18:
+ case OPT_default_character_set:
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
break;
- case 19: /* Interactive-timeout */
+ case OPT_interactive_timeout:
options->client_flag|= CLIENT_INTERACTIVE;
break;
- case 21:
+ case OPT_local_infile:
if (!opt_arg || atoi(opt_arg) != 0)
options->client_flag|= CLIENT_LOCAL_FILES;
else
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 22:
+ case OPT_disable_local_infile:
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
- case 23: /* replication probe */
+ case OPT_replication_probe:
#ifndef TO_BE_DELETED
options->rpl_probe= 1;
#endif
break;
- case 24: /* enable-reads-from-master */
+ case OPT_enable_reads_from_master:
options->no_master_reads= 0;
break;
- case 25: /* repl-parse-query */
+ case OPT_repl_parse_query:
#ifndef TO_BE_DELETED
options->rpl_parse= 1;
#endif
break;
- case 27:
+ case OPT_max_allowed_packet:
if (opt_arg)
options->max_allowed_packet= atoi(opt_arg);
break;
- case 28: /* protocol */
+ case OPT_protocol:
if ((options->protocol= find_type(opt_arg,
&sql_protocol_typelib,0)) <= 0)
{
@@ -1202,26 +1226,32 @@ void mysql_read_default_options(struct st_mysql_options *options,
exit(1);
}
break;
- case 29: /* shared_memory_base_name */
+ case OPT_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 OPT_multi_results:
options->client_flag|= CLIENT_MULTI_RESULTS;
break;
- case 31:
- case 32:
+ case OPT_multi_statements:
+ case OPT_multi_queries:
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
break;
- case 33: /* secure-auth */
+ case OPT_secure_auth:
options->secure_auth= TRUE;
break;
- case 34: /* report-data-truncation */
+ case OPT_report_data_truncation:
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
break;
+ case OPT_plugin_dir:
+ extension_set_string(options, plugin_dir, opt_arg);
+ break;
+ case OPT_default_auth:
+ extension_set_string(options, default_auth, opt_arg);
+ break;
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -1765,6 +1795,11 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
static my_bool cli_read_query_result(MYSQL *mysql);
static MYSQL_RES *cli_use_result(MYSQL *mysql);
+int cli_read_change_user_result(MYSQL *mysql)
+{
+ return cli_safe_read(mysql);
+}
+
static MYSQL_METHODS client_methods=
{
cli_read_query_result, /* read_query_result */
@@ -1772,7 +1807,8 @@ static MYSQL_METHODS client_methods=
cli_read_rows, /* read_rows */
cli_use_result, /* use_result */
cli_fetch_lengths, /* fetch_lengths */
- cli_flush_use_result /* flush_use_result */
+ cli_flush_use_result, /* flush_use_result */
+ cli_read_change_user_result /* read_change_user_result */
#ifndef MYSQL_SERVER
,cli_list_fields, /* list_fields */
cli_read_prepare_result, /* read_prepare_result */
@@ -1782,7 +1818,6 @@ static MYSQL_METHODS client_methods=
NULL, /* free_embedded_thd */
cli_read_statistics, /* read_statistics */
cli_read_query_result, /* next_result */
- cli_read_change_user_result, /* read_change_user_result */
cli_read_binary_rows /* read_rows_from_cursor */
#endif
};
@@ -1856,6 +1891,646 @@ int mysql_init_character_set(MYSQL *mysql)
}
C_MODE_END
+/*********** client side authentication support **************************/
+
+typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
+static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, int);
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+
+static auth_plugin_t native_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ native_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Native MySQL authentication",
+ {1, 0, 0},
+ NULL,
+ NULL,
+ native_password_auth_client
+};
+
+static auth_plugin_t old_password_client_plugin=
+{
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+ old_password_plugin_name,
+ "R.J.Silk, Sergei Golubchik",
+ "Old MySQL-3.23 authentication",
+ {1, 0, 0},
+ NULL,
+ NULL,
+ old_password_auth_client
+};
+
+struct st_mysql_client_plugin *mysql_client_builtins[]=
+{
+ (struct st_mysql_client_plugin *)&native_password_client_plugin,
+ (struct st_mysql_client_plugin *)&old_password_client_plugin,
+ 0
+};
+
+
+
+/* this is a "superset" of MYSQL_PLUGIN_VIO, in C++ I use inheritance */
+typedef struct {
+ int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
+ int (*write_packet)(struct st_plugin_vio *vio, const uchar *pkt, int pkt_len);
+ void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info);
+ /* -= end of MYSQL_PLUGIN_VIO =- */
+ MYSQL *mysql;
+ auth_plugin_t *plugin; /**< what plugin we're under */
+ const char *db;
+ struct {
+ uchar *pkt; /**< pointer into NET::buff */
+ uint pkt_len;
+ } cached_server_reply;
+ uint packets_read, packets_written; /**< counters for send/received packets */
+ my_bool mysql_change_user; /**< if it's mysql_change_user() */
+ int last_read_packet_len; /**< the length of the last *read* packet */
+} MCPVIO_EXT;
+
+/**
+ sends a COM_CHANGE_USER command with a caller provided payload
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ n user name - \0-terminated string
+ n password
+ 3.23 scramble - \0-terminated string (9 bytes)
+ otherwise - length (1 byte) coded
+ n database name - \0-terminated string
+ 2 character set number (if the server >= 4.1.x)
+ n client auth plugin name - \0-terminated string,
+ (if the server supports plugin auth)
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static int send_change_user_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ char *buff, *end;
+ int res= 1;
+
+ buff= my_alloca(USERNAME_LENGTH + data_len + 1 + NAME_LEN + 2 + NAME_LEN);
+
+ end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1;
+
+ if (!data_len)
+ *end++= 0;
+ else
+ {
+ if (mysql->client_flag & CLIENT_SECURE_CONNECTION)
+ {
+ DBUG_ASSERT(data_len <= 255);
+ if (data_len > 255)
+ {
+ set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+ goto error;
+ }
+ *end++= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1);
+ DBUG_ASSERT(data[SCRAMBLE_LENGTH_323] == 0);
+ }
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ end= strmake(end, mpvio->db ? mpvio->db : "", NAME_LEN) + 1;
+
+ if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
+ {
+ int2store(end, (ushort) mysql->charset->number);
+ end+= 2;
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ res= simple_command(mysql, COM_CHANGE_USER,
+ (uchar*)buff, (ulong)(end-buff), 1);
+
+error:
+ my_afree(buff);
+ return res;
+}
+
+
+/**
+ sends a client authentication packet (second packet in the 3-way handshake)
+
+ Packet format (when the server is 4.0 or earlier):
+
+ Bytes Content
+ ----- ----
+ 2 client capabilities
+ 3 max packet size
+ n user name, \0-terminated
+ 9 scramble_323, \0-terminated
+
+ Packet format (when the server is 4.1 or newer):
+
+ Bytes Content
+ ----- ----
+ 4 client capabilities
+ 4 max packet size
+ 1 charset number
+ 23 reserved (always 0)
+ n user name, \0-terminated
+ n plugin auth data (e.g. scramble), length (1 byte) coded
+ n database name, \0-terminated
+ (if CLIENT_CONNECT_WITH_DB is set in the capabilities)
+ n client auth plugin name - \0-terminated string,
+ (if CLIENT_PLUGIN_AUTH is set in the capabilities)
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static int send_client_reply_packet(MCPVIO_EXT *mpvio,
+ const uchar *data, int data_len)
+{
+ MYSQL *mysql= mpvio->mysql;
+ NET *net= &mysql->net;
+ char *buff, *end;
+
+ /* see end= buff+32 below, fixed size of the packet is 32 bytes */
+ buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN);
+
+ mysql->client_flag|= mysql->options.client_flag;
+ mysql->client_flag|= CLIENT_CAPABILITIES;
+
+ if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
+ mysql->client_flag|= CLIENT_MULTI_RESULTS;
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
+ if (mysql->options.ssl_key || mysql->options.ssl_cert ||
+ mysql->options.ssl_ca || mysql->options.ssl_capath ||
+ mysql->options.ssl_cipher)
+ mysql->options.use_ssl= 1;
+ if (mysql->options.use_ssl)
+ mysql->client_flag|= CLIENT_SSL;
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
+ if (mpvio->db)
+ mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
+
+ /* Remove options that server doesn't support */
+ mysql->client_flag= mysql->client_flag &
+ (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)
+ | mysql->server_capabilities);
+
+#ifndef HAVE_COMPRESS
+ mysql->client_flag&= ~CLIENT_COMPRESS;
+#endif
+
+ if (mysql->client_flag & CLIENT_PROTOCOL_41)
+ {
+ /* 4.1 server and 4.1 client has a 32 byte option flag */
+ int4store(buff,mysql->client_flag);
+ int4store(buff+4, net->max_packet_size);
+ buff[8]= (char) mysql->charset->number;
+ bzero(buff+9, 32-9);
+ end= buff+32;
+ }
+ else
+ {
+ int2store(buff, mysql->client_flag);
+ int3store(buff+2, net->max_packet_size);
+ end= buff+5;
+ }
+#ifdef HAVE_OPENSSL
+ if (mysql->client_flag & CLIENT_SSL)
+ {
+ /* Do the SSL layering. */
+ struct st_mysql_options *options= &mysql->options;
+ struct st_VioSSLFd *ssl_fd;
+ char error_string[1024];
+
+ /*
+ Send mysql->client_flag, max_packet_size - unencrypted otherwise
+ the server does not know we want to do SSL
+ */
+ if (my_net_write(net, (uchar*)buff, (size_t) (end-buff)) || net_flush(net))
+ {
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending connection information to server",
+ errno);
+ goto error;
+ }
+
+ /* Create the VioSSLConnectorFd - init SSL and load certs */
+ if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
+ options->ssl_cert,
+ options->ssl_ca,
+ options->ssl_capath,
+ options->ssl_cipher)))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+ mysql->connector_fd= (void*)ssl_fd;
+
+ /* Connect to the server */
+ DBUG_PRINT("info", ("IO layer change in progress..."));
+ if (sslconnect(ssl_fd, net->vio,
+ (long) (mysql->options.connect_timeout),
+ error_string))
+ {
+ set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
+ unknown_sqlstate, "SSL error: %s",
+ error_string[0] ? error_string :
+ ER(CR_SSL_CONNECTION_ERROR));
+ goto error;
+ }
+ DBUG_PRINT("info", ("IO layer change done!"));
+
+ /* Verify server cert */
+ if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
+ ssl_verify_server_cert(net->vio, mysql->host))
+ {
+ set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ goto error;
+ }
+ }
+#endif /* HAVE_OPENSSL */
+
+ DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
+ mysql->server_version, mysql->server_capabilities,
+ mysql->server_status, mysql->client_flag));
+
+ compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
+
+ /* This needs to be changed as it's not useful with big packets */
+ if (mysql->user[0])
+ strmake(end, mysql->user, USERNAME_LENGTH);
+ else
+ read_user_name(end);
+
+ /* We have to handle different version of handshake here */
+ DBUG_PRINT("info",("user: %s",end));
+ end= strend(end) + 1;
+ if (data_len)
+ {
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ *end++= data_len;
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
+ memcpy(end, data, data_len);
+ end+= data_len;
+ }
+ }
+ else
+ *end++= 0;
+
+ /* Add database if needed */
+ if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
+ {
+ end= strmake(end, mpvio->db, NAME_LEN) + 1;
+ mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
+ }
+
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;
+
+ /* Write authentication package */
+ if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
+ {
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ goto error;
+ }
+ my_afree(buff);
+ return 0;
+
+error:
+ my_afree(buff);
+ return 1;
+}
+
+
+/**
+ vio->read_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to read data from the server.
+*/
+
+static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+ MYSQL *mysql= mpvio->mysql;
+ ulong pkt_len;
+
+ /* there are cached data left, feed it to a plugin */
+ if (mpvio->cached_server_reply.pkt)
+ {
+ *buf= mpvio->cached_server_reply.pkt;
+ mpvio->cached_server_reply.pkt= 0;
+ mpvio->packets_read++;
+ return mpvio->cached_server_reply.pkt_len;
+ }
+
+ if (mpvio->packets_read == 0)
+ {
+ /*
+ the server handshake packet came from the wrong plugin,
+ or it's mysql_change_user(). Either way, there is no data
+ for a plugin to read. send a dummy packet to the server
+ to initiate a dialog.
+ */
+ if (client_mpvio_write_packet(mpv, 0, 0))
+ return (int)packet_error;
+ }
+
+ /* otherwise read the data */
+ pkt_len= (*mysql->methods->read_change_user_result)(mysql);
+ mpvio->last_read_packet_len= pkt_len;
+ *buf= mysql->net.read_pos;
+
+ /* was it a request to change plugins ? */
+ if (**buf == 254)
+ return (int)packet_error; /* if yes, this plugin shan't continue */
+
+ /*
+ the server sends \1\255 or \1\254 instead of just \255 or \254 -
+ for us to not confuse it with an error or "change plugin" packets.
+ We remove this escaping \1 here.
+
+ See also server_mpvio_write_packet() where the escaping is done.
+ */
+ if (pkt_len && **buf == 1)
+ {
+ (*buf)++;
+ pkt_len--;
+ }
+ mpvio->packets_read++;
+ return pkt_len;
+}
+
+
+/**
+ vio->write_packet() callback method for client authentication plugins
+
+ This function is called by a client authentication plugin, when it wants
+ to send data to the server.
+
+ It transparently wraps the data into a change user or authentication
+ handshake packet, if neccessary.
+*/
+
+static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
+ const uchar *pkt, int pkt_len)
+{
+ int res;
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;
+
+ if (mpvio->packets_written == 0)
+ {
+ if (mpvio->mysql_change_user)
+ res= send_change_user_packet(mpvio, pkt, pkt_len);
+ else
+ res= send_client_reply_packet(mpvio, pkt, pkt_len);
+ }
+ else
+ {
+ NET *net= &mpvio->mysql->net;
+ if (mpvio->mysql->thd)
+ res= 1; /* no chit-chat in embedded */
+ else
+ res= my_net_write(net, pkt, pkt_len) || net_flush(net);
+ if (res)
+ set_mysql_extended_error(mpvio->mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
+{
+ bzero(info, sizeof(*info));
+ switch (vio->type) {
+ case VIO_TYPE_TCPIP:
+ info->protocol= MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ case VIO_TYPE_SOCKET:
+ info->protocol= MYSQL_VIO_SOCKET;
+ info->socket= vio->sd;
+ return;
+ case VIO_TYPE_SSL:
+ {
+ struct sockaddr addr;
+ SOCKET_SIZE_TYPE addrlen= sizeof(addr);
+ if (getsockname(vio->sd, &addr, &addrlen))
+ return;
+ info->protocol= addr.sa_family == AF_UNIX ?
+ MYSQL_VIO_SOCKET : MYSQL_VIO_TCP;
+ info->socket= vio->sd;
+ return;
+ }
+#ifdef _WIN32
+ case VIO_TYPE_NAMEDPIPE:
+ info->protocol= MYSQL_VIO_PIPE;
+ info->handle= vio->hPipe;
+ return;
+ case VIO_TYPE_SHARED_MEMORY:
+ info->protocol= MYSQL_VIO_MEMORY;
+ info->handle= vio->handle_file_map; /* or what ? */
+ return;
+#endif
+ default: DBUG_ASSERT(0);
+ }
+}
+
+
+static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MCPVIO_EXT *mpvio= (MCPVIO_EXT*)vio;
+ mpvio_info(mpvio->mysql->net.vio, info);
+}
+
+
+/**
+ Client side of the plugin driver authentication.
+
+ @note this is used by both the mysql_real_connect and mysql_change_user
+
+ @param mysql mysql
+ @param data pointer to the plugin auth data (scramble) in the
+ handshake packet
+ @param data_len the length of the data
+ @param data_plugin a plugin that data were prepared for
+ or 0 if it's mysql_change_user()
+ @param db initial db to use, can be 0
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
+ const char *data_plugin, const char *db)
+{
+ const char *auth_plugin_name;
+ auth_plugin_t *auth_plugin;
+ MCPVIO_EXT mpvio;
+ ulong pkt_length;
+ int res;
+
+ /* determine the default/initial plugin to use */
+ if (mysql->options.extension && mysql->options.extension->default_auth &&
+ mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ auth_plugin_name= mysql->options.extension->default_auth;
+ if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ return 1; /* oops, not found */
+ }
+ else
+ {
+ auth_plugin= mysql->server_capabilities & CLIENT_PROTOCOL_41 ?
+ &native_password_client_plugin : &old_password_client_plugin;
+ auth_plugin_name= auth_plugin->name;
+ }
+
+ mysql->net.last_errno= 0; /* just in case */
+
+ if (data_plugin && strcmp(data_plugin, auth_plugin_name))
+ {
+ /* data was prepared for a different plugin, don't show it to this one */
+ data= 0;
+ data_len= 0;
+ }
+
+ mpvio.mysql_change_user= data_plugin == 0;
+ mpvio.cached_server_reply.pkt= (uchar*)data;
+ mpvio.cached_server_reply.pkt_len= data_len;
+ mpvio.read_packet= client_mpvio_read_packet;
+ mpvio.write_packet= client_mpvio_write_packet;
+ mpvio.info= client_mpvio_info;
+ mpvio.mysql= mysql;
+ mpvio.packets_read= mpvio.packets_written= 0;
+ mpvio.db= db;
+ mpvio.plugin= auth_plugin;
+
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ compile_time_assert(CR_OK == -1);
+ compile_time_assert(CR_ERROR == 0);
+ if (res > CR_OK && mysql->net.read_pos[0] != 254)
+ {
+ /*
+ the plugin returned an error. write it down in mysql,
+ unless the error code is CR_ERROR and mysql->net.last_errno
+ is already set (the plugin has done it)
+ */
+ if (res > CR_ERROR)
+ set_mysql_error(mysql, res, unknown_sqlstate);
+ else
+ if (!mysql->net.last_errno)
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return 1;
+ }
+
+ /* read the OK packet (or use the cached value in mysql->net.read_pos */
+ if (res == CR_OK)
+ pkt_length= (*mysql->methods->read_change_user_result)(mysql);
+ else /* res == CR_OK_HANDSHAKE_COMPLETE */
+ pkt_length= mpvio.last_read_packet_len;
+
+ if (pkt_length == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading authorization packet",
+ errno);
+ return 1;
+ }
+
+ if (mysql->net.read_pos[0] == 254)
+ {
+ /* The server asked to use a different authentication plugin */
+ if (pkt_length == 1)
+ {
+ /* old "use short scramble" packet */
+ auth_plugin_name= old_password_plugin_name;
+ mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble;
+ mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* new "use different plugin" packet */
+ uint len;
+ auth_plugin_name= (char*)mysql->net.read_pos + 1;
+ len= strlen(auth_plugin_name); /* safe as my_net_read always appends \0 */
+ mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
+ mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
+ }
+
+ if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
+ auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
+ return 1;
+
+ mpvio.plugin= auth_plugin;
+ res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
+
+ if (res > CR_OK)
+ {
+ if (res > CR_ERROR)
+ set_mysql_error(mysql, res, unknown_sqlstate);
+ else
+ if (!mysql->net.last_errno)
+ set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+ return 1;
+ }
+
+ if (res != CR_OK_HANDSHAKE_COMPLETE)
+ {
+ /* Read what server thinks about out new auth message report */
+ if (cli_safe_read(mysql) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading final connect information",
+ errno);
+ return 1;
+ }
+ }
+ }
+ /*
+ net->read_pos[0] should always be 0 here if the server implements
+ the protocol correctly
+ */
+ return mysql->net.read_pos[0] != 0;
+}
+
MYSQL * STDCALL
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
@@ -1863,7 +2538,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
uint port, const char *unix_socket,ulong client_flag)
{
char buff[NAME_LEN+USERNAME_LENGTH+100];
- char *end,*host_info= NULL;
+ int scramble_data_len, pkt_scramble_len;
+ char *end, *host_info=0, *server_version_end, *pkt_end;
+ char *scramble_data;
+ const char *scramble_plugin;
my_socket sock;
in_addr_t ip_addr;
struct sockaddr_in sock_addr;
@@ -2179,8 +2857,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
errno);
goto error;
}
+ pkt_end= (char*)net->read_pos + pkt_length;
/* Check if version of protocol matches current one */
-
mysql->protocol_version= net->read_pos[0];
DBUG_DUMP("packet",(uchar*) net->read_pos,10);
DBUG_PRINT("info",("mysql protocol version %d, server=%d",
@@ -2192,31 +2870,29 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
PROTOCOL_VERSION);
goto error;
}
- end=strend((char*) net->read_pos+1);
+ server_version_end= end= strend((char*) net->read_pos+1);
mysql->thread_id=uint4korr(end+1);
end+=5;
/*
- Scramble is split into two parts because old clients does not understand
+ Scramble is split into two parts because old clients do not understand
long scrambles; here goes the first part.
*/
- strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
- end+= SCRAMBLE_LENGTH_323+1;
+ scramble_data= end;
+ scramble_data_len= SCRAMBLE_LENGTH_323 + 1;
+ scramble_plugin= old_password_plugin_name;
+ end+= scramble_data_len;
- if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
+ if (pkt_end >= end + 1)
mysql->server_capabilities=uint2korr(end);
- if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
+ if (pkt_end >= end + 18)
{
/* New protocol with 16 bytes to describe server characteristics */
mysql->server_language=end[2];
mysql->server_status=uint2korr(end+3);
+ mysql->server_capabilities|= uint2korr(end+5) << 16;
+ pkt_scramble_len= end[7];
}
end+= 18;
- if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
- (char *) net->read_pos))
- strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
- SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
- else
- mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
if (mysql->options.secure_auth && passwd[0] &&
!(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
@@ -2235,7 +2911,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
&mysql->unix_socket,unix_socket ?
(uint) strlen(unix_socket)+1 : (uint) 1,
&mysql->server_version,
- (uint) (end - (char*) net->read_pos),
+ (uint) (server_version_end - (char*) net->read_pos + 1),
NullS) ||
!(mysql->user=my_strdup(user,MYF(0))) ||
!(mysql->passwd=my_strdup(passwd,MYF(0))))
@@ -2252,204 +2928,47 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port;
- /*
- Part 2: format and send client info to the server for access check
- */
-
- client_flag|=mysql->options.client_flag;
- client_flag|=CLIENT_CAPABILITIES;
- if (client_flag & CLIENT_MULTI_STATEMENTS)
- client_flag|= CLIENT_MULTI_RESULTS;
-
-#ifdef HAVE_OPENSSL
- if (mysql->options.ssl_key || mysql->options.ssl_cert ||
- mysql->options.ssl_ca || mysql->options.ssl_capath ||
- mysql->options.ssl_cipher)
- mysql->options.use_ssl= 1;
- if (mysql->options.use_ssl)
- client_flag|=CLIENT_SSL;
-#endif /* HAVE_OPENSSL */
- if (db)
- client_flag|=CLIENT_CONNECT_WITH_DB;
-
- /* Remove options that server doesn't support */
- client_flag= ((client_flag &
- ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
- (client_flag & mysql->server_capabilities));
-#ifndef HAVE_COMPRESS
- client_flag&= ~CLIENT_COMPRESS;
-#endif
-
- if (client_flag & CLIENT_PROTOCOL_41)
+ if (pkt_end >= end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1)
{
- /* 4.1 server and 4.1 client has a 32 byte option flag */
- int4store(buff,client_flag);
- int4store(buff+4, net->max_packet_size);
- buff[8]= (char) mysql->charset->number;
- bzero(buff+9, 32-9);
- end= buff+32;
- }
- else
- {
- int2store(buff,client_flag);
- int3store(buff+2,net->max_packet_size);
- end= buff+5;
- }
- mysql->client_flag=client_flag;
-
-#ifdef HAVE_OPENSSL
- if (client_flag & CLIENT_SSL)
- {
- /* Do the SSL layering. */
- struct st_mysql_options *options= &mysql->options;
- struct st_VioSSLFd *ssl_fd;
- char error_string[1024];
-
/*
- Send client_flag, max_packet_size - unencrypted otherwise
- the server does not know we want to do SSL
+ move the first scramble part - directly in the NET buffer -
+ to get a full continuous scramble. We've read all the header,
+ and can overwrite it now.
*/
- if (my_net_write(net, (uchar*) buff, (uint) (end-buff)) || net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending connection information to server",
- errno);
- goto error;
- }
-
- /* Create the VioSSLConnectorFd - init SSL and load certs */
- if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
- options->ssl_cert,
- options->ssl_ca,
- options->ssl_capath,
- options->ssl_cipher)))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
- goto error;
- }
- mysql->connector_fd= (void*)ssl_fd;
-
- /* Connect to the server */
- DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslconnect(ssl_fd, mysql->net.vio,
- (long) (mysql->options.connect_timeout),
- error_string))
- {
- set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR,
- unknown_sqlstate,
- "SSL error: %s",
- error_string[0] ? error_string :
- ER(CR_SSL_CONNECTION_ERROR));
- goto error;
- }
- DBUG_PRINT("info", ("IO layer change done!"));
-
- /* Verify server cert */
- if ((client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
- ssl_verify_server_cert(mysql->net.vio, mysql->host))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
- goto error;
- }
-
- }
-#endif /* HAVE_OPENSSL */
-
- DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu",
- mysql->server_version,mysql->server_capabilities,
- mysql->server_status, client_flag));
- /* This needs to be changed as it's not useful with big packets */
- if (user && user[0])
- strmake(end,user,USERNAME_LENGTH); /* Max user name */
- else
- read_user_name((char*) end);
-
- /* We have to handle different version of handshake here */
-#ifdef _CUSTOMCONFIG_
-#include "_cust_libmysql.h"
-#endif
- DBUG_PRINT("info",("user: %s",end));
- end= strend(end) + 1;
- if (passwd[0])
- {
- if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ memmove(end - SCRAMBLE_LENGTH_323, scramble_data,
+ SCRAMBLE_LENGTH_323);
+ scramble_data= end - SCRAMBLE_LENGTH_323;
+ if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
{
- *end++= SCRAMBLE_LENGTH;
- scramble(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH;
+ scramble_data_len= pkt_scramble_len;
+ scramble_plugin= scramble_data + scramble_data_len;
+ if (scramble_data + scramble_data_len > pkt_end)
+ scramble_data_len= pkt_end - scramble_data;
}
else
{
- scramble_323(end, mysql->scramble, passwd);
- end+= SCRAMBLE_LENGTH_323 + 1;
+ scramble_data_len= pkt_end - scramble_data;
+ scramble_plugin= native_password_plugin_name;
}
}
else
- *end++= '\0'; /* empty password */
+ mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
+
+ mysql->client_flag= client_flag;
- /* Add database if needed */
- if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
- {
- end= strmake(end, db, NAME_LEN) + 1;
- mysql->db= my_strdup(db,MYF(MY_WME));
- db= 0;
- }
- /* Write authentication package */
- if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending authentication information",
- errno);
- goto error;
- }
-
/*
- Part 3: Authorization data's been sent. Now server can reply with
- OK-packet, or re-request scrambled password.
+ Part 2: invoke the plugin to send the authentication data to the server
*/
- if ((pkt_length=cli_safe_read(mysql)) == packet_error)
- {
- if (mysql->net.last_errno == CR_SERVER_LOST)
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "reading authorization packet",
- errno);
+ if (run_plugin_auth(mysql, scramble_data, scramble_data_len,
+ scramble_plugin, db))
goto error;
- }
- if (pkt_length == 1 && net->read_pos[0] == 254 &&
- mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
- {
- /*
- By sending this very specific reply server asks us to send scrambled
- password in old format.
- */
- scramble_323(buff, mysql->scramble, passwd);
- if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net))
- {
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "sending password information",
- errno);
- goto error;
- }
- /* Read what server thinks about out new auth message report */
- if (cli_safe_read(mysql) == packet_error)
- {
- if (mysql->net.last_errno == CR_SERVER_LOST)
- set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
- ER(CR_SERVER_LOST_EXTENDED),
- "reading final connect information",
- errno);
- goto error;
- }
- }
+ /*
+ Part 3: authenticated, finish the initialization of the connection
+ */
- if (client_flag & CLIENT_COMPRESS) /* We will use compression */
+ if (mysql->client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
#ifdef CHECK_LICENSE
@@ -2457,7 +2976,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error;
#endif
- if (db && mysql_select_db(mysql, db))
+ if (db && !mysql->db && mysql_select_db(mysql, db))
{
if (mysql->net.last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
@@ -2523,7 +3042,7 @@ error:
/* Free alloced memory */
end_server(mysql);
mysql_close_free(mysql);
- if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
+ if (!(client_flag & CLIENT_REMEMBER_OPTIONS))
mysql_close_free_options(mysql);
}
DBUG_RETURN(0);
@@ -2668,6 +3187,12 @@ static void mysql_close_free_options(MYSQL *mysql)
if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif /* HAVE_SMEM */
+ if (mysql->options.extension)
+ {
+ my_free(mysql->options.extension->plugin_dir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.extension->default_auth,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.extension,MYF(0));
+ }
bzero((char*) &mysql->options,sizeof(mysql->options));
DBUG_VOID_RETURN;
}
@@ -3198,6 +3723,12 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
else
mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
break;
+ case MYSQL_PLUGIN_DIR:
+ extension_set_string(&mysql->options, plugin_dir, arg);
+ break;
+ case MYSQL_DEFAULT_AUTH:
+ extension_set_string(&mysql->options, default_auth, arg);
+ break;
default:
DBUG_RETURN(1);
}
@@ -3274,7 +3805,7 @@ mysql_get_server_version(MYSQL *mysql)
*/
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
{
- struct charset_info_st *cs;
+ CHARSET_INFO *cs;
const char *save_csdir= charsets_dir;
if (mysql->options.charset_dir)
@@ -3306,3 +3837,99 @@ int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
}
+/**
+ client authentication plugin that does native MySQL authentication
+ using a 20-byte (4.1+) scramble
+*/
+
+static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ int pkt_len;
+ uchar *pkt;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble;
+ pkt_len= SCRAMBLE_LENGTH + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
+ mysql->scramble[SCRAMBLE_LENGTH] = 0;
+ }
+
+ if (mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH + 1];
+ scramble(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
+
+/**
+ client authentication plugin that does old MySQL authentication
+ using an 8-byte (4.0-) scramble
+*/
+
+static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+ uchar *pkt;
+ int pkt_len;
+
+ if (((MCPVIO_EXT *)vio)->mysql_change_user)
+ {
+ /*
+ in mysql_change_user() the client sends the first packet.
+ we use the old scramble.
+ */
+ pkt= (uchar*)mysql->scramble;
+ pkt_len= SCRAMBLE_LENGTH_323 + 1;
+ }
+ else
+ {
+ /* read the scramble */
+ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+ return CR_ERROR;
+
+ if (pkt_len != SCRAMBLE_LENGTH_323 + 1 &&
+ pkt_len != SCRAMBLE_LENGTH + 1)
+ return CR_SERVER_HANDSHAKE_ERR;
+
+ /* save it in MYSQL */
+ memcpy(mysql->scramble, pkt, pkt_len);
+ mysql->scramble[pkt_len] = 0;
+ }
+
+ if (mysql->passwd[0])
+ {
+ char scrambled[SCRAMBLE_LENGTH_323 + 1];
+ scramble_323(scrambled, (char*)pkt, mysql->passwd);
+ if (vio->write_packet(vio, (uchar*)scrambled, SCRAMBLE_LENGTH_323 + 1))
+ return CR_ERROR;
+ }
+ else
+ if (vio->write_packet(vio, 0, 0)) /* no password */
+ return CR_ERROR;
+
+ return CR_OK;
+}
+
diff --git a/sql-common/client_plugin.c b/sql-common/client_plugin.c
new file mode 100644
index 00000000000..c609f165d1c
--- /dev/null
+++ b/sql-common/client_plugin.c
@@ -0,0 +1,436 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program 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 */
+
+/**
+ @file
+
+ Support code for the client side (libmysql) plugins
+
+ Client plugins are somewhat different from server plugins, they are simpler.
+
+ They do not need to be installed or in any way explicitly loaded on the
+ client, they are loaded automatically on demand.
+ One client plugin per shared object, soname *must* match the plugin name.
+
+ There is no reference counting and no unloading either.
+*/
+
+#include <my_global.h>
+#include "mysql.h"
+#include <my_sys.h>
+#include <m_string.h>
+#ifdef THREAD
+#include <my_pthread.h>
+#else
+#include <my_no_pthread.h>
+#endif
+
+#include <sql_common.h>
+#include "errmsg.h"
+#include <mysql/client_plugin.h>
+
+struct st_client_plugin_int {
+ struct st_client_plugin_int *next;
+ void *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+};
+
+static my_bool initialized= 0;
+static MEM_ROOT mem_root;
+
+static const char *plugin_declarations_sym= "_mysql_client_plugin_declaration_";
+static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]=
+{
+ 0, /* these two are taken by Connector/C */
+ 0, /* these two are taken by Connector/C */
+ MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION
+};
+
+/*
+ Loaded plugins are stored in a linked list.
+ The list is append-only, the elements are added to the head (like in a stack).
+ The elements are added under a mutex, but the list can be read and traversed
+ without any mutex because once an element is added to the list, it stays
+ there. The main purpose of a mutex is to prevent two threads from
+ loading the same plugin twice in parallel.
+*/
+struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS];
+#ifdef THREAD
+static pthread_mutex_t LOCK_load_client_plugin;
+#endif
+
+static int is_not_initialized(MYSQL *mysql, const char *name)
+{
+ if (initialized)
+ return 0;
+
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ name, "not initialized");
+ return 1;
+}
+
+
+/**
+ finds a plugin in the list
+
+ @param name plugin name to search for
+ @param type plugin type
+
+ @note this does NOT necessarily need a mutex, take care!
+
+ @retval a pointer to a found plugin or 0
+*/
+
+static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
+{
+ struct st_client_plugin_int *p;
+
+ DBUG_ASSERT(initialized);
+ DBUG_ASSERT(type >= 0 && type < MYSQL_CLIENT_MAX_PLUGINS);
+ if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
+ return 0;
+
+ for (p= plugin_list[type]; p; p= p->next)
+ {
+ if (strcmp(p->plugin->name, name) == 0)
+ return p->plugin;
+ }
+ return NULL;
+}
+
+
+/**
+ verifies the plugin and adds it to the list
+
+ @param mysql MYSQL structure (for error reporting)
+ @param plugin plugin to install
+ @param dlhandle a handle to the shared object (returned by dlopen)
+ or 0 if the plugin was not dynamically loaded
+ @param argc number of arguments in the 'va_list args'
+ @param args arguments passed to the plugin initialization function
+
+ @retval a pointer to an installed plugin or 0
+*/
+
+static struct st_mysql_client_plugin *
+add_plugin(MYSQL *mysql, struct st_mysql_client_plugin *plugin, void *dlhandle,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ struct st_client_plugin_int plugin_int, *p;
+ char errbuf[1024];
+
+ DBUG_ASSERT(initialized);
+
+ plugin_int.plugin= plugin;
+ plugin_int.dlhandle= dlhandle;
+
+ if (plugin->type >= MYSQL_CLIENT_MAX_PLUGINS)
+ {
+ errmsg= "Unknown client plugin type";
+ goto err1;
+ }
+
+ if (plugin->interface_version < plugin_version[plugin->type] ||
+ (plugin->interface_version >> 8) >
+ (plugin_version[plugin->type] >> 8))
+ {
+ errmsg= "Incompatible client plugin interface";
+ goto err1;
+ }
+
+ /* Call the plugin initialization function, if any */
+ if (plugin->init && plugin->init(errbuf, sizeof(errbuf), argc, args))
+ {
+ errmsg= errbuf;
+ goto err1;
+ }
+
+ p= (struct st_client_plugin_int *)
+ memdup_root(&mem_root, &plugin_int, sizeof(plugin_int));
+
+ if (!p)
+ {
+ errmsg= "Out of memory";
+ goto err2;
+ }
+
+ safe_mutex_assert_owner(&LOCK_load_client_plugin);
+
+ p->next= plugin_list[plugin->type];
+ plugin_list[plugin->type]= p;
+
+ return plugin;
+
+err2:
+ if (plugin->deinit)
+ plugin->deinit();
+err1:
+ if (dlhandle)
+ dlclose(dlhandle);
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name,
+ errmsg);
+ return NULL;
+}
+
+
+/**
+ Loads plugins which are specified in the environment variable
+ LIBMYSQL_PLUGINS.
+
+ Multiple plugins must be separated by semicolon. This function doesn't
+ return or log an error.
+
+ The function is be called by mysql_client_plugin_init
+
+ @todo
+ Support extended syntax, passing parameters to plugins, for example
+ LIBMYSQL_PLUGINS="plugin1(param1,param2);plugin2;..."
+ or
+ LIBMYSQL_PLUGINS="plugin1=int:param1,str:param2;plugin2;..."
+*/
+
+static void load_env_plugins(MYSQL *mysql)
+{
+ char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
+
+ /* no plugins to load */
+ if (!s)
+ return;
+
+ free_env= plugs= my_strdup(s, MYF(MY_WME));
+
+ do {
+ if ((s= strchr(plugs, ';')))
+ *s= '\0';
+ mysql_load_plugin(mysql, plugs, -1, 0);
+ plugs= s + 1;
+ } while (s);
+
+ my_free(free_env, MYF(0));
+}
+
+/********** extern functions to be used by libmysql *********************/
+
+/**
+ Initializes the client plugin layer.
+
+ This function must be called before any other client plugin function.
+
+ @retval 0 successful
+ @retval != 0 error occured
+*/
+
+int mysql_client_plugin_init()
+{
+ MYSQL mysql;
+ struct st_mysql_client_plugin **builtin;
+
+ if (initialized)
+ return 0;
+
+ bzero(&mysql, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
+
+ pthread_mutex_init(&LOCK_load_client_plugin, MY_MUTEX_INIT_SLOW);
+ init_alloc_root(&mem_root, 128, 128);
+
+ bzero(&plugin_list, sizeof(plugin_list));
+
+ initialized= 1;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ for (builtin= mysql_client_builtins; *builtin; builtin++)
+ add_plugin(&mysql, *builtin, 0, 0, 0);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ load_env_plugins(&mysql);
+
+ return 0;
+}
+
+
+/**
+ Deinitializes the client plugin layer.
+
+ Unloades all client plugins and frees any associated resources.
+*/
+
+void mysql_client_plugin_deinit()
+{
+ int i;
+ struct st_client_plugin_int *p;
+
+ if (!initialized)
+ return;
+
+ for (i=0; i < MYSQL_CLIENT_MAX_PLUGINS; i++)
+ for (p= plugin_list[i]; p; p= p->next)
+ {
+ if (p->plugin->deinit)
+ p->plugin->deinit();
+ if (p->dlhandle)
+ dlclose(p->dlhandle);
+ }
+
+ bzero(&plugin_list, sizeof(plugin_list));
+ initialized= 0;
+ free_root(&mem_root, MYF(0));
+ pthread_mutex_destroy(&LOCK_load_client_plugin);
+}
+
+/************* public facing functions, for client consumption *********/
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_client_register_plugin(MYSQL *mysql,
+ struct st_mysql_client_plugin *plugin)
+{
+ if (is_not_initialized(mysql, plugin->name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (find_plugin(plugin->name, plugin->type))
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ plugin->name, "it is already loaded");
+ plugin= NULL;
+ }
+ else
+ plugin= add_plugin(mysql, plugin, 0, 0, 0);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ return plugin;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
+ int argc, va_list args)
+{
+ const char *errmsg;
+ char dlpath[FN_REFLEN+1];
+ void *sym, *dlhandle;
+ struct st_mysql_client_plugin *plugin;
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ pthread_mutex_lock(&LOCK_load_client_plugin);
+
+ /* make sure the plugin wasn't loaded meanwhile */
+ if (type >= 0 && find_plugin(name, type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ /* Compile dll path */
+ strxnmov(dlpath, sizeof(dlpath) - 1,
+ mysql->options.extension && mysql->options.extension->plugin_dir ?
+ mysql->options.extension->plugin_dir : PLUGINDIR, "/",
+ name, SO_EXT, NullS);
+
+ /* Open new dll handle */
+ if (!(dlhandle= dlopen(dlpath, RTLD_NOW)))
+ {
+ errmsg= dlerror();
+ goto err;
+ }
+
+ if (!(sym= dlsym(dlhandle, plugin_declarations_sym)))
+ {
+ errmsg= "not a plugin";
+ dlclose(dlhandle);
+ goto err;
+ }
+
+ plugin= (struct st_mysql_client_plugin*)sym;
+
+ if (type >=0 && type != plugin->type)
+ {
+ errmsg= "type mismatch";
+ goto err;
+ }
+
+ if (strcmp(name, plugin->name))
+ {
+ errmsg= "name mismatch";
+ goto err;
+ }
+
+ if (type < 0 && find_plugin(name, plugin->type))
+ {
+ errmsg= "it is already loaded";
+ goto err;
+ }
+
+ plugin= add_plugin(mysql, plugin, dlhandle, argc, args);
+
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+
+ return plugin;
+
+err:
+ pthread_mutex_unlock(&LOCK_load_client_plugin);
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name, errmsg);
+ return NULL;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_load_plugin(MYSQL *mysql, const char *name, int type, int argc, ...)
+{
+ struct st_mysql_client_plugin *p;
+ va_list args;
+ va_start(args, argc);
+ p= mysql_load_plugin_v(mysql, name, type, argc, args);
+ va_end(args);
+ return p;
+}
+
+
+/* see <mysql/client_plugin.h> for a full description */
+struct st_mysql_client_plugin *
+mysql_client_find_plugin(MYSQL *mysql, const char *name, int type)
+{
+ struct st_mysql_client_plugin *p;
+
+ if (is_not_initialized(mysql, name))
+ return NULL;
+
+ if (type < 0 || type >= MYSQL_CLIENT_MAX_PLUGINS)
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD), name,
+ "invalid type");
+ }
+
+ if ((p= find_plugin(name, type)))
+ return p;
+
+ /* not found, load it */
+ return mysql_load_plugin(mysql, name, type, 0);
+}
+
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index af9ed5ed8e3..b431ee075fe 100755
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -18,7 +18,7 @@ SET(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
SET(CMAKE_C_FLAGS_DEBUG
"${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
-SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /MAP /MAPINFO:EXPORTS")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MAP /MAPINFO:EXPORTS")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/extra/yassl/include
@@ -46,7 +46,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
@@ -54,7 +54,7 @@ SET (SQL_SOURCE
log_event.cc rpl_record.cc rpl_reporting.cc
log_event_old.cc rpl_record_old.cc
message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c
- mysqld.cc net_serv.cc
+ mysqld.cc net_serv.cc ../sql-common/client_plugin.c
nt_servc.cc nt_servc.h opt_range.cc opt_range.h opt_sum.cc
../sql-common/pack.c parse_file.cc password.c procedure.cc
protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc
@@ -77,6 +77,7 @@ SET (SQL_SOURCE
rpl_rli.cc rpl_mi.cc sql_servers.cc
sql_connect.cc scheduler.cc
sql_profile.cc event_parse_data.cc opt_table_elimination.cc
+ create_options.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
diff --git a/sql/Makefile.am b/sql/Makefile.am
index af34e961480..b738565f818 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -49,7 +49,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 \
@@ -78,7 +78,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
+ contributors.h sql_servers.h \
+ create_options.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -124,9 +125,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \
sql_servers.cc event_parse_data.cc \
- opt_table_elimination.cc
+ opt_table_elimination.cc create_options.cc
-nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
+nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c client_plugin.c
libndb_la_CPPFLAGS= @ndbcluster_includes@
libndb_la_SOURCES= ha_ndbcluster.cc \
@@ -140,10 +141,10 @@ mysql_tzinfo_to_sql_SOURCES = tztime.cc
mysql_tzinfo_to_sql_CXXFLAGS= -DTZINFO2SQL
DEFS = -DMYSQL_SERVER \
- -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
- -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \
- -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
- -DPLUGINDIR="\"$(pkgplugindir)\"" \
+ -DDEFAULT_MYSQL_HOME='"$(MYSQLBASEdir)"' \
+ -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
+ -DSHAREDIR='"$(MYSQLSHAREdir)"' \
+ -DPLUGINDIR='"$(pkgplugindir)"' \
-DHAVE_EVENT_SCHEDULER \
@DEFS@
@@ -167,6 +168,8 @@ link_sources:
@LN_CP_F@ $(top_srcdir)/sql-common/pack.c pack.c
rm -f client.c
@LN_CP_F@ $(top_srcdir)/sql-common/client.c client.c
+ rm -f client_plugin.c
+ @LN_CP_F@ $(top_srcdir)/sql-common/client_plugin.c client_plugin.c
rm -f my_time.c
@LN_CP_F@ $(top_srcdir)/sql-common/my_time.c my_time.c
rm -f my_user.c
diff --git a/sql/authors.h b/sql/authors.h
index 925c942fa24..bab319e3dcb 100644
--- a/sql/authors.h
+++ b/sql/authors.h
@@ -34,23 +34,35 @@ struct show_table_authors_st {
*/
struct show_table_authors_st show_table_authors[]= {
+ { "Michael (Monty) Widenius", "Tusby, Finland",
+ "Lead developer and main author" },
+ { "David Axmark", "London, England",
+ "MySQL founder; Small stuff long time ago, Monty ripped it out!" },
+ { "Sergei Golubchik", "Kerpen, Germany",
+ "Full-text search, precision math" },
+ { "Igor Babaev", "Bellevue, USA", "Optimizer, keycache, core work"},
+ { "Sergey Petrunia", "St. Petersburg, Russia", "Optimizer"},
+ { "Oleksandr Byelkin", "Lugansk, Ukraine",
+ "Query Cache (4.0), Subqueries (4.1), Views (5.0)" },
{ "Brian (Krow) Aker", "Seattle, WA, USA",
"Architecture, archive, federated, bunch of little stuff :)" },
- { "Venu Anuganti", "", "Client/server protocol (4.1)" },
- { "David Axmark", "Uppsala, Sweden",
- "Small stuff long time ago, Monty ripped it out!" },
+ { "Kristian Nielsen", "Copenhagen, Denmark",
+ "General build stuff," },
{ "Alexander (Bar) Barkov", "Izhevsk, Russia",
"Unicode and character sets (4.1)" },
+ { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" },
+ { "Venu Anuganti", "", "Client/server protocol (4.1)" },
+ { "Konstantin Osipov", "Moscow, Russia",
+ "Prepared statements (4.1), Cursors (5.0)" },
+ { "Dmitri Lenev", "Moscow, Russia",
+ "Time zones support (4.1), Triggers (5.0)" },
{ "Omer BarNir", "Sunnyvale, CA, USA",
"Testing (sometimes) and general QA stuff" },
- { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" },
{ "John Birrell", "", "Emulation of pthread_mutex() for OS/2" },
{ "Andreas F. Bobak", "", "AGGREGATE extension to user-defined functions" },
{ "Alexey Botchkov (Holyfoot)", "Izhevsk, Russia",
"GIS extensions (4.1), embedded server (4.1), precision math (5.0)"},
{ "Reggie Burnett", "Nashville, TN, USA", "Windows development, Connectors" },
- { "Oleksandr Byelkin", "Lugansk, Ukraine",
- "Query Cache (4.0), Subqueries (4.1), Views (5.0)" },
{ "Kent Boortz", "Orebro, Sweden", "Test platform, and general build stuff" },
{ "Tim Bunce", "", "mysqlhotcopy" },
{ "Yves Carlier", "", "mysqlaccess" },
@@ -67,8 +79,6 @@ struct show_table_authors_st show_table_authors[]= {
{ "Yuri Dario", "", "OS/2 port" },
{ "Andrei Elkin", "Espoo, Finland", "Replication" },
{ "Patrick Galbraith", "Sharon, NH", "Federated Engine, mysqlslap" },
- { "Sergei Golubchik", "Kerpen, Germany",
- "Full-text search, precision math" },
{ "Lenz Grimmer", "Hamburg, Germany",
"Production (build and release) engineering" },
{ "Nikolay Grishakin", "Austin, TX, USA", "Testing - Server" },
@@ -84,8 +94,6 @@ struct show_table_authors_st show_table_authors[]= {
{ "Hakan Küçükyılmaz", "Walldorf, Germany", "Testing - Server" },
{ "Greg (Groggy) Lehey", "Uchunga, SA, Australia", "Backup" },
{ "Matthias Leich", "Berlin, Germany", "Testing - Server" },
- { "Dmitri Lenev", "Moscow, Russia",
- "Time zones support (4.1), Triggers (5.0)" },
{ "Arjen Lentz", "Brisbane, Australia",
"Documentation (2001-2004), Dutch error messages, LOG2()" },
{ "Marc Liyanage", "", "Created Mac OS X packages" },
@@ -97,8 +105,6 @@ struct show_table_authors_st show_table_authors[]= {
{ "Jonathan (Jeb) Miller", "Kyle, TX, USA",
"Testing - Cluster, Replication" },
{ "Elliot Murphy", "Cocoa, FL, USA", "Replication and backup" },
- { "Kristian Nielsen", "Copenhagen, Denmark",
- "General build stuff" },
{ "Pekka Nouisiainen", "Stockholm, Sweden",
"NDB Cluster: BLOB support, character set support, ordered indexes" },
{ "Alexander Nozdrin", "Moscow, Russia",
@@ -106,8 +112,6 @@ struct show_table_authors_st show_table_authors[]= {
{ "Per Eric Olsson", "", "Testing of dynamic record format" },
{ "Jonas Oreland", "Stockholm, Sweden",
"NDB Cluster, Online Backup, lots of other things" },
- { "Konstantin Osipov", "Moscow, Russia",
- "Prepared statements (4.1), Cursors (5.0)" },
{ "Alexander (Sasha) Pachev", "Provo, UT, USA",
"Statement-based replication, SHOW CREATE TABLE, mysql-bench" },
{ "Irena Pancirov", "", "Port to Windows with Borland compiler" },
@@ -145,9 +149,9 @@ struct show_table_authors_st show_table_authors[]= {
{ "Sergey Vojtovich", "Izhevsk, Russia", "Plugins infrastructure (5.1)" },
{ "Matt Wagner", "Northfield, MN, USA", "Bug fixing" },
{ "Jim Winstead Jr.", "Los Angeles, CA, USA", "Bug fixing" },
- { "Michael (Monty) Widenius", "Tusby, Finland",
- "Lead developer and main author" },
{ "Peter Zaitsev", "Tacoma, WA, USA",
"SHA1(), AES_ENCRYPT(), AES_DECRYPT(), bug fixing" },
+ {"Mark Mark Callaghan", "Texas, USA", "Statistics patches"},
+ {"Percona", "CA, USA", "Microslow patches"},
{NULL, NULL, NULL}
};
diff --git a/sql/client_settings.h b/sql/client_settings.h
index 4f06c15a29e..850903a24e5 100644
--- a/sql/client_settings.h
+++ b/sql/client_settings.h
@@ -15,6 +15,7 @@
#include <thr_alarm.h>
+#include <sql_common.h>
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
CLIENT_SECURE_CONNECTION | CLIENT_TRANSACTIONS | \
@@ -28,10 +29,10 @@
#define mysql_master_send_query(A, B, C) 1
#define mysql_slave_send_query(A, B, C) 1
#define mysql_rpl_probe(mysql) 0
-#undef HAVE_SMEM
#undef _CUSTOMCONFIG_
-#define mysql_server_init(a,b,c) 0
+#define mysql_server_init(a,b,c) mysql_client_plugin_init()
+#define mysql_server_end() mysql_client_plugin_deinit()
#ifdef HAVE_REPLICATION
C_MODE_START
diff --git a/sql/create_options.cc b/sql/create_options.cc
new file mode 100644
index 00000000000..6d682853ae6
--- /dev/null
+++ b/sql/create_options.cc
@@ -0,0 +1,612 @@
+/* Copyright (C) 2010 Monty Program 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 */
+
+/**
+ @file
+
+ Engine defined options of tables/fields/keys in CREATE/ALTER TABLE.
+*/
+
+#include "mysql_priv.h"
+#include "create_options.h"
+#include <my_getopt.h>
+
+#define FRM_QUOTED_VALUE 0x8000
+
+/**
+ Links this item to the given list end
+
+ @param start The list beginning or NULL
+ @param end The list last element or does not matter
+*/
+
+void engine_option_value::link(engine_option_value **start,
+ engine_option_value **end)
+{
+ DBUG_ENTER("engine_option_value::link");
+ DBUG_PRINT("enter", ("name: '%s' (%u) value: '%s' (%u)",
+ name.str, (uint) name.length,
+ value.str, (uint) value.length));
+ engine_option_value *opt;
+ /* check duplicates to avoid writing them to frm*/
+ for(opt= *start;
+ opt && ((opt->parsed && !opt->value.str) ||
+ my_strnncoll(system_charset_info,
+ (uchar *)name.str, name.length,
+ (uchar*)opt->name.str, opt->name.length));
+ opt= opt->next) /* no-op */;
+ if (opt)
+ {
+ opt->value.str= NULL; /* remove previous value */
+ opt->parsed= TRUE; /* and don't issue warnings for it anymore */
+ }
+ /*
+ Add this option to the end of the list
+
+ @note: We add even if it is opt->value.str == NULL because it can be
+ ALTER TABLE to remove the option.
+ */
+ if (*start)
+ {
+ (*end)->next= this;
+ *end= this;
+ }
+ else
+ {
+ /*
+ note that is *start == 0, the value of *end does not matter,
+ it can be uninitialized.
+ */
+ *start= *end= this;
+ }
+ DBUG_VOID_RETURN;
+}
+
+static bool report_wrong_value(THD *thd, const char *name, const char *val,
+ my_bool suppress_warning)
+{
+ if (suppress_warning)
+ return 0;
+
+ if (!(thd->variables.sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) &&
+ !thd->slave_thread)
+ {
+ my_error(ER_BAD_OPTION_VALUE, MYF(0), val, name);
+ return 1;
+ }
+
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_OPTION_VALUE,
+ ER(ER_BAD_OPTION_VALUE), val, name);
+ return 0;
+}
+
+static bool report_unknown_option(THD *thd, engine_option_value *val,
+ my_bool suppress_warning)
+{
+ DBUG_ENTER("report_unknown_option");
+
+ if (val->parsed || suppress_warning)
+ {
+ DBUG_PRINT("info", ("parsed => exiting"));
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!(thd->variables.sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) &&
+ !thd->slave_thread)
+ {
+ my_error(ER_UNKNOWN_OPTION, MYF(0), val->name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_OPTION, ER(ER_UNKNOWN_OPTION), val->name.str);
+ DBUG_RETURN(FALSE);
+}
+
+static bool set_one_value(ha_create_table_option *opt,
+ THD *thd, LEX_STRING *value, void *base,
+ my_bool suppress_warning,
+ MEM_ROOT *root)
+{
+ DBUG_ENTER("set_one_value");
+ DBUG_PRINT("enter", ("opt: 0x%lx type: %u name '%s' value: '%s'",
+ (ulong) opt,
+ opt->type, opt->name,
+ (value->str ? value->str : "<DEFAULT>")));
+ switch (opt->type)
+ {
+ case HA_OPTION_TYPE_ULL:
+ {
+ ulonglong *val= (ulonglong*)((char*)base + opt->offset);
+ if (!value->str)
+ {
+ *val= opt->def_value;
+ DBUG_RETURN(0);
+ }
+
+ my_option optp= { opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
+ REQUIRED_ARG, opt->def_value, opt->min_value, opt->max_value,
+ 0, opt->block_size, 0};
+
+ ulonglong orig_val= strtoull(value->str, NULL, 10);
+ my_bool unused;
+ *val= orig_val;
+ *val= getopt_ull_limit_value(*val, &optp, &unused);
+ if (*val == orig_val)
+ DBUG_RETURN(0);
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ case HA_OPTION_TYPE_STRING:
+ {
+ char **val= (char **)((char *)base + opt->offset);
+ if (!value->str)
+ {
+ *val= 0;
+ DBUG_RETURN(0);
+ }
+
+ if (!(*val= strmake_root(root, value->str, value->length)))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+ }
+ case HA_OPTION_TYPE_ENUM:
+ {
+ uint *val= (uint *)((char *)base + opt->offset), num;
+
+ *val= opt->def_value;
+ if (!value->str)
+ DBUG_RETURN(0);
+
+ const char *start= opt->values, *end;
+
+ num= 0;
+ while (*start)
+ {
+ for (end=start;
+ *end && *end != ',';
+ end+= my_mbcharlen(system_charset_info, *end)) /* no-op */;
+ if (!my_strnncoll(system_charset_info,
+ (uchar*)start, end-start,
+ (uchar*)value->str, value->length))
+ {
+ *val= num;
+ DBUG_RETURN(0);
+ }
+ if (*end) *end++;
+ start= end;
+ num++;
+ }
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ case HA_OPTION_TYPE_BOOL:
+ {
+ bool *val= (bool *)((char *)base + opt->offset);
+ *val= opt->def_value;
+
+ if (!value->str)
+ DBUG_RETURN(0);
+
+ if (!my_strnncoll(system_charset_info,
+ (const uchar*)"NO", 2,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"OFF", 3,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"0", 1,
+ (uchar *)value->str, value->length))
+ {
+ *val= FALSE;
+ DBUG_RETURN(FALSE);
+ }
+
+ if (!my_strnncoll(system_charset_info,
+ (const uchar*)"YES", 3,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"ON", 2,
+ (uchar *)value->str, value->length) ||
+ !my_strnncoll(system_charset_info,
+ (const uchar*)"1", 1,
+ (uchar *)value->str, value->length))
+ {
+ *val= TRUE;
+ DBUG_RETURN(FALSE);
+ }
+
+ DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+ suppress_warning));
+ }
+ }
+ DBUG_ASSERT(0);
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ DBUG_RETURN(1);
+}
+
+static const size_t ha_option_type_sizeof[]=
+{ sizeof(ulonglong), sizeof(char *), sizeof(uint), sizeof(bool)};
+
+/**
+ Creates option structure and parses list of options in it
+
+ @param thd thread handler
+ @param option_struct where to store pointer on the option struct
+ @param option_list list of options given by user
+ @param rules list of option description by engine
+ @param suppress_warning second parse so we do not need warnings
+ @param root MEM_ROOT where allocate memory
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool parse_option_list(THD* thd, void **option_struct,
+ engine_option_value *option_list,
+ ha_create_table_option *rules,
+ my_bool suppress_warning,
+ MEM_ROOT *root)
+{
+ ha_create_table_option *opt;
+ size_t option_struct_size= 0;
+ engine_option_value *val= option_list;
+ DBUG_ENTER("parse_option_list");
+ DBUG_PRINT("enter",
+ ("struct: 0x%lx list: 0x%lx rules: 0x%lx suppres %u root 0x%lx",
+ (ulong) *option_struct, (ulong)option_list, (ulong)rules,
+ (uint) suppress_warning, (ulong) root));
+
+ if (rules)
+ {
+ LEX_STRING default_val= {NULL, 0};
+ for (opt= rules; opt->name; opt++)
+ set_if_bigger(option_struct_size, opt->offset +
+ ha_option_type_sizeof[opt->type]);
+
+ *option_struct= alloc_root(root, option_struct_size);
+
+ /* set all values to default */
+ for (opt= rules; opt->name; opt++)
+ set_one_value(opt, thd, &default_val, *option_struct,
+ suppress_warning, root);
+ }
+
+ for (; val; val= val->next)
+ {
+ for (opt= rules; opt && opt->name; opt++)
+ {
+ if (my_strnncoll(system_charset_info,
+ (uchar*)opt->name, opt->name_length,
+ (uchar*)val->name.str, val->name.length))
+ continue;
+
+ if (set_one_value(opt, thd, &val->value,
+ *option_struct, suppress_warning || val->parsed, root))
+ DBUG_RETURN(TRUE);
+ val->parsed= true;
+ break;
+ }
+ if (report_unknown_option(thd, val, suppress_warning))
+ DBUG_RETURN(TRUE);
+ val->parsed= true;
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Parses all table/fields/keys options
+
+ @param thd thread handler
+ @param file handler of the table
+ @parem share descriptor of the table
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+ TABLE_SHARE *share)
+{
+ MEM_ROOT *root= &share->mem_root;
+ DBUG_ENTER("parse_engine_table_options");
+
+ if (parse_option_list(thd, &share->option_struct, share->option_list,
+ ht->table_options, TRUE, root))
+ DBUG_RETURN(TRUE);
+
+ for (Field **field= share->field; *field; field++)
+ {
+ if (parse_option_list(thd, &(*field)->option_struct, (*field)->option_list,
+ ht->field_options, TRUE, root))
+ DBUG_RETURN(TRUE);
+ }
+
+ for (uint index= 0; index < share->keys; index ++)
+ {
+ if (parse_option_list(thd, &share->key_info[index].option_struct,
+ share->key_info[index].option_list,
+ ht->index_options, TRUE, root))
+ DBUG_RETURN(TRUE);
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Returns representation length of key and value in the frm file
+*/
+
+uint engine_option_value::frm_length()
+{
+ /*
+ 1 byte - name length
+ 2 bytes - value length
+
+ if value.str is NULL, this option is not written to frm (=DEFAULT)
+ */
+ return value.str ? 1 + name.length + 2 + value.length : 0;
+}
+
+
+/**
+ Returns length of representation of option list in the frm file
+*/
+
+static uint option_list_frm_length(engine_option_value *opt)
+{
+ uint res= 0;
+
+ for (; opt; opt= opt->next)
+ res+= opt->frm_length();
+
+ return res;
+}
+
+
+/**
+ Calculates length of options image in the .frm
+
+ @param table_option_list list of table options
+ @param create_fields field descriptors list
+ @param keys number of keys
+ @param key_info array of key descriptors
+
+ @returns length of image in frm
+*/
+
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ uint res, index;
+ DBUG_ENTER("engine_table_options_frm_length");
+
+ res= option_list_frm_length(table_option_list);
+
+ while ((field= it++))
+ res+= option_list_frm_length(field->option_list);
+
+ for (index= 0; index < keys; index++, key_info++)
+ res+= option_list_frm_length(key_info->option_list);
+
+ /*
+ if there's at least one option somewhere (res > 0)
+ we write option lists for all fields and keys, zero-terminated.
+ If there're no options we write nothing at all (backward compatibility)
+ */
+ DBUG_RETURN(res ? res + 1 + create_fields.elements + keys : 0);
+}
+
+
+/**
+ Writes image of the key and value to the frm image buffer
+
+ @param buff pointer to the buffer free space beginning
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_option_value::frm_image(uchar *buff)
+{
+ if (value.str)
+ {
+ *buff++= name.length;
+ memcpy(buff, name.str, name.length);
+ buff+= name.length;
+ int2store(buff, value.length | (quoted_value ? FRM_QUOTED_VALUE : 0));
+ buff+= 2;
+ memcpy(buff, (const uchar *) value.str, value.length);
+ buff+= value.length;
+ }
+ return buff;
+}
+
+/**
+ Writes image of the key and value to the frm image buffer
+
+ @param buff pointer to the buffer to store the options in
+ @param opt list of options;
+
+ @returns pointer to the end of the stored data in the buffer
+*/
+static uchar *option_list_frm_image(uchar *buff, engine_option_value *opt)
+{
+ for (; opt; opt= opt->next)
+ buff= opt->frm_image(buff);
+
+ *buff++= 0;
+ return buff;
+}
+
+
+/**
+ Writes options image in the .frm buffer
+
+ @param buff pointer to the buffer
+ @param table_option_list list of table options
+ @param create_fields field descriptors list
+ @param keys number of keys
+ @param key_info array of key descriptors
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ KEY *key_info_end= key_info + keys;
+ DBUG_ENTER("engine_table_options_frm_image");
+
+ buff= option_list_frm_image(buff, table_option_list);
+
+ while ((field= it++))
+ buff= option_list_frm_image(buff, field->option_list);
+
+ while (key_info < key_info_end)
+ buff= option_list_frm_image(buff, (key_info++)->option_list);
+
+ DBUG_RETURN(buff);
+}
+
+/**
+ Reads name and value from buffer, then link it in the list
+
+ @param buff the buffer to read from
+ @param start The list beginning or NULL
+ @param end The list last element or does not matter
+ @param root MEM_ROOT for allocating
+
+ @returns pointer to byte after last recorded in the buffer
+*/
+uchar *engine_option_value::frm_read(const uchar *buff, engine_option_value **start,
+ engine_option_value **end, MEM_ROOT *root)
+{
+ LEX_STRING name, value;
+ uint len;
+
+ name.length= buff[0];
+ buff++;
+ if (!(name.str= strmake_root(root, (const char*)buff, name.length)))
+ return NULL;
+ buff+= name.length;
+ len= uint2korr(buff);
+ value.length= len & ~FRM_QUOTED_VALUE;
+ buff+= 2;
+ if (!(value.str= strmake_root(root, (const char*)buff, value.length)))
+ return NULL;
+ buff+= value.length;
+
+ engine_option_value *ptr=new (root)
+ engine_option_value(name, value, len & FRM_QUOTED_VALUE, start, end);
+ if (!ptr)
+ return NULL;
+
+ return (uchar *)buff;
+}
+
+
+/**
+ Reads options from this buffer
+
+ @param buff the buffer to read from
+ @param length buffer length
+ @param share table descriptor
+ @param root MEM_ROOT for allocating
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool engine_table_options_frm_read(const uchar *buff, uint length,
+ TABLE_SHARE *share)
+{
+ const uchar *buff_end= buff + length;
+ engine_option_value *end;
+ MEM_ROOT *root= &share->mem_root;
+ uint count;
+ DBUG_ENTER("engine_table_options_frm_read");
+
+ while (buff < buff_end && *buff)
+ {
+ if (!(buff= engine_option_value::frm_read(buff, &share->option_list, &end,
+ root)))
+ DBUG_RETURN(TRUE);
+ }
+ buff++;
+
+ for (count=0; count < share->fields; count++)
+ {
+ while (buff < buff_end && *buff)
+ {
+ if (!(buff= engine_option_value::frm_read(buff,
+ &share->field[count]->option_list,
+ &end, root)))
+ DBUG_RETURN(TRUE);
+ }
+ buff++;
+ }
+
+ for (count=0; count < share->keys; count++)
+ {
+ while (buff < buff_end && *buff)
+ {
+ if (!(buff= engine_option_value::frm_read(buff,
+ &share->key_info[count].option_list,
+ &end, root)))
+ DBUG_RETURN(TRUE);
+ }
+ buff++;
+ }
+
+ if (buff < buff_end)
+ sql_print_warning("Table '%s' was created in a later MariaDB version - "
+ "unknown table attributes were ignored",
+ share->table_name.str);
+
+ DBUG_RETURN(buff > buff_end);
+}
+
+/**
+ Merges two lists of engine_option_value's with duplicate removal.
+*/
+
+engine_option_value *merge_engine_table_options(engine_option_value *first,
+ engine_option_value *second,
+ MEM_ROOT *root)
+{
+ engine_option_value *end, *opt;
+ DBUG_ENTER("merge_engine_table_options");
+
+ /* find last element */
+ if (first && second)
+ for (end= first; end->next; end= end->next) /* no-op */;
+
+ for (opt= second; opt; opt= opt->next)
+ new (root) engine_option_value(opt->name, opt->value, opt->quoted_value,
+ &first, &end);
+ DBUG_RETURN(first);
+}
diff --git a/sql/create_options.h b/sql/create_options.h
new file mode 100644
index 00000000000..b66bbf43570
--- /dev/null
+++ b/sql/create_options.h
@@ -0,0 +1,92 @@
+/* Copyright (C) 2010 Monty Program 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 */
+
+/**
+ @file
+
+ Engine defined options of tables/fields/keys in CREATE/ALTER TABLE.
+*/
+
+#ifndef SQL_CREATE_OPTIONS_INCLUDED
+#define SQL_CREATE_OPTIONS_INCLUDED
+
+#include "handler.h"
+
+class engine_option_value: public Sql_alloc
+{
+ public:
+ LEX_STRING name;
+ LEX_STRING value;
+ engine_option_value *next; ///< parser puts them in a FIFO linked list
+ bool parsed; ///< to detect unrecognized options
+ bool quoted_value; ///< option=VAL vs. option='VAL'
+
+ engine_option_value(LEX_STRING &name_arg, LEX_STRING &value_arg, bool quoted,
+ engine_option_value **start, engine_option_value **end) :
+ name(name_arg), value(value_arg),
+ next(NULL), parsed(false), quoted_value(quoted)
+ {
+ link(start, end);
+ }
+ engine_option_value(LEX_STRING &name_arg,
+ engine_option_value **start, engine_option_value **end) :
+ name(name_arg), value(null_lex_str),
+ next(NULL), parsed(false), quoted_value(false)
+ {
+ link(start, end);
+ }
+ engine_option_value(LEX_STRING &name_arg, ulonglong value_arg,
+ engine_option_value **start, engine_option_value **end,
+ MEM_ROOT *root) :
+ name(name_arg), next(NULL), parsed(false), quoted_value(false)
+ {
+ if ((value.str= (char *)alloc_root(root, 22)))
+ {
+ value.length= longlong10_to_str(value_arg, value.str, 10) - value.str;
+ link(start, end);
+ }
+ }
+ static uchar *frm_read(const uchar *buff, engine_option_value **start,
+ engine_option_value **end, MEM_ROOT *root);
+ void link(engine_option_value **start, engine_option_value **end);
+ uint frm_length();
+ uchar *frm_image(uchar *buff);
+};
+
+typedef struct st_key KEY;
+class Create_field;
+
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+ TABLE_SHARE *share);
+my_bool parse_option_list(THD* thd, void **option_struct,
+ engine_option_value *option_list,
+ ha_create_table_option *rules,
+ my_bool suppress_warning,
+ MEM_ROOT *root);
+my_bool engine_table_options_frm_read(const uchar *buff,
+ uint length,
+ TABLE_SHARE *share);
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+ engine_option_value *changes,
+ MEM_ROOT *root);
+
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
+uchar *engine_table_options_frm_image(uchar *buff,
+ engine_option_value *table_option_list,
+ List<Create_field> &create_fields,
+ uint keys, KEY *key_info);
+#endif
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 62e7c670346..959f6ec06c0 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -1367,7 +1367,7 @@ Event_job_data::execute(THD *thd, bool drop)
DBUG_ENTER("Event_job_data::execute");
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, 0);
/*
MySQL parser currently assumes that current database is either
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 753e9d21b65..1349f6b5cba 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -105,7 +105,8 @@ const TABLE_FIELD_TYPE event_table_fields[ET_FIELD_COUNT] =
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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',"
@@ -422,17 +423,18 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
}
key_copy(key_buf, event_table->record[0], key_info, key_len);
- if (!(ret= event_table->file->index_read_map(event_table->record[0], key_buf,
- (key_part_map)1,
- HA_READ_PREFIX)))
+ if (!(ret= event_table->file->ha_index_read_map(event_table->record[0],
+ key_buf,
+ (key_part_map)1,
+ HA_READ_PREFIX)))
{
DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
do
{
ret= copy_event_to_schema_table(thd, schema_table, event_table);
if (ret == 0)
- ret= event_table->file->index_next_same(event_table->record[0],
- key_buf, key_len);
+ ret= event_table->file->ha_index_next_same(event_table->record[0],
+ key_buf, key_len);
} while (ret == 0);
}
DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
@@ -472,7 +474,8 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
READ_RECORD read_record_info;
DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
- init_read_record(&read_record_info, thd, event_table, NULL, 1, 0, FALSE);
+ if (init_read_record(&read_record_info, thd, event_table, NULL, 1, 0, FALSE))
+ DBUG_RETURN(TRUE);
/*
rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
@@ -901,8 +904,9 @@ Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
- if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0], 0, key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
DBUG_PRINT("info", ("Row not found"));
DBUG_RETURN(TRUE);
@@ -957,7 +961,9 @@ Event_db_repository::drop_events_by_field(THD *thd,
DBUG_VOID_RETURN;
/* only enabled events are in memory, so we go now and delete the rest */
- init_read_record(&read_record_info, thd, table, NULL, 1, 0, FALSE);
+ if (init_read_record(&read_record_info, thd, table, NULL, 1, 0, FALSE))
+ goto end;
+
while (!ret && !(read_record_info.read_record(&read_record_info)) )
{
char *et_field= get_field(thd->mem_root, table->field[field]);
@@ -979,8 +985,9 @@ Event_db_repository::drop_events_by_field(THD *thd,
}
}
end_read_record(&read_record_info);
- close_thread_tables(thd);
+end:
+ close_thread_tables(thd);
DBUG_VOID_RETURN;
}
diff --git a/sql/events.cc b/sql/events.cc
index 0f3fc8eee4a..8bb7406b615 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -1214,7 +1214,12 @@ Events::load_events_from_db(THD *thd)
DBUG_RETURN(TRUE);
}
- init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE);
+ if (init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE))
+ {
+ close_thread_tables(thd);
+ DBUG_RETURN(TRUE);
+ }
+
while (!(read_record_info.read_record(&read_record_info)))
{
Event_queue_element *et;
diff --git a/sql/field.cc b/sql/field.cc
index a0b4ec61c68..597ec4f68d0 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -57,7 +57,7 @@ const char field_separator=',';
((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1)))
#define ASSERT_COLUMN_MARKED_FOR_READ DBUG_ASSERT(!table || (!table->read_set || bitmap_is_set(table->read_set, field_index)))
-#define ASSERT_COLUMN_MARKED_FOR_WRITE DBUG_ASSERT(!table || (!table->write_set || bitmap_is_set(table->write_set, field_index)))
+#define ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED DBUG_ASSERT(!table || (!table->write_set || bitmap_is_set(table->write_set, field_index) || bitmap_is_set(table->vcol_set, field_index)))
/*
Rules for merging different types of fields in UNION
@@ -1306,13 +1306,13 @@ String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_val)
Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg)
- :ptr(ptr_arg), null_ptr(null_ptr_arg),
- table(0), orig_table(0), table_name(0),
- field_name(field_name_arg),
- key_start(0), part_of_key(0), part_of_key_not_clustered(0),
- part_of_sortkey(0), unireg_check(unireg_check_arg),
- field_length(length_arg), null_bit(null_bit_arg),
- is_created_from_null_item(FALSE)
+ :ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0),
+ table_name(0), field_name(field_name_arg), option_list(0),
+ option_struct(0), key_start(0), part_of_key(0),
+ part_of_key_not_clustered(0), part_of_sortkey(0),
+ unireg_check(unireg_check_arg), field_length(length_arg),
+ null_bit(null_bit_arg), is_created_from_null_item(FALSE), vcol_info(0),
+ stored_in_db(TRUE)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -1613,7 +1613,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val,
int Field_num::store_decimal(const my_decimal *val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int err= 0;
longlong i= convert_decimal2longlong(val, unsigned_flag, &err);
return test(err | store(i, unsigned_flag));
@@ -1685,7 +1685,7 @@ void Field_num::make_field(Send_field *field)
int Field_str::store_decimal(const my_decimal *d)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
double val;
/* TODO: use decimal2string? */
int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
@@ -1761,7 +1761,7 @@ bool Field::get_time(MYSQL_TIME *ltime)
int Field::store_time(MYSQL_TIME *ltime, timestamp_type type_arg)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[MAX_DATE_STRING_REP_LENGTH];
uint length= (uint) my_TIME_to_str(ltime, buff);
return store(buff, length, &my_charset_bin);
@@ -1888,7 +1888,7 @@ void Field_decimal::overflow(bool negative)
int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff,sizeof(buff), &my_charset_bin);
const uchar *from= (uchar*) from_arg;
@@ -2254,7 +2254,7 @@ int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
int Field_decimal::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
if (unsigned_flag && nr < 0)
{
overflow(1);
@@ -2299,7 +2299,7 @@ int Field_decimal::store(double nr)
int Field_decimal::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[22];
uint length, int_part;
char fyllchar;
@@ -2579,7 +2579,7 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
DBUG_ENTER("Field_new_decimal::store_value");
#ifndef DBUG_OFF
@@ -2624,7 +2624,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
int Field_new_decimal::store(const char *from, uint length,
CHARSET_INFO *charset_arg)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int err;
my_decimal decimal_value;
DBUG_ENTER("Field_new_decimal::store(char*)");
@@ -2691,7 +2691,7 @@ int Field_new_decimal::store(const char *from, uint length,
int Field_new_decimal::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
my_decimal decimal_value;
int err;
DBUG_ENTER("Field_new_decimal::store(double)");
@@ -2726,7 +2726,7 @@ int Field_new_decimal::store(double nr)
int Field_new_decimal::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
my_decimal decimal_value;
int err;
@@ -2748,7 +2748,7 @@ int Field_new_decimal::store(longlong nr, bool unsigned_val)
int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
return store_value(decimal_value);
}
@@ -2970,7 +2970,7 @@ Field_new_decimal::unpack(uchar* to,
int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error;
longlong rnd;
@@ -2982,7 +2982,7 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_tiny::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
nr=rint(nr);
if (unsigned_flag)
@@ -3025,7 +3025,7 @@ int Field_tiny::store(double nr)
int Field_tiny::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if (unsigned_flag)
@@ -3145,7 +3145,7 @@ void Field_tiny::sql_type(String &res) const
int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int store_tmp;
int error;
longlong rnd;
@@ -3166,7 +3166,7 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_short::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int16 res;
nr=rint(nr);
@@ -3218,7 +3218,7 @@ int Field_short::store(double nr)
int Field_short::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int16 res;
@@ -3392,7 +3392,7 @@ void Field_short::sql_type(String &res) const
int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int store_tmp;
int error;
longlong rnd;
@@ -3406,7 +3406,7 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_medium::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
nr=rint(nr);
if (unsigned_flag)
@@ -3452,7 +3452,7 @@ int Field_medium::store(double nr)
int Field_medium::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if (unsigned_flag)
@@ -3582,7 +3582,7 @@ void Field_medium::sql_type(String &res) const
int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long store_tmp;
int error;
longlong rnd;
@@ -3603,7 +3603,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_long::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int32 res;
nr=rint(nr);
@@ -3655,7 +3655,7 @@ int Field_long::store(double nr)
int Field_long::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
int32 res;
@@ -3829,7 +3829,7 @@ void Field_long::sql_type(String &res) const
int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
char *end;
ulonglong tmp;
@@ -3859,7 +3859,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_longlong::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
longlong res;
@@ -3911,7 +3911,7 @@ int Field_longlong::store(double nr)
int Field_longlong::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if (nr < 0) // Only possible error
@@ -4137,7 +4137,7 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_float::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= truncate(&nr, FLT_MAX);
float j= (float)nr;
@@ -4399,7 +4399,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
int Field_double::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= truncate(&nr, DBL_MAX);
#ifdef WORDS_BIGENDIAN
@@ -4826,7 +4826,7 @@ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
my_time_t tmp= 0;
int error;
@@ -4889,7 +4889,7 @@ int Field_timestamp::store(double nr)
int Field_timestamp::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
my_time_t timestamp= 0;
int error;
@@ -5188,7 +5188,7 @@ int Field_time::store_time(MYSQL_TIME *ltime, timestamp_type time_type)
int Field_time::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
int error= 0;
if (nr > (double)TIME_MAX_VALUE)
@@ -5226,7 +5226,7 @@ int Field_time::store(double nr)
int Field_time::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
int error= 0;
if (nr < (longlong) -TIME_MAX_VALUE && !unsigned_val)
@@ -5384,7 +5384,7 @@ void Field_time::sql_type(String &res) const
int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char *end;
int error;
longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error);
@@ -5432,7 +5432,7 @@ int Field_year::store(double nr)
int Field_year::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155)
{
*ptr= 0;
@@ -5505,7 +5505,7 @@ void Field_year::sql_type(String &res) const
int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
uint32 tmp;
int error;
@@ -5560,7 +5560,7 @@ int Field_date::store(double nr)
int Field_date::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME not_used;
int error;
longlong initial_nr= nr;
@@ -5739,7 +5739,7 @@ void Field_date::sql_type(String &res) const
int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
MYSQL_TIME l_time;
int error;
@@ -5789,7 +5789,7 @@ int Field_newdate::store(double nr)
int Field_newdate::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME l_time;
longlong tmp;
int error;
@@ -5825,7 +5825,7 @@ int Field_newdate::store(longlong nr, bool unsigned_val)
int Field_newdate::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
long tmp;
int error= 0;
if (time_type == MYSQL_TIMESTAMP_DATE ||
@@ -5972,7 +5972,7 @@ void Field_newdate::sql_type(String &res) const
int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME time_tmp;
int error;
ulonglong tmp= 0;
@@ -6025,7 +6025,7 @@ int Field_datetime::store(double nr)
int Field_datetime::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
MYSQL_TIME not_used;
int error;
longlong initial_nr= nr;
@@ -6063,7 +6063,7 @@ int Field_datetime::store(longlong nr, bool unsigned_val)
int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
longlong tmp;
int error= 0;
/*
@@ -6366,7 +6366,7 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end,
int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
@@ -6407,7 +6407,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
int Field_str::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
uint length;
uint local_char_length= field_length / charset()->mbmaxlen;
@@ -7011,7 +7011,7 @@ int Field_varstring::do_save_field_metadata(uchar *metadata_ptr)
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
@@ -7675,7 +7675,7 @@ void Field_blob::put_length(uchar *pos, uint32 length)
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint copy_length, new_length;
const char *well_formed_error_pos;
const char *cannot_convert_error_pos;
@@ -8436,7 +8436,7 @@ void Field_enum::store_type(ulonglong value)
int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int err= 0;
uint32 not_used;
char buff[STRING_BUFFER_USUAL_SIZE];
@@ -8485,7 +8485,7 @@ int Field_enum::store(double nr)
int Field_enum::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
if ((ulonglong) nr > typelib->count || nr == 0)
{
@@ -8654,7 +8654,7 @@ Field *Field_enum::new_field(MEM_ROOT *root, struct st_table *new_table,
int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
bool got_warning= 0;
int err= 0;
char *not_used;
@@ -8694,7 +8694,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
int Field_set::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
ulonglong max_nr= set_bits(ulonglong, typelib->count);
if ((ulonglong) nr > max_nr)
@@ -9007,7 +9007,7 @@ uint Field_bit::is_equal(Create_field *new_field)
int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int delta;
for (; length && !*from; from++, length--) // skip left 0's
@@ -9429,7 +9429,7 @@ Field_bit_as_char::Field_bit_as_char(uchar *ptr_arg, uint32 len_arg,
int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE;
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int delta;
uchar bits= (uchar) (field_length & 7);
@@ -9537,6 +9537,8 @@ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg,
((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
(maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
(is_unsigned ? 0 : FIELDFLAG_DECIMAL));
+ vcol_info= 0;
+ stored_in_db= TRUE;
}
@@ -9556,6 +9558,7 @@ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg,
@param fld_interval_list Interval list (if any)
@param fld_charset Field charset
@param fld_geom_type Field geometry type (if any)
+ @param fld_vcol_info Virtual column data
@retval
FALSE on success
@@ -9568,17 +9571,20 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
uint fld_type_modifier, Item *fld_default_value,
Item *fld_on_update_value, LEX_STRING *fld_comment,
char *fld_change, List<String> *fld_interval_list,
- CHARSET_INFO *fld_charset, uint fld_geom_type)
+ CHARSET_INFO *fld_charset, uint fld_geom_type,
+ Virtual_column_info *fld_vcol_info,
+ engine_option_value *create_opt)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("Create_field::init()");
-
+
field= 0;
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
+ option_list= create_opt;
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
@@ -9599,6 +9605,33 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
interval_list.empty();
comment= *fld_comment;
+ vcol_info= fld_vcol_info;
+ stored_in_db= TRUE;
+
+ /* Initialize data for a computed field */
+ if ((uchar)fld_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ {
+ DBUG_ASSERT(vcol_info && vcol_info->expr_item);
+ stored_in_db= vcol_info->is_stored();
+ /*
+ Walk through the Item tree checking if all items are valid
+ to be part of the virtual column
+ */
+ if (vcol_info->expr_item->walk(&Item::check_vcol_func_processor, 0, NULL))
+ {
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ Make a field created for the real type.
+ Note that regular and computed fields differ from each other only by
+ Field::vcol_info. It is is always NULL for a column that is not
+ computed.
+ */
+ sql_type= fld_type= vcol_info->get_real_type();
+ }
+
/*
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
@@ -9888,7 +9921,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
case MYSQL_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
- }
+ }
/* Remember the value of length */
char_length= length;
@@ -9998,7 +10031,6 @@ uint pack_length_to_packflag(uint type)
return 0; // This shouldn't happen
}
-
Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
@@ -10190,6 +10222,10 @@ Create_field::Create_field(Field *old_field,Field *orig_field)
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
+ vcol_info= old_field->vcol_info;
+ stored_in_db= old_field->stored_in_db;
+ option_list= old_field->option_list;
+ option_struct= old_field->option_struct;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -10264,6 +10300,19 @@ Create_field::Create_field(Field *old_field,Field *orig_field)
/**
+ Makes a clone of this object for ALTER/CREATE TABLE
+
+ @param mem_root MEM_ROOT where to clone the field
+*/
+
+Create_field *Create_field::clone(MEM_ROOT *mem_root) const
+{
+ Create_field *res= new (mem_root) Create_field(*this);
+ return res;
+}
+
+
+/**
maximum possible display length for blob.
@return
diff --git a/sql/field.h b/sql/field.h
index 1907ad803bc..53cfb982e32 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -45,6 +45,71 @@ inline uint get_set_pack_length(int elements)
return len > 4 ? 8 : len;
}
+/*
+ Virtual_column_info is the class to contain additional
+ characteristics that is specific for a virtual/computed
+ field such as:
+ - the defining expression that is evaluated to compute the value
+ of the field
+ - whether the field is to be stored in the database
+ - whether the field is used in a partitioning expression
+*/
+
+class Virtual_column_info: public Sql_alloc
+{
+private:
+ /*
+ The following data is only updated by the parser and read
+ when a Create_field object is created/initialized.
+ */
+ enum_field_types field_type; /* Real field type*/
+ /* Flag indicating that the field is physically stored in the database */
+ my_bool stored_in_db;
+ /* Flag indicating that the field used in a partitioning expression */
+ my_bool in_partitioning_expr;
+
+public:
+ /* The expression to compute the value of the virtual column */
+ Item *expr_item;
+ /* Text representation of the defining expression */
+ LEX_STRING expr_str;
+
+ Virtual_column_info()
+ : field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
+ stored_in_db(FALSE), in_partitioning_expr(FALSE),
+ expr_item(NULL)
+ {
+ expr_str.str= NULL;
+ expr_str.length= 0;
+ };
+ ~Virtual_column_info() {}
+ enum_field_types get_real_type()
+ {
+ return field_type;
+ }
+ void set_field_type(enum_field_types fld_type)
+ {
+ /* Calling this function can only be done once. */
+ field_type= fld_type;
+ }
+ bool is_stored()
+ {
+ return stored_in_db;
+ }
+ void set_stored_in_db_flag(bool stored)
+ {
+ stored_in_db= stored;
+ }
+ bool is_in_partitioning_expr()
+ {
+ return in_partitioning_expr;
+ }
+ void mark_as_in_partitioning_expr()
+ {
+ in_partitioning_expr= TRUE;
+ }
+};
+
class Field
{
Field(const Item &); /* Prevent use of these */
@@ -61,20 +126,23 @@ public:
*/
uchar *null_ptr;
/*
- Note that you can use table->in_use as replacement for current_thd member
+ 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
const char **table_name, *field_name;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
key_map part_of_sortkey;
- /*
- We use three additional unireg types for TIMESTAMP to overcome limitation
- of current binary format of .frm file. We'd like to be able to support
- NOW() as default and on update value for such fields but unable to hold
+ /*
+ We use three additional unireg types for TIMESTAMP to overcome limitation
+ of current binary format of .frm file. We'd like to be able to support
+ NOW() as default and on update value for such fields but unable to hold
this info anywhere except unireg_check field. This issue will be resolved
in more clean way with transition to new text based .frm format.
See also comment for Field_timestamp::Field_timestamp().
@@ -107,6 +175,19 @@ public:
*/
bool is_created_from_null_item;
+ /*
+ This is additional data provided for any computed(virtual) field.
+ In particular it includes a pointer to the item by which this field
+ can be computed from other fields.
+ */
+ Virtual_column_info *vcol_info;
+ /*
+ Flag indicating that the field is physically stored in tables
+ rather than just computed from other fields.
+ As of now, FALSE can be set only for computed virtual columns.
+ */
+ bool stored_in_db;
+
Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg);
@@ -2065,14 +2146,31 @@ public:
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
+ engine_option_value *option_list;
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */
+ void *option_struct;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
- Create_field() :after(0) {}
+
+ /*
+ This is additinal data provided for any computed(virtual) field.
+ In particular it includes a pointer to the item by which this field
+ can be computed from other fields.
+ */
+ Virtual_column_info *vcol_info;
+ /*
+ Flag indicating that the field is physically stored in tables
+ rather than just computed from other fields.
+ As of now, FALSE can be set only for computed virtual columns.
+ */
+ bool stored_in_db;
+
+ Create_field() :after(0), option_list(NULL), option_struct(NULL)
+ {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
- Create_field *clone(MEM_ROOT *mem_root) const
- { return new (mem_root) Create_field(*this); }
+ Create_field *clone(MEM_ROOT *mem_root) const;
void create_length_to_internal_length(void);
/* Init for a tmp table field. To be extended if need be. */
@@ -2084,7 +2182,8 @@ public:
char *decimals, uint type_modifier, Item *default_value,
Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type, Virtual_column_info *vcol_info,
+ engine_option_value *option_list);
bool field_flags_are_binary()
{
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 0e476d3d957..3f2e2e55046 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -515,7 +515,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
THD *thd= current_thd;
volatile THD::killed_state *killed= &thd->killed;
handler *file;
- MY_BITMAP *save_read_set, *save_write_set;
+ MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set;
DBUG_ENTER("find_all_keys");
DBUG_PRINT("info",("using: %s",
(select ? select->quick ? "ranges" : "where":
@@ -537,7 +537,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
if (! indexfile && ! quick_select)
{
next_pos=(uchar*) 0; /* Find records in sequence */
- file->ha_rnd_init(1);
+ if (file->ha_rnd_init_with_error(1))
+ DBUG_RETURN(HA_POS_ERROR);
file->extra_opt(HA_EXTRA_CACHE,
current_thd->variables.read_buff_size);
}
@@ -551,6 +552,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
/* Remember original bitmaps */
save_read_set= sort_form->read_set;
save_write_set= sort_form->write_set;
+ save_vcol_set= sort_form->vcol_set;
/* Set up temporary column read map for columns used by sort */
bitmap_clear_all(&sort_form->tmp_set);
/* Temporary set for register_used_fields and register_field_in_read_map */
@@ -559,7 +561,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
if (select && select->cond)
select->cond->walk(&Item::register_field_in_read_map, 1,
(uchar*) sort_form);
- sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
+ sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set,
+ &sort_form->tmp_set);
for (;;)
{
@@ -567,6 +570,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
{
if ((error= select->quick->get_next()))
break;
+ if (!error)
+ update_virtual_fields(thd, sort_form);
file->position(sort_form->record[0]);
DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE););
}
@@ -579,11 +584,13 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
error= my_errno ? my_errno : -1; /* Abort */
break;
}
- error=file->rnd_pos(sort_form->record[0],next_pos);
+ error=file->ha_rnd_pos(sort_form->record[0],next_pos);
}
else
{
- error=file->rnd_next(sort_form->record[0]);
+ error=file->ha_rnd_next(sort_form->record[0]);
+ if (!error)
+ update_virtual_fields(thd, sort_form);
if (!flag)
{
my_store_ptr(ref_pos,ref_length,record); // Position to row
@@ -638,7 +645,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
DBUG_RETURN(HA_POS_ERROR);
/* Signal we should use orignal column read and write maps */
- sort_form->column_bitmaps_set(save_read_set, save_write_set);
+ sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set);
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
if (error != HA_ERR_END_OF_FILE)
@@ -1005,7 +1012,14 @@ static void register_used_fields(SORTPARAM *param)
if ((field= sort_field->field))
{
if (field->table == table)
- bitmap_set_bit(bitmap, field->field_index);
+ {
+ if (field->vcol_info)
+ {
+ Item *vcol_item= field->vcol_info->expr_item;
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ }
+ bitmap_set_bit(bitmap, field->field_index);
+ }
}
else
{ // Item
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index ceb60d127cf..782b77eac51 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -9174,7 +9174,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
thd->main_security_ctx.master_access= ~0;
- thd->main_security_ctx.priv_user = 0;
+ thd->main_security_ctx.priv_user[0] = 0;
CHARSET_INFO *charset_connection;
charset_connection= get_charset_by_csname("utf8",
@@ -10553,6 +10553,23 @@ mysql_declare_plugin(ndbcluster)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_storage_engine,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ "Clustered, fault-tolerant tables",
+ PLUGIN_LICENSE_GPL,
+ ndbcluster_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ ndb_status_variables_export,/* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
#else
int Sun_ar_require_a_symbol_here= 0;
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index b24b17106c6..77851119e34 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -3681,7 +3681,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
thd->client_capabilities= 0;
my_net_init(&thd->net, 0);
thd->main_security_ctx.master_access= ~0;
- thd->main_security_ctx.priv_user= 0;
+ thd->main_security_ctx.priv_user[0]= 0;
/*
Set up ndb binlog
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index ed2cb96a115..2bd2eabb58b 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -52,6 +52,7 @@
#endif
#include "mysql_priv.h"
+#include "create_options.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -1665,11 +1666,11 @@ int ha_partition::copy_partitions(ulonglong * const copied,
uint32 new_part;
late_extra_cache(reorg_part);
- if ((result= file->ha_rnd_init(1)))
+ if ((result= file->ha_rnd_init_with_error(1)))
goto error;
while (TRUE)
{
- if ((result= file->rnd_next(m_rec0)))
+ if ((result= file->ha_rnd_next(m_rec0)))
{
if (result == HA_ERR_RECORD_DELETED)
continue; //Probably MyISAM
@@ -1891,6 +1892,8 @@ uint ha_partition::del_ren_cre_table(const char *from,
{
if ((error= set_up_table_before_create(table_arg, from_buff,
create_info, i, NULL)) ||
+ parse_engine_table_options(ha_thd(), (*file)->ht,
+ (*file)->table_share) ||
((error= (*file)->ha_create(from_buff, table_arg, create_info))))
goto create_error;
}
@@ -2487,7 +2490,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
DBUG_RETURN(1);
m_start_key.length= 0;
m_rec0= table->record[0];
- m_rec_length= table_share->reclength;
+ m_rec_length= table_share->stored_rec_length;
alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
alloc_len+= table_share->max_key_length;
if (!m_ordered_rec_buffer)
@@ -3645,6 +3648,7 @@ int ha_partition::rnd_next(uchar *buf)
int result= HA_ERR_END_OF_FILE;
uint part_id= m_part_spec.start_part;
DBUG_ENTER("ha_partition::rnd_next");
+ decrement_statistics(&SSV::ha_read_rnd_next_count);
if (NO_CURRENT_PART_ID == part_id)
{
@@ -3660,7 +3664,7 @@ int ha_partition::rnd_next(uchar *buf)
while (TRUE)
{
- result= file->rnd_next(buf);
+ result= file->ha_rnd_next(buf);
if (!result)
{
m_last_part= part_id;
@@ -3788,6 +3792,7 @@ int ha_partition::rnd_pos(uchar * buf, uchar *pos)
uint part_id;
handler *file;
DBUG_ENTER("ha_partition::rnd_pos");
+ decrement_statistics(&SSV::ha_read_rnd_count);
part_id= uint2korr((const uchar *) pos);
DBUG_ASSERT(part_id < m_tot_parts);
@@ -4000,6 +4005,7 @@ int ha_partition::index_read_map(uchar *buf, const uchar *key,
enum ha_rkey_function find_flag)
{
DBUG_ENTER("ha_partition::index_read_map");
+ decrement_statistics(&SSV::ha_read_key_count);
end_range= 0;
m_index_scan_type= partition_index_read;
m_start_key.key= key;
@@ -4128,6 +4134,7 @@ int ha_partition::common_index_read(uchar *buf, bool have_start_key)
int ha_partition::index_first(uchar * buf)
{
DBUG_ENTER("ha_partition::index_first");
+ decrement_statistics(&SSV::ha_read_first_count);
end_range= 0;
m_index_scan_type= partition_index_first;
@@ -4159,6 +4166,7 @@ int ha_partition::index_first(uchar * buf)
int ha_partition::index_last(uchar * buf)
{
DBUG_ENTER("ha_partition::index_last");
+ decrement_statistics(&SSV::ha_read_last_count);
m_index_scan_type= partition_index_last;
DBUG_RETURN(common_first_last(buf));
@@ -4187,39 +4195,6 @@ int ha_partition::common_first_last(uchar *buf)
/*
- Read last using key
-
- SYNOPSIS
- index_read_last_map()
- buf Read row in MySQL Row Format
- key Key
- keypart_map Which part of key is used
-
- RETURN VALUE
- >0 Error code
- 0 Success
-
- DESCRIPTION
- This is used in join_read_last_key to optimise away an ORDER BY.
- Can only be used on indexes supporting HA_READ_ORDER
-*/
-
-int ha_partition::index_read_last_map(uchar *buf, const uchar *key,
- key_part_map keypart_map)
-{
- DBUG_ENTER("ha_partition::index_read_last");
-
- m_ordered= TRUE; // Safety measure
- end_range= 0;
- m_index_scan_type= partition_index_read_last;
- m_start_key.key= key;
- m_start_key.keypart_map= keypart_map;
- m_start_key.flag= HA_READ_PREFIX_LAST;
- DBUG_RETURN(common_index_read(buf, TRUE));
-}
-
-
-/*
Read next record in a forward index scan
SYNOPSIS
@@ -4237,6 +4212,7 @@ int ha_partition::index_read_last_map(uchar *buf, const uchar *key,
int ha_partition::index_next(uchar * buf)
{
DBUG_ENTER("ha_partition::index_next");
+ decrement_statistics(&SSV::ha_read_next_count);
/*
TODO(low priority):
@@ -4273,6 +4249,7 @@ int ha_partition::index_next(uchar * buf)
int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen)
{
DBUG_ENTER("ha_partition::index_next_same");
+ decrement_statistics(&SSV::ha_read_next_count);
DBUG_ASSERT(keylen == m_start_key.length);
DBUG_ASSERT(m_index_scan_type != partition_index_last);
@@ -4300,6 +4277,7 @@ int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen)
int ha_partition::index_prev(uchar * buf)
{
DBUG_ENTER("ha_partition::index_prev");
+ decrement_statistics(&SSV::ha_read_prev_count);
/* TODO: read comment in index_next */
DBUG_ASSERT(m_index_scan_type != partition_index_first);
@@ -4510,8 +4488,8 @@ int ha_partition::handle_unordered_next(uchar *buf, bool is_next_same)
}
else if (is_next_same)
{
- if (!(error= file->index_next_same(buf, m_start_key.key,
- m_start_key.length)))
+ if (!(error= file->ha_index_next_same(buf, m_start_key.key,
+ m_start_key.length)))
{
m_last_part= m_part_spec.start_part;
DBUG_RETURN(0);
@@ -4519,7 +4497,7 @@ int ha_partition::handle_unordered_next(uchar *buf, bool is_next_same)
}
else
{
- if (!(error= file->index_next(buf)))
+ if (!(error= file->ha_index_next(buf)))
{
m_last_part= m_part_spec.start_part;
DBUG_RETURN(0); // Row was in range
@@ -4574,13 +4552,26 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf)
break;
case partition_index_read:
DBUG_PRINT("info", ("index_read on partition %d", i));
- error= file->index_read_map(buf, m_start_key.key,
- m_start_key.keypart_map,
- m_start_key.flag);
+ error= file->ha_index_read_map(buf, m_start_key.key,
+ m_start_key.keypart_map,
+ m_start_key.flag);
break;
case partition_index_first:
DBUG_PRINT("info", ("index_first on partition %d", i));
- error= file->index_first(buf);
+ /*
+ MyISAM engine can fail if we call index_first() when indexes disabled
+ that happens if the table is empty.
+ Here we use file->stats.records instead of file->records() because
+ file->records() is supposed to return an EXACT count, and it can be
+ possibly slow. We don't need an exact number, an approximate one- from
+ the last ::info() call - is sufficient.
+ */
+ if (file->stats.records == 0)
+ {
+ error= HA_ERR_END_OF_FILE;
+ break;
+ }
+ error= file->ha_index_first(buf);
break;
case partition_index_first_unordered:
/*
@@ -4661,23 +4652,43 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
switch (m_index_scan_type) {
case partition_index_read:
- error= file->index_read_map(rec_buf_ptr,
- m_start_key.key,
- m_start_key.keypart_map,
- m_start_key.flag);
+ error= file->ha_index_read_map(rec_buf_ptr,
+ m_start_key.key,
+ m_start_key.keypart_map,
+ m_start_key.flag);
break;
case partition_index_first:
- error= file->index_first(rec_buf_ptr);
+ /*
+ MyISAM engine can fail if we call index_first() when indexes disabled
+ that happens if the table is empty.
+ Here we use file->stats.records instead of file->records() because
+ file->records() is supposed to return an EXACT count, and it can be
+ possibly slow. We don't need an exact number, an approximate one- from
+ the last ::info() call - is sufficient.
+ */
+ if (file->stats.records == 0)
+ {
+ error= HA_ERR_END_OF_FILE;
+ break;
+ }
+ error= file->ha_index_first(rec_buf_ptr);
reverse_order= FALSE;
break;
case partition_index_last:
- error= file->index_last(rec_buf_ptr);
- reverse_order= TRUE;
- break;
- case partition_index_read_last:
- error= file->index_read_last_map(rec_buf_ptr,
- m_start_key.key,
- m_start_key.keypart_map);
+ /*
+ MyISAM engine can fail if we call index_last() when indexes disabled
+ that happens if the table is empty.
+ Here we use file->stats.records instead of file->records() because
+ file->records() is supposed to return an EXACT count, and it can be
+ possibly slow. We don't need an exact number, an approximate one- from
+ the last ::info() call - is sufficient.
+ */
+ if (file->stats.records == 0)
+ {
+ error= HA_ERR_END_OF_FILE;
+ break;
+ }
+ error= file->ha_index_last(rec_buf_ptr);
reverse_order= TRUE;
break;
case partition_read_range:
@@ -4779,10 +4790,10 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
memcpy(rec_buf(part_id), table->record[0], m_rec_length);
}
else if (!is_next_same)
- error= file->index_next(rec_buf(part_id));
+ error= file->ha_index_next(rec_buf(part_id));
else
- error= file->index_next_same(rec_buf(part_id), m_start_key.key,
- m_start_key.length);
+ error= file->ha_index_next_same(rec_buf(part_id), m_start_key.key,
+ m_start_key.length);
if (error)
{
if (error == HA_ERR_END_OF_FILE)
@@ -4827,7 +4838,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
handler *file= m_file[part_id];
DBUG_ENTER("ha_partition::handle_ordered_prev");
- if ((error= file->index_prev(rec_buf(part_id))))
+ if ((error= file->ha_index_prev(rec_buf(part_id))))
{
if (error == HA_ERR_END_OF_FILE)
{
@@ -6723,5 +6734,22 @@ mysql_declare_plugin(partition)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_storage_engine,
+ "partition",
+ "Mikael Ronstrom, MySQL AB",
+ "Partition Storage Engine Helper",
+ PLUGIN_LICENSE_GPL,
+ partition_initialize, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#endif
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 9f6d9e0a5ba..c8c45d72b26 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -64,9 +64,8 @@ private:
partition_index_first= 1,
partition_index_first_unordered= 2,
partition_index_last= 3,
- partition_index_read_last= 4,
- partition_read_range = 5,
- partition_no_index_scan= 6
+ partition_read_range = 4,
+ partition_no_index_scan= 5
};
/* Data for the partition handler */
int m_mode; // Open mode
@@ -250,6 +249,7 @@ public:
DBUG_RETURN(0);
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes);
private:
@@ -457,8 +457,6 @@ public:
virtual int index_first(uchar * buf);
virtual int index_last(uchar * buf);
virtual int index_next_same(uchar * buf, const uchar * key, uint keylen);
- virtual int index_read_last_map(uchar * buf, const uchar * key,
- key_part_map keypart_map);
/*
read_first_row is virtual method but is only implemented by
@@ -1112,4 +1110,27 @@ public:
-------------------------------------------------------------------------
virtual void append_create_info(String *packet)
*/
+
+ /*
+ the following heavily relies on the fact that all partitions
+ are in the same storage engine.
+
+ When this limitation is lifted, the following hack should go away,
+ and a proper interface for engines needs to be introduced:
+
+ an PARTITION_SHARE structure that has a pointer to the TABLE_SHARE.
+ is given to engines everywhere where TABLE_SHARE is used now
+ has members like option_struct, ha_data
+ perhaps TABLE needs to be split the same way too...
+
+ this can also be done before partition will support a mix of engines,
+ but preferably together with other incompatible API changes.
+ */
+ virtual handlerton *partition_ht() const
+ {
+ handlerton *h= m_file[0]->ht;
+ for (uint i=1; i < m_tot_parts; i++)
+ DBUG_ASSERT(h == m_file[i]->ht);
+ return h;
+ }
};
diff --git a/sql/handler.cc b/sql/handler.cc
index afd9d08971d..10f14be26ae 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -24,6 +24,7 @@
#endif
#include "mysql_priv.h"
+#include "create_options.h"
#include "rpl_filter.h"
#include <myisampack.h>
#include "myisam.h"
@@ -1236,6 +1237,7 @@ int ha_commit_one_phase(THD *thd, bool all)
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
error=1;
}
+ /* Should this be done only if is_real_trans is set ? */
status_var_increment(thd->status_var.ha_commit_count);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
@@ -2043,12 +2045,6 @@ handler *handler::clone(MEM_ROOT *mem_root)
}
-
-void handler::ha_statistic_increment(ulong SSV::*offset) const
-{
- status_var_increment(table->in_use->status_var.*offset);
-}
-
void **handler::ha_data(THD *thd) const
{
return thd_ha_data(thd, ht);
@@ -2113,10 +2109,24 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
dup_ref=ref+ALIGN_SIZE(ref_length);
cached_table_flags= table_flags();
}
+ rows_read= rows_changed= 0;
+ memset(index_rows_read, 0, sizeof(index_rows_read));
DBUG_RETURN(error);
}
+/* Initialize handler for random reading, with error handling */
+
+int handler::ha_rnd_init_with_error(bool scan)
+{
+ int error;
+ if (!(error= ha_rnd_init(scan)))
+ return 0;
+ table->file->print_error(error, MYF(0));
+ return error;
+}
+
+
/**
Read first row (only) from a table.
@@ -2128,8 +2138,6 @@ int handler::read_first_row(uchar * buf, uint primary_key)
register int error;
DBUG_ENTER("handler::read_first_row");
- ha_statistic_increment(&SSV::ha_read_first_count);
-
/*
If there is very few deleted rows in the table, find the first row by
scanning the table.
@@ -2138,15 +2146,17 @@ int handler::read_first_row(uchar * buf, uint primary_key)
if (stats.deleted < 10 || primary_key >= MAX_KEY ||
!(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
{
- (void) ha_rnd_init(1);
- while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
- (void) ha_rnd_end();
+ if ((!(error= ha_rnd_init(1))))
+ {
+ while ((error= ha_rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
+ (void) ha_rnd_end();
+ }
}
else
{
/* Find the first row through the primary key */
if (!(error = ha_index_init(primary_key, 0)))
- error= index_first(buf);
+ error= ha_index_first(buf);
(void) ha_index_end();
}
DBUG_RETURN(error);
@@ -2517,10 +2527,10 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
table->read_set);
column_bitmaps_signal();
- index_init(table->s->next_number_index, 1);
+ ha_index_init(table->s->next_number_index, 1);
if (table->s->next_number_keypart == 0)
{ // Autoincrement at key-start
- error=index_last(table->record[1]);
+ error=ha_index_last(table->record[1]);
/*
MySQL implicitely assumes such method does locking (as MySQL decides to
use nr+increment without checking again with the handler, in
@@ -2534,9 +2544,10 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
key_copy(key, table->record[0],
table->key_info + table->s->next_number_index,
table->s->next_number_key_offset);
- error= index_read_map(table->record[1], key,
- make_prev_keypart_map(table->s->next_number_keypart),
- HA_READ_PREFIX_LAST);
+ error= ha_index_read_map(table->record[1], key,
+ make_prev_keypart_map(table->s->
+ next_number_keypart),
+ HA_READ_PREFIX_LAST);
/*
MySQL needs to call us for next row: assume we are inserting ("a",null)
here, we return 3, and next this statement will want to insert
@@ -2551,7 +2562,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
else
nr= ((ulonglong) table->next_number_field->
val_int_offset(table->s->rec_buff_length)+1);
- index_end();
+ ha_index_end();
(void) extra(HA_EXTRA_NO_KEYREAD);
*first_value= nr;
}
@@ -3106,16 +3117,46 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
return update_frm_version(table);
}
+/*
+ Calculate cost of 'index only' scan for given index and number of records.
+
+ SYNOPSIS
+ handler->keyread_read_time()
+ index key to read
+ ranges number of ranges
+ rows #of records to read
+
+ NOTES
+ It is assumed that we will read trough all key ranges and that all
+ key blocks are half full (normally things are much better). It is also
+ assumed that each time we read the next key from the index, the handler
+ performs a random seek, thus the cost is proportional to the number of
+ blocks read.
+*/
+
+double handler::keyread_read_time(uint index, uint ranges, ha_rows rows)
+{
+ double read_time;
+ uint keys_per_block= (stats.block_size/2/
+ (table->key_info[index].key_length + ref_length) + 1);
+ read_time=((double) (rows+keys_per_block-1)/ (double) keys_per_block);
+ return read_time;
+}
+
+
/**
A helper function to mark a transaction read-write,
if it is started.
*/
-inline
void
-handler::mark_trx_read_write()
+handler::mark_trx_read_write_part2()
{
Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
+
+ /* Don't call this function again for this statement */
+ mark_trx_done= TRUE;
+
/*
When a storage engine method is called, the transaction must
have been started, unless it's a DDL call, for which the
@@ -3496,7 +3537,7 @@ int ha_enable_transaction(THD *thd, bool on)
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
{
int error;
- DBUG_ENTER("index_next_same");
+ DBUG_ENTER("handler::index_next_same");
if (!(error=index_next(buf)))
{
my_ptrdiff_t ptrdiff= buf - table->record[0];
@@ -3541,6 +3582,7 @@ int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
key_part->field->move_field_offset(-ptrdiff);
}
}
+ DBUG_PRINT("return",("%i", error));
DBUG_RETURN(error);
}
@@ -3566,6 +3608,122 @@ void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info,
}
+/*
+ Updates the global table stats with the TABLE this handler represents
+*/
+
+void handler::update_global_table_stats()
+{
+ TABLE_STATS * table_stats;
+
+ status_var_add(table->in_use->status_var.rows_read, rows_read);
+
+ if (!table->in_use->userstat_running)
+ {
+ rows_read= rows_changed= 0;
+ return;
+ }
+
+ if (rows_read + rows_changed == 0)
+ return; // Nothing to update.
+
+ DBUG_ASSERT(table->s && table->s->table_cache_key.str);
+
+ pthread_mutex_lock(&LOCK_global_table_stats);
+ /* Gets the global table stats, creating one if necessary. */
+ if (!(table_stats= (TABLE_STATS*)
+ hash_search(&global_table_stats,
+ (uchar*) table->s->table_cache_key.str,
+ table->s->table_cache_key.length)))
+ {
+ if (!(table_stats = ((TABLE_STATS*)
+ my_malloc(sizeof(TABLE_STATS),
+ MYF(MY_WME | MY_ZEROFILL)))))
+ {
+ /* Out of memory error already given */
+ goto end;
+ }
+ memcpy(table_stats->table, table->s->table_cache_key.str,
+ table->s->table_cache_key.length);
+ table_stats->table_name_length= table->s->table_cache_key.length;
+ table_stats->engine_type= ht->db_type;
+ /* No need to set variables to 0, as we use MY_ZEROFILL above */
+
+ if (my_hash_insert(&global_table_stats, (uchar*) table_stats))
+ {
+ /* Out of memory error is already given */
+ my_free(table_stats, 0);
+ goto end;
+ }
+ }
+ // Updates the global table stats.
+ table_stats->rows_read+= rows_read;
+ table_stats->rows_changed+= rows_changed;
+ table_stats->rows_changed_x_indexes+= (rows_changed *
+ (table->s->keys ? table->s->keys :
+ 1));
+ rows_read= rows_changed= 0;
+end:
+ pthread_mutex_unlock(&LOCK_global_table_stats);
+}
+
+
+/*
+ Updates the global index stats with this handler's accumulated index reads.
+*/
+
+void handler::update_global_index_stats()
+{
+ DBUG_ASSERT(table->s);
+
+ if (!table->in_use->userstat_running)
+ {
+ /* Reset all index read values */
+ bzero(index_rows_read, sizeof(index_rows_read[0]) * table->s->keys);
+ return;
+ }
+
+ for (uint index = 0; index < table->s->keys; index++)
+ {
+ if (index_rows_read[index])
+ {
+ INDEX_STATS* index_stats;
+ uint key_length;
+ KEY *key_info = &table->key_info[index]; // Rows were read using this
+
+ DBUG_ASSERT(key_info->cache_name);
+ if (!key_info->cache_name)
+ continue;
+ key_length= table->s->table_cache_key.length + key_info->name_length + 1;
+ pthread_mutex_lock(&LOCK_global_index_stats);
+ // Gets the global index stats, creating one if necessary.
+ if (!(index_stats= (INDEX_STATS*) hash_search(&global_index_stats,
+ key_info->cache_name,
+ key_length)))
+ {
+ if (!(index_stats = ((INDEX_STATS*)
+ my_malloc(sizeof(INDEX_STATS),
+ MYF(MY_WME | MY_ZEROFILL)))))
+ goto end; // Error is already given
+
+ memcpy(index_stats->index, key_info->cache_name, key_length);
+ index_stats->index_name_length= key_length;
+ if (my_hash_insert(&global_index_stats, (uchar*) index_stats))
+ {
+ my_free(index_stats, 0);
+ goto end;
+ }
+ }
+ /* Updates the global index stats. */
+ index_stats->rows_read+= index_rows_read[index];
+ index_rows_read[index]= 0;
+end:
+ pthread_mutex_unlock(&LOCK_global_index_stats);
+ }
+ }
+}
+
+
/****************************************************************************
** Some general functions that isn't in the handler class
****************************************************************************/
@@ -3602,6 +3760,7 @@ int ha_create_table(THD *thd, const char *path,
name= get_canonical_filename(table.file, share.path.str, name_buff);
error= table.file->ha_create(name, &table, create_info);
+
VOID(closefrm(&table, 0));
if (error)
{
@@ -3708,11 +3867,13 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
uint tmp_block_size= (uint) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold;
+ uint partitions= key_cache->param_partitions;
pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(!init_key_cache(key_cache,
tmp_block_size,
tmp_buff_size,
- division_limit, age_threshold));
+ division_limit, age_threshold,
+ partitions));
}
DBUG_RETURN(0);
}
@@ -3742,10 +3903,12 @@ int ha_resize_key_cache(KEY_CACHE *key_cache)
/**
- Change parameters for key cache (like size)
+ Change parameters for key cache (like division_limit)
*/
int ha_change_key_cache_param(KEY_CACHE *key_cache)
{
+ DBUG_ENTER("ha_change_key_cache_param");
+
if (key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
@@ -3754,9 +3917,35 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache)
pthread_mutex_unlock(&LOCK_global_system_variables);
change_key_cache_param(key_cache, division_limit, age_threshold);
}
- return 0;
+ DBUG_RETURN(0);
}
+
+/**
+ Repartition key cache
+*/
+int ha_repartition_key_cache(KEY_CACHE *key_cache)
+{
+ DBUG_ENTER("ha_repartition_key_cache");
+
+ if (key_cache->key_cache_inited)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
+ long tmp_block_size= (long) key_cache->param_block_size;
+ uint division_limit= key_cache->param_division_limit;
+ uint age_threshold= key_cache->param_age_threshold;
+ uint partitions= key_cache->param_partitions;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ DBUG_RETURN(!repartition_key_cache(key_cache, tmp_block_size,
+ tmp_buff_size,
+ division_limit, age_threshold,
+ partitions));
+ }
+ DBUG_RETURN(0);
+}
+
+
/**
Free memory allocated by a key cache.
*/
@@ -4225,17 +4414,16 @@ int handler::read_range_first(const key_range *start_key,
range_key_part= table->key_info[active_index].key_part;
if (!start_key) // Read first record
- result= index_first(table->record[0]);
+ result= ha_index_first(table->record[0]);
else
- result= index_read_map(table->record[0],
- start_key->key,
- start_key->keypart_map,
- start_key->flag);
+ result= ha_index_read_map(table->record[0],
+ start_key->key,
+ start_key->keypart_map,
+ start_key->flag);
if (result)
DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
? HA_ERR_END_OF_FILE
: result);
-
DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
}
@@ -4261,11 +4449,11 @@ int handler::read_range_next()
if (eq_range)
{
/* We trust that index_next_same always gives a row in range */
- DBUG_RETURN(index_next_same(table->record[0],
- end_range->key,
- end_range->length));
+ DBUG_RETURN(ha_index_next_same(table->record[0],
+ end_range->key,
+ end_range->length));
}
- result= index_next(table->record[0]);
+ result= ha_index_next(table->record[0]);
if (result)
DBUG_RETURN(result);
DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
@@ -4446,6 +4634,8 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
if (!result)
my_eof(thd);
+ else if (!thd->is_error())
+ my_error(ER_GET_ERRNO, MYF(0), 0);
return result;
}
@@ -4646,9 +4836,11 @@ int handler::ha_write_row(uchar *buf)
DBUG_ENTER("handler::ha_write_row");
mark_trx_read_write();
+ increment_statistics(&SSV::ha_write_count);
if (unlikely(error= write_row(buf)))
DBUG_RETURN(error);
+ rows_changed++;
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
DBUG_RETURN(error); /* purecov: inspected */
DBUG_RETURN(0);
@@ -4667,9 +4859,11 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
DBUG_ASSERT(new_data == table->record[0]);
mark_trx_read_write();
+ increment_statistics(&SSV::ha_update_count);
if (unlikely(error= update_row(old_data, new_data)))
return error;
+ rows_changed++;
if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
return error;
return 0;
@@ -4681,9 +4875,11 @@ int handler::ha_delete_row(const uchar *buf)
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
mark_trx_read_write();
+ increment_statistics(&SSV::ha_delete_count);
if (unlikely(error= delete_row(buf)))
return error;
+ rows_changed++;
if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
return error;
return 0;
diff --git a/sql/handler.h b/sql/handler.h
index 9fefca99908..ad4743b78b1 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -16,6 +16,9 @@
/* Definitions for parameters to do with handler-routines */
+#ifndef SQL_HANDLER_INCLUDED
+#define SQL_HANDLER_INCLUDED
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -30,6 +33,10 @@
#define USING_TRANSACTIONS
+#if MAX_KEY > 128
+#error MAX_KEY is too large. Values up to 128 are supported.
+#endif
+
// the following is for checking tables
#define HA_ADMIN_ALREADY_DONE 1
@@ -545,6 +552,103 @@ struct handler_log_file_data {
enum log_status status;
};
+/*
+ Definitions for engine-specific table/field/index options in the CREATE TABLE.
+
+ Options are declared with HA_*OPTION_* macros (HA_TOPTION_NUMBER,
+ HA_FOPTION_ENUM, HA_IOPTION_STRING, etc).
+
+ Every macros takes the option name, and the name of the underlying field of
+ the appropriate C structure. The "appropriate C structure" is
+ ha_table_option_struct for table level options,
+ ha_field_option_struct for field level options,
+ ha_index_option_struct for key level options. The engine either
+ defines a structure of this name, or uses #define's to map
+ these "appropriate" names to the actual structure type name.
+
+ ULL options use a ulonglong as the backing store.
+ HA_*OPTION_NUMBER() takes the option name, the structure field name,
+ the default value for the option, min, max, and blk_siz values.
+
+ STRING options use a char* as a backing store.
+ HA_*OPTION_STRING takes the option name and the structure field name.
+ The default value will be 0.
+
+ ENUM options use a uint as a backing store (not enum!!!).
+ HA_*OPTION_ENUM takes the option name, the structure field name,
+ the default value for the option as a number, and a string with the
+ permitted values for this enum - one string with comma separated values,
+ for example: "gzip,bzip2,lzma"
+
+ BOOL options use a bool as a backing store.
+ HA_*OPTION_BOOL takes the option name, the structure field name,
+ and the default value for the option.
+ From the SQL, BOOL options accept YES/NO, ON/OFF, and 1/0.
+
+ The name of the option is limited to 255 bytes,
+ the value (for string options) - to the 32767 bytes.
+
+ See ha_example.cc for an example.
+*/
+enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */
+ HA_OPTION_TYPE_STRING, /* char * */
+ HA_OPTION_TYPE_ENUM, /* uint */
+ HA_OPTION_TYPE_BOOL}; /* bool */
+
+#define HA_xOPTION_NUMBER(name, struc, field, def, min, max, blk_siz) \
+ { HA_OPTION_TYPE_ULL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, min, max, blk_siz, 0 }
+#define HA_xOPTION_STRING(name, struc, field) \
+ { HA_OPTION_TYPE_STRING, name, sizeof(name)-1, \
+ offsetof(struc, field), 0, 0, 0, 0, 0 }
+#define HA_xOPTION_ENUM(name, struc, field, values, def) \
+ { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, \
+ sizeof(values)-1, 0, values }
+#define HA_xOPTION_BOOL(name, struc, field, def) \
+ { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1, \
+ offsetof(struc, field), def, 0, 1, 0, 0 }
+#define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define HA_TOPTION_NUMBER(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_NUMBER(name, ha_table_option_struct, field, def, min, max, blk_siz)
+#define HA_TOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_table_option_struct, field)
+#define HA_TOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def)
+#define HA_TOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_table_option_struct, field, def)
+#define HA_TOPTION_END HA_xOPTION_END
+
+#define HA_FOPTION_NUMBER(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_NUMBER(name, ha_field_option_struct, field, def, min, max, blk_siz)
+#define HA_FOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_field_option_struct, field)
+#define HA_FOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def)
+#define HA_FOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_field_option_struct, field, def)
+#define HA_FOPTION_END HA_xOPTION_END
+
+#define HA_IOPTION_NUMBER(name, field, def, min, max, blk_siz) \
+ HA_xOPTION_NUMBER(name, ha_index_option_struct, field, def, min, max, blk_siz)
+#define HA_IOPTION_STRING(name, field) \
+ HA_xOPTION_STRING(name, ha_index_option_struct, field)
+#define HA_IOPTION_ENUM(name, field, values, def) \
+ HA_xOPTION_ENUM(name, ha_index_option_struct, field, values, def)
+#define HA_IOPTION_BOOL(name, field, values, def) \
+ HA_xOPTION_BOOL(name, ha_index_option_struct, field, values, def)
+#define HA_IOPTION_END HA_xOPTION_END
+
+typedef struct st_ha_create_table_option {
+ enum ha_option_type type;
+ const char *name;
+ size_t name_length;
+ ptrdiff_t offset;
+ ulonglong def_value;
+ ulonglong min_value, max_value, block_size;
+ const char *values;
+} ha_create_table_option;
enum handler_iterator_type
{
@@ -605,8 +709,9 @@ struct handlerton
SHOW_COMP_OPTION state;
/*
- Historical number used for frm file to determine the correct storage engine.
- This is going away and new engines will just use "name" for this.
+ Historical number used for frm file to determine the correct
+ storage engine. This is going away and new engines will just use
+ "name" for this.
*/
enum legacy_db_type db_type;
/*
@@ -716,7 +821,13 @@ struct handlerton
int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
const char *name);
uint32 license; /* Flag for Engine License */
- void *data; /* Location for engines to keep personal structures */
+ /*
+ Optional clauses in the CREATE/ALTER TABLE
+ */
+ ha_create_table_option *table_options; // table level options
+ ha_create_table_option *field_options; // these are specified per field
+ ha_create_table_option *index_options; // these are specified per index
+
};
@@ -732,7 +843,6 @@ inline LEX_STRING *hton_name(const handlerton *hton)
#define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter
#define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate
#define HTON_HIDDEN (1 << 3) //Engine does not appear in lists
-#define HTON_FLUSH_AFTER_RENAME (1 << 4)
#define HTON_NOT_USER_SELECTABLE (1 << 5)
#define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported
#define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables
@@ -940,11 +1050,16 @@ typedef struct st_ha_create_information
uint extra_size; /* length of extra data segment */
/** Transactional or not. Unused; reserved for future versions. */
enum ha_choice transactional;
- bool table_existed; /* 1 in create if table existed */
- bool frm_only; /* 1 if no ha_create_table() */
- bool varchar; /* 1 if table has a VARCHAR */
- enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
- enum ha_choice page_checksum; /* If we have page_checksums */
+ bool table_existed; ///< 1 in create if table existed
+ bool frm_only; ///< 1 if no ha_create_table()
+ bool varchar; ///< 1 if table has a VARCHAR
+ enum ha_storage_media storage_media; ///< DEFAULT, DISK or MEMORY
+ enum ha_choice page_checksum; ///< If we have page_checksums
+ engine_option_value *option_list; ///< list of table create options
+ /* the following three are only for ALTER TABLE, check_if_incompatible_data() */
+ void *option_struct; ///< structure with parsed table options
+ void **fileds_option_struct; ///< array of field option structures
+ void **indexes_option_struct; ///< array of index option structures
} HA_CREATE_INFO;
@@ -1129,6 +1244,7 @@ public:
enum {NONE=0, INDEX, RND} inited;
bool locked;
bool implicit_emptied; /* Can be !=0 only if HEAP */
+ bool mark_trx_done;
const COND *pushed_cond;
/**
next_insert_id is the next value which should be inserted into the
@@ -1151,6 +1267,12 @@ public:
Interval returned by get_auto_increment() and being consumed by the
inserter.
*/
+ /* Statistics variables */
+ ulonglong rows_read;
+ ulonglong rows_changed;
+ /* One bigger than needed to avoid to test if key == MAX_KEY */
+ ulonglong index_rows_read[MAX_KEY+1];
+
Discrete_interval auto_inc_interval_for_cur_row;
/**
Number of reserved auto-increment intervals. Serves as a heuristic
@@ -1166,10 +1288,13 @@ public:
ref(0), key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
ref_length(sizeof(my_off_t)),
ft_handler(0), inited(NONE),
- locked(FALSE), implicit_emptied(0),
+ locked(FALSE), implicit_emptied(FALSE), mark_trx_done(FALSE),
pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
auto_inc_intervals_count(0)
- {}
+ {
+ reset_statistics();
+ }
+
virtual ~handler(void)
{
DBUG_ASSERT(locked == FALSE);
@@ -1202,7 +1327,7 @@ public:
}
/* This is called after index_init() if we need to do a index scan */
virtual int prepare_index_scan() { return 0; }
- int ha_rnd_init(bool scan)
+ int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result))
{
int result;
DBUG_ENTER("ha_rnd_init");
@@ -1217,7 +1342,15 @@ public:
inited=NONE;
DBUG_RETURN(rnd_end());
}
+ int ha_rnd_init_with_error(bool scan) __attribute__ ((warn_unused_result));
int ha_reset();
+ /* Tell handler (not storage engine) this is start of a new statement */
+ void ha_start_of_new_statement()
+ {
+ ft_handler= 0;
+ mark_trx_done= FALSE;
+ }
+
/* this is necessary in many places, e.g. in HANDLER command */
int ha_index_or_rnd_end()
{
@@ -1291,15 +1424,22 @@ public:
virtual void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error);
+ void reset_statistics()
+ {
+ rows_read= rows_changed= 0;
+ bzero(index_rows_read, sizeof(index_rows_read));
+ }
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
{
table= table_arg;
table_share= share;
+ reset_statistics();
}
virtual double scan_time()
{ return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
virtual double read_time(uint index, uint ranges, ha_rows rows)
{ return rows2double(ranges+rows); }
+ virtual double keyread_read_time(uint index, uint ranges, ha_rows rows);
virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
bool has_transactions()
{ return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; }
@@ -1403,22 +1543,23 @@ public:
}
/**
@brief
- Positions an index cursor to the index specified in the handle. Fetches the
- row if available. If the key value is null, begin at the first key of the
- index.
+ Positions an index cursor to the index specified in the
+ handle. Fetches the row if available. If the key value is null,
+ begin at the first key of the index.
*/
+protected:
virtual int index_read_map(uchar * buf, const uchar * key,
key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
uint key_len= calculate_key_len(table, active_index, key, keypart_map);
- return index_read(buf, key, key_len, find_flag);
+ return index_read(buf, key, key_len, find_flag);
}
/**
@brief
- Positions an index cursor to the index specified in the handle. Fetches the
- row if available. If the key value is null, begin at the first key of the
- index.
+ Positions an index cursor to the index specified in the
+ handle. Fetches the row if available. If the key value is null,
+ begin at the first key of the index.
*/
virtual int index_read_idx_map(uchar * buf, uint index, const uchar * key,
key_part_map keypart_map,
@@ -1432,17 +1573,26 @@ public:
virtual int index_last(uchar * buf)
{ return HA_ERR_WRONG_COMMAND; }
virtual int index_next_same(uchar *buf, const uchar *key, uint keylen);
- /**
- @brief
- The following functions works like index_read, but it find the last
- row with the current key value or prefix.
- */
- virtual int index_read_last_map(uchar * buf, const uchar * key,
- key_part_map keypart_map)
+ inline void update_index_statistics()
{
- uint key_len= calculate_key_len(table, active_index, key, keypart_map);
- return index_read_last(buf, key, key_len);
+ index_rows_read[active_index]++;
+ rows_read++;
}
+public:
+
+ /* Similar functions like the above, but does statistics counting */
+ inline int ha_index_read_map(uchar * buf, const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ inline int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ inline int ha_index_next(uchar * buf);
+ inline int ha_index_prev(uchar * buf);
+ inline int ha_index_first(uchar * buf);
+ inline int ha_index_last(uchar * buf);
+ inline int ha_index_next_same(uchar *buf, const uchar *key, uint keylen);
+
virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
KEY_MULTI_RANGE *ranges, uint range_count,
bool sorted, HANDLER_BUFFER *buffer);
@@ -1456,6 +1606,7 @@ public:
void ft_end() { ft_handler=NULL; }
virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
{ return NULL; }
+private:
virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; }
virtual int rnd_next(uchar *buf)=0;
virtual int rnd_pos(uchar * buf, uchar *pos)=0;
@@ -1466,11 +1617,20 @@ public:
handlers for random position.
*/
virtual int rnd_pos_by_record(uchar *record)
- {
- position(record);
- return rnd_pos(record, ref);
- }
+ {
+ position(record);
+ return rnd_pos(record, ref);
+ }
virtual int read_first_row(uchar *buf, uint primary_key);
+public:
+
+ /* Same as above, but with statistics */
+ inline int ha_ft_read(uchar *buf);
+ inline int ha_rnd_next(uchar *buf);
+ inline int ha_rnd_pos(uchar *buf, uchar *pos);
+ inline int ha_rnd_pos_by_record(uchar *buf);
+ inline int ha_read_first_row(uchar *buf, uint primary_key);
+
/**
The following 3 function is only needed for tables that may be
internal temporary tables during joins.
@@ -1639,6 +1799,9 @@ public:
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
+ void update_global_table_stats();
+ void update_global_index_stats();
+
#define CHF_CREATE_FLAG 0
#define CHF_DELETE_FLAG 1
#define CHF_RENAME_FLAG 2
@@ -1773,9 +1936,22 @@ public:
LEX_STRING *engine_name() { return hton_name(ht); }
+ /*
+ @brief
+ Check whether the engine supports virtual columns
+
+ @retval
+ FALSE if the engine does not support virtual columns
+ @retval
+ TRUE if the engine supports virtual columns
+ */
+ virtual bool check_if_supported_virtual_columns(void) { return FALSE;}
+
protected:
+ /* deprecated, don't use in new engines */
+ inline void ha_statistic_increment(ulong SSV::*offset) const { }
+
/* Service methods for use by storage engines. */
- void ha_statistic_increment(ulong SSV::*offset) const;
void **ha_data(THD *) const;
THD *ha_thd(void) const;
@@ -1795,7 +1971,15 @@ protected:
private:
/* Private helpers */
- inline void mark_trx_read_write();
+ void mark_trx_read_write_part2();
+ inline void mark_trx_read_write()
+ {
+ if (!mark_trx_done)
+ mark_trx_read_write_part2();
+ }
+ inline void increment_statistics(ulong SSV::*offset) const;
+ inline void decrement_statistics(ulong SSV::*offset) const;
+
/*
Low-level primitives for storage engines. These should be
overridden by the storage engine class. To call these methods, use
@@ -1882,8 +2066,6 @@ private:
virtual int index_read(uchar * buf, const uchar * key, uint key_len,
enum ha_rkey_function find_flag)
{ return HA_ERR_WRONG_COMMAND; }
- virtual int index_read_last(uchar * buf, const uchar * key, uint key_len)
- { return (my_errno= HA_ERR_WRONG_COMMAND); }
/**
This method is similar to update_row, however the handler doesn't need
to execute the updates at this point in time. The handler can be certain
@@ -1956,6 +2138,11 @@ private:
{ return HA_ERR_WRONG_COMMAND; }
virtual int rename_partitions(const char *path)
{ return HA_ERR_WRONG_COMMAND; }
+ friend class ha_partition;
+public:
+ /* XXX to be removed, see ha_partition::partition_ht() */
+ virtual handlerton *partition_ht() const
+ { return ht; }
};
@@ -2038,6 +2225,7 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
int ha_resize_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache_param(KEY_CACHE *key_cache);
+int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
int ha_end_key_cache(KEY_CACHE *key_cache);
@@ -2091,3 +2279,5 @@ int ha_binlog_end(THD *thd);
#define ha_binlog_wait(a) do {} while (0)
#define ha_binlog_end(a) do {} while (0)
#endif
+
+#endif
diff --git a/sql/item.cc b/sql/item.cc
index c2ab2a9046f..2edeb4c0ee0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -693,9 +693,24 @@ bool Item_field::register_field_in_read_map(uchar *arg)
TABLE *table= (TABLE *) arg;
if (field->table == table || !table)
bitmap_set_bit(field->table->read_set, field->field_index);
+ if (field->vcol_info && field->vcol_info->expr_item)
+ return field->vcol_info->expr_item->walk(&Item::register_field_in_read_map,
+ 1, arg);
return 0;
}
+/*
+ @brief
+ Mark field in bitmap supplied as *arg
+*/
+
+bool Item_field::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap= (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ bitmap_set_bit(bitmap, field->field_index);
+ return 0;
+}
bool Item::check_cols(uint c)
{
@@ -4474,6 +4489,21 @@ error:
return TRUE;
}
+/*
+ @brief
+ Mark virtual columns as used in a partitioning expression
+*/
+
+bool Item_field::vcol_in_partition_func_processor(uchar *int_arg)
+{
+ DBUG_ASSERT(fixed);
+ if (field->vcol_info)
+ {
+ field->vcol_info->mark_as_in_partitioning_expr();
+ }
+ return FALSE;
+}
+
Item *Item_field::safe_charset_converter(CHARSET_INFO *tocs)
{
diff --git a/sql/item.h b/sql/item.h
index 45cfb4881dd..865f9cf0886 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -18,6 +18,24 @@
#pragma interface /* gcc class implementation */
#endif
+inline
+bool trace_unsupported_func(const char *where, const char *processor_name)
+{
+ char buff[64];
+ sprintf(buff, "%s::%s", where, processor_name);
+ DBUG_ENTER(buff);
+ sprintf(buff, "%s returns TRUE: unsupported function", processor_name);
+ DBUG_PRINT("info", ("%s", buff));
+ DBUG_RETURN(TRUE);
+}
+
+inline
+bool trace_unsupported_by_check_vcol_func_processor(const char *where)
+{
+ return trace_unsupported_func(where, "check_vcol_func_processor");
+}
+
+
class Protocol;
struct TABLE_LIST;
void item_init(void); /* Init item functions */
@@ -909,6 +927,11 @@ public:
virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; }
virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; }
/*
+ The next function differs from the previous one that a bitmap to be updated
+ is passed as uchar *arg.
+ */
+ virtual bool register_field_in_bitmap(uchar *arg) { return 0; }
+ /*
Check if a partition function is allowed
SYNOPSIS
check_partition_func_processor()
@@ -960,11 +983,43 @@ public:
fields.
*/
virtual bool check_partition_func_processor(uchar *bool_arg) { return TRUE;}
+ /*
+ @brief
+ Processor used to mark virtual columns used in partitioning expression
+
+ @param
+ arg always ignored
+
+ @retval
+ FALSE always
+ */
+ virtual bool vcol_in_partition_func_processor(uchar *arg)
+ {
+ return FALSE;
+ }
+
virtual bool subst_argument_checker(uchar **arg)
- {
+ {
if (*arg)
- *arg= NULL;
- return TRUE;
+ *arg= NULL;
+ return TRUE;
+ }
+ /*
+ @brief
+ Processor used to check acceptability of an item in the defining
+ expression for a virtual column
+
+ @param
+ arg always ignored
+
+ @retval
+ FALSE the item is accepted in the definition of a virtual column
+ @retval
+ TRUE otherwise
+ */
+ virtual bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(full_name());
}
virtual Item *equal_fields_propagator(uchar * arg) { return this; }
@@ -1373,6 +1428,10 @@ public:
{
return value_item->send(protocol, str);
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("name_const");
+ }
};
bool agg_item_collations(DTCollation &c, const char *name,
@@ -1392,6 +1451,7 @@ public:
virtual Item_num *neg()= 0;
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
#define NO_CACHED_FIELD_INDEX ((uint)(-1))
@@ -1552,7 +1612,10 @@ public:
bool collect_item_field_processor(uchar * arg);
bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool vcol_in_partition_func_processor(uchar *bool_arg);
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
bool enumerate_field_refs_processor(uchar *arg);
void cleanup();
bool result_as_longlong()
@@ -1613,6 +1676,7 @@ public:
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
class Item_null_result :public Item_null
@@ -1626,7 +1690,11 @@ public:
save_in_field(result_field, no_conversions);
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
-};
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(full_name());
+ }
+};
/* Item represents one placeholder ('?') of prepared statement */
@@ -1767,6 +1835,7 @@ public:
/** Item is a argument to a limit clause. */
bool limit_clause_param;
void set_param_type_and_swap_value(Item_param *from);
+
};
@@ -1802,6 +1871,7 @@ public:
{ return (uint)(max_length - test(value < 0)); }
bool eq(const Item *, bool binary_cmp) const;
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar arg) { return FALSE;}
};
@@ -1820,6 +1890,7 @@ public:
Item_num *neg ();
uint decimal_precision() const { return max_length; }
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
@@ -1861,6 +1932,7 @@ public:
bool eq(const Item *, bool binary_cmp) const;
void set_decimal_value(my_decimal *value_par);
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
};
@@ -2018,6 +2090,7 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
/**
Return TRUE if character-set-introducer was explicitly specified in the
@@ -2071,7 +2144,7 @@ double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end);
class Item_static_string_func :public Item_string
{
const char *func_name;
-public:
+ public:
Item_static_string_func(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs,
Derivation dv= DERIVATION_COERCIBLE)
@@ -2085,6 +2158,10 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name);
+ }
};
@@ -2096,6 +2173,10 @@ public:
CHARSET_INFO *cs= NULL):
Item_string(name_arg, length, cs)
{}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("safe_string");
+ }
};
@@ -2175,6 +2256,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
private:
void hex_string_init(const char *str, uint str_length);
};
@@ -2207,6 +2289,7 @@ public:
save_in_field(result_field, no_conversions);
}
void cleanup();
+ bool check_vcol_func_processor(uchar *arg) { return FALSE;}
/*
This method is used for debug purposes to print the name of an
item to the debug log. The second use of this method is as
@@ -2358,12 +2441,15 @@ public:
if (ref && result_type() == ROW_RESULT)
(*ref)->bring_value();
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("ref");
+ }
bool get_time(MYSQL_TIME *ltime)
{
DBUG_ASSERT(fixed);
return (*ref)->get_time(ltime);
}
-
};
@@ -2651,6 +2737,10 @@ public:
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
bool is_null() { return null_value; }
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("copy");
+ }
/*
Override the methods below as pure virtual to make sure all the
@@ -2893,6 +2983,10 @@ public:
return arg->walk(processor, walk_subquery, args) ||
(this->*processor)(args);
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("values");
+ }
};
@@ -2989,6 +3083,10 @@ private:
BEFORE INSERT of BEFORE UPDATE trigger.
*/
bool read_only;
+ virtual bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("trigger");
+ }
};
@@ -3058,6 +3156,11 @@ public:
{
return this == item;
}
+ bool check_vcol_func_processor(uchar *arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("cache");
+ }
+
virtual void store(Item *item);
virtual bool cache_value()= 0;
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 3875f73a36f..36a999c9e76 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -825,7 +825,6 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
return cmp_type;
}
-
/*
Retrieves correct TIME value from the given item.
@@ -876,7 +875,12 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
if (item->const_item() && cache_arg && (item->type() != Item::FUNC_ITEM ||
((Item_func*)item)->functype() != Item_func::GUSERVAR_FUNC))
{
+ Query_arena backup;
+ Query_arena *save_arena= thd->switch_to_arena_for_cached_items(&backup);
Item_cache_int *cache= new Item_cache_int();
+ if (save_arena)
+ thd->set_query_arena(save_arena);
+
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
cache->store_longlong(item, value);
@@ -912,7 +916,12 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
cache_converted_constant can't be used here because it can't
correctly convert a DATETIME value from string to int representation.
*/
+ Query_arena backup;
+ Query_arena *save_arena= thd->switch_to_arena_for_cached_items(&backup);
Item_cache_int *cache= new Item_cache_int();
+ if (save_arena)
+ thd->set_query_arena(save_arena);
+
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
if (!(*a)->is_datetime())
@@ -1142,7 +1151,12 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
if (item->const_item() && cache_arg && (item->type() != Item::FUNC_ITEM ||
((Item_func*)item)->functype() != Item_func::GUSERVAR_FUNC))
{
+ Query_arena backup;
+ Query_arena *save_arena= thd->switch_to_arena_for_cached_items(&backup);
Item_cache_int *cache= new Item_cache_int(MYSQL_TYPE_DATETIME);
+ if (save_arena)
+ thd->set_query_arena(save_arena);
+
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
cache->store_longlong(item, value);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index e0bd09fc2bf..afde48b56f7 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -782,7 +782,7 @@ public:
virtual uchar *get_value(Item *item)=0;
void sort()
{
- my_qsort2(base,used_count,size,compare,collation);
+ my_qsort2(base,used_count,size,compare,(void*)collation);
}
int find(Item *item);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index dc7c75fb5d2..3cb9d4724b9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2040,10 +2040,12 @@ double Item_func_round::real_op()
{
double value= args[0]->val_real();
- if (!(null_value= args[0]->null_value || args[1]->null_value))
- return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag,
- truncate);
-
+ if (!(null_value= args[0]->null_value))
+ {
+ longlong dec= args[1]->val_int();
+ if (!(null_value= args[1]->null_value))
+ return my_double_round(value, dec, args[1]->unsigned_flag, truncate);
+ }
return 0.0;
}
@@ -3825,10 +3827,30 @@ bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
TABLE *table= (TABLE *) arg;
if (result_field->table == table || !table)
bitmap_set_bit(result_field->table->read_set, result_field->field_index);
+ if (result_field->vcol_info)
+ return result_field->vcol_info->
+ expr_item->walk(&Item::register_field_in_read_map, 1, arg);
}
return 0;
}
+/*
+ Mark field in bitmap supplied as *arg
+
+*/
+
+bool Item_func_set_user_var::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap = (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ if (result_field)
+ {
+ if (!bitmap)
+ return 1;
+ bitmap_set_bit(bitmap, result_field->field_index);
+ }
+ return 0;
+}
/**
Set value to user variable.
diff --git a/sql/item_func.h b/sql/item_func.h
index b7994bd941e..507f5d21a3e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -356,6 +356,7 @@ public:
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};
@@ -416,6 +417,7 @@ public:
Item_func_additive_op(Item *a,Item *b) :Item_num_op(a,b) {}
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -451,6 +453,7 @@ public:
my_decimal *decimal_op(my_decimal *);
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -483,6 +486,7 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -497,6 +501,7 @@ public:
void result_precision();
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -513,6 +518,7 @@ public:
void fix_num_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -526,6 +532,7 @@ public:
const char *func_name() const { return "abs"; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
// A class to handle logarithmic and trigonometric functions
@@ -681,6 +688,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -693,6 +701,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
/* This handles round and truncate */
@@ -724,6 +733,10 @@ public:
void update_used_tables();
bool fix_fields(THD *thd, Item **ref);
void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
private:
void seed_random (Item * val);
};
@@ -1006,6 +1019,10 @@ public:
max_length= args[0]->max_length;
}
bool fix_fields(THD *thd, Item **ref);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1019,6 +1036,10 @@ public:
const char *func_name() const { return "benchmark"; }
void fix_length_and_dec() { max_length=1; maybe_null=0; }
virtual void print(String *str, enum_query_type query_type);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1034,6 +1055,10 @@ public:
used_tables_cache|= RAND_TABLE_BIT;
}
longlong val_int();
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1283,6 +1308,10 @@ class Item_func_get_lock :public Item_int_func
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
class Item_func_release_lock :public Item_int_func
@@ -1293,6 +1322,10 @@ public:
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
/* replication functions */
@@ -1306,6 +1339,10 @@ public:
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1377,6 +1414,7 @@ public:
}
void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); }
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
void cleanup();
};
@@ -1551,6 +1589,11 @@ public:
bool fix_index();
void init_search(bool no_order);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /* TODO: consider adding in support for the MATCH-based virtual columns */
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1570,6 +1613,17 @@ public:
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+#if 0
+ DBUG_ENTER("Item_func_is_free_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+#else
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+#endif
+ }
};
class Item_func_is_used_lock :public Item_int_func
@@ -1580,6 +1634,10 @@ public:
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
/* For type casts */
@@ -1599,6 +1657,11 @@ public:
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1707,6 +1770,10 @@ public:
{
return sp_result_field;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1717,6 +1784,10 @@ public:
longlong val_int();
const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -1731,5 +1802,9 @@ public:
void fix_length_and_dec()
{ max_length= 21; unsigned_flag=1; }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
diff --git a/sql/item_row.h b/sql/item_row.h
index 76d1c875e7d..3566ff079c6 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -78,4 +78,5 @@ public:
bool check_cols(uint c);
bool null_inside() { return with_null; };
void bring_value();
-};
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE; }
+ };
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 0a6375e80a5..53219e70973 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -344,6 +344,10 @@ public:
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
const char *func_name() const { return "encrypt"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
#include "sql_crypt.h"
@@ -392,6 +396,11 @@ public:
call
*/
virtual const char *fully_qualified_func_name() const = 0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(
+ fully_qualified_func_name());
+ }
};
@@ -655,6 +664,10 @@ public:
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -852,5 +865,9 @@ public:
}
const char *func_name() const{ return "uuid"; }
String *val_str(String *);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a2bb91a47f5..a82c93304e6 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -2070,13 +2070,14 @@ int subselect_uniquesubquery_engine::scan_table()
if (table->file->inited)
table->file->ha_index_end();
- table->file->ha_rnd_init(1);
+ if (table->file->ha_rnd_init_with_error(1))
+ DBUG_RETURN(1);
table->file->extra_opt(HA_EXTRA_CACHE,
current_thd->variables.read_buff_size);
table->null_row= 0;
for (;;)
{
- error=table->file->rnd_next(table->record[0]);
+ error=table->file->ha_rnd_next(table->record[0]);
if (error && error != HA_ERR_END_OF_FILE)
{
error= report_error(table, error);
@@ -2250,10 +2251,11 @@ int subselect_uniquesubquery_engine::exec()
if (!table->file->inited)
table->file->ha_index_init(tab->ref.key, 0);
- 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);
+ error= table->file->ha_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)
error= report_error(table, error);
@@ -2371,10 +2373,11 @@ int subselect_indexsubquery_engine::exec()
if (!table->file->inited)
table->file->ha_index_init(tab->ref.key, 1);
- 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);
+ error= table->file->ha_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)
error= report_error(table, error);
@@ -2395,9 +2398,9 @@ int subselect_indexsubquery_engine::exec()
((Item_in_subselect *) item)->value= 1;
break;
}
- error= table->file->index_next_same(table->record[0],
- tab->ref.key_buff,
- tab->ref.key_length);
+ error= table->file->ha_index_next_same(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length);
if (error && error != HA_ERR_END_OF_FILE)
{
error= report_error(table, error);
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index cea02f2acb6..6f94a08f1c1 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -137,6 +137,10 @@ public:
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
bool mark_as_eliminated_processor(uchar *arg);
bool enumerate_field_refs_processor(uchar *arg);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("subselect");
+ }
Item *safe_charset_converter(CHARSET_INFO *tocs);
/**
diff --git a/sql/item_sum.h b/sql/item_sum.h
index b82f2d961f1..7720de2450f 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -383,6 +383,10 @@ public:
Item *get_arg(int i) { return args[i]; }
Item *set_arg(int i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -663,6 +667,10 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("avg_field");
+ }
const char *func_name() const { DBUG_ASSERT(0); return "avg_field"; }
};
@@ -732,6 +740,10 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("var_field");
+ }
const char *func_name() const { DBUG_ASSERT(0); return "variance_field"; }
};
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a7a64090f6c..e11449c200e 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -70,6 +70,7 @@ public:
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -86,6 +87,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -111,6 +113,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -124,6 +127,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE;}
};
@@ -140,6 +144,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -156,6 +161,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -172,6 +178,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -188,6 +195,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -204,6 +212,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -234,6 +243,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -252,6 +262,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -282,6 +293,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
class Item_func_dayname :public Item_func_weekday
@@ -294,6 +306,7 @@ class Item_func_dayname :public Item_func_weekday
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -320,6 +333,14 @@ public:
decimals=0;
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /*
+ TODO: Allow UNIX_TIMESTAMP called with an argument to be a part
+ of the expression for a virtual column
+ */
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -335,6 +356,7 @@ public:
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -455,6 +477,10 @@ public:
*/
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
bool result_as_longlong() { return TRUE; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -491,6 +517,10 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -531,6 +561,10 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
@@ -588,6 +622,7 @@ public:
const char *func_name() const { return "from_days"; }
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -715,6 +750,7 @@ class Item_extract :public Item_int_func
bool eq(const Item *item, bool binary_cmp) const;
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -963,6 +999,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 3e178dd8938..537965b60cc 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -220,6 +220,11 @@ public:
collation.collation= pxml->charset();
}
const char *func_name() const { return "nodeset"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
+
};
@@ -526,6 +531,10 @@ public:
enum Type type() const { return XPATH_NODESET_CMP; };
const char *func_name() const { return "xpath_nodeset_to_const_comparator"; }
bool is_bool_func() { return 1; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
longlong val_int()
{
diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h
index dadbb5ccf42..ce33d161c79 100644
--- a/sql/item_xmlfunc.h
+++ b/sql/item_xmlfunc.h
@@ -40,6 +40,10 @@ public:
}
void fix_length_and_dec();
String *parse_xml(String *raw_xml, String *parsed_xml_buf);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor(func_name());
+ }
};
diff --git a/sql/key.cc b/sql/key.cc
index 5b2ae8029dd..89423e5280e 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -278,8 +278,7 @@ bool key_cmp_if_same(TABLE *table,const uchar *key,uint idx,uint key_length)
key++;
store_length--;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
- HA_BIT_PART))
+ if (!(key_part->key_part_flag & HA_CAN_MEMCMP))
{
if (key_part->field->key_cmp(key, key_part->length))
return 1;
diff --git a/sql/lex.h b/sql/lex.h
index d9c382347c9..7671f23682d 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -62,6 +62,7 @@ static SYMBOL symbols[] = {
{ "ALL", SYM(ALL)},
{ "ALGORITHM", SYM(ALGORITHM_SYM)},
{ "ALTER", SYM(ALTER)},
+ { "ALWAYS", SYM(ALWAYS_SYM)},
{ "ANALYZE", SYM(ANALYZE_SYM)},
{ "AND", SYM(AND_SYM)},
{ "ANY", SYM(ANY_SYM)},
@@ -106,6 +107,7 @@ static SYMBOL symbols[] = {
{ "CHECKSUM", SYM(CHECKSUM_SYM)},
{ "CIPHER", SYM(CIPHER_SYM)},
{ "CLIENT", SYM(CLIENT_SYM)},
+ { "CLIENT_STATISTICS", SYM(CLIENT_STATS_SYM)},
{ "CLOSE", SYM(CLOSE_SYM)},
{ "COALESCE", SYM(COALESCE)},
{ "CODE", SYM(CODE_SYM)},
@@ -220,6 +222,7 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL)},
{ "FULLTEXT", SYM(FULLTEXT_SYM)},
{ "FUNCTION", SYM(FUNCTION_SYM)},
+ { "GENERATED", SYM(GENERATED_SYM)},
{ "GEOMETRY", SYM(GEOMETRY_SYM)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)},
@@ -245,6 +248,7 @@ static SYMBOL symbols[] = {
{ "IN", SYM(IN_SYM)},
{ "INDEX", SYM(INDEX_SYM)},
{ "INDEXES", SYM(INDEXES)},
+ { "INDEX_STATISTICS", SYM(INDEX_STATS_SYM)},
{ "INFILE", SYM(INFILE)},
{ "INITIAL_SIZE", SYM(INITIAL_SIZE_SYM)},
{ "INNER", SYM(INNER_SYM)},
@@ -385,14 +389,16 @@ static SYMBOL symbols[] = {
{ "OUTFILE", SYM(OUTFILE)},
{ "OWNER", SYM(OWNER_SYM)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
- { "PARSER", SYM(PARSER_SYM)},
{ "PAGE", SYM(PAGE_SYM)},
{ "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)},
+ { "PARSER", SYM(PARSER_SYM)},
+ { "PARSE_VCOL_EXPR", SYM(PARSE_VCOL_EXPR_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
{ "PARTITION", SYM(PARTITION_SYM)},
{ "PARTITIONING", SYM(PARTITIONING_SYM)},
{ "PARTITIONS", SYM(PARTITIONS_SYM)},
{ "PASSWORD", SYM(PASSWORD)},
+ { "PERSISTENT", SYM(PERSISTENT_SYM)},
{ "PHASE", SYM(PHASE_SYM)},
{ "PLUGIN", SYM(PLUGIN_SYM)},
{ "PLUGINS", SYM(PLUGINS_SYM)},
@@ -478,6 +484,7 @@ static SYMBOL symbols[] = {
{ "SIGNED", SYM(SIGNED_SYM)},
{ "SIMPLE", SYM(SIMPLE_SYM)},
{ "SLAVE", SYM(SLAVE)},
+ { "SLOW", SYM(SLOW_SYM)},
{ "SNAPSHOT", SYM(SNAPSHOT_SYM)},
{ "SMALLINT", SYM(SMALLINT)},
{ "SOCKET", SYM(SOCKET_SYM)},
@@ -526,6 +533,7 @@ static SYMBOL symbols[] = {
{ "TABLE", SYM(TABLE_SYM)},
{ "TABLES", SYM(TABLES)},
{ "TABLESPACE", SYM(TABLESPACE)},
+ { "TABLE_STATISTICS", SYM(TABLE_STATS_SYM)},
{ "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)},
{ "TEMPORARY", SYM(TEMPORARY)},
{ "TEMPTABLE", SYM(TEMPTABLE_SYM)},
@@ -569,6 +577,7 @@ static SYMBOL symbols[] = {
{ "USE", SYM(USE_SYM)},
{ "USER", SYM(USER)},
{ "USER_RESOURCES", SYM(RESOURCES)},
+ { "USER_STATISTICS", SYM(USER_STATS_SYM)},
{ "USE_FRM", SYM(USE_FRM)},
{ "USING", SYM(USING)},
{ "UTC_DATE", SYM(UTC_DATE_SYM)},
@@ -581,13 +590,15 @@ static SYMBOL symbols[] = {
{ "VARCHARACTER", SYM(VARCHAR)},
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
+ { "VIA", SYM(VIA_SYM)},
+ { "VIEW", SYM(VIEW_SYM)},
+ { "VIRTUAL", SYM(VIRTUAL_SYM)},
{ "WAIT", SYM(WAIT_SYM)},
{ "WARNINGS", SYM(WARNINGS)},
{ "WEEK", SYM(WEEK_SYM)},
{ "WHEN", SYM(WHEN_SYM)},
{ "WHERE", SYM(WHERE)},
{ "WHILE", SYM(WHILE_SYM)},
- { "VIEW", SYM(VIEW_SYM)},
{ "WITH", SYM(WITH)},
{ "WORK", SYM(WORK_SYM)},
{ "WRAPPER", SYM(WRAPPER_SYM)},
diff --git a/sql/log.cc b/sql/log.cc
index cbbe294387b..570418d97dd 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -412,7 +412,7 @@ bool Log_to_csv_event_handler::
need_close= TRUE;
if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
- table->file->ha_rnd_init(0))
+ table->file->ha_rnd_init_with_error(0))
goto err;
need_rnd_end= TRUE;
@@ -563,7 +563,7 @@ bool Log_to_csv_event_handler::
need_close= TRUE;
if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
- table->file->ha_rnd_init(0))
+ table->file->ha_rnd_init_with_error(0))
goto err;
need_rnd_end= TRUE;
@@ -824,6 +824,13 @@ void Log_to_file_event_handler::flush()
mysql_slow_log.reopen_file();
}
+void Log_to_file_event_handler::flush_slow_log()
+{
+ /* reopen slow log file */
+ if (opt_slow_log)
+ mysql_slow_log.reopen_file();
+}
+
/*
Log error with all enabled log event handlers
@@ -919,8 +926,6 @@ void LOGGER::init_log_tables()
bool LOGGER::flush_logs(THD *thd)
{
- int rc= 0;
-
/*
Now we lock logger, as nobody should be able to use logging routines while
log tables are closed
@@ -932,7 +937,24 @@ bool LOGGER::flush_logs(THD *thd)
/* end of log flush */
logger.unlock();
- return rc;
+ return 0;
+}
+
+
+bool LOGGER::flush_slow_log(THD *thd)
+{
+ /*
+ Now we lock logger, as nobody should be able to use logging routines while
+ log tables are closed
+ */
+ logger.lock_exclusive();
+
+ /* reopen log files */
+ file_log_handler->flush_slow_log();
+
+ /* end of log flush */
+ logger.unlock();
+ return 0;
}
@@ -4331,6 +4353,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
if (likely(is_open()))
{
IO_CACHE *file= &log_file;
+ my_off_t my_org_b_tell;
#ifdef HAVE_REPLICATION
/*
In the future we need to add to the following if tests like
@@ -4348,6 +4371,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
}
#endif /* HAVE_REPLICATION */
+ my_org_b_tell= my_b_tell(file);
+
#if defined(USING_TRANSACTIONS)
/*
Should we write to the binlog cache or to the binlog on disk?
@@ -4366,7 +4391,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
2 - --binlog-direct-non-transactional-updates is set and we are about to
use the statement format. When using the row format (cache_stmt == TRUE).
*/
- if (opt_using_transactions && thd)
+ if (opt_using_transactions)
{
if (thd->binlog_setup_trx_data())
goto err;
@@ -4409,7 +4434,6 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
If row-based binlogging, Insert_id, Rand and other kind of "setting
context" events are not needed.
*/
- if (thd)
{
if (!thd->current_stmt_binlog_row_based)
{
@@ -4456,16 +4480,16 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
}
}
- /*
- Write the SQL command
- */
-
+ /* Write the SQL command */
if (event_info->write(file) ||
DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0))
goto err;
if (file == &log_file) // we are writing to the real log (disk)
{
+ ulonglong data_written= (my_b_tell(file) - my_org_b_tell);
+ status_var_add(thd->status_var.binlog_bytes_written, data_written);
+
if (flush_and_sync())
goto err;
signal_update();
@@ -4599,6 +4623,7 @@ uint MYSQL_BIN_LOG::next_file_id()
SYNOPSIS
write_cache()
+ thd Current_thread
cache Cache to write to the binary log
lock_log True if the LOCK_log mutex should be aquired, false otherwise
sync_log True if the log should be flushed and sync:ed
@@ -4608,7 +4633,8 @@ uint MYSQL_BIN_LOG::next_file_id()
be reset as a READ_CACHE to be able to read the contents from it.
*/
-int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
+int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache, bool lock_log,
+ bool sync_log)
{
Mutex_sentry sentry(lock_log ? &LOCK_log : NULL);
@@ -4656,6 +4682,7 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
/* write the first half of the split header */
if (my_b_write(&log_file, header, carry))
return ER_ERROR_ON_WRITE;
+ status_var_add(thd->status_var.binlog_bytes_written, carry);
/*
copy fixed second half of header to cache so the correct
@@ -4724,6 +4751,8 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
/* Write data to the binary log file */
if (my_b_write(&log_file, cache->read_pos, length))
return ER_ERROR_ON_WRITE;
+ status_var_add(thd->status_var.binlog_bytes_written, length);
+
cache->read_pos=cache->read_end; // Mark buffer used up
} while ((length= my_b_fill(cache)));
@@ -4775,6 +4804,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
if (lock)
pthread_mutex_lock(&LOCK_log);
error= ev.write(&log_file);
+ status_var_add(thd->status_var.binlog_bytes_written, ev.data_written);
if (lock)
{
if (!error && !(error= flush_and_sync()))
@@ -4846,21 +4876,28 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
*/
if (qinfo.write(&log_file))
goto err;
+ status_var_add(thd->status_var.binlog_bytes_written, qinfo.data_written);
DBUG_EXECUTE_IF("crash_before_writing_xid",
{
- if ((write_error= write_cache(cache, false, true)))
+ if ((write_error= write_cache(thd, cache, FALSE,
+ TRUE)))
DBUG_PRINT("info", ("error writing binlog cache: %d",
write_error));
DBUG_PRINT("info", ("crashing before writing xid"));
abort();
});
- if ((write_error= write_cache(cache, false, false)))
+ if ((write_error= write_cache(thd, cache, FALSE, FALSE)))
goto err;
- if (commit_event && commit_event->write(&log_file))
- goto err;
+ if (commit_event)
+ {
+ if (commit_event->write(&log_file))
+ goto err;
+ status_var_add(thd->status_var.binlog_bytes_written,
+ commit_event->data_written);
+ }
if (incident && write_incident(thd, FALSE))
goto err;
@@ -6048,3 +6085,20 @@ mysql_declare_plugin(binlog)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_storage_engine,
+ "binlog",
+ "MySQL AB",
+ "This is a pseudo storage engine to represent the binlog in a transaction",
+ PLUGIN_LICENSE_GPL,
+ binlog_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/sql/log.h b/sql/log.h
index 8d3880d9171..1cfd7ce9ae5 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -360,7 +360,8 @@ public:
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
bool write_incident(THD *thd, bool lock);
- int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
+ int write_cache(THD *thd, IO_CACHE *cache, bool lock_log,
+ bool flush_and_sync);
void set_write_error(THD *thd);
bool check_write_error(THD *thd);
@@ -498,6 +499,7 @@ public:
const char *sql_text, uint sql_text_len,
CHARSET_INFO *client_cs);
void flush();
+ void flush_slow_log();
void init_pthread_objects();
MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
@@ -542,6 +544,7 @@ public:
void init_base();
void init_log_tables();
bool flush_logs(THD *thd);
+ bool flush_slow_log(THD *thd);
/* Perform basic logger cleanup. this will leave e.g. error log open. */
void cleanup_base();
/* Free memory. Nothing could be logged after this function is called */
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 90885315ce1..a1ecb79ff56 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1121,7 +1121,7 @@ failed my_b_read"));
goto err;
}
if ((res= read_log_event(buf, data_len, &error, description_event)))
- res->register_temp_buf(buf);
+ res->register_temp_buf(buf, TRUE);
err:
UNLOCK_MUTEX;
@@ -4581,7 +4581,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
*/
lex_start(thd);
thd->lex->local_file= local_fname;
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, 0);
if (!use_rli_only_for_errors)
{
@@ -6377,7 +6377,7 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli)
as the present method does not call mysql_parse().
*/
lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, 0);
my_delete(fname, MYF(0)); // old copy may exist already
if ((fd= my_create(fname, CREATE_MODE,
O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
@@ -7317,7 +7317,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
we need to do any changes to that value after this function.
*/
lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, 0);
/*
The current statement is just about to begin and
has not yet modified anything. Note, all.modified is reset
@@ -8109,6 +8109,111 @@ Table_map_log_event::~Table_map_log_event()
my_free(m_memory, MYF(MY_ALLOW_ZERO_PTR));
}
+
+#ifdef MYSQL_CLIENT
+
+/*
+ Rewrite database name for the event to name specified by new_db
+ SYNOPSIS
+ new_db Database name to change to
+ new_len Length
+ desc Event describing binlog that we're writing to.
+
+ DESCRIPTION
+ Reset db name. This function assumes that temp_buf member contains event
+ representation taken from a binary log. It resets m_dbnam and m_dblen and
+ rewrites temp_buf with new db name.
+
+ RETURN
+ 0 - Success
+ other - Error
+*/
+
+int Table_map_log_event::rewrite_db(const char* new_db, size_t new_len,
+ const Format_description_log_event* desc)
+{
+ DBUG_ENTER("Table_map_log_event::rewrite_db");
+ DBUG_ASSERT(temp_buf);
+
+ uint header_len= min(desc->common_header_len,
+ LOG_EVENT_MINIMAL_HEADER_LEN) + TABLE_MAP_HEADER_LEN;
+ int len_diff;
+
+ if (!(len_diff= new_len - m_dblen))
+ {
+ memcpy((void*) (temp_buf + header_len + 1), new_db, m_dblen + 1);
+ memcpy((void*) m_dbnam, new_db, m_dblen + 1);
+ DBUG_RETURN(0);
+ }
+
+ // Create new temp_buf
+ ulong event_cur_len= uint4korr(temp_buf + EVENT_LEN_OFFSET);
+ ulong event_new_len= event_cur_len + len_diff;
+ char* new_temp_buf= (char*) my_malloc(event_new_len, MYF(MY_WME));
+
+ if (!new_temp_buf)
+ {
+ sql_print_error("Table_map_log_event::rewrite_db: "
+ "failed to allocate new temp_buf (%d bytes required)",
+ event_new_len);
+ DBUG_RETURN(-1);
+ }
+
+ // Rewrite temp_buf
+ char* ptr= new_temp_buf;
+ ulong cnt= 0;
+
+ // Copy header and change event length
+ memcpy(ptr, temp_buf, header_len);
+ int4store(ptr + EVENT_LEN_OFFSET, event_new_len);
+ ptr += header_len;
+ cnt += header_len;
+
+ // Write new db name length and new name
+ *ptr++ = new_len;
+ memcpy(ptr, new_db, new_len + 1);
+ ptr += new_len + 1;
+ cnt += m_dblen + 2;
+
+ // Copy rest part
+ memcpy(ptr, temp_buf + cnt, event_cur_len - cnt);
+
+ // Reregister temp buf
+ free_temp_buf();
+ register_temp_buf(new_temp_buf, TRUE);
+
+ // Reset m_dbnam and m_dblen members
+ m_dblen= new_len;
+
+ // m_dbnam resides in m_memory together with m_tblnam and m_coltype
+ uchar* memory= m_memory;
+ char const* tblnam= m_tblnam;
+ uchar* coltype= m_coltype;
+
+ m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
+ &m_dbnam, (uint) m_dblen + 1,
+ &m_tblnam, (uint) m_tbllen + 1,
+ &m_coltype, (uint) m_colcnt,
+ NullS);
+
+ if (!m_memory)
+ {
+ sql_print_error("Table_map_log_event::rewrite_db: "
+ "failed to allocate new m_memory (%d + %d + %d bytes required)",
+ m_dblen + 1, m_tbllen + 1, m_colcnt);
+ DBUG_RETURN(-1);
+ }
+
+ memcpy((void*)m_dbnam, new_db, m_dblen + 1);
+ memcpy((void*)m_tblnam, tblnam, m_tbllen + 1);
+ memcpy(m_coltype, coltype, m_colcnt);
+
+ my_free(memory, MYF(MY_WME));
+ DBUG_RETURN(0);
+}
+#endif /* MYSQL_CLIENT */
+
+
/*
Return value is an error code, one of:
@@ -8586,7 +8691,7 @@ Rows_log_event::write_row(const Relay_log_info *const rli,
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
{
DBUG_PRINT("info",("Locating offending record using rnd_pos()"));
- error= table->file->rnd_pos(table->record[1], table->file->dup_ref);
+ error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
if (error)
{
DBUG_PRINT("info",("rnd_pos() returns error %d",error));
@@ -8618,10 +8723,10 @@ Rows_log_event::write_row(const Relay_log_info *const rli,
key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum,
0);
- error= table->file->index_read_idx_map(table->record[1], keynum,
- (const uchar*)key.get(),
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT);
+ error= table->file->ha_index_read_idx_map(table->record[1], keynum,
+ (const uchar*)key.get(),
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT);
if (error)
{
DBUG_PRINT("info",("index_read_idx() returns %s", HA_ERR(error)));
@@ -8845,10 +8950,10 @@ record_compare_exit:
/**
Locate the current row in event's table.
- The current row is pointed by @c m_curr_row. Member @c m_width tells how many
- columns are there in the row (this can be differnet from the number of columns
- in the table). It is assumed that event's table is already open and pointed
- by @c m_table.
+ The current row is pointed by @c m_curr_row. Member @c m_width tells
+ how many columns are there in the row (this can be differnet from
+ the number of columns in the table). It is assumed that event's
+ table is already open and pointed by @c m_table.
If a corresponding record is found in the table it is stored in
@c m_table->record[0]. Note that when record is located based on a primary
@@ -8909,13 +9014,14 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
length. Something along these lines should work:
ADD>>> store_record(table,record[1]);
- int error= table->file->rnd_pos(table->record[0], table->file->ref);
+ int error= table->file->ha_rnd_pos(table->record[0],
+ table->file->ref);
ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0],
table->s->reclength) == 0);
*/
DBUG_PRINT("info",("locating record using primary key (position)"));
- int error= table->file->rnd_pos_by_record(table->record[0]);
+ int error= table->file->ha_rnd_pos_by_record(table->record[0]);
if (error)
{
DBUG_PRINT("info",("rnd_pos returns error %d",error));
@@ -8975,9 +9081,9 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
table->record[0][table->s->null_bytes - 1]|=
256U - (1U << table->s->last_null_bit_pos);
- if ((error= table->file->index_read_map(table->record[0], m_key,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_map(table->record[0], m_key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT)))
{
DBUG_PRINT("info",("no record matching the key found in the table"));
if (error == HA_ERR_RECORD_DELETED)
@@ -9066,7 +9172,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
256U - (1U << table->s->last_null_bit_pos);
}
- while ((error= table->file->index_next(table->record[0])))
+ while ((error= table->file->ha_index_next(table->record[0])))
{
/* We just skip records that has already been deleted */
if (error == HA_ERR_RECORD_DELETED)
@@ -9090,11 +9196,10 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
int restart_count= 0; // Number of times scanning has restarted from top
/* We don't have a key: search the table using rnd_next() */
- if ((error= table->file->ha_rnd_init(1)))
+ if ((error= table->file->ha_rnd_init_with_error(1)))
{
DBUG_PRINT("info",("error initializing table scan"
" (ha_rnd_init returns %d)",error));
- table->file->print_error(error, MYF(0));
goto err;
}
@@ -9102,7 +9207,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
do
{
restart_rnd_next:
- error= table->file->rnd_next(table->record[0]);
+ error= table->file->ha_rnd_next(table->record[0]);
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
switch (error) {
@@ -9119,7 +9224,14 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
case HA_ERR_END_OF_FILE:
if (++restart_count < 2)
- table->file->ha_rnd_init(1);
+ {
+ int error2;
+ if ((error2= table->file->ha_rnd_init_with_error(1)))
+ {
+ error= error2;
+ goto err;
+ }
+ }
break;
default:
diff --git a/sql/log_event.h b/sql/log_event.h
index 7a6606badf5..d82fc385d86 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -878,6 +878,13 @@ public:
event's type, and its content is distributed in the event-specific fields.
*/
char *temp_buf;
+
+ /*
+ TRUE <=> this event 'owns' temp_buf and should call my_free() when done
+ with it
+ */
+ bool event_owns_temp_buf;
+
/*
Timestamp on the master(for debugging and replication of
NOW()/TIMESTAMP). It is important for queries and LOAD DATA
@@ -1019,12 +1026,17 @@ public:
Log_event(const char* buf, const Format_description_log_event
*description_event);
virtual ~Log_event() { free_temp_buf();}
- void register_temp_buf(char* buf) { temp_buf = buf; }
+ void register_temp_buf(char* buf, bool must_free)
+ {
+ temp_buf= buf;
+ event_owns_temp_buf= must_free;
+ }
void free_temp_buf()
{
if (temp_buf)
{
- my_free(temp_buf, MYF(0));
+ if (event_owns_temp_buf)
+ my_free(temp_buf, MYF(0));
temp_buf = 0;
}
}
@@ -1359,7 +1371,7 @@ protected:
MODE_PIPES_AS_CONCAT==0x2
MODE_ANSI_QUOTES==0x4
MODE_IGNORE_SPACE==0x8
- MODE_NOT_USED==0x10
+ MODE_IGNORE_BAD_TABLE_OPTIONS==0x10
MODE_ONLY_FULL_GROUP_BY==0x20
MODE_NO_UNSIGNED_SUBTRACTION==0x40
MODE_NO_DIR_IN_CREATE==0x80
@@ -3345,6 +3357,8 @@ public:
ulong get_table_id() const { return m_table_id; }
const char *get_table_name() const { return m_tblnam; }
const char *get_db_name() const { return m_dbnam; }
+ int rewrite_db(const char* new_name, size_t new_name_len,
+ const Format_description_log_event*);
#endif
virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; }
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index d1b17be1691..b96d1684d77 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -63,7 +63,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
we need to do any changes to that value after this function.
*/
lex_start(ev_thd);
- mysql_reset_thd_for_next_command(ev_thd);
+ mysql_reset_thd_for_next_command(ev_thd, 0);
/*
Check if the slave is set to use SBR. If so, it should switch
@@ -568,7 +568,7 @@ replace_record(THD *thd, TABLE *table,
*/
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
{
- error= table->file->rnd_pos(table->record[1], table->file->dup_ref);
+ error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
if (error)
{
DBUG_PRINT("info",("rnd_pos() returns error %d",error));
@@ -594,10 +594,10 @@ replace_record(THD *thd, TABLE *table,
key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum,
0);
- error= table->file->index_read_idx_map(table->record[1], keynum,
- (const uchar*)key.get(),
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT);
+ error= table->file->ha_index_read_idx_map(table->record[1], keynum,
+ (const uchar*)key.get(),
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT);
if (error)
{
DBUG_PRINT("info", ("index_read_idx() returns error %d", error));
@@ -709,13 +709,13 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
length. Something along these lines should work:
ADD>>> store_record(table,record[1]);
- int error= table->file->rnd_pos(table->record[0], table->file->ref);
+ int error= table->file->ha_rnd_pos(table->record[0], table->file->ref);
ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0],
table->s->reclength) == 0);
*/
table->file->position(table->record[0]);
- int error= table->file->rnd_pos(table->record[0], table->file->ref);
+ int error= table->file->ha_rnd_pos(table->record[0], table->file->ref);
/*
rnd_pos() returns the record in table->record[0], so we have to
move it to table->record[1].
@@ -753,8 +753,9 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
my_ptrdiff_t const pos=
table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0;
table->record[1][pos]= 0xFF;
- if ((error= table->file->index_read_map(table->record[1], key, HA_WHOLE_KEY,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_map(table->record[1], key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT)))
{
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
@@ -808,7 +809,7 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
256U - (1U << table->s->last_null_bit_pos);
}
- while ((error= table->file->index_next(table->record[1])))
+ while ((error= table->file->ha_index_next(table->record[1])))
{
/* We just skip records that has already been deleted */
if (error == HA_ERR_RECORD_DELETED)
@@ -830,14 +831,14 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
int error;
/* We don't have a key: search the table using rnd_next() */
- if ((error= table->file->ha_rnd_init(1)))
+ if ((error= table->file->ha_rnd_init_with_error(1)))
return error;
/* Continue until we find the right record or have made a full loop */
do
{
restart_rnd_next:
- error= table->file->rnd_next(table->record[1]);
+ error= table->file->ha_rnd_next(table->record[1]);
DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
DBUG_DUMP("record[1]", table->record[1], table->s->reclength);
@@ -854,15 +855,19 @@ static int find_and_fetch_row(TABLE *table, uchar *key)
goto restart_rnd_next;
case HA_ERR_END_OF_FILE:
- if (++restart_count < 2)
- table->file->ha_rnd_init(1);
- break;
+ if (++restart_count < 2)
+ {
+ int error2;
+ if ((error2= table->file->ha_rnd_init_with_error(1)))
+ DBUG_RETURN(error2);
+ }
+ break;
default:
- table->file->print_error(error, MYF(0));
+ table->file->print_error(error, MYF(0));
DBUG_PRINT("info", ("Record not found"));
table->file->ha_rnd_end();
- DBUG_RETURN(error);
+ DBUG_RETURN(error);
}
}
while (restart_count < 2 && record_compare(table));
@@ -2130,7 +2135,7 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli,
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
{
DBUG_PRINT("info",("Locating offending record using rnd_pos()"));
- error= table->file->rnd_pos(table->record[1], table->file->dup_ref);
+ error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
if (error)
{
DBUG_PRINT("info",("rnd_pos() returns error %d",error));
@@ -2162,10 +2167,10 @@ Old_rows_log_event::write_row(const Relay_log_info *const rli,
key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum,
0);
- error= table->file->index_read_idx_map(table->record[1], keynum,
- (const uchar*)key.get(),
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT);
+ error= table->file->ha_index_read_idx_map(table->record[1], keynum,
+ (const uchar*)key.get(),
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT);
if (error)
{
DBUG_PRINT("info",("index_read_idx() returns error %d", error));
@@ -2316,13 +2321,13 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
length. Something along these lines should work:
ADD>>> store_record(table,record[1]);
- int error= table->file->rnd_pos(table->record[0], table->file->ref);
+ int error= table->file->ha_rnd_pos(table->record[0], table->file->ref);
ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0],
table->s->reclength) == 0);
*/
DBUG_PRINT("info",("locating record using primary key (position)"));
- int error= table->file->rnd_pos_by_record(table->record[0]);
+ int error= table->file->ha_rnd_pos_by_record(table->record[0]);
if (error)
{
DBUG_PRINT("info",("rnd_pos returns error %d",error));
@@ -2382,9 +2387,9 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0;
table->record[0][pos]= 0xFF;
- if ((error= table->file->index_read_map(table->record[0], m_key,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_map(table->record[0], m_key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT)))
{
DBUG_PRINT("info",("no record matching the key found in the table"));
if (error == HA_ERR_RECORD_DELETED)
@@ -2473,7 +2478,7 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
256U - (1U << table->s->last_null_bit_pos);
}
- while ((error= table->file->index_next(table->record[0])))
+ while ((error= table->file->ha_index_next(table->record[0])))
{
/* We just skip records that has already been deleted */
if (error == HA_ERR_RECORD_DELETED)
@@ -2497,11 +2502,10 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
int restart_count= 0; // Number of times scanning has restarted from top
/* We don't have a key: search the table using rnd_next() */
- if ((error= table->file->ha_rnd_init(1)))
+ if ((error= table->file->ha_rnd_init_with_error(1)))
{
DBUG_PRINT("info",("error initializing table scan"
" (ha_rnd_init returns %d)",error));
- table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
@@ -2509,7 +2513,7 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
do
{
restart_rnd_next:
- error= table->file->rnd_next(table->record[0]);
+ error= table->file->ha_rnd_next(table->record[0]);
switch (error) {
@@ -2521,7 +2525,11 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli)
case HA_ERR_END_OF_FILE:
if (++restart_count < 2)
- table->file->ha_rnd_init(1);
+ {
+ int error2;
+ if ((error2= table->file->ha_rnd_init_with_error(1)))
+ DBUG_RETURN(error2);
+ }
break;
default:
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index bf973b7bfa0..299597632dd 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>
@@ -92,12 +102,16 @@ extern MYSQL_PLUGIN_IMPORT const char *primary_key_name;
#include "unireg.h"
void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size);
+#endif // MYSQL_CLIENT
+
void *sql_alloc(size_t);
void *sql_calloc(size_t);
char *sql_strdup(const char *str);
char *sql_strmake(const char *str, size_t len);
void *sql_memdup(const void * ptr, size_t size);
void sql_element_free(void *ptr);
+
+#ifndef MYSQL_CLIENT
char *sql_strmake_with_convert(const char *str, size_t arg_length,
CHARSET_INFO *from_cs,
size_t max_res_length,
@@ -508,7 +522,7 @@ protected:
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
-#define MODE_NOT_USED 16
+#define MODE_IGNORE_BAD_TABLE_OPTIONS 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define MODE_NO_DIR_IN_CREATE 128
@@ -999,9 +1013,6 @@ int write_bin_log(THD *thd, bool clear_error,
char const *query, ulong query_length);
/* sql_connect.cc */
-int check_user(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count);
pthread_handler_t handle_one_connection(void *arg);
bool init_new_connection_handler_thread();
void reset_mqh(LEX_USER *lu, bool get_them);
@@ -1013,6 +1024,10 @@ bool setup_connection_thread_globals(THD *thd);
bool login_connection(THD *thd);
void end_connection(THD *thd);
void prepare_new_connection_state(THD* thd);
+void update_global_user_stats(THD* thd, bool create_user, time_t now);
+int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host, USER_RESOURCES *mqh);
+int check_for_max_user_connections(THD *thd, USER_CONN *uc);
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
@@ -1049,14 +1064,22 @@ bool is_update_query(enum enum_sql_command command);
bool is_log_table_write_query(enum enum_sql_command command);
bool alloc_query(THD *thd, const char *packet, uint packet_length);
void mysql_init_select(LEX *lex);
-void mysql_reset_thd_for_next_command(THD *thd);
+void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat);
bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex);
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
+void init_global_user_stats(void);
+void init_global_table_stats(void);
+void init_global_index_stats(void);
+void init_global_client_stats(void);
void free_max_user_conn(void);
+void free_global_user_stats(void);
+void free_global_table_stats(void);
+void free_global_index_stats(void);
+void free_global_client_stats(void);
pthread_handler_t handle_bootstrap(void *arg);
int mysql_execute_command(THD *thd);
bool do_command(THD *thd);
@@ -1300,6 +1323,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
bool allow_rowid, uint *cached_field_index_ptr);
Field *
find_field_in_table_sef(TABLE *table, const char *name);
+int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE);
#endif /* MYSQL_SERVER */
@@ -1430,14 +1454,17 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum enum_field_types t
LEX_STRING *comment,
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *group,bool asc);
bool push_new_name_resolution_context(THD *thd,
@@ -1934,6 +1961,7 @@ extern ulong max_connect_errors, connect_timeout;
extern ulong extra_max_connections;
extern ulong slave_net_timeout, slave_trans_retries;
extern uint max_user_connections;
+extern ulonglong denied_connections;
extern ulong what_to_log,flush_time;
extern ulong query_buff_size;
extern ulong max_prepared_stmt_count, prepared_stmt_count;
@@ -1982,12 +2010,14 @@ extern bool volatile abort_loop, shutdown_in_progress;
extern bool in_bootstrap;
extern uint volatile thread_count, thread_running, global_read_lock;
extern ulong thread_created;
+extern uint thread_handling;
extern uint connection_count, extra_connection_count;
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern ulong slave_exec_mode_options;
extern my_bool opt_readonly, lower_case_file_system;
+extern my_bool opt_userstat_running;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern char* opt_secure_file_priv;
@@ -2028,6 +2058,11 @@ extern pthread_mutex_t LOCK_des_key_file;
#endif
extern pthread_mutex_t LOCK_server_started;
extern pthread_cond_t COND_server_started;
+extern pthread_mutex_t LOCK_global_user_client_stats;
+extern pthread_mutex_t LOCK_global_table_stats;
+extern pthread_mutex_t LOCK_global_index_stats;
+extern pthread_mutex_t LOCK_stats;
+
extern int mysqld_server_started;
extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
extern rw_lock_t LOCK_system_variables_hash;
@@ -2054,6 +2089,11 @@ extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
extern String null_string;
extern HASH open_cache, lock_db_cache;
+extern HASH global_user_stats;
+extern HASH global_client_stats;
+extern HASH global_table_stats;
+extern HASH global_index_stats;
+
extern TABLE *unused_tables;
extern const char* any_db;
extern struct my_option my_long_options[];
@@ -2221,7 +2261,7 @@ 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,
+bool 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,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index eb46ba14f19..261589cfd34 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -23,6 +23,7 @@
#include "rpl_mi.h"
#include "sql_repl.h"
#include "rpl_filter.h"
+#include "client_settings.h"
#include "repl_failsafe.h"
#include <my_stacktrace.h>
#include "mysqld_suffix.h"
@@ -278,7 +279,7 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
static const char *sql_mode_names[]=
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "IGNORE_BAD_TABLE_OPTIONS", "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",
@@ -298,7 +299,7 @@ static const unsigned int sql_mode_names_len[]=
/*PIPES_AS_CONCAT*/ 15,
/*ANSI_QUOTES*/ 11,
/*IGNORE_SPACE*/ 12,
- /*?*/ 1,
+ /*IGNORE_BAD_TABLE_OPTIONS*/ 24,
/*ONLY_FULL_GROUP_BY*/ 18,
/*NO_UNSIGNED_SUBTRACTION*/ 23,
/*NO_DIR_IN_CREATE*/ 16,
@@ -381,6 +382,16 @@ TYPELIB thread_handling_typelib=
thread_handling_names, NULL
};
+const char *plugin_maturity_names[]=
+{ "unknown", "experimental", "alpha", "beta", "gamma", "stable", 0 };
+
+TYPELIB plugin_maturity_values=
+{
+ array_elements(plugin_maturity_names) - 1, "", plugin_maturity_names, 0
+};
+
+const int server_maturity= MariaDB_PLUGIN_MATURITY_UNKNOWN;
+
const char *first_keyword= "first", *binary_keyword= "BINARY";
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
@@ -420,6 +431,7 @@ static my_bool opt_short_log_format= 0;
static my_bool opt_ignore_wrong_options= 0, opt_expect_abort= 0;
static uint kill_cached_threads, wake_thread;
ulong thread_created;
+uint thread_handling;
static ulong max_used_connections;
static ulong my_bind_addr; /**< the address we bind to */
static volatile ulong cached_thread_count= 0;
@@ -452,6 +464,7 @@ static pthread_cond_t COND_thread_cache, COND_flush_thread_cache;
bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0;
my_bool opt_log, opt_slow_log;
+my_bool opt_userstat_running;
ulong log_output_options;
my_bool opt_log_queries_not_using_indexes= 0;
bool opt_error_log= IF_WIN(1,0);
@@ -588,6 +601,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
ulong max_connections, max_connect_errors;
ulong extra_max_connections;
uint max_user_connections= 0;
+ulonglong denied_connections;
/**
Limit of the total number of prepared statements in the server.
Is necessary to protect the server against out-of-memory attacks.
@@ -690,6 +704,9 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_global_system_variables,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
LOCK_connection_count, LOCK_uuid_generator;
+pthread_mutex_t LOCK_stats, LOCK_global_user_client_stats;
+pthread_mutex_t LOCK_global_table_stats, LOCK_global_index_stats;
+
/**
The below lock protects access to two global server variables:
max_prepared_stmt_count and prepared_stmt_count. These variables
@@ -1398,6 +1415,10 @@ void clean_up(bool print_message)
x_free(opt_secure_file_priv);
bitmap_free(&temp_pool);
free_max_user_conn();
+ free_global_user_stats();
+ free_global_client_stats();
+ free_global_table_stats();
+ free_global_index_stats();
#ifdef HAVE_REPLICATION
end_slave_list();
#endif
@@ -1422,6 +1443,7 @@ void clean_up(bool print_message)
if (print_message && errmesg && server_start_time)
sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
thread_scheduler.end();
+ mysql_library_end();
finish_client_errs();
my_free((uchar*) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
@@ -1488,6 +1510,11 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_bytes_received);
(void) pthread_mutex_destroy(&LOCK_user_conn);
(void) pthread_mutex_destroy(&LOCK_connection_count);
+ (void) pthread_mutex_destroy(&LOCK_stats);
+ (void) pthread_mutex_destroy(&LOCK_global_user_client_stats);
+ (void) pthread_mutex_destroy(&LOCK_global_table_stats);
+ (void) pthread_mutex_destroy(&LOCK_global_index_stats);
+
Events::destroy_mutexes();
#ifdef HAVE_OPENSSL
(void) pthread_mutex_destroy(&LOCK_des_key_file);
@@ -1530,20 +1557,23 @@ static void clean_up_mutexes()
mysys/thr_mutex.c, will give a warning on first wrong mutex usage!
*/
+#ifdef SAFE_MUTEX
+#define always_in_that_order(A,B) \
+ pthread_mutex_lock(A); pthread_mutex_lock(B); \
+ pthread_mutex_unlock(B); pthread_mutex_unlock(A)
+#else
+#define always_in_that_order(A,B)
+#endif
+
static void register_mutex_order()
{
-#ifdef SAFE_MUTEX
/*
We must have LOCK_open before LOCK_global_system_variables because
LOCK_open is hold while sql_plugin.c::intern_sys_var_ptr() is called.
*/
- pthread_mutex_lock(&LOCK_open);
- pthread_mutex_lock(&LOCK_global_system_variables);
-
- pthread_mutex_unlock(&LOCK_global_system_variables);
- pthread_mutex_unlock(&LOCK_open);
-#endif
+ always_in_that_order(&LOCK_open, &LOCK_global_system_variables);
}
+#undef always_in_that_order
/****************************************************************************
@@ -3285,6 +3315,7 @@ SHOW_VAR com_status_vars[]= {
{"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
{"show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
{"show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
+ {"show_client_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CLIENT_STATS]), SHOW_LONG_STATUS},
{"show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
{"show_column_types", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS},
{"show_contributors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS},
@@ -3307,6 +3338,7 @@ SHOW_VAR com_status_vars[]= {
{"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
{"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
{"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
+ {"show_index_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS},
{"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
{"show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
{"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
@@ -3323,9 +3355,11 @@ SHOW_VAR com_status_vars[]= {
{"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
{"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
{"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
+ {"show_table_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS},
{"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
{"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
{"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
+ {"show_user_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS},
{"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
{"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
{"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
@@ -3529,6 +3563,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
if (init_errmessage()) /* Read error messages from file */
return 1;
init_client_errs();
+ mysql_library_init(never,never,never); /* for replication */
lex_init();
if (item_create_init())
return 1;
@@ -3737,6 +3772,12 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_connection_count, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_stats, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_global_user_client_stats,
+ MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_global_table_stats, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_global_index_stats, MY_MUTEX_INIT_FAST);
+
#ifdef HAVE_OPENSSL
(void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
#ifndef HAVE_YASSL
@@ -4122,6 +4163,9 @@ a file name for --log-bin-index option", opt_binlog_index_name);
/* call ha_init_key_cache() on all key caches to init them */
process_key_caches(&ha_init_key_cache);
+ init_global_table_stats();
+ init_global_index_stats();
+
/* Allow storage engine to give real error messages */
if (ha_init_errors())
DBUG_RETURN(1);
@@ -4329,6 +4373,8 @@ a file name for --log-bin-index option", opt_binlog_index_name);
init_max_user_conn();
init_update_queries();
+ init_global_user_stats();
+ init_global_client_stats();
DBUG_RETURN(0);
}
@@ -5147,6 +5193,7 @@ static void create_new_thread(THD *thd)
DBUG_PRINT("error",("Too many connections"));
close_connection(thd, ER_CON_COUNT_ERROR, 1);
+ statistic_increment(denied_connections, &LOCK_status);
delete thd;
DBUG_VOID_RETURN;
}
@@ -5857,6 +5904,7 @@ enum options_mysqld
OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
+ OPT_KEY_CACHE_PARTITIONS,
OPT_LONG_QUERY_TIME,
OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
@@ -5935,6 +5983,7 @@ enum options_mysqld
OPT_TABLE_LOCK_WAIT_TIMEOUT,
OPT_PLUGIN_LOAD,
OPT_PLUGIN_DIR,
+ OPT_PLUGIN_MATURITY,
OPT_SYMBOLIC_LINKS,
OPT_WARNINGS,
OPT_RECORD_BUFFER_OLD,
@@ -5962,6 +6011,7 @@ enum options_mysqld
OPT_LOG_SLOW_RATE_LIMIT,
OPT_LOG_SLOW_VERBOSITY,
OPT_LOG_SLOW_FILTER,
+ OPT_USERSTAT,
OPT_GENERAL_LOG_FILE,
OPT_SLOW_QUERY_LOG_FILE,
OPT_IGNORE_BUILTIN_INNODB,
@@ -6723,8 +6773,6 @@ thread is in the relay logs.",
{"shared-memory", OPT_ENABLE_SHARED_MEMORY,
"Enable the shared memory.",&opt_enable_shared_memory, &opt_enable_shared_memory,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
-#ifdef HAVE_SMEM
{"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME,
"Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -7028,6 +7076,11 @@ thread is in the relay logs.",
"The minimum percentage of warm blocks in key cache.",
&dflt_key_cache_var.param_division_limit, 0, 0,
(GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0},
+ {"key_cache_segments", OPT_KEY_CACHE_PARTITIONS,
+ "The number of segments in a key cache",
+ &dflt_key_cache_var.param_partitions, 0,
+ 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, DEFAULT_KEY_CACHE_PARTITIONS,
+ 0, MAX_KEY_CACHE_PARTITIONS, 0, 1, 0},
{"log-slow-filter", OPT_LOG_SLOW_FILTER,
"Log only the queries that followed certain execution plan. Multiple flags "
"allowed in a comma-separated string. [admin, filesort, filesort_on_disk, "
@@ -7293,6 +7346,10 @@ thread is in the relay logs.",
"is the plugin library in plugin_dir.",
&opt_plugin_load, &opt_plugin_load, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"plugin-maturity", OPT_PLUGIN_MATURITY,
+ "The lowest desirable plugin maturity. Plugins less mature than that will not be installed or loaded.",
+ (uchar**) &plugin_maturity, (uchar**) &plugin_maturity, &plugin_maturity_values,
+ GET_ENUM, REQUIRED_ARG, server_maturity, 0, 0, 0, 0, 0},
{"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
"The size of the buffer that is allocated when preloading indexes.",
&global_system_variables.preload_buff_size,
@@ -7498,6 +7555,10 @@ thread is in the relay logs.",
&max_system_variables.net_wait_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT),
0, 1, 0},
+ {"userstat", OPT_USERSTAT,
+ "Control USER_STATISTICS, CLIENT_STATISTICS, INDEX_STATISTICS and TABLE_STATISTICS running",
+ (uchar**) &opt_userstat_running, (uchar**) &opt_userstat_running,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
{"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
"Causes updates to non-transactional engines using statement format to be "
"written directly to binary log. Before using this option, make sure that "
@@ -7878,19 +7939,24 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
SHOW_VAR status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
+ {"Access_denied_errors", (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS},
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
{"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG},
+ {"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
{"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
{"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
+ {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
{"Com", (char*) com_status_vars, SHOW_ARRAY},
{"Compression", (char*) &show_net_compression, SHOW_FUNC},
{"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH},
+ {"Cpu_time", (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS},
{"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
{"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG},
{"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
{"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
{"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
+ {"Empty_queries", (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH},
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
{"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
@@ -7925,6 +7991,8 @@ SHOW_VAR status_vars[]= {
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
{"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC},
+ {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONG_STATUS},
+ {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONG_STATUS},
#ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
@@ -8530,6 +8598,7 @@ mysqld_get_one_option(int optid,
}
case (int)OPT_REPLICATE_REWRITE_DB:
{
+ /* See also OPT_REWRITE_DB handling in client/mysqlbinlog.cc */
char* key = argument,*p, *val;
if (!(p= strstr(argument, "->")))
@@ -8979,16 +9048,16 @@ mysqld_get_one_option(int optid,
break;
}
case OPT_ONE_THREAD:
- global_system_variables.thread_handling= SCHEDULER_NO_THREADS;
- opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling];
+ thread_handling= SCHEDULER_NO_THREADS;
+ opt_thread_handling= thread_handling_typelib.type_names[thread_handling];
break;
case OPT_THREAD_HANDLING:
{
int id;
LINT_INIT(id);
if (!find_opt_type(argument, &thread_handling_typelib, opt->name, &id))
- global_system_variables.thread_handling= id - 1;
- opt_thread_handling= thread_handling_typelib.type_names[global_system_variables.thread_handling];
+ thread_handling= id - 1;
+ opt_thread_handling= thread_handling_typelib.type_names[thread_handling];
break;
}
case OPT_FT_BOOLEAN_SYNTAX:
@@ -9050,6 +9119,7 @@ mysql_getopt_value(const char *keyname, uint key_length,
case OPT_KEY_CACHE_BLOCK_SIZE:
case OPT_KEY_CACHE_DIVISION_LIMIT:
case OPT_KEY_CACHE_AGE_THRESHOLD:
+ case OPT_KEY_CACHE_PARTITIONS:
{
KEY_CACHE *key_cache;
if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
@@ -9067,6 +9137,8 @@ mysql_getopt_value(const char *keyname, uint key_length,
return &key_cache->param_division_limit;
case OPT_KEY_CACHE_AGE_THRESHOLD:
return &key_cache->param_age_threshold;
+ case OPT_KEY_CACHE_PARTITIONS:
+ return (uchar**) &key_cache->param_partitions;
}
}
}
@@ -9146,7 +9218,7 @@ static int get_options(int *argc,char **argv)
if (mysqld_chroot)
set_root(mysqld_chroot);
#else
- global_system_variables.thread_handling = SCHEDULER_NO_THREADS;
+ thread_handling = SCHEDULER_NO_THREADS;
max_allowed_packet= global_system_variables.max_allowed_packet;
net_buffer_length= global_system_variables.net_buffer_length;
#endif
@@ -9185,11 +9257,10 @@ static int get_options(int *argc,char **argv)
one_thread_scheduler(&thread_scheduler);
one_thread_scheduler(&extra_thread_scheduler);
#else
- if (global_system_variables.thread_handling <=
- SCHEDULER_ONE_THREAD_PER_CONNECTION)
+ if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
one_thread_per_connection_scheduler(&thread_scheduler, &max_connections,
&connection_count);
- else if (global_system_variables.thread_handling == SCHEDULER_NO_THREADS)
+ else if (thread_handling == SCHEDULER_NO_THREADS)
one_thread_scheduler(&thread_scheduler);
else
pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */
@@ -9551,6 +9622,8 @@ void refresh_status(THD *thd)
/* Reset thread's status variables */
bzero((uchar*) &thd->status_var, sizeof(thd->status_var));
+ bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var));
+ thd->start_bytes_received= 0;
/* Reset some global variables */
reset_status_vars();
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 76f1c93e295..2f88841d6a2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -707,10 +707,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
static
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
double read_time);
-static
-TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree);
-static double get_index_only_read_time(const PARAM* param, ha_rows records,
- int keynr);
+static TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree);
#ifndef DBUG_OFF
static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
@@ -1435,7 +1432,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
quick->record= head->record[0];
}
- if (need_to_fetch_row && head->file->ha_rnd_init(1))
+ if (need_to_fetch_row && head->file->ha_rnd_init_with_error(1))
{
DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
DBUG_RETURN(1);
@@ -1606,7 +1603,7 @@ int QUICK_ROR_UNION_SELECT::reset()
queue_insert(&queue, (uchar*)quick);
}
- if (head->file->ha_rnd_init(1))
+ if (head->file->ha_rnd_init_with_error(1))
{
DBUG_PRINT("error", ("ROR index_merge rnd_init call failed"));
DBUG_RETURN(1);
@@ -2315,9 +2312,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (!head->covering_keys.is_clear_all())
{
int key_for_use= find_shortest_key(head, &head->covering_keys);
- double key_read_time= (get_index_only_read_time(&param, records,
- key_for_use) +
- (double) records / TIME_FOR_COMPARE);
+ double key_read_time= param.table->file->keyread_read_time(key_for_use,
+ 1, records) +
+ (double) records / TIME_FOR_COMPARE;
DBUG_PRINT("info", ("'all'+'using index' scan will be using key %d, "
"read time %g", key_for_use, key_read_time));
if (key_read_time < read_time)
@@ -3939,42 +3936,6 @@ skip_to_ror_scan:
}
-/*
- Calculate cost of 'index only' scan for given index and number of records.
-
- SYNOPSIS
- get_index_only_read_time()
- param parameters structure
- records #of records to read
- keynr key to read
-
- NOTES
- It is assumed that we will read trough the whole key range and that all
- key blocks are half full (normally things are much better). It is also
- assumed that each time we read the next key from the index, the handler
- performs a random seek, thus the cost is proportional to the number of
- blocks read.
-
- TODO:
- Move this to handler->read_time() by adding a flag 'index-only-read' to
- this call. The reason for doing this is that the current function doesn't
- handle the case when the row is stored in the b-tree (like in innodb
- clustered index)
-*/
-
-static double get_index_only_read_time(const PARAM* param, ha_rows records,
- int keynr)
-{
- double read_time;
- uint keys_per_block= (param->table->file->stats.block_size/2/
- (param->table->key_info[keynr].key_length+
- param->table->file->ref_length) + 1);
- read_time=((double) (records+keys_per_block-1)/
- (double) keys_per_block);
- return read_time;
-}
-
-
typedef struct st_ror_scan_info
{
uint idx; /* # of used key in param->keys */
@@ -4051,8 +4012,8 @@ ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg)
bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr-1);
}
ror_scan->index_read_cost=
- get_index_only_read_time(param, param->table->quick_rows[ror_scan->keynr],
- ror_scan->keynr);
+ param->table->file->keyread_read_time(ror_scan->keynr, 1,
+ param->table->quick_rows[ror_scan->keynr]);
DBUG_RETURN(ror_scan);
}
@@ -4887,7 +4848,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
We can resolve this by only reading through this key.
0.01 is added to avoid races between range and 'index' scan.
*/
- found_read_time= get_index_only_read_time(param,found_records,keynr) +
+ found_read_time= param->table->file->keyread_read_time(keynr,1,
+ found_records) +
cpu_cost + 0.01;
}
else
@@ -7632,8 +7594,8 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
param->range_count++;
if (!tmp_min_flag && ! tmp_max_flag &&
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
- (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
- HA_NOSAME && min_key_length == max_key_length &&
+ (param->table->key_info[keynr].flags & HA_NOSAME) &&
+ min_key_length == max_key_length &&
!memcmp(param->min_key, param->max_key, min_key_length) &&
!param->first_null_comp)
{
@@ -7922,7 +7884,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
{
KEY *table_key=quick->head->key_info+quick->index;
flag=EQ_RANGE;
- if ((table_key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
+ if ((table_key->flags & HA_NOSAME) &&
key->part == table_key->key_parts-1)
{
if (!(table_key->flags & HA_NULL_PART_KEY) ||
@@ -7972,7 +7934,7 @@ bool QUICK_RANGE_SELECT::unique_key_range()
if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
{
KEY *key=head->key_info+index;
- return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
+ return ((key->flags & HA_NOSAME) &&
key->key_length == tmp->min_length);
}
}
@@ -8091,8 +8053,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
range->min_length= range->max_length= ref->key_length;
range->min_keypart_map= range->max_keypart_map=
make_prev_keypart_map(ref->key_parts);
- range->flag= ((ref->key_length == key_info->key_length &&
- (key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0);
+ range->flag= (ref->key_length == key_info->key_length ? EQ_RANGE : 0);
if (!(quick->key_parts=key_part=(KEY_PART *)
alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
@@ -8249,7 +8210,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
index_merge currently doesn't support "using index" at all
*/
head->disable_keyread();
- init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE);
+ if (init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE))
+ result= 1;
DBUG_RETURN(result);
err:
@@ -8381,7 +8343,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
/* We get here if we got the same row ref in all scans. */
if (need_to_fetch_row)
- error= head->file->rnd_pos(head->record[0], last_rowid);
+ error= head->file->ha_rnd_pos(head->record[0], last_rowid);
} while (error == HA_ERR_RECORD_DELETED);
DBUG_RETURN(error);
}
@@ -8447,7 +8409,7 @@ int QUICK_ROR_UNION_SELECT::get_next()
cur_rowid= prev_rowid;
prev_rowid= tmp;
- error= head->file->rnd_pos(quick->record, prev_rowid);
+ error= head->file->ha_rnd_pos(quick->record, prev_rowid);
} while (error == HA_ERR_RECORD_DELETED);
DBUG_RETURN(error);
}
@@ -8651,10 +8613,12 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
int result;
if (last_range)
{
- /* Read the next record in the same range with prefix after cur_prefix. */
+ /*
+ Read the next record in the same range with prefix after cur_prefix.
+ */
DBUG_ASSERT(cur_prefix != NULL);
- result= file->index_read_map(record, cur_prefix, keypart_map,
- HA_READ_AFTER_KEY);
+ result= file->ha_index_read_map(record, cur_prefix, keypart_map,
+ HA_READ_AFTER_KEY);
if (result || last_range->max_keypart_map == 0)
DBUG_RETURN(result);
@@ -8703,8 +8667,8 @@ int QUICK_RANGE_SELECT_GEOM::get_next()
if (last_range)
{
// Already read through key
- result= file->index_next_same(record, last_range->min_key,
- last_range->min_length);
+ result= file->ha_index_next_same(record, last_range->min_key,
+ last_range->min_length);
if (result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
}
@@ -8718,10 +8682,10 @@ int QUICK_RANGE_SELECT_GEOM::get_next()
}
last_range= *(cur_range++);
- result= file->index_read_map(record, last_range->min_key,
- last_range->min_keypart_map,
- (ha_rkey_function)(last_range->flag ^
- GEOM_FLAG));
+ result= file->ha_index_read_map(record, last_range->min_key,
+ last_range->min_keypart_map,
+ (ha_rkey_function)(last_range->flag ^
+ GEOM_FLAG));
if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
last_range= 0; // Not found, to next range
@@ -8833,9 +8797,9 @@ int QUICK_SELECT_DESC::get_next()
{ // Already read through key
result = ((last_range->flag & EQ_RANGE &&
used_key_parts <= head->key_info[index].key_parts) ?
- file->index_next_same(record, last_range->min_key,
+ file->ha_index_next_same(record, last_range->min_key,
last_range->min_length) :
- file->index_prev(record));
+ file->ha_index_prev(record));
if (!result)
{
if (cmp_prev(*rev_it.ref()) == 0)
@@ -8851,7 +8815,7 @@ int QUICK_SELECT_DESC::get_next()
if (last_range->flag & NO_MAX_RANGE) // Read last record
{
int local_error;
- if ((local_error=file->index_last(record)))
+ if ((local_error= file->ha_index_last(record)))
DBUG_RETURN(local_error); // Empty table
if (cmp_prev(last_range) == 0)
DBUG_RETURN(0);
@@ -8863,9 +8827,9 @@ int QUICK_SELECT_DESC::get_next()
used_key_parts <= head->key_info[index].key_parts)
{
- result = file->index_read_map(record, last_range->max_key,
- last_range->max_keypart_map,
- HA_READ_KEY_EXACT);
+ result= file->ha_index_read_map(record, last_range->max_key,
+ last_range->max_keypart_map,
+ HA_READ_KEY_EXACT);
}
else
{
@@ -8873,11 +8837,11 @@ int QUICK_SELECT_DESC::get_next()
(last_range->flag & EQ_RANGE &&
used_key_parts > head->key_info[index].key_parts) ||
range_reads_after_key(last_range));
- result=file->index_read_map(record, last_range->max_key,
- last_range->max_keypart_map,
- ((last_range->flag & NEAR_MAX) ?
- HA_READ_BEFORE_KEY :
- HA_READ_PREFIX_LAST_OR_PREV));
+ result= file->ha_index_read_map(record, last_range->max_key,
+ last_range->max_keypart_map,
+ ((last_range->flag & NEAR_MAX) ?
+ HA_READ_BEFORE_KEY :
+ HA_READ_PREFIX_LAST_OR_PREV));
}
if (result)
{
@@ -10625,7 +10589,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void)
DBUG_RETURN(result);
if (quick_prefix_select && quick_prefix_select->reset())
DBUG_RETURN(1);
- result= file->index_last(record);
+ result= file->ha_index_last(record);
if (result == HA_ERR_END_OF_FILE)
DBUG_RETURN(0);
/* Save the prefix of the last group. */
@@ -10727,9 +10691,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
first sub-group with the extended prefix.
*/
if (!have_min && !have_max && key_infix_len > 0)
- result= file->index_read_map(record, group_prefix,
- make_prev_keypart_map(real_key_parts),
- HA_READ_KEY_EXACT);
+ result= file->ha_index_read_map(record, group_prefix,
+ make_prev_keypart_map(real_key_parts),
+ HA_READ_KEY_EXACT);
result= have_min ? min_res : have_max ? max_res : result;
} while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
@@ -10791,9 +10755,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
/* Apply the constant equality conditions to the non-group select fields */
if (key_infix_len > 0)
{
- if ((result= file->index_read_map(record, group_prefix,
- make_prev_keypart_map(real_key_parts),
- HA_READ_KEY_EXACT)))
+ if ((result=
+ file->ha_index_read_map(record, group_prefix,
+ make_prev_keypart_map(real_key_parts),
+ HA_READ_KEY_EXACT)))
DBUG_RETURN(result);
}
@@ -10808,9 +10773,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
{
/* Find the first subsequent record without NULL in the MIN/MAX field. */
key_copy(tmp_record, record, index_info, 0);
- result= file->index_read_map(record, tmp_record,
- make_keypart_map(real_key_parts),
- HA_READ_AFTER_KEY);
+ result= file->ha_index_read_map(record, tmp_record,
+ make_keypart_map(real_key_parts),
+ HA_READ_AFTER_KEY);
/*
Check if the new record belongs to the current group by comparing its
prefix with the group's prefix. If it is from the next group, then the
@@ -10865,9 +10830,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max()
if (min_max_ranges.elements > 0)
result= next_max_in_range();
else
- result= file->index_read_map(record, group_prefix,
- make_prev_keypart_map(real_key_parts),
- HA_READ_PREFIX_LAST);
+ result= file->ha_index_read_map(record, group_prefix,
+ make_prev_keypart_map(real_key_parts),
+ HA_READ_PREFIX_LAST);
DBUG_RETURN(result);
}
@@ -10911,7 +10876,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
{
if (!seen_first_key)
{
- result= file->index_first(record);
+ result= file->ha_index_first(record);
if (result)
DBUG_RETURN(result);
seen_first_key= TRUE;
@@ -10919,9 +10884,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
else
{
/* Load the first key in this group into record. */
- result= file->index_read_map(record, group_prefix,
- make_prev_keypart_map(group_key_parts),
- HA_READ_AFTER_KEY);
+ result= file->ha_index_read_map(record, group_prefix,
+ make_prev_keypart_map(group_key_parts),
+ HA_READ_AFTER_KEY);
if (result)
DBUG_RETURN(result);
}
@@ -10998,7 +10963,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
}
- result= file->index_read_map(record, group_prefix, keypart_map, find_flag);
+ result= file->ha_index_read_map(record, group_prefix, keypart_map,
+ find_flag);
if (result)
{
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
@@ -11137,7 +11103,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
}
- result= file->index_read_map(record, group_prefix, keypart_map, find_flag);
+ result= file->ha_index_read_map(record, group_prefix, keypart_map,
+ find_flag);
if (result)
{
diff --git a/sql/opt_range.h b/sql/opt_range.h
index f2a1cce29b5..758dffe7a52 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -823,7 +823,7 @@ public:
~FT_SELECT() { file->ft_end(); }
int init() { return error=file->ft_init(); }
int reset() { return 0; }
- int get_next() { return error=file->ft_read(record); }
+ int get_next() { return error= file->ha_ft_read(record); }
int get_type() { return QS_TYPE_FULLTEXT; }
};
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index ae9debf06e7..450ded89653 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -109,7 +109,7 @@ static int get_index_min_value(TABLE *table, TABLE_REF *ref,
int error;
if (!ref->key_length)
- error= table->file->index_first(table->record[0]);
+ error= table->file->ha_index_first(table->record[0]);
else
{
/*
@@ -131,10 +131,10 @@ static int get_index_min_value(TABLE *table, TABLE_REF *ref,
Closed interval: Either The MIN argument is non-nullable, or
we have a >= predicate for the MIN argument.
*/
- error= table->file->index_read_map(table->record[0],
- ref->key_buff,
- make_prev_keypart_map(ref->key_parts),
- HA_READ_KEY_OR_NEXT);
+ error= table->file->ha_index_read_map(table->record[0],
+ ref->key_buff,
+ make_prev_keypart_map(ref->key_parts),
+ HA_READ_KEY_OR_NEXT);
else
{
/*
@@ -146,10 +146,10 @@ static int get_index_min_value(TABLE *table, TABLE_REF *ref,
and it would not work.
*/
DBUG_ASSERT(prefix_len < ref->key_length);
- error= table->file->index_read_map(table->record[0],
- ref->key_buff,
- make_prev_keypart_map(ref->key_parts),
- HA_READ_AFTER_KEY);
+ error= table->file->ha_index_read_map(table->record[0],
+ ref->key_buff,
+ make_prev_keypart_map(ref->key_parts),
+ HA_READ_AFTER_KEY);
/*
If the found record is outside the group formed by the search
prefix, or there is no such record at all, check if all
@@ -172,10 +172,10 @@ static int get_index_min_value(TABLE *table, TABLE_REF *ref,
key_cmp_if_same(table, ref->key_buff, ref->key, prefix_len)))
{
DBUG_ASSERT(item_field->field->real_maybe_null());
- error= table->file->index_read_map(table->record[0],
- ref->key_buff,
- make_prev_keypart_map(ref->key_parts),
- HA_READ_KEY_EXACT);
+ error= table->file->ha_index_read_map(table->record[0],
+ ref->key_buff,
+ make_prev_keypart_map(ref->key_parts),
+ HA_READ_KEY_EXACT);
}
}
}
@@ -198,12 +198,12 @@ static int get_index_min_value(TABLE *table, TABLE_REF *ref,
static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl)
{
return (ref->key_length ?
- table->file->index_read_map(table->record[0], ref->key_buff,
- make_prev_keypart_map(ref->key_parts),
- range_fl & NEAR_MAX ?
- HA_READ_BEFORE_KEY :
- HA_READ_PREFIX_LAST_OR_PREV) :
- table->file->index_last(table->record[0]));
+ table->file->ha_index_read_map(table->record[0], ref->key_buff,
+ make_prev_keypart_map(ref->key_parts),
+ range_fl & NEAR_MAX ?
+ HA_READ_BEFORE_KEY :
+ HA_READ_PREFIX_LAST_OR_PREV) :
+ table->file->ha_index_last(table->record[0]));
}
@@ -374,12 +374,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- table->file->ha_index_init((uint) ref.key, 1);
-
- error= is_max ?
- get_index_max_value(table, &ref, range_fl) :
- get_index_min_value(table, &ref, item_field, range_fl,
- prefix_len);
+ if (!(error= table->file->ha_index_init((uint) ref.key, 1)))
+ error= (is_max ?
+ get_index_max_value(table, &ref, range_fl) :
+ get_index_min_value(table, &ref, item_field, range_fl,
+ prefix_len));
/* Verify that the read tuple indeed matches the search key */
if (!error && reckey_in_range(is_max, &ref, item_field->field,
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 5d952021365..174dcbf9c13 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -1539,7 +1539,7 @@ Dep_value_table *Dep_analysis_context::create_table_value(TABLE *table)
for (uint i=0; i < table->s->keys; i++)
{
KEY *key= table->key_info + i;
- if ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME)
+ if (key->flags & HA_NOSAME)
{
Dep_module_key *key_dep;
if (!(key_dep= new Dep_module_key(tbl_dep, i, key->key_parts)))
diff --git a/sql/password.c b/sql/password.c
index 3c662e0c8f3..0cfa15b15d6 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -193,13 +193,13 @@ void scramble_323(char *to, const char *message, const char *password)
*/
my_bool
-check_scramble_323(const char *scrambled, const char *message,
+check_scramble_323(const unsigned char *scrambled, const char *message,
ulong *hash_pass)
{
struct my_rnd_struct rand_st;
ulong hash_message[2];
- char buff[16],*to,extra; /* Big enough for check */
- const char *pos;
+ uchar buff[16],*to,extra; /* Big enough for check */
+ const uchar *pos;
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
my_rnd_init(&rand_st,hash_pass[0] ^ hash_message[0],
@@ -214,7 +214,7 @@ check_scramble_323(const char *scrambled, const char *message,
to=buff;
while (*scrambled)
{
- if (*scrambled++ != (char) (*to++ ^ extra))
+ if (*scrambled++ != (uchar) (*to++ ^ extra))
return 1; /* Wrong password */
}
return 0;
@@ -481,7 +481,7 @@ scramble(char *to, const char *message, const char *password)
*/
my_bool
-check_scramble(const char *scramble_arg, const char *message,
+check_scramble(const uchar *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
SHA1_CONTEXT sha1_context;
@@ -494,7 +494,7 @@ check_scramble(const char *scramble_arg, const char *message,
mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
mysql_sha1_result(&sha1_context, buf);
/* encrypt scramble */
- my_crypt((char *) buf, buf, (const uchar *) scramble_arg, SCRAMBLE_LENGTH);
+ my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
mysql_sha1_reset(&sha1_context);
mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
diff --git a/sql/procedure.h b/sql/procedure.h
index ceb586766b1..30a8a0efccb 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -42,7 +42,11 @@ public:
{
init_make_field(tmp_field,field_type());
}
- unsigned int size_of() { return sizeof(*this);}
+ unsigned int size_of() { return sizeof(*this);}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("proc");
+ }
};
class Item_proc_real :public Item_proc
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 41ebbcfba90..7721d43f936 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -341,24 +341,6 @@ static bool write_eof_packet(THD *thd, NET *net,
}
/**
- Please client to send scrambled_password in old format.
-
- @param thd thread handle
-
- @retval
- 0 ok
- @retval
- !0 error
-*/
-
-bool send_old_password_request(THD *thd)
-{
- NET *net= &thd->net;
- return my_net_write(net, eof_buff, 1) || net_flush(net);
-}
-
-
-/**
@param thd Thread handler
@param sql_errno The error code to send
@param err A pointer to the error message
diff --git a/sql/protocol.h b/sql/protocol.h
index 5a043d9c482..3eb5091a7c7 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -177,7 +177,6 @@ public:
void send_warning(THD *thd, uint sql_errno, const char *err=0);
bool net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
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);
uchar *net_store_data(uchar *to,longlong from);
diff --git a/sql/records.cc b/sql/records.cc
index 2fc5a26a210..10d145fb1e2 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -157,7 +157,8 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
This is the most basic access method of a table using rnd_init,
rnd_next and rnd_end. No indexes are used.
*/
-void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
+
+bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
SQL_SELECT *select,
int use_record_cache, bool print_error,
bool disable_rr_cache)
@@ -205,7 +206,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
info->ref_pos=table->file->ref;
if (!table->file->inited)
- table->file->ha_rnd_init(0);
+ if (table->file->ha_rnd_init_with_error(0))
+ DBUG_RETURN(1);
/*
table->sort.addon_field is checked because if we use addon fields,
@@ -242,7 +244,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
else if (table->sort.record_pointers)
{
DBUG_PRINT("info",("using record_pointers"));
- table->file->ha_rnd_init(0);
+ if (table->file->ha_rnd_init_with_error(0))
+ DBUG_RETURN(1);
info->cache_pos=table->sort.record_pointers;
info->cache_end=info->cache_pos+
table->sort.found_records*info->ref_length;
@@ -253,7 +256,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
{
DBUG_PRINT("info",("using rr_sequential"));
info->read_record=rr_sequential;
- table->file->ha_rnd_init(1);
+ if (table->file->ha_rnd_init_with_error(1))
+ DBUG_RETURN(1);
/* We can use record cache if we don't update dynamic length tables */
if (!table->no_cache &&
(use_record_cache > 0 ||
@@ -271,7 +275,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
!table->file->pushed_cond)
table->file->cond_push(select->cond);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
} /* init_read_record */
@@ -327,6 +331,7 @@ static int rr_quick(READ_RECORD *info)
break;
}
}
+ update_virtual_fields(info->thd, info->table);
return tmp;
}
@@ -346,7 +351,7 @@ static int rr_quick(READ_RECORD *info)
static int rr_index_first(READ_RECORD *info)
{
- int tmp= info->file->index_first(info->record);
+ int tmp= info->file->ha_index_first(info->record);
info->read_record= rr_index;
if (tmp)
tmp= rr_handle_error(info, tmp);
@@ -372,7 +377,7 @@ static int rr_index_first(READ_RECORD *info)
static int rr_index(READ_RECORD *info)
{
- int tmp= info->file->index_next(info->record);
+ int tmp= info->file->ha_index_next(info->record);
if (tmp)
tmp= rr_handle_error(info, tmp);
return tmp;
@@ -382,7 +387,7 @@ static int rr_index(READ_RECORD *info)
int rr_sequential(READ_RECORD *info)
{
int tmp;
- while ((tmp=info->file->rnd_next(info->record)))
+ while ((tmp= info->file->ha_rnd_next(info->record)))
{
/*
rnd_next can return RECORD_DELETED for MyISAM when one thread is
@@ -394,6 +399,8 @@ int rr_sequential(READ_RECORD *info)
break;
}
}
+ if (!tmp)
+ update_virtual_fields(info->thd, info->table);
return tmp;
}
@@ -405,7 +412,7 @@ static int rr_from_tempfile(READ_RECORD *info)
{
if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
return -1; /* End of file */
- if (!(tmp=info->file->rnd_pos(info->record,info->ref_pos)))
+ if (!(tmp= info->file->ha_rnd_pos(info->record,info->ref_pos)))
break;
/* The following is extremely unlikely to happen */
if (tmp == HA_ERR_RECORD_DELETED ||
@@ -456,7 +463,7 @@ static int rr_from_pointers(READ_RECORD *info)
cache_pos= info->cache_pos;
info->cache_pos+= info->ref_length;
- if (!(tmp=info->file->rnd_pos(info->record,cache_pos)))
+ if (!(tmp= info->file->ha_rnd_pos(info->record,cache_pos)))
break;
/* The following is extremely unlikely to happen */
@@ -589,7 +596,7 @@ static int rr_from_cache(READ_RECORD *info)
record=uint3korr(position);
position+=3;
record_pos=info->cache+record*info->reclength;
- if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos)))
+ if ((error=(int16) info->file->ha_rnd_pos(record_pos,info->ref_pos)))
{
record_pos[info->error_offset]=1;
shortstore(record_pos,error);
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
index ee3fc358b60..ffae94f733a 100644
--- a/sql/rpl_filter.cc
+++ b/sql/rpl_filter.cc
@@ -45,6 +45,7 @@ Rpl_filter::~Rpl_filter()
}
+#ifndef MYSQL_CLIENT
/*
Returns true if table should be logged/replicated
@@ -129,6 +130,7 @@ Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables)
!do_table_inited && !wild_do_table_inited);
}
+#endif
/*
Checks whether a db matches some do_db and ignore_db rules
@@ -520,6 +522,13 @@ Rpl_filter::get_wild_ignore_table(String* str)
}
+bool
+Rpl_filter::rewrite_db_is_empty()
+{
+ return rewrite_db.is_empty();
+}
+
+
const char*
Rpl_filter::get_rewrite_db(const char* db, size_t *new_len)
{
diff --git a/sql/rpl_filter.h b/sql/rpl_filter.h
index ff7e4081bb1..88951600e56 100644
--- a/sql/rpl_filter.h
+++ b/sql/rpl_filter.h
@@ -42,7 +42,9 @@ public:
/* Checks - returns true if ok to replicate/log */
- bool tables_ok(const char* db, TABLE_LIST* tables);
+#ifndef MYSQL_CLIENT
+ bool tables_ok(const char* db, TABLE_LIST *tables);
+#endif
bool db_ok(const char* db);
bool db_ok_with_wild_table(const char *db);
@@ -69,6 +71,7 @@ public:
void get_wild_do_table(String* str);
void get_wild_ignore_table(String* str);
+ bool rewrite_db_is_empty();
const char* get_rewrite_db(const char* db, size_t *new_len);
I_List<i_string>* get_do_db();
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 9198832dd3c..3e2d27a012d 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -320,15 +320,18 @@ static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout",
static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size",
&SV::join_buff_size);
static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size");
-static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size",
- offsetof(KEY_CACHE,
- param_block_size));
-static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit",
- offsetof(KEY_CACHE,
- param_division_limit));
-static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold",
- offsetof(KEY_CACHE,
- param_age_threshold));
+static sys_var_key_cache_long sys_key_cache_block_size(&vars,
+ "key_cache_block_size",
+ offsetof(KEY_CACHE,param_block_size));
+static sys_var_key_cache_long sys_key_cache_division_limit(&vars,
+ "key_cache_division_limit",
+ offsetof(KEY_CACHE, param_division_limit));
+static sys_var_key_cache_long sys_key_cache_age_threshold(&vars,
+ "key_cache_age_threshold",
+ offsetof(KEY_CACHE, param_age_threshold));
+static sys_var_key_cache_long sys_key_cache_partitions(&vars,
+ "key_cache_segments",
+ offsetof(KEY_CACHE, param_partitions));
static sys_var_const sys_language(&vars, "language",
OPT_GLOBAL, SHOW_CHAR,
(uchar*) language);
@@ -517,6 +520,9 @@ static sys_var_const sys_protocol_version(&vars, "protocol_version",
static sys_var_thd_ulong sys_read_buff_size(&vars, "read_buffer_size",
&SV::read_buff_size);
static sys_var_opt_readonly sys_readonly(&vars, "read_only", &opt_readonly);
+static sys_var_bool_ptr sys_userstat(&vars, "userstat",
+ &opt_userstat_running);
+
static sys_var_thd_ulong sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size",
&SV::read_rnd_buff_size);
static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment",
@@ -586,9 +592,8 @@ static sys_var_thd_ulong sys_trans_prealloc_size(&vars, "transaction_prealloc_si
&SV::trans_prealloc_size,
0, fix_trans_mem_root);
sys_var_enum_const sys_thread_handling(&vars, "thread_handling",
- &SV::thread_handling,
- &thread_handling_typelib,
- NULL);
+ &thread_handling,
+ &thread_handling_typelib);
#ifdef HAVE_QUERY_CACHE
static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit",
@@ -951,6 +956,9 @@ static sys_var_readonly sys_myisam_mmap_size(&vars, "myisam_mmap_size",
SHOW_LONGLONG,
get_myisam_mmap_size);
+static sys_var_enum_const sys_plugin_maturity(&vars, "plugin_maturity",
+ &plugin_maturity,
+ &plugin_maturity_values);
bool sys_var::check(THD *thd, set_var *var)
{
@@ -1683,12 +1691,6 @@ uchar *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
return (uchar*) enum_names->type_names[*value];
}
-uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type,
- LEX_STRING *base)
-{
- return (uchar*) enum_names->type_names[global_system_variables.*offset];
-}
-
bool sys_var_thd_ulong::check(THD *thd, set_var *var)
{
if (get_unsigned(thd, var, max_system_variables.*offset, GET_ULONG))
@@ -2549,7 +2551,15 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
pthread_mutex_unlock(&LOCK_global_system_variables);
- error= (bool) (ha_resize_key_cache(key_cache));
+ if (offset == offsetof(KEY_CACHE, param_block_size))
+ error= (bool) (ha_resize_key_cache(key_cache));
+ else
+ if (offset == offsetof(KEY_CACHE, param_division_limit) ||
+ offset == offsetof(KEY_CACHE, param_age_threshold))
+ error= (bool) (ha_change_key_cache_param(key_cache));
+ else
+ if (offset == offsetof(KEY_CACHE, param_partitions))
+ error= (bool) (ha_repartition_key_cache(key_cache));
pthread_mutex_lock(&LOCK_global_system_variables);
key_cache->in_init= 0;
@@ -4180,6 +4190,7 @@ static KEY_CACHE *create_key_cache(const char *name, uint length)
key_cache->param_block_size= dflt_key_cache_var.param_block_size;
key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold;
+ key_cache->param_partitions= dflt_key_cache_var.param_partitions;
}
}
DBUG_RETURN(key_cache);
diff --git a/sql/set_var.h b/sql/set_var.h
index c3067ebc42b..54e4ac7e2f1 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -376,21 +376,14 @@ public:
};
-class sys_var_enum_const :public sys_var
+class sys_var_enum_const :public sys_var_enum
{
- ulong SV::*offset;
- TYPELIB *enum_names;
public:
- sys_var_enum_const(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg,
- TYPELIB *typelib, sys_after_update_func func)
- :sys_var(name_arg,func), offset(offset_arg), enum_names(typelib)
- { chain_sys_var(chain); }
- bool check(THD *thd, set_var *var) { return 1; }
- bool update(THD *thd, set_var *var) { return 1; }
- SHOW_TYPE show_type() { return SHOW_CHAR; }
- bool check_update_type(Item_result type) { return 1; }
+ sys_var_enum_const(sys_var_chain *chain, const char *name_arg,
+ uint *value_arg, TYPELIB *typelib)
+ :sys_var_enum(chain, name_arg, value_arg, typelib, 0)
+ { }
bool is_readonly() const { return 1; }
- uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
@@ -1428,6 +1421,7 @@ public:
my_free((uchar*) name, MYF(0));
}
friend bool process_key_caches(process_key_cache_t func);
+ friend int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond);
friend void delete_elements(I_List<NAMED_LIST> *list,
void (*free_element)(const char*, uchar*));
};
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 0f9e2a24a93..023bd57e14f 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6207,9 +6207,44 @@ ER_TOO_MANY_CONCURRENT_TRXS
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED
eng "Non-ASCII separator arguments are not fully supported"
+ER_VCOL_BASED_ON_VCOL
+ eng "A computed column cannot be based on a computed column"
+
+ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+ eng "Function or expression is not allowed for column '%s'"
+
+ER_DATA_CONVERSION_ERROR_FOR_VIRTUAL_COLUMN
+ eng "Generated value for computed column '%s' cannot be converted to type '%s'"
+
+ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN
+ eng "Primary key cannot be defined upon a computed column"
+
+ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+ eng "Key/Index cannot be defined on a non-stored computed column"
+
+ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+ eng "Cannot define foreign key with %s clause on a computed column"
+
+ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN
+ eng "The value specified for computed column '%s' in table '%s' ignored"
+
+ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+ eng "'%s' is not yet supported for computed columns"
+
+ER_CONST_EXPR_IN_VCOL
+ eng "Constant expression in computed column function is not allowed"
+
+ER_ROW_EXPR_FOR_VCOL
+ eng "Expression for computed column cannot return a row"
+
ER_DEBUG_SYNC_TIMEOUT
eng "debug sync point wait timed out"
ger "Debug Sync Point Wartezeit überschritten"
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"
+
+ER_UNKNOWN_OPTION
+ eng "Unknown option '%-.64s'"
+ER_BAD_OPTION_VALUE
+ eng "Incorrect value '%-.64s' for option '%-.64s'"
diff --git a/sql/sp.cc b/sql/sp.cc
index ddddaee2e10..e2e7583b901 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -147,7 +147,8 @@ TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] =
{
{ C_STRING_WITH_LEN("sql_mode") },
{ C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
- "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','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',"
@@ -512,8 +513,9 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
key_copy(key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0], 0, key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
DBUG_RETURN(SP_KEY_NOT_FOUND);
DBUG_RETURN(SP_OK);
@@ -1279,6 +1281,7 @@ sp_drop_db_routines(THD *thd, char *db)
TABLE *table;
int ret;
uint key_len;
+ uchar keybuf[MAX_KEY_LENGTH];
DBUG_ENTER("sp_drop_db_routines");
DBUG_PRINT("enter", ("db: %s", db));
@@ -1288,12 +1291,14 @@ sp_drop_db_routines(THD *thd, char *db)
table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
key_len= table->key_info->key_part[0].store_length;
+ table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW);
+
+
ret= SP_OK;
table->file->ha_index_init(0, 1);
- if (! table->file->index_read_map(table->record[0],
- (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
- (key_part_map)1, HA_READ_KEY_EXACT))
+ if (!table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1,
+ HA_READ_KEY_EXACT))
{
int nxtres;
bool deleted= FALSE;
@@ -1308,9 +1313,8 @@ sp_drop_db_routines(THD *thd, char *db)
nxtres= 0;
break;
}
- } while (! (nxtres= table->file->index_next_same(table->record[0],
- (uchar *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
- key_len)));
+ } while (!(nxtres= table->file->ha_index_next_same(table->record[0],
+ keybuf, key_len)));
if (nxtres != HA_ERR_END_OF_FILE)
ret= SP_KEY_NOT_FOUND;
if (deleted)
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 1084c3efc82..9f9219566d7 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -841,6 +841,8 @@ sp_head::create_result_field(uint field_max_length, const char *field_name,
m_return_field_def.interval,
field_name ? field_name : (const char *) m_name.str);
+ field->vcol_info= m_return_field_def.vcol_info;
+ field->stored_in_db= m_return_field_def.stored_in_db;
if (field)
field->init(table);
@@ -2111,6 +2113,8 @@ sp_head::reset_lex(THD *thd)
sublex->dec= NULL;
sublex->interval_list.empty();
sublex->type= 0;
+ sublex->uint_geom_type= 0;
+ sublex->vcol_info= 0;
DBUG_RETURN(FALSE);
}
@@ -2237,7 +2241,8 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
&lex->interval_list,
lex->charset ? lex->charset :
thd->variables.collation_database,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info, NULL))
return TRUE;
if (field_def->interval_list.elements)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 6e9ec902577..be093b8738e 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -30,6 +30,8 @@
#include <stdarg.h>
#include "sp_head.h"
#include "sp.h"
+#include <sql_common.h>
+#include <mysql/plugin_auth.h>
static const
TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
@@ -148,6 +150,87 @@ TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
const TABLE_FIELD_DEF
mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields};
+static LEX_STRING native_password_plugin_name= {
+ C_STRING_WITH_LEN("mysql_native_password")
+};
+
+static LEX_STRING old_password_plugin_name= {
+ C_STRING_WITH_LEN("mysql_old_password")
+};
+
+/// @todo make it configurable
+LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
+
+static plugin_ref native_password_plugin;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+static plugin_ref old_password_plugin;
+#endif
+
+/* Classes */
+
+struct acl_host_and_ip
+{
+ char *hostname;
+ long ip,ip_mask; // Used with masked ip:s
+};
+
+class ACL_ACCESS {
+public:
+ ulong sort;
+ ulong access;
+};
+
+/* ACL_HOST is used if no host is specified */
+
+class ACL_HOST :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *db;
+};
+
+class ACL_USER :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ uint hostname_length;
+ USER_RESOURCES user_resource;
+ char *user;
+ uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
+ uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 4.0, 20 - 4.1.1
+ enum SSL_type ssl_type;
+ const char *ssl_cipher, *x509_issuer, *x509_subject;
+ LEX_STRING plugin;
+ LEX_STRING auth_string;
+
+ ACL_USER *copy(MEM_ROOT *root)
+ {
+ ACL_USER *dst= (ACL_USER *)alloc_root(root, sizeof(ACL_USER));
+ if (!dst)
+ return 0;
+ *dst= *this;
+ dst->user= safe_strdup_root(root, user);
+ dst->ssl_cipher= safe_strdup_root(root, ssl_cipher);
+ dst->x509_issuer= safe_strdup_root(root, x509_issuer);
+ dst->x509_subject= safe_strdup_root(root, x509_subject);
+ if (plugin.str == native_password_plugin_name.str ||
+ plugin.str == old_password_plugin_name.str)
+ dst->plugin= plugin;
+ else
+ dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
+ dst->auth_string.str = safe_strdup_root(root, auth_string.str);
+ dst->host.hostname= safe_strdup_root(root, host.hostname);
+ return dst;
+ }
+};
+
+class ACL_DB :public ACL_ACCESS
+{
+public:
+ acl_host_and_ip host;
+ char *user,*db;
+};
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#define FIRST_NON_YN_FIELD 26
@@ -171,6 +254,24 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length,
#define IP_ADDR_STRLEN (3+1+3+1+3+1+3)
#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1)
+#if defined(HAVE_OPENSSL)
+/*
+ Without SSL the handshake consists of one packet. This packet
+ has both client capabilites and scrambled password.
+ With SSL the handshake might consist of two packets. If the first
+ packet (client capabilities) has CLIENT_SSL flag set, we have to
+ switch to SSL and read the second packet. The scrambled password
+ is in the second packet and client_capabilites field will be ignored.
+ Maybe it is better to accept flags other than CLIENT_SSL from the
+ second packet?
+*/
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
+#else
+#define MIN_HANDSHAKE_SIZE 6
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
+
static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
static bool initialized=0;
@@ -186,9 +287,8 @@ static void init_check_host(void);
static void rebuild_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user,
my_bool exact);
-static bool update_user_table(THD *thd, TABLE *table,
- const char *host, const char *user,
- const char *new_password, uint new_password_len);
+static bool update_user_table(THD *, TABLE *, const char *, const char *,
+ const char *, uint);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
@@ -218,6 +318,48 @@ set_user_salt(ACL_USER *acl_user, const char *password, uint password_len)
acl_user->salt_len= 0;
}
+static char *fix_plugin_ptr(char *name)
+{
+ if (my_strcasecmp(system_charset_info, name,
+ native_password_plugin_name.str) == 0)
+ return native_password_plugin_name.str;
+ else
+ if (my_strcasecmp(system_charset_info, name,
+ old_password_plugin_name.str) == 0)
+ return old_password_plugin_name.str;
+ else
+ return name;
+}
+
+/**
+ Fix ACL::plugin pointer to point to a hard-coded string, if appropriate
+
+ Make sure that if ACL_USER's plugin is a built-in, then it points
+ to a hard coded string, not to an allocated copy. Run-time, for
+ authentication, we want to be able to detect built-ins by comparing
+ pointers, not strings.
+
+ Additionally - update the salt if the plugin is built-in.
+
+ @retval 0 the pointers were fixed
+ @retval 1 this ACL_USER uses a not built-in plugin
+*/
+static bool fix_user_plugin_ptr(ACL_USER *user)
+{
+ if (my_strcasecmp(system_charset_info, user->plugin.str,
+ native_password_plugin_name.str) == 0)
+ user->plugin= native_password_plugin_name;
+ else
+ if (my_strcasecmp(system_charset_info, user->plugin.str,
+ old_password_plugin_name.str) == 0)
+ user->plugin= old_password_plugin_name;
+ else
+ return true;
+
+ set_user_salt(user, user->auth_string.str, user->auth_string.length);
+ return false;
+}
+
/*
This after_update function is used when user.password is less than
SCRAMBLE_LENGTH bytes.
@@ -265,6 +407,19 @@ my_bool acl_init(bool dont_read_acl_tables)
(hash_get_key) acl_entry_get_key,
(hash_free_key) free,
&my_charset_utf8_bin);
+
+ /*
+ cache built-in native authentication plugins,
+ to avoid hash searches and a global mutex lock on every connect
+ */
+ native_password_plugin= my_plugin_lock_by_name(0,
+ &native_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
+ old_password_plugin= my_plugin_lock_by_name(0,
+ &old_password_plugin_name, MYSQL_AUTHENTICATION_PLUGIN);
+
+ if (!native_password_plugin || !old_password_plugin)
+ DBUG_RETURN(1);
+
if (dont_read_acl_tables)
{
DBUG_RETURN(0); /* purecov: tested */
@@ -324,8 +479,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
acl_cache->clear(1); // Clear locked hostname cache
init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
- init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0,
- FALSE);
+ if (init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0,
+ FALSE))
+ goto end;
+
table->use_all_columns();
VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50));
while (!(read_record_info.read_record(&read_record_info)))
@@ -374,7 +531,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
end_read_record(&read_record_info);
freeze_size(&acl_hosts);
- init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE);
+ if (init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,
+ FALSE))
+ goto end;
+
table->use_all_columns();
VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100));
password_length= table->field[2]->field_length /
@@ -422,6 +582,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
+ char *password;
+ uint password_len;
+
+ bzero(&user, sizeof(user));
update_hostname(&user.host, get_field(&mem, table->field[0]));
user.user= get_field(&mem, table->field[1]);
if (check_no_resolve && hostname_requires_resolving(user.host.hostname))
@@ -433,27 +597,34 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
continue;
}
- const char *password= get_field(thd->mem_root, table->field[2]);
- uint password_len= password ? strlen(password) : 0;
+ password= get_field(&mem, table->field[2]);
+ password_len= password ? strlen(password) : 0;
+ user.auth_string.str= password ? password : const_cast<char*>("");
+ user.auth_string.length= password_len;
set_user_salt(&user, password, password_len);
- if (user.salt_len == 0 && password_len != 0)
- {
- switch (password_len) {
- case 45: /* 4.1: to be removed */
- sql_print_warning("Found 4.1 style password for user '%s@%s'. "
- "Ignoring user. "
- "You should change password for this user.",
- user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : "");
- break;
- default:
- sql_print_warning("Found invalid password for user: '%s@%s'; "
- "Ignoring user", user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : "");
- break;
- }
+
+ switch (password_len) {
+ case 0: /* no password */
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH:
+ user.plugin= native_password_plugin_name;
+ break;
+ case SCRAMBLED_PASSWORD_CHAR_LENGTH_323:
+ user.plugin= old_password_plugin_name;
+ break;
+ case 45: /* 4.1: to be removed */
+ sql_print_warning("Found 4.1.0 style password for user '%s@%s'. "
+ "Ignoring user. "
+ "You should change password for this user.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ continue;
+ default:
+ sql_print_warning("Found invalid password for user: '%s@%s'; "
+ "Ignoring user", user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ continue;
}
- else // password is correct
+
{
uint next_field;
user.access= get_access(table,3,&next_field) & GLOBAL_ACLS;
@@ -530,13 +701,35 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
ptr= get_field(thd->mem_root, table->field[next_field++]);
user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
}
- else
- user.user_resource.user_conn= 0;
+
+ if (table->s->fields >= 41)
+ {
+ /* We may have plugin & auth_String fields */
+ char *tmpstr= get_field(&mem, table->field[next_field++]);
+ if (tmpstr)
+ {
+ user.plugin.str= tmpstr;
+ user.plugin.length= strlen(user.plugin.str);
+ if (user.auth_string.length)
+ {
+ sql_print_warning("'user' entry '%s@%s' has both a password "
+ "and an authentication plugin specified. The "
+ "password will be ignored.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ }
+ user.auth_string.str= get_field(&mem, table->field[next_field++]);
+ if (!user.auth_string.str)
+ user.auth_string.str= const_cast<char*>("");
+ user.auth_string.length= strlen(user.auth_string.str);
+
+ fix_user_plugin_ptr(&user);
+ }
+ }
}
else
{
user.ssl_type=SSL_TYPE_NONE;
- bzero((char *)&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED
if (table->s->fields <= 13)
{ // Without grant
@@ -562,7 +755,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
end_read_record(&read_record_info);
freeze_size(&acl_users);
- init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE);
+ if (init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,
+ FALSE))
+ goto end;
+
table->use_all_columns();
VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100));
while (!(read_record_info.read_record(&read_record_info)))
@@ -639,6 +835,8 @@ void acl_free(bool end)
delete_dynamic(&acl_dbs);
delete_dynamic(&acl_wild_hosts);
hash_free(&acl_check_hosts);
+ plugin_unlock(0, native_password_plugin);
+ plugin_unlock(0, old_password_plugin);
if (!end)
acl_cache->clear(1); /* purecov: inspected */
else
@@ -841,246 +1039,10 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
/*
- Seek ACL entry for a user, check password, SSL cypher, and if
- everything is OK, update THD user data and USER_RESOURCES struct.
-
- IMPLEMENTATION
- This function does not check if the user has any sensible privileges:
- only user's existence and validity is checked.
- Note, that entire operation is protected by acl_cache_lock.
+ Gets user credentials without authentication and resource limit checks.
SYNOPSIS
acl_getroot()
- thd thread handle. If all checks are OK,
- thd->security_ctx->priv_user/master_access are updated.
- thd->security_ctx->host/ip/user are used for checks.
- mqh user resources; on success mqh is reset, else
- unchanged
- passwd scrambled & crypted password, received from client
- (to check): thd->scramble or thd->scramble_323 is
- used to decrypt passwd, so they must contain
- original random string,
- passwd_len length of passwd, must be one of 0, 8,
- SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
- 'thd' and 'mqh' are updated on success; other params are IN.
-
- RETURN VALUE
- 0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
- updated
- 1 user not found or authentication failure
- 2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
- -1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
-*/
-
-int acl_getroot(THD *thd, USER_RESOURCES *mqh,
- const char *passwd, uint passwd_len)
-{
- ulong user_access= NO_ACCESS;
- int res= 1;
- ACL_USER *acl_user= 0;
- Security_context *sctx= thd->security_ctx;
- DBUG_ENTER("acl_getroot");
-
- if (!initialized)
- {
- /*
- here if mysqld's been started with --skip-grant-tables option.
- */
- sctx->skip_grants();
- bzero((char*) mqh, sizeof(*mqh));
- DBUG_RETURN(0);
- }
-
- VOID(pthread_mutex_lock(&acl_cache->lock));
-
- /*
- Find acl entry in user database. Note, that find_acl_user is not the same,
- because it doesn't take into account the case when user is not empty,
- but acl_user->user is empty
- */
-
- for (uint i=0 ; i < acl_users.elements ; i++)
- {
- ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
- if (!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user))
- {
- if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
- {
- /* check password: it should be empty or valid */
- if (passwd_len == acl_user_tmp->salt_len)
- {
- if (acl_user_tmp->salt_len == 0 ||
- (acl_user_tmp->salt_len == SCRAMBLE_LENGTH ?
- check_scramble(passwd, thd->scramble, acl_user_tmp->salt) :
- check_scramble_323(passwd, thd->scramble,
- (ulong *) acl_user_tmp->salt)) == 0)
- {
- acl_user= acl_user_tmp;
- res= 0;
- }
- }
- else if (passwd_len == SCRAMBLE_LENGTH &&
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH_323)
- res= -1;
- else if (passwd_len == SCRAMBLE_LENGTH_323 &&
- acl_user_tmp->salt_len == SCRAMBLE_LENGTH)
- res= 2;
- /* linear search complete: */
- break;
- }
- }
- }
- /*
- This was moved to separate tree because of heavy HAVE_OPENSSL case.
- If acl_user is not null, res is 0.
- */
-
- if (acl_user)
- {
- /* OK. User found and password checked continue validation */
-#ifdef HAVE_OPENSSL
- Vio *vio=thd->net.vio;
- SSL *ssl= (SSL*) vio->ssl_arg;
- X509 *cert;
-#endif
-
- /*
- At this point we know that user is allowed to connect
- from given host by given username/password pair. Now
- we check if SSL is required, if user is using SSL and
- if X509 certificate attributes are OK
- */
- switch (acl_user->ssl_type) {
- case SSL_TYPE_NOT_SPECIFIED: // Impossible
- case SSL_TYPE_NONE: // SSL is not required
- user_access= acl_user->access;
- break;
-#ifdef HAVE_OPENSSL
- case SSL_TYPE_ANY: // Any kind of SSL is ok
- if (vio_type(vio) == VIO_TYPE_SSL)
- user_access= acl_user->access;
- break;
- case SSL_TYPE_X509: /* Client should have any valid certificate. */
- /*
- Connections with non-valid certificates are dropped already
- in sslaccept() anyway, so we do not check validity here.
-
- We need to check for absence of SSL because without SSL
- we should reject connection.
- */
- if (vio_type(vio) == VIO_TYPE_SSL &&
- SSL_get_verify_result(ssl) == X509_V_OK &&
- (cert= SSL_get_peer_certificate(ssl)))
- {
- user_access= acl_user->access;
- X509_free(cert);
- }
- break;
- case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
- /*
- We do not check for absence of SSL because without SSL it does
- not pass all checks here anyway.
- If cipher name is specified, we compare it to actual cipher in
- use.
- */
- if (vio_type(vio) != VIO_TYPE_SSL ||
- SSL_get_verify_result(ssl) != X509_V_OK)
- break;
- if (acl_user->ssl_cipher)
- {
- DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
- acl_user->ssl_cipher,SSL_get_cipher(ssl)));
- if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl)))
- user_access= acl_user->access;
- else
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
- acl_user->ssl_cipher,
- SSL_get_cipher(ssl));
- break;
- }
- }
- /* Prepare certificate (if exists) */
- DBUG_PRINT("info",("checkpoint 1"));
- if (!(cert= SSL_get_peer_certificate(ssl)))
- {
- user_access=NO_ACCESS;
- break;
- }
- DBUG_PRINT("info",("checkpoint 2"));
- /* If X509 issuer is specified, we check it... */
- if (acl_user->x509_issuer)
- {
- DBUG_PRINT("info",("checkpoint 3"));
- char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
- acl_user->x509_issuer, ptr));
- if (strcmp(acl_user->x509_issuer, ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 issuer mismatch: should be '%s' "
- "but is '%s'", acl_user->x509_issuer, ptr);
- free(ptr);
- X509_free(cert);
- user_access=NO_ACCESS;
- break;
- }
- user_access= acl_user->access;
- free(ptr);
- }
- DBUG_PRINT("info",("checkpoint 4"));
- /* X509 subject is specified, we check it .. */
- if (acl_user->x509_subject)
- {
- char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
- acl_user->x509_subject, ptr));
- if (strcmp(acl_user->x509_subject,ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
- acl_user->x509_subject, ptr);
- free(ptr);
- X509_free(cert);
- user_access=NO_ACCESS;
- break;
- }
- user_access= acl_user->access;
- free(ptr);
- }
- /* Deallocate the X509 certificate. */
- X509_free(cert);
- break;
-#else /* HAVE_OPENSSL */
- default:
- /*
- If we don't have SSL but SSL is required for this user the
- authentication should fail.
- */
- break;
-#endif /* HAVE_OPENSSL */
- }
- sctx->master_access= user_access;
- sctx->priv_user= acl_user->user ? sctx->user : (char *) "";
- *mqh= acl_user->user_resource;
-
- if (acl_user->host.hostname)
- strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
- else
- *sctx->priv_host= 0;
- }
- VOID(pthread_mutex_unlock(&acl_cache->lock));
- DBUG_RETURN(res);
-}
-
-
-/*
- This is like acl_getroot() above, but it doesn't check password,
- and we don't care about the user resources.
-
- SYNOPSIS
- acl_getroot_no_password()
sctx Context which should be initialized
user user name
host host name
@@ -1092,13 +1054,13 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
TRUE Error
*/
-bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
- char *ip, char *db)
+bool acl_getroot(Security_context *sctx, char *user, char *host,
+ char *ip, char *db)
{
int res= 1;
uint i;
ACL_USER *acl_user= 0;
- DBUG_ENTER("acl_getroot_no_password");
+ DBUG_ENTER("acl_getroot");
DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'",
(host ? host : "(NULL)"), (ip ? ip : "(NULL)"),
@@ -1121,8 +1083,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
sctx->master_access= 0;
sctx->db_access= 0;
- sctx->priv_user= (char *) "";
- *sctx->priv_host= 0;
+ *sctx->priv_user= *sctx->priv_host= 0;
/*
Find acl entry in user database.
@@ -1164,7 +1125,11 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
}
}
sctx->master_access= acl_user->access;
- sctx->priv_user= acl_user->user ? user : (char *) "";
+
+ if (acl_user->user)
+ strmake(sctx->priv_user, user, USERNAME_LENGTH);
+ else
+ *sctx->priv_user= 0;
if (acl_user->host.hostname)
strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME - 1);
@@ -1190,7 +1155,9 @@ static void acl_update_user(const char *user, const char *host,
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- ulong privileges)
+ ulong privileges,
+ const LEX_STRING *plugin,
+ const LEX_STRING *auth)
{
safe_mutex_assert_owner(&acl_cache->lock);
@@ -1204,6 +1171,22 @@ static void acl_update_user(const char *user, const char *host,
(acl_user->host.hostname &&
!my_strcasecmp(system_charset_info, host, acl_user->host.hostname)))
{
+ if (plugin->str[0])
+ {
+ acl_user->plugin= *plugin;
+ acl_user->auth_string.str= auth->str ?
+ strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
+ acl_user->auth_string.length= auth->length;
+ if (fix_user_plugin_ptr(acl_user))
+ acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
+ }
+ else
+ if (password)
+ {
+ acl_user->auth_string.str= strmake_root(&mem, password, password_len);
+ acl_user->auth_string.length= password_len;
+ set_user_salt(acl_user, password, password_len);
+ }
acl_user->access=privileges;
if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
acl_user->user_resource.questions=mqh->questions;
@@ -1223,8 +1206,6 @@ static void acl_update_user(const char *user, const char *host,
acl_user->x509_subject= (x509_subject ?
strdup_root(&mem,x509_subject) : 0);
}
- if (password)
- set_user_salt(acl_user, password, password_len);
/* search complete: */
break;
}
@@ -1240,7 +1221,9 @@ static void acl_insert_user(const char *user, const char *host,
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- ulong privileges)
+ ulong privileges,
+ const LEX_STRING *plugin,
+ const LEX_STRING *auth)
{
ACL_USER acl_user;
@@ -1248,6 +1231,24 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.user=*user ? strdup_root(&mem,user) : 0;
update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0);
+ if (plugin->str[0])
+ {
+ acl_user.plugin= *plugin;
+ acl_user.auth_string.str= auth->str ?
+ strmake_root(&mem, auth->str, auth->length) : const_cast<char*>("");
+ acl_user.auth_string.length= auth->length;
+ if (fix_user_plugin_ptr(&acl_user))
+ acl_user.plugin.str= strmake_root(&mem, plugin->str, plugin->length);
+ }
+ else
+ {
+ acl_user.plugin= password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323 ?
+ old_password_plugin_name : native_password_plugin_name;
+ acl_user.auth_string.str= strmake_root(&mem, password, password_len);
+ acl_user.auth_string.length= password_len;
+ set_user_salt(&acl_user, password, password_len);
+ }
+
acl_user.access=privileges;
acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@@ -1258,8 +1259,6 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
- set_user_salt(&acl_user, password, password_len);
-
VOID(push_dynamic(&acl_users,(uchar*) &acl_user));
if (!acl_user.host.hostname ||
(acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1]))
@@ -1637,7 +1636,13 @@ bool change_password(THD *thd, const char *host, const char *user,
goto end;
}
/* update loaded acl entry: */
- set_user_salt(acl_user, new_password, new_password_len);
+ if (acl_user->plugin.str == native_password_plugin_name.str ||
+ acl_user->plugin.str == old_password_plugin_name.str)
+ {
+ acl_user->auth_string.str= strmake_root(&mem, new_password, new_password_len);
+ acl_user->auth_string.length= new_password_len;
+ set_user_salt(acl_user, new_password, new_password_len);
+ }
if (update_user_table(thd, table,
acl_user->host.hostname ? acl_user->host.hostname : "",
@@ -1839,9 +1844,9 @@ static bool update_user_table(THD *thd, TABLE *table,
key_copy((uchar *) user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx_map(table->record[0], 0,
- (uchar *) user_key, HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar *) user_key, HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
MYF(0)); /* purecov: deadcode */
@@ -1932,9 +1937,9 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx_map(table->record[0], 0, user_key,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0], 0, user_key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
/* what == 'N' means revoke */
if (what == 'N')
@@ -1966,6 +1971,15 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
thd->security_ctx->user, thd->security_ctx->host_or_ip);
goto end;
}
+ else if (combo.plugin.str[0])
+ {
+ if (!plugin_is_ready(&combo.plugin, MYSQL_AUTHENTICATION_PLUGIN))
+ {
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo.plugin.str);
+ goto end;
+ }
+ }
+
old_row_exists = 0;
restore_record(table,s->default_values);
table->field[0]->store(combo.host.str,combo.host.length,
@@ -1979,7 +1993,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
{
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
- if (combo.password.str) // If password given
+ if (combo.password.str) // If password given
table->field[2]->store(password, password_len, system_charset_info);
else if (!rights && !revoke_grant &&
lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
@@ -2060,7 +2074,17 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE);
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
+
+ next_field+=4;
+ if (table->s->fields >= 41 && combo.plugin.str[0])
+ {
+ table->field[next_field]->store(combo.plugin.str, combo.plugin.length,
+ system_charset_info);
+ table->field[next_field+1]->store(combo.auth.str, combo.auth.length,
+ system_charset_info);
+ }
}
+
if (old_row_exists)
{
/*
@@ -2104,7 +2128,9 @@ end:
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
- rights);
+ rights,
+ &combo.plugin,
+ &combo.auth);
else
acl_insert_user(combo.user.str, combo.host.str, password, password_len,
lex->ssl_type,
@@ -2112,7 +2138,9 @@ end:
lex->x509_issuer,
lex->x509_subject,
&lex->mqh,
- rights);
+ rights,
+ &combo.plugin,
+ &combo.auth);
}
DBUG_RETURN(error);
}
@@ -2156,9 +2184,9 @@ static int replace_db_table(TABLE *table, const char *db,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx_map(table->record[0],0, user_key,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0],0, user_key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
if (what == 'N')
{ // no row, no revoke
@@ -2390,8 +2418,9 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
col_privs->field[4]->store("",0, &my_charset_latin1);
col_privs->file->ha_index_init(0, 1);
- if (col_privs->file->index_read_map(col_privs->record[0], (uchar*) key,
- (key_part_map)15, HA_READ_KEY_EXACT))
+ if (col_privs->file->ha_index_read_map(col_privs->record[0], (uchar*) key,
+ (key_part_map)15,
+ HA_READ_KEY_EXACT))
{
cols = 0; /* purecov: deadcode */
col_privs->file->ha_index_end();
@@ -2417,7 +2446,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
privs= cols= 0;
return;
}
- } while (!col_privs->file->index_next(col_privs->record[0]) &&
+ } while (!col_privs->file->ha_index_next(col_privs->record[0]) &&
!key_cmp_if_same(col_privs,key,0,key_prefix_len));
col_privs->file->ha_index_end();
}
@@ -2561,8 +2590,8 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_map(table->record[0], user_key, HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_map(table->record[0], user_key,
+ HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
if (revoke_grant)
{
@@ -2643,9 +2672,9 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_copy(user_key, table->record[0], table->key_info,
key_prefix_length);
- if (table->file->index_read_map(table->record[0], user_key,
- (key_part_map)15,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_map(table->record[0], user_key,
+ (key_part_map)15,
+ HA_READ_KEY_EXACT))
goto end;
/* Scan through all rows with the same host,db,user and table */
@@ -2696,7 +2725,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
hash_delete(&g_t->hash_columns,(uchar*) grant_column);
}
}
- } while (!table->file->index_next(table->record[0]) &&
+ } while (!table->file->ha_index_next(table->record[0]) &&
!key_cmp_if_same(table, key, 0, key_prefix_length));
}
@@ -2746,9 +2775,9 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
- if (table->file->index_read_idx_map(table->record[0], 0, user_key,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0], 0, user_key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
/*
The following should never happen as we first check the in memory
@@ -2873,10 +2902,10 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
TRUE);
store_record(table,record[1]); // store at pos 1
- if (table->file->index_read_idx_map(table->record[0], 0,
- (uchar*) table->field[0]->ptr,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar*) table->field[0]->ptr,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
/*
The following should never happen as we first check the in memory
@@ -3620,7 +3649,7 @@ static my_bool grant_load_procs_priv(TABLE *p_table)
p_table->file->ha_index_init(0, 1);
p_table->use_all_columns();
- if (!p_table->file->index_first(p_table->record[0]))
+ if (!p_table->file->ha_index_first(p_table->record[0]))
{
memex_ptr= &memex;
my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr);
@@ -3672,7 +3701,7 @@ static my_bool grant_load_procs_priv(TABLE *p_table)
goto end_unlock;
}
}
- while (!p_table->file->index_next(p_table->record[0]));
+ while (!p_table->file->ha_index_next(p_table->record[0]));
}
/* Return ok */
return_val= 0;
@@ -3722,7 +3751,7 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables)
t_table->use_all_columns();
c_table->use_all_columns();
- if (!t_table->file->index_first(t_table->record[0]))
+ if (!t_table->file->ha_index_first(t_table->record[0]))
{
memex_ptr= &memex;
my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr);
@@ -3757,7 +3786,7 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables)
goto end_unlock;
}
}
- while (!t_table->file->index_next(t_table->record[0]));
+ while (!t_table->file->ha_index_next(t_table->record[0]));
}
return_val=0; // Return ok
@@ -4029,6 +4058,8 @@ err:
{
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
+ status_var_increment(thd->status_var.access_denied_errors);
+
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
command,
sctx->priv_user,
@@ -4442,16 +4473,14 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name,
ulong get_table_grant(THD *thd, TABLE_LIST *table)
{
ulong privilege;
-#ifndef EMBEDDED_LIBRARY
- Security_context *sctx= thd->security_ctx;
- const char *db = table->db ? table->db : thd->db;
-#endif
GRANT_TABLE *grant_table;
rw_rdlock(&LOCK_grant);
#ifdef EMBEDDED_LIBRARY
grant_table= NULL;
#else
+ Security_context *sctx= thd->security_ctx;
+ const char *db = table->db ? table->db : thd->db;
grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user,
table->table_name, 0);
#endif
@@ -4644,16 +4673,27 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(lex_user->host.str,lex_user->host.length,
system_charset_info);
global.append ('\'');
- if (acl_user->salt_len)
+ if (acl_user->plugin.str == native_password_plugin_name.str ||
+ acl_user->plugin.str == old_password_plugin_name.str)
{
- char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
- if (acl_user->salt_len == SCRAMBLE_LENGTH)
- make_password_from_salt(passwd_buff, acl_user->salt);
- else
- make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
- global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
- global.append(passwd_buff);
- global.append('\'');
+ if (acl_user->auth_string.length)
+ {
+ DBUG_ASSERT(acl_user->salt_len);
+ global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
+ global.append(acl_user->auth_string.str, acl_user->auth_string.length);
+ global.append('\'');
+ }
+ }
+ else
+ {
+ global.append(STRING_WITH_LEN(" IDENTIFIED VIA "));
+ global.append(acl_user->plugin.str, acl_user->plugin.length);
+ if (acl_user->auth_string.length)
+ {
+ global.append(STRING_WITH_LEN(" USING '"));
+ global.append(acl_user->auth_string.str, acl_user->auth_string.length);
+ global.append('\'');
+ }
}
/* "show grants" SSL related stuff */
if (acl_user->ssl_type == SSL_TYPE_ANY)
@@ -5276,9 +5316,9 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
table->key_info->key_part[1].store_length);
key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
- if ((error= table->file->index_read_idx_map(table->record[0], 0,
- user_key, (key_part_map)3,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
+ user_key, (key_part_map)3,
+ HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
@@ -5313,7 +5353,7 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'",
table->s->table_name.str, user_str, host_str));
#endif
- while ((error= table->file->rnd_next(table->record[0])) !=
+ while ((error= table->file->ha_rnd_next(table->record[0])) !=
HA_ERR_END_OF_FILE)
{
if (error)
@@ -5458,7 +5498,7 @@ static int handle_grant_struct(uint struct_no, bool drop,
host= grant_name->host.hostname;
break;
default:
- assert(0);
+ DBUG_ASSERT(0);
}
if (! user)
user= "";
@@ -6327,38 +6367,44 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
tables->db= (char*)sp_db;
tables->table_name= tables->alias= (char*)sp_name;
- combo->host.length= strlen(combo->host.str);
- combo->user.length= strlen(combo->user.str);
- combo->host.str= thd->strmake(combo->host.str,combo->host.length);
- combo->user.str= thd->strmake(combo->user.str,combo->user.length);
+ thd->make_lex_string(&combo->user,
+ combo->user.str, strlen(combo->user.str), 0);
+ thd->make_lex_string(&combo->host,
+ combo->host.str, strlen(combo->host.str), 0);
+ combo->password= empty_lex_str;
+ combo->plugin= empty_lex_str;
+ combo->auth= empty_lex_str;
- if(au && au->salt_len)
+ if(au)
{
- if (au->salt_len == SCRAMBLE_LENGTH)
- {
- make_password_from_salt(passwd_buff, au->salt);
- combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
- }
- else if (au->salt_len == SCRAMBLE_LENGTH_323)
+ if (au->salt_len)
{
- make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
- combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ if (au->salt_len == SCRAMBLE_LENGTH)
+ {
+ make_password_from_salt(passwd_buff, au->salt);
+ combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+ }
+ else if (au->salt_len == SCRAMBLE_LENGTH_323)
+ {
+ make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
+ combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ }
+ else
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
+ ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ return TRUE;
+ }
+ combo->password.str= passwd_buff;
}
- else
+
+ if (au->plugin.str != native_password_plugin_name.str &&
+ au->plugin.str != old_password_plugin_name.str)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PASSWD_LENGTH,
- ER(ER_PASSWD_LENGTH),
- SCRAMBLED_PASSWORD_CHAR_LENGTH);
- return TRUE;
+ combo->plugin= au->plugin;
+ combo->auth= au->auth_string;
}
- combo->password.str= passwd_buff;
- }
- else
- {
- combo->password.str= (char*)"";
- combo->password.length= 0;
}
if (user_list.push_back(combo))
@@ -6852,3 +6898,1470 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name,
}
#endif
+
+/****************************************************************************
+ AUTHENTICATION CODE
+ including initial connect handshake, invoking appropriate plugins,
+ client-server plugin negotiation, COM_CHANGE_USER, and native
+ MySQL authentication plugins.
+****************************************************************************/
+
+/* few defines to have less ifdef's in the code below */
+#ifdef EMBEDDED_LIBRARY
+#undef HAVE_OPENSSL
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+#define initialized 0
+#define decrease_user_connections(X) /* nothing */
+#define check_for_max_user_connections(X,Y) 0
+#define get_or_create_user_conn(A,B,C,D) 0
+#endif
+#endif
+#ifndef HAVE_OPENSSL
+#define ssl_acceptor_fd 0
+#define sslaccept(A,B,C,D) 1
+#define NORMAL_HANDSHAKE_SIZE 6
+#endif
+
+/**
+ The internal version of what plugins know as MYSQL_PLUGIN_VIO,
+ basically the context of the authentication session
+*/
+struct MPVIO_EXT : public MYSQL_PLUGIN_VIO
+{
+ MYSQL_SERVER_AUTH_INFO auth_info;
+ THD *thd;
+ ACL_USER *acl_user; ///< a copy, independent from acl_users array
+ plugin_ref plugin; ///< what plugin we're under
+ LEX_STRING db; ///< db name from the handshake packet
+ /** when restarting a plugin this caches the last client reply */
+ struct {
+ char *plugin, *pkt; ///< pointers into NET::buff
+ uint pkt_len;
+ } cached_client_reply;
+ /** this caches the first plugin packet for restart request on the client */
+ struct {
+ char *pkt;
+ uint pkt_len;
+ } cached_server_packet;
+ int packets_read, packets_written; ///< counters for send/received packets
+ uint connect_errors; ///< if there were connect errors for this host
+ /** when plugin returns a failure this tells us what really happened */
+ enum { SUCCESS, FAILURE, RESTART } status;
+};
+
+
+/**
+ a helper function to report an access denied error in all the proper places
+*/
+
+static void login_failed_error(THD *thd, bool passwd_used)
+{
+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ status_var_increment(thd->status_var.access_denied_errors);
+ /*
+ Log access denied messages to the error log when log-warnings = 2
+ so that the overhead of the general query log is not required to track
+ failed connections.
+ */
+ if (global_system_variables.log_warnings > 1)
+ {
+ sql_print_warning(ER(ER_ACCESS_DENIED_ERROR),
+ thd->main_security_ctx.user,
+ thd->main_security_ctx.host_or_ip,
+ passwd_used ? ER(ER_YES) : ER(ER_NO));
+ }
+}
+
+
+/**
+ sends a server handshake initialization packet, the very first packet
+ after the connection was established
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ 1 protocol version (always 10)
+ n server version string, \0-terminated
+ 4 thread id
+ 8 first 8 bytes of the plugin provided data (scramble)
+ 1 \0 byte, terminating the first part of a scramble
+ 2 server capabilities (two lower bytes)
+ 1 server character set
+ 2 server status
+ 2 server capabilities (two upper bytes)
+ 1 length of the scramble
+ 10 reserved, always 0
+ n rest of the plugin provided data (at least 12 bytes)
+ 1 \0 byte, terminating the second part of a scramble
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static bool send_server_handshake_packet(MPVIO_EXT *mpvio,
+ const char *data, uint data_len)
+{
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
+ DBUG_ASSERT(data_len <= 255);
+
+ THD *thd= mpvio->thd;
+ char *buff= (char *)my_alloca(1 + SERVER_VERSION_LENGTH + 1 + data_len + 64);
+ char scramble_buf[SCRAMBLE_LENGTH];
+ char *end= buff;
+
+ *end++= protocol_version;
+
+ thd->client_capabilities= CLIENT_BASIC_FLAGS;
+
+ if (data_len)
+ {
+ mpvio->cached_server_packet.pkt= (char*)thd->memdup(data, data_len);
+ mpvio->cached_server_packet.pkt_len= data_len;
+ }
+
+ if (data_len < SCRAMBLE_LENGTH)
+ {
+ if (data_len)
+ { /*
+ the first packet *must* have at least 20 bytes of a scramble.
+ if a plugin provided less, we pad it to 20 with zeros
+ */
+ memcpy(scramble_buf, data, data_len);
+ bzero(scramble_buf+data_len, SCRAMBLE_LENGTH-data_len);
+ data= scramble_buf;
+ }
+ else
+ {
+ /*
+ if the default plugin does not provide the data for the scramble at
+ all, we generate a scramble internally anyway, just in case the
+ user account (that will be known only later) uses a
+ native_password_plugin (which needs a scramble). If we don't send a
+ scramble now - wasting 20 bytes in the packet -
+ native_password_plugin will have to send it in a separate packet,
+ adding one more round trip.
+ */
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+ data= thd->scramble;
+ }
+ data_len= SCRAMBLE_LENGTH;
+ }
+
+ if (opt_using_transactions)
+ thd->client_capabilities|= CLIENT_TRANSACTIONS;
+
+ thd->client_capabilities|= CAN_CLIENT_COMPRESS;
+
+ if (ssl_acceptor_fd)
+ {
+ thd->client_capabilities |= CLIENT_SSL;
+ thd->client_capabilities |= CLIENT_SSL_VERIFY_SERVER_CERT;
+ }
+
+ end= strnmov(end, server_version, SERVER_VERSION_LENGTH) + 1;
+ int4store((uchar*) end, mpvio->thd->thread_id);
+ end+= 4;
+
+ /*
+ Old clients does not understand long scrambles, but can ignore packet
+ tail: that's why first part of the scramble is placed here, and second
+ part at the end of packet.
+ */
+ end= (char*)memcpy(end, data, SCRAMBLE_LENGTH_323);
+ end+= SCRAMBLE_LENGTH_323;
+ *end++= 0;
+
+ int2store(end, thd->client_capabilities);
+ /* write server characteristics: up to 16 bytes allowed */
+ end[2]=(char) default_charset_info->number;
+ int2store(end+3, mpvio->thd->server_status);
+ int2store(end+5, thd->client_capabilities >> 16);
+ end[7]= data_len;
+ bzero(end+8, 10);
+ end+= 18;
+ /* write scramble tail */
+ end= (char*)memcpy(end, data + SCRAMBLE_LENGTH_323,
+ data_len - SCRAMBLE_LENGTH_323);
+ end+= data_len - SCRAMBLE_LENGTH_323;
+ end= strmake(end, plugin_name(mpvio->plugin)->str,
+ plugin_name(mpvio->plugin)->length);
+
+ int res= my_net_write(&mpvio->thd->net, (uchar*) buff, (size_t) (end-buff)) ||
+ net_flush(&mpvio->thd->net);
+ my_afree(buff);
+ return res;
+}
+
+static bool secure_auth(THD *thd)
+{
+ if (!opt_secure_auth)
+ return 0;
+
+ /*
+ If the server is running in secure auth mode, short scrambles are
+ forbidden. Extra juggling to report the same error as the old code.
+ */
+ if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
+ thd->security_ctx->user,
+ thd->security_ctx->host_or_ip);
+ general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
+ thd->security_ctx->user,
+ thd->security_ctx->host_or_ip);
+ }
+ else
+ {
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ }
+ return 1;
+}
+
+/**
+ sends a "change plugin" packet, requesting a client to restart authentication
+ using a different authentication plugin
+
+ Packet format:
+
+ Bytes Content
+ ----- ----
+ 1 byte with the value 254
+ n client plugin to use, \0-terminated
+ n plugin provided data
+
+ In a special case of switching from native_password_plugin to
+ old_password_plugin, the packet contains only one - the first - byte,
+ plugin name is omitted, plugin data aren't needed as the scramble was
+ already sent. This one-byte packet is identical to the "use the short
+ scramble" packet in the protocol before plugins were introduced.
+
+ @retval 0 ok
+ @retval 1 error
+*/
+
+static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
+ const uchar *data, uint data_len)
+{
+ DBUG_ASSERT(mpvio->packets_written == 1);
+ DBUG_ASSERT(mpvio->packets_read == 1);
+ NET *net= &mpvio->thd->net;
+ static uchar switch_plugin_request_buf[]= { 254 };
+
+
+ mpvio->status= MPVIO_EXT::FAILURE; // the status is no longer RESTART
+
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+
+ DBUG_ASSERT(client_auth_plugin);
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, client_auth_plugin,
+ mpvio->cached_client_reply.plugin));
+
+ /*
+ we send an old "short 4.0 scramble request", if we need to request a
+ client to use 4.0 auth plugin (short scramble) and the scramble was
+ already sent to the client
+
+ below, cached_client_reply.plugin is the plugin name that client has used,
+ client_auth_plugin is derived from mysql.user table, for the given
+ user account, it's the plugin that the client need to use to login.
+ */
+ bool switch_from_long_to_short_scramble=
+ native_password_plugin_name.str == mpvio->cached_client_reply.plugin &&
+ client_auth_plugin == old_password_plugin_name.str;
+
+ if (switch_from_long_to_short_scramble)
+ return secure_auth(mpvio->thd) ||
+ my_net_write(net, switch_plugin_request_buf, 1) ||
+ net_flush(net);
+
+ /*
+ We never request a client to switch from a short to long scramble.
+ Plugin-aware clients can do that, but traditionally it meant to
+ ask an old 4.0 client to use the new 4.1 authentication protocol.
+ */
+ bool switch_from_short_to_long_scramble=
+ old_password_plugin_name.str == mpvio->cached_client_reply.plugin &&
+ client_auth_plugin == native_password_plugin_name.str;
+
+ if (switch_from_short_to_long_scramble)
+ {
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ return 1;
+ }
+
+ return net_write_command(net, switch_plugin_request_buf[0],
+ (uchar*)client_auth_plugin,
+ strlen(client_auth_plugin)+1,
+ (uchar*)data, data_len);
+}
+
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+/**
+ Finds acl entry in user database for authentication purposes.
+
+ Finds a user and copies it into mpvio. Reports an authentication
+ failure if a user is not found.
+
+ @note find_acl_user is not the same, because it doesn't take into
+ account the case when user is not empty, but acl_user->user is empty
+
+ @retval 0 found
+ @retval 1 not found
+*/
+
+static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx)
+{
+ DBUG_ASSERT(mpvio->acl_user == 0);
+
+ pthread_mutex_lock(&acl_cache->lock);
+ for (uint i=0 ; i < acl_users.elements ; i++)
+ {
+ ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
+ if ((!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user)) &&
+ compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
+ {
+ mpvio->acl_user= acl_user_tmp->copy(mpvio->thd->mem_root);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&acl_cache->lock);
+
+ if (!mpvio->acl_user)
+ {
+ login_failed_error(mpvio->thd, 0);
+ return 1;
+ }
+
+ /* user account requires non-default plugin and the client is too old */
+ if (mpvio->acl_user->plugin.str != native_password_plugin_name.str &&
+ mpvio->acl_user->plugin.str != old_password_plugin_name.str &&
+ !(mpvio->thd->client_capabilities & CLIENT_PLUGIN_AUTH))
+ {
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ native_password_plugin_name.str));
+ DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ old_password_plugin_name.str));
+ my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
+ general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ return 1;
+ }
+
+ mpvio->auth_info.user_name= sctx->user;
+ mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str;
+ strmake(mpvio->auth_info.authenticated_as, mpvio->acl_user->user ?
+ mpvio->acl_user->user : "", USERNAME_LENGTH);
+
+ return 0;
+}
+#endif
+
+
+/* the packet format is described in send_change_user_packet() */
+static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
+{
+ THD *thd= mpvio->thd;
+ NET *net= &thd->net;
+ Security_context *sctx= thd->security_ctx;
+
+ char *user= (char*) net->read_pos;
+ char *end= user + packet_length;
+ /* Safe because there is always a trailing \0 at the end of the packet */
+ char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1;
+ char *db= passwd;
+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
+ uint dummy_errors;
+
+ if (passwd >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
+
+ Cast *passwd to an unsigned char, so that it doesn't extend the sign for
+ *passwd > 127 and become 2**32-127+ after casting to uint.
+ */
+ uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ (uchar)(*passwd++) : strlen(passwd));
+
+ db+= passwd_len + 1;
+ /*
+ Database name is always NUL-terminated, so in case of empty database
+ the packet must contain at least the trailing '\0'.
+ */
+ if (db >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+
+ uint db_len= strlen(db);
+
+ char *ptr= db + db_len + 1;
+
+ if (ptr+1 < end)
+ {
+ uint cs_number= uint2korr(ptr);
+ thd_init_client_charset(thd, cs_number);
+ thd->update_charset();
+ }
+
+ /* Convert database and user names to utf8 */
+ db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
+ db, db_len, thd->charset(), &dummy_errors);
+
+ user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors);
+
+ if (!(sctx->user= my_strndup(user_buff, user_len, MYF(MY_WME))))
+ return 1;
+
+ /* Clear variables that are allocated */
+ thd->user_connect= 0;
+ strmake(sctx->priv_user, sctx->user, USERNAME_LENGTH);
+
+ if (thd->make_lex_string(&mpvio->db, db_buff, db_len, 0) == 0)
+ return 1; /* The error is set by make_lex_string(). */
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed.
+ */
+ thd->reset_db(NULL, 0);
+
+ if (!initialized)
+ {
+ // if mysqld's been started with --skip-grant-tables option
+ mpvio->status= MPVIO_EXT::SUCCESS;
+ return 0;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (find_mpvio_user(mpvio, sctx))
+ return 1;
+
+ char *client_plugin;
+ if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ client_plugin= ptr + 2;
+ if (client_plugin >= end)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ return 1;
+ }
+ client_plugin= fix_plugin_ptr(client_plugin);
+ }
+ else
+ {
+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+ client_plugin= native_password_plugin_name.str;
+ else
+ {
+ client_plugin= old_password_plugin_name.str;
+ /*
+ For a passwordless accounts we use native_password_plugin.
+ But when an old 4.0 client connects to it, we change it to
+ old_password_plugin, otherwise MySQL will think that server
+ and client plugins don't match.
+ */
+ if (mpvio->acl_user->auth_string.length == 0)
+ mpvio->acl_user->plugin= old_password_plugin_name;
+ }
+ }
+
+ /* remember the data part of the packet, to present it to plugin in read_packet() */
+ mpvio->cached_client_reply.pkt= passwd;
+ mpvio->cached_client_reply.pkt_len= passwd_len;
+ mpvio->cached_client_reply.plugin= client_plugin;
+ mpvio->status= MPVIO_EXT::RESTART;
+#endif
+
+ return 0;
+}
+
+
+/* the packet format is described in send_client_reply_packet() */
+static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
+ uchar **buff, ulong pkt_len)
+{
+#ifndef EMBEDDED_LIBRARY
+ THD *thd= mpvio->thd;
+ NET *net= &thd->net;
+ char *end;
+
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
+
+ if (pkt_len < MIN_HANDSHAKE_SIZE)
+ return packet_error;
+
+ if (mpvio->connect_errors)
+ reset_host_errors(&net->vio->remote.sin_addr);
+
+ ulong client_capabilities= uint2korr(net->read_pos);
+ if (client_capabilities & CLIENT_PROTOCOL_41)
+ {
+ client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
+ thd->max_client_packet_length= uint4korr(net->read_pos+4);
+ DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
+ thd_init_client_charset(thd, (uint) net->read_pos[8]);
+ thd->update_charset();
+ end= (char*) net->read_pos+32;
+ }
+ else
+ {
+ thd->max_client_packet_length= uint3korr(net->read_pos+2);
+ end= (char*) net->read_pos+5;
+ }
+
+ /* Disable those bits which are not supported by the client. */
+ thd->client_capabilities&= client_capabilities;
+
+ if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
+ thd->variables.sql_mode|= MODE_IGNORE_SPACE;
+
+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
+ if (thd->client_capabilities & CLIENT_SSL)
+ {
+ char error_string[1024] __attribute__((unused));
+
+ /* Do the SSL layering. */
+ if (!ssl_acceptor_fd)
+ return packet_error;
+
+ DBUG_PRINT("info", ("IO layer change in progress..."));
+ if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, error_string))
+ {
+ DBUG_PRINT("error", ("Failed to accept new SSL connection"));
+ return packet_error;
+ }
+
+ DBUG_PRINT("info", ("Reading user information over SSL layer"));
+ pkt_len= my_net_read(net);
+ if (pkt_len == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE)
+ {
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
+ return packet_error;
+ }
+ }
+
+ if (end >= (char*) net->read_pos+ pkt_len +2)
+ return packet_error;
+
+ if (thd->client_capabilities & CLIENT_INTERACTIVE)
+ thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
+ if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
+ opt_using_transactions)
+ net->return_status= &thd->server_status;
+
+ char *user= end;
+ char *passwd= strend(user)+1;
+ uint user_len= passwd - user - 1, db_len;
+ char *db= passwd;
+ char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
+ char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
+ uint dummy_errors;
+
+ /*
+ Old clients send null-terminated string as password; new clients send
+ the size (1 byte) + string (not null-terminated). Hence in case of empty
+ password both send '\0'.
+
+ This strlen() can't be easily deleted without changing protocol.
+
+ Cast *passwd to an unsigned char, so that it doesn't extend the sign for
+ *passwd > 127 and become 2**32-127+ after casting to uint.
+ */
+ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+ (uchar)(*passwd++) : strlen(passwd);
+
+ if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
+ {
+ db= db + passwd_len + 1;
+ /* strlen() can't be easily deleted without changing protocol */
+ db_len= strlen(db);
+ }
+ else
+ {
+ db= 0;
+ db_len= 0;
+ }
+
+ if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
+ return packet_error;
+
+ char *client_plugin= passwd + passwd_len + (db ? db_len + 1 : 0);
+
+ /* Since 4.1 all database names are stored in utf8 */
+ if (db)
+ {
+ db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
+ db, db_len, thd->charset(), &dummy_errors);
+ db= db_buff;
+ }
+
+ user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
+ system_charset_info, user, user_len,
+ thd->charset(), &dummy_errors);
+ user= user_buff;
+
+ /* If username starts and ends in "'", chop them off */
+ if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
+ {
+ user++;
+ user_len-= 2;
+ }
+
+ Security_context *sctx= thd->security_ctx;
+
+ if (thd->make_lex_string(&mpvio->db, db, db_len, 0) == 0)
+ return packet_error; /* The error is set by make_lex_string(). */
+ if (sctx->user)
+ x_free(sctx->user);
+ if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME))))
+ return packet_error; /* The error is set by my_strdup(). */
+
+ /*
+ Clear thd->db as it points to something, that will be freed when
+ connection is closed. We don't want to accidentally free a wrong
+ pointer if connect failed.
+ */
+ thd->reset_db(NULL, 0);
+
+ if (!initialized)
+ {
+ // if mysqld's been started with --skip-grant-tables option
+ mpvio->status= MPVIO_EXT::SUCCESS;
+ return packet_error;
+ }
+
+ if (find_mpvio_user(mpvio, sctx))
+ return packet_error;
+
+ if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+ {
+ if ((client_plugin + strlen(client_plugin)) >
+ (char *)net->read_pos + pkt_len)
+ return packet_error;
+ client_plugin= fix_plugin_ptr(client_plugin);
+ }
+ else
+ {
+ if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+ client_plugin= native_password_plugin_name.str;
+ else
+ {
+ client_plugin= old_password_plugin_name.str;
+ /*
+ For a passwordless accounts we use native_password_plugin.
+ But when an old 4.0 client connects to it, we change it to
+ old_password_plugin, otherwise MySQL will think that server
+ and client plugins don't match.
+ */
+ if (mpvio->acl_user->auth_string.length == 0)
+ mpvio->acl_user->plugin= old_password_plugin_name;
+ }
+ }
+
+ /*
+ if the acl_user needs a different plugin to authenticate
+ (specified in GRANT ... AUTHENTICATED VIA plugin_name ..)
+ we need to restart the authentication in the server.
+ But perhaps the client has already used the correct plugin -
+ in that case the authentication on the client may not need to be
+ restarted and a server auth plugin will read the data that the client
+ has just send. Cache them to return in the next server_mpvio_read_packet().
+ */
+ if (my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+ plugin_name(mpvio->plugin)->str) != 0)
+ {
+ mpvio->cached_client_reply.pkt= passwd;
+ mpvio->cached_client_reply.pkt_len= passwd_len;
+ mpvio->cached_client_reply.plugin= client_plugin;
+ mpvio->status= MPVIO_EXT::RESTART;
+ return packet_error;
+ }
+
+ /*
+ ok, we don't need to restart the authentication on the server.
+ but if the client used the wrong plugin, we need to restart
+ the authentication on the client. Do it here, the server plugin
+ doesn't need to know.
+ */
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+
+ if (client_auth_plugin &&
+ my_strcasecmp(system_charset_info, client_plugin, client_auth_plugin))
+ {
+ mpvio->cached_client_reply.plugin= client_plugin;
+ if (send_plugin_request_packet(mpvio,
+ (uchar*)mpvio->cached_server_packet.pkt,
+ mpvio->cached_server_packet.pkt_len))
+ return packet_error;
+
+ passwd_len= my_net_read(&mpvio->thd->net);
+ passwd = (char*)mpvio->thd->net.read_pos;
+ }
+
+ *buff= (uchar*)passwd;
+ return passwd_len;
+#else
+ return 0;
+#endif
+}
+
+
+/**
+ vio->write_packet() callback method for server authentication plugins
+
+ This function is called by a server authentication plugin, when it wants
+ to send data to the client.
+
+ It transparently wraps the data into a handshake packet,
+ and handles plugin negotiation with the client. If necessary,
+ it escapes the plugin data, if it starts with a mysql protocol packet byte.
+*/
+
+static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param,
+ const uchar *packet, int packet_len)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)param;
+ int res;
+
+ /* reset cached_client_reply */
+ mpvio->cached_client_reply.pkt= 0;
+ /* for the 1st packet we wrap plugin data into the handshake packet */
+ if (mpvio->packets_written == 0)
+ res= send_server_handshake_packet(mpvio, (char*)packet, packet_len);
+ else if (mpvio->status == MPVIO_EXT::RESTART)
+ res= send_plugin_request_packet(mpvio, packet, packet_len);
+ else if (packet_len > 0 && (*packet == 1 || *packet == 255 || *packet == 254))
+ {
+ /*
+ we cannot allow plugin data packet to start from 255 or 254 -
+ as the client will treat it as an error or "change plugin" packet.
+ We'll escape these bytes with \1. Consequently, we
+ have to escape \1 byte too.
+ */
+ res= net_write_command(&mpvio->thd->net, 1, (uchar*)"", 0,
+ packet, packet_len);
+ }
+ else
+ {
+ res= my_net_write(&mpvio->thd->net, packet, packet_len) ||
+ net_flush(&mpvio->thd->net);
+ }
+ mpvio->packets_written++;
+ return res;
+}
+
+
+/**
+ vio->read_packet() callback method for server authentication plugins
+
+ This function is called by a server authentication plugin, when it wants
+ to read data from the client.
+
+ It transparently extracts the client plugin data, if embedded into
+ a client authentication handshake packet, and handles plugin negotiation
+ with the client, if necessary.
+*/
+
+static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)param;
+ ulong pkt_len;
+
+ if (mpvio->packets_written == 0)
+ {
+ /*
+ plugin wants to read the data without sending anything first.
+ send an empty packet to force a server handshake packet to be sent
+ */
+ if (server_mpvio_write_packet(mpvio, 0, 0))
+ pkt_len= packet_error;
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+ }
+ else
+ if (mpvio->cached_client_reply.pkt)
+ {
+ DBUG_ASSERT(mpvio->status == MPVIO_EXT::RESTART);
+ DBUG_ASSERT(mpvio->packets_read > 0);
+ /*
+ if the have the data cached from the last server_mpvio_read_packet
+ (which can be the case if it's a restarted authentication)
+ and a client has used the correct plugin, then we can return the
+ cached data straight away and avoid one round trip.
+ */
+ const char *client_auth_plugin=
+ ((st_mysql_auth *)(plugin_decl(mpvio->plugin)->info))->client_auth_plugin;
+ if (client_auth_plugin == 0 ||
+ my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin,
+ client_auth_plugin) == 0)
+ {
+ mpvio->status= MPVIO_EXT::FAILURE;
+ *buf= (uchar*)mpvio->cached_client_reply.pkt;
+ mpvio->cached_client_reply.pkt= 0;
+ mpvio->packets_read++;
+ return (int)mpvio->cached_client_reply.pkt_len;
+ }
+ /*
+ But if the client has used the wrong plugin, the cached data are
+ useless. Furthermore, we have to send a "change plugin" request
+ to the client.
+ */
+ if (server_mpvio_write_packet(mpvio, 0, 0))
+ pkt_len= packet_error;
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+ }
+ else
+ pkt_len= my_net_read(&mpvio->thd->net);
+
+ if (pkt_len == packet_error)
+ goto err;
+
+ mpvio->packets_read++;
+
+ /*
+ the 1st packet has the plugin data wrapped into the client authentication
+ handshake packet
+ */
+ if (mpvio->packets_read == 1)
+ {
+ pkt_len= parse_client_handshake_packet(mpvio, buf, pkt_len);
+ if (pkt_len == packet_error)
+ goto err;
+ }
+ else
+ *buf = mpvio->thd->net.read_pos;
+
+ return (int)pkt_len;
+
+err:
+ if (mpvio->status == MPVIO_EXT::FAILURE && !mpvio->thd->is_error())
+ {
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0),
+ mpvio->thd->security_ctx->host_or_ip);
+ }
+ return -1;
+}
+
+
+/**
+ fills MYSQL_PLUGIN_VIO_INFO structure with the information about the
+ connection
+*/
+
+static void server_mpvio_info(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_PLUGIN_VIO_INFO *info)
+{
+ MPVIO_EXT *mpvio= (MPVIO_EXT*)vio;
+ mpvio_info(mpvio->thd->net.vio, info);
+}
+
+
+static bool acl_check_ssl(THD *thd, ACL_USER *acl_user)
+{
+#if defined(HAVE_OPENSSL)
+ Vio *vio=thd->net.vio;
+ SSL *ssl= (SSL*) vio->ssl_arg;
+ X509 *cert;
+#endif
+
+ /*
+ At this point we know that user is allowed to connect
+ from given host by given username/password pair. Now
+ we check if SSL is required, if user is using SSL and
+ if X509 certificate attributes are OK
+ */
+ switch (acl_user->ssl_type) {
+ case SSL_TYPE_NOT_SPECIFIED: // Impossible
+ case SSL_TYPE_NONE: // SSL is not required
+ return 0;
+#if defined(HAVE_OPENSSL)
+ case SSL_TYPE_ANY: // Any kind of SSL is ok
+ return vio_type(vio) != VIO_TYPE_SSL;
+ case SSL_TYPE_X509: /* Client should have any valid certificate. */
+ /*
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
+ */
+ if (vio_type(vio) == VIO_TYPE_SSL &&
+ SSL_get_verify_result(ssl) == X509_V_OK &&
+ (cert= SSL_get_peer_certificate(ssl)))
+ {
+ X509_free(cert);
+ return 0;
+ }
+ return 1;
+ case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
+ /* If a cipher name is specified, we compare it to actual cipher in use. */
+ if (vio_type(vio) != VIO_TYPE_SSL ||
+ SSL_get_verify_result(ssl) != X509_V_OK)
+ return 1;
+ if (acl_user->ssl_cipher)
+ {
+ DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
+ acl_user->ssl_cipher,SSL_get_cipher(ssl)));
+ if (strcmp(acl_user->ssl_cipher,SSL_get_cipher(ssl)))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
+ acl_user->ssl_cipher, SSL_get_cipher(ssl));
+ return 1;
+ }
+ }
+ /* Prepare certificate (if exists) */
+ if (!(cert= SSL_get_peer_certificate(ssl)))
+ return 1;
+ /* If X509 issuer is specified, we check it... */
+ if (acl_user->x509_issuer)
+ {
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ acl_user->x509_issuer, ptr));
+ if (strcmp(acl_user->x509_issuer, ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 issuer mismatch: should be '%s' "
+ "but is '%s'", acl_user->x509_issuer, ptr);
+ free(ptr);
+ X509_free(cert);
+ return 1;
+ }
+ free(ptr);
+ }
+ /* X509 subject is specified, we check it .. */
+ if (acl_user->x509_subject)
+ {
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
+ acl_user->x509_subject, ptr);
+ free(ptr);
+ X509_free(cert);
+ return 1;
+ }
+ free(ptr);
+ }
+ X509_free(cert);
+ return 0;
+#else /* HAVE_OPENSSL */
+ default:
+ /*
+ If we don't have SSL but SSL is required for this user the
+ authentication should fail.
+ */
+ return 1;
+#endif /* HAVE_OPENSSL */
+ }
+ return 1;
+}
+
+static int do_auth_once(THD *thd, LEX_STRING *auth_plugin_name,
+ MPVIO_EXT *mpvio)
+{
+ int res= CR_OK, old_status= MPVIO_EXT::FAILURE;
+ bool unlock_plugin= false;
+ plugin_ref plugin;
+
+#ifdef EMBEDDED_LIBRARY
+ plugin= native_password_plugin;
+#else
+ if (auth_plugin_name->str == native_password_plugin_name.str)
+ plugin= native_password_plugin;
+ else if (auth_plugin_name->str == old_password_plugin_name.str)
+ plugin= old_password_plugin;
+ else if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
+ MYSQL_AUTHENTICATION_PLUGIN)))
+ unlock_plugin= true;
+#endif
+
+ mpvio->plugin= plugin;
+ old_status= mpvio->status;
+
+ if (plugin)
+ {
+ st_mysql_auth *auth= (st_mysql_auth*)plugin_decl(plugin)->info;
+ res= auth->authenticate_user(mpvio, &mpvio->auth_info);
+
+ if (unlock_plugin)
+ plugin_unlock(thd, plugin);
+ }
+ else
+ {
+ /* Server cannot load the required plugin. */
+ my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth_plugin_name->str);
+ res= CR_ERROR;
+ }
+
+ /*
+ If the status was MPVIO_EXT::RESTART before the authenticate_user() call
+ it can never be MPVIO_EXT::RESTART after the call, because any call
+ to write_packet() or read_packet() will reset the status.
+
+ But (!) if a plugin never called a read_packet() or write_packet(), the
+ status will stay unchanged. We'll fix it, by resetting the status here.
+ */
+ if (old_status == MPVIO_EXT::RESTART && mpvio->status == MPVIO_EXT::RESTART)
+ mpvio->status= MPVIO_EXT::FAILURE; // reset to the default
+
+ return res;
+}
+
+/**
+ Perform the handshake, authorize the client and update thd sctx variables.
+
+ @param thd thread handle
+ @param connect_errors number of previous failed connect attemps
+ from this host
+ @param com_change_user_pkt_len size of the COM_CHANGE_USER packet
+ (without the first, command, byte) or 0
+ if it's not a COM_CHANGE_USER (that is, if
+ it's a new connection)
+
+ @retval 0 success, thd is updated.
+ @retval 1 error
+*/
+
+bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
+{
+ int res= CR_OK;
+ MPVIO_EXT mpvio;
+ LEX_STRING *auth_plugin_name= default_auth_plugin_name;
+ enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER
+ : COM_CONNECT;
+ DBUG_ENTER("acl_authenticate");
+
+ compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
+
+ bzero(&mpvio, sizeof(mpvio));
+ mpvio.read_packet= server_mpvio_read_packet;
+ mpvio.write_packet= server_mpvio_write_packet;
+ mpvio.info= server_mpvio_info;
+ mpvio.thd= thd;
+ mpvio.connect_errors= connect_errors;
+ mpvio.status= MPVIO_EXT::FAILURE;
+
+ if (command == COM_CHANGE_USER)
+ {
+ mpvio.packets_written++; // pretend that a server handshake packet was sent
+ mpvio.packets_read++; // take COM_CHANGE_USER packet into account
+
+ if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len))
+ DBUG_RETURN(1);
+
+ DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
+ mpvio.status == MPVIO_EXT::SUCCESS);
+ }
+ else
+ {
+ /* mark the thd as having no scramble yet */
+ thd->scramble[SCRAMBLE_LENGTH]= 1;
+
+ /*
+ perform the first authentication attempt, with the default plugin.
+ This sends the server handshake packet, reads the client reply
+ with a user name, and performs the authentication if everyone has used
+ the correct plugin.
+ */
+ res= do_auth_once(thd, auth_plugin_name, &mpvio);
+ }
+
+ /*
+ retry the authentication, if - after receiving the user name -
+ we found that we need to switch to a non-default plugin
+ */
+ if (mpvio.status == MPVIO_EXT::RESTART)
+ {
+ DBUG_ASSERT(mpvio.acl_user);
+ DBUG_ASSERT(command == COM_CHANGE_USER ||
+ my_strcasecmp(system_charset_info, auth_plugin_name->str,
+ mpvio.acl_user->plugin.str));
+ auth_plugin_name= &mpvio.acl_user->plugin;
+ res= do_auth_once(thd, auth_plugin_name, &mpvio);
+ }
+
+ Security_context *sctx= thd->security_ctx;
+ ACL_USER *acl_user= mpvio.acl_user;
+
+ thd->password= mpvio.auth_info.password_used; // remember for error messages
+
+ /*
+ Log the command here so that the user can check the log
+ for the tried logins and also to detect break-in attempts.
+
+ if sctx->user is unset it's protocol failure, bad packet.
+ */
+ if (sctx->user)
+ {
+ if (strcmp(sctx->priv_user, sctx->user))
+ {
+ general_log_print(thd, command, "%s@%s as %s on %s",
+ sctx->user, sctx->host_or_ip,
+ sctx->priv_user[0] ? sctx->priv_user : "anonymous",
+ mpvio.db.str ? mpvio.db.str : (char*) "");
+ }
+ else
+ general_log_print(thd, command, (char*) "%s@%s on %s",
+ sctx->user, sctx->host_or_ip,
+ mpvio.db.str ? mpvio.db.str : (char*) "");
+ }
+
+ if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
+ {
+ DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
+
+ if (!thd->is_error())
+ login_failed_error(thd, thd->password);
+ DBUG_RETURN(1);
+ }
+
+ if (initialized) // if not --skip-grant-tables
+ {
+ sctx->master_access= acl_user->access;
+ strmake(sctx->priv_user, mpvio.auth_info.authenticated_as, USERNAME_LENGTH);
+ if (acl_user->host.hostname)
+ strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *sctx->priv_host= 0;
+
+ /*
+ OK. Let's check the SSL. Historically it was checked after the password,
+ as an additional layer, not instead of the password
+ (in which case it would've been a plugin too).
+ */
+ if (acl_check_ssl(thd, acl_user))
+ {
+ login_failed_error(thd, thd->password);
+ DBUG_RETURN(1);
+ }
+
+ /* Don't allow the user to connect if he has done too many queries */
+ if ((acl_user->user_resource.questions || acl_user->user_resource.updates ||
+ acl_user->user_resource.conn_per_hour ||
+ acl_user->user_resource.user_conn || max_user_connections) &&
+ get_or_create_user_conn(thd,
+ (opt_old_style_user_limits ? sctx->user : sctx->priv_user),
+ (opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
+ &acl_user->user_resource))
+ DBUG_RETURN(1); // The error is set by get_or_create_user_conn()
+ }
+ else
+ sctx->skip_grants();
+
+ if (thd->user_connect &&
+ (thd->user_connect->user_resources.conn_per_hour ||
+ thd->user_connect->user_resources.user_conn ||
+ max_user_connections) &&
+ check_for_max_user_connections(thd, thd->user_connect))
+ {
+ status_var_increment(denied_connections);
+ DBUG_RETURN(1); // The error is set in check_for_max_user_connections()
+ }
+
+ DBUG_PRINT("info",
+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
+ "Login user: '%s' Priv_user: '%s' Using password: %s "
+ "Access: %lu db: '%s'",
+ thd->client_capabilities, thd->max_client_packet_length,
+ sctx->host_or_ip, sctx->user, sctx->priv_user,
+ thd->password ? "yes": "no",
+ sctx->master_access, mpvio.db.str));
+
+ if (command == COM_CONNECT &&
+ !(thd->main_security_ctx.master_access & SUPER_ACL))
+ {
+ pthread_mutex_lock(&LOCK_connection_count);
+ bool count_ok= (*thd->scheduler->connection_count <=
+ *thd->scheduler->max_connections);
+ VOID(pthread_mutex_unlock(&LOCK_connection_count));
+ if (!count_ok)
+ { // too many connections
+ my_error(ER_CON_COUNT_ERROR, MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+
+ /*
+ This is the default access rights for the current database. It's
+ set to 0 here because we don't have an active database yet (and we
+ may not have an active database to set.
+ */
+ sctx->db_access=0;
+
+ /* Change a database if necessary */
+ if (mpvio.db.length)
+ {
+ if (mysql_change_db(thd, &mpvio.db, FALSE))
+ {
+ /* mysql_change_db() has pushed the error message. */
+ if (thd->user_connect)
+ {
+ status_var_increment(thd->status_var.access_denied_errors);
+ decrease_user_connections(thd->user_connect);
+ thd->user_connect= 0;
+ }
+ DBUG_RETURN(1);
+ }
+ }
+
+ thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
+
+ if (res == CR_OK_HANDSHAKE_COMPLETE)
+ thd->main_da.disable_status();
+ else
+ my_ok(thd);
+
+ /* Ready to handle queries */
+ DBUG_RETURN(0);
+}
+
+
+/**
+ MySQL Server Password Authentication Plugin
+
+ In the MySQL authentication protocol:
+ 1. the server sends the random scramble to the client
+ 2. client sends the encrypted password back to the server
+ 3. the server checks the password.
+*/
+
+static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ uchar *pkt;
+ int pkt_len;
+ MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
+ THD *thd=mpvio->thd;
+
+ /* generate the scramble, or reuse the old one */
+ if (thd->scramble[SCRAMBLE_LENGTH])
+ {
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+ /* and send it to the client */
+ if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+ return CR_ERROR;
+ }
+
+ /* reply and authenticate */
+
+ /*
+ <digression>
+ This is more complex than it looks.
+
+ The plugin (we) may be called right after the client was connected -
+ and will need to send a scramble, read reply, authenticate.
+
+ Or the plugin may be called after another plugin has sent a scramble,
+ and read the reply. If the client has used the correct client-plugin,
+ we won't need to read anything here from the client, the client
+ has already sent a reply with everything we need for authentication.
+
+ Or the plugin may be called after another plugin has sent a scramble,
+ and read the reply, but the client has used the wrong client-plugin.
+ We'll need to sent a "switch to another plugin" packet to the
+ client and read the reply. "Use the short scramble" packet is a special
+ case of "switch to another plugin" packet.
+
+ Or, perhaps, the plugin may be called after another plugin has
+ done the handshake but did not send a useful scramble. We'll need
+ to send a scramble (and perhaps a "switch to another plugin" packet)
+ and read the reply.
+
+ Besides, a client may be an old one, that doesn't understand plugins.
+ Or doesn't even understand 4.0 scramble.
+
+ And we want to keep the same protocol on the wire unless non-native
+ plugins are involved.
+
+ Anyway, it still looks simple from a plugin point of view:
+ "send the scramble, read the reply and authenticate".
+ All the magic is transparently handled by the server.
+ </digression>
+ */
+
+ /* read the reply with the encrypted password */
+ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+ return CR_ERROR;
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return CR_OK;
+#endif
+
+ if (pkt_len == 0) /* no password */
+ return info->auth_string[0] ? CR_ERROR : CR_OK;
+
+ info->password_used = 1;
+ if (pkt_len == SCRAMBLE_LENGTH)
+ return info->auth_string[0] == 0 ||
+ check_scramble(pkt, thd->scramble, mpvio->acl_user->salt) ?
+ CR_ERROR : CR_OK;
+
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ return CR_ERROR;
+}
+
+
+static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+ MYSQL_SERVER_AUTH_INFO *info)
+{
+ uchar *pkt;
+ int pkt_len;
+ MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
+ THD *thd=mpvio->thd;
+
+ /* generate the scramble, or reuse the old one */
+ if (thd->scramble[SCRAMBLE_LENGTH])
+ {
+ create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+ /* and send it to the client */
+ if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+ return CR_ERROR;
+ }
+
+ /* read the reply and authenticate */
+ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+ return CR_ERROR;
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return CR_OK;
+#endif
+
+ /*
+ legacy: if switch_from_long_to_short_scramble,
+ the password is sent \0-terminated, the pkt_len is always 9 bytes.
+ We need to figure out the correct scramble length here.
+ */
+ if (pkt_len == SCRAMBLE_LENGTH_323+1)
+ pkt_len= strnlen((char*)pkt, pkt_len);
+
+ if (pkt_len == 0) /* no password */
+ return info->auth_string[0] ? CR_ERROR : CR_OK;
+
+ if (secure_auth(thd))
+ return CR_ERROR;
+
+ info->password_used = 1;
+
+ if (pkt_len == SCRAMBLE_LENGTH_323)
+ return info->auth_string[0] == 0 ||
+ check_scramble_323(pkt, thd->scramble,
+ (ulong *)mpvio->acl_user->salt) ? CR_ERROR : CR_OK;
+
+ inc_host_errors(&mpvio->thd->net.vio->remote.sin_addr);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ return CR_ERROR;
+}
+
+static struct st_mysql_auth native_password_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ native_password_plugin_name.str,
+ native_password_authenticate
+};
+
+static struct st_mysql_auth old_password_handler=
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ old_password_plugin_name.str,
+ old_password_authenticate
+};
+
+mysql_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
+
+maria_declare_plugin(mysql_password)
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &native_password_handler, /* type descriptor */
+ native_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Native MySQL authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+},
+{
+ MYSQL_AUTHENTICATION_PLUGIN, /* type constant */
+ &old_password_handler, /* type descriptor */
+ old_password_plugin_name.str, /* Name */
+ "R.J.Silk, Sergei Golubchik", /* Author */
+ "Old MySQL-4.0 authentication", /* Description */
+ PLUGIN_LICENSE_GPL, /* License */
+ NULL, /* Init function */
+ NULL, /* Deinit function */
+ 0x0100, /* Version (1.0) */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* String version */
+ MariaDB_PLUGIN_MATURITY_BETA /* Maturity */
+}
+maria_declare_plugin_end;
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 4c835e2718c..5078c80cedf 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -161,53 +161,6 @@ enum mysql_db_table_field
extern const TABLE_FIELD_DEF mysql_db_table_def;
-/* Classes */
-
-struct acl_host_and_ip
-{
- char *hostname;
- long ip,ip_mask; // Used with masked ip:s
-};
-
-
-class ACL_ACCESS {
-public:
- ulong sort;
- ulong access;
-};
-
-
-/* ACL_HOST is used if no host is specified */
-
-class ACL_HOST :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *db;
-};
-
-
-class ACL_USER :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- uint hostname_length;
- USER_RESOURCES user_resource;
- char *user;
- uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
- uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 3.23, 20 - 4.1.1
- enum SSL_type ssl_type;
- const char *ssl_cipher, *x509_issuer, *x509_subject;
-};
-
-
-class ACL_DB :public ACL_ACCESS
-{
-public:
- acl_host_and_ip host;
- char *user,*db;
-};
-
/* prototypes */
bool hostname_requires_resolving(const char *hostname);
@@ -216,10 +169,9 @@ my_bool acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip,
const char *user, const char *db, my_bool db_is_pattern);
-int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd,
- uint passwd_len);
-bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
- char *ip, char *db);
+bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len);
+bool acl_getroot(Security_context *sctx, char *user, char *host,
+ char *ip, char *db);
bool acl_check_host(const char *host, const char *ip);
int check_change_password(THD *thd, const char *host, const char *user,
char *password, uint password_len);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 81b13136b8e..66a4f7694f9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1386,6 +1386,12 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
DBUG_PRINT("tcache", ("table: '%s'.'%s' 0x%lx", table->s->db.str,
table->s->table_name.str, (long) table));
+ if (table->file)
+ {
+ table->file->update_global_table_stats();
+ table->file->update_global_index_stats();
+ }
+
*table_ptr=table->next;
/*
When closing a MERGE parent or child table, detach the children first.
@@ -1926,6 +1932,13 @@ void close_temporary(TABLE *table, bool free_share, bool delete_table)
DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'",
table->s->db.str, table->s->table_name.str));
+ /* in_use is not set for replication temporary tables during shutdown */
+ if (table->in_use)
+ {
+ table->file->update_global_table_stats();
+ table->file->update_global_index_stats();
+ }
+
free_io_cache(table);
closefrm(table, 0);
if (delete_table)
@@ -2999,7 +3012,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->status=STATUS_NO_RECORD;
table->insert_values= 0;
table->fulltext_searched= 0;
- table->file->ft_handler= 0;
+ table->file->ha_start_of_new_statement();
table->reginfo.impossible_range= 0;
/* Catch wrong handling of the auto_increment_field_not_null. */
DBUG_ASSERT(!table->auto_increment_field_not_null);
@@ -5706,6 +5719,9 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
table->covering_keys.intersect(field->part_of_key);
table->merge_keys.merge(field->part_of_key);
+ if (field->vcol_info)
+ table->mark_virtual_col(field);
+
if (thd->mark_used_columns == MARK_COLUMNS_READ)
current_bitmap= table->read_set;
else
@@ -8002,6 +8018,12 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
{
/* Mark fields as used to allow storage engine to optimze access */
bitmap_set_bit(field->table->read_set, field->field_index);
+ /*
+ Mark virtual fields for write and others that the virtual fields
+ depend on for read.
+ */
+ if (field->vcol_info)
+ field->table->mark_virtual_col(field);
if (table)
{
table->covering_keys.intersect(field->part_of_key);
@@ -8213,7 +8235,10 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
Item *value, *fld;
Item_field *field;
TABLE *table= 0;
+ List<TABLE> tbl_list;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
@@ -8235,6 +8260,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
table->auto_increment_field_not_null= FALSE;
f.rewind();
}
+ else if (thd->lex->unit.insert_table_with_stored_vcol)
+ tbl_list.push_back(thd->lex->unit.insert_table_with_stored_vcol);
while ((fld= f++))
{
if (!(field= fld->filed_for_view_update()))
@@ -8247,14 +8274,54 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (rfield->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ rfield->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
+ tbl_list.push_back(table);
}
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> it(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= it++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields(thd, table, TRUE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8290,9 +8357,31 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, fields, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, fields, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers)
+ {
+ TABLE *table= 0;
+ List_iterator_fast<Item> f(fields);
+ Item *fld;
+ Item_field *item_field;
+ if (fields.elements)
+ {
+ fld= (Item_field*)f++;
+ item_field= fld->filed_for_view_update();
+ if (item_field && item_field->field &&
+ (table= item_field->field->table) &&
+ table->vfield)
+ result= update_virtual_fields(thd, table, TRUE);
+ }
+ }
+ return result;
}
@@ -8320,11 +8409,14 @@ bool
fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
+ List<TABLE> tbl_list;
Item *value;
TABLE *table= 0;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
Field *field;
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
only one row.
@@ -8344,12 +8436,52 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (field->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ field->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if (value->save_in_field(field, 0) < 0)
goto err;
+ tbl_list.push_back(table);
}
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields(thd, table, TRUE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8385,9 +8517,22 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, ptr, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, ptr, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers && *ptr)
+ {
+ TABLE *table= (*ptr)->table;
+ if (table->vfield)
+ result= update_virtual_fields(thd, table, TRUE);
+ }
+ return result;
+
}
diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in
index 7ecd4918d7b..3ba47e3a14e 100644
--- a/sql/sql_builtin.cc.in
+++ b/sql/sql_builtin.cc.in
@@ -16,13 +16,12 @@
#include <my_global.h>
#include <mysql/plugin.h>
-typedef struct st_mysql_plugin builtin_plugin[];
+typedef struct st_maria_plugin builtin_maria_plugin[];
-extern builtin_plugin
- builtin_binlog_plugin@mysql_plugin_defs@;
+extern builtin_maria_plugin
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@;
-struct st_mysql_plugin *mysqld_builtins[]=
+struct st_maria_plugin *mariadb_builtins[]=
{
- builtin_binlog_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+ builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin@maria_plugin_defs@,(struct st_maria_plugin *)0
};
-
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index fc0853d1871..b4e34fc1890 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -106,6 +106,7 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root)
key_create_info(rhs.key_create_info),
columns(rhs.columns, mem_root),
name(rhs.name),
+ option_list(rhs.option_list),
generated(rhs.generated)
{
list_copy_and_replace_each_value(columns, mem_root);
@@ -195,6 +196,59 @@ bool foreign_key_prefix(Key *a, Key *b)
#endif
}
+/*
+ @brief
+ Check if the foreign key options are compatible with the specification
+ of the columns on which the key is created
+
+ @retval
+ FALSE The foreign key options are compatible with key columns
+ @retval
+ TRUE Otherwise
+*/
+bool Foreign_key::validate(List<Create_field> &table_fields)
+{
+ Create_field *sql_field;
+ Key_part_spec *column;
+ List_iterator<Key_part_spec> cols(columns);
+ List_iterator<Create_field> it(table_fields);
+ DBUG_ENTER("Foreign_key::validate");
+ while ((column= cols++))
+ {
+ it.rewind();
+ while ((sql_field= it++) &&
+ my_strcasecmp(system_charset_info,
+ column->field_name,
+ sql_field->field_name)) {}
+ if (!sql_field)
+ {
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+ DBUG_RETURN(TRUE);
+ }
+ if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
+ {
+ if (delete_opt == FK_OPTION_SET_NULL)
+ {
+ my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
+ "ON DELETE SET NULL");
+ DBUG_RETURN(TRUE);
+ }
+ if (update_opt == FK_OPTION_SET_NULL)
+ {
+ my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
+ "ON UPDATE SET NULL");
+ DBUG_RETURN(TRUE);
+ }
+ if (update_opt == FK_OPTION_CASCADE)
+ {
+ my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
+ "ON UPDATE CASCADE");
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
/****************************************************************************
** Thread specific functions
@@ -680,6 +734,7 @@ THD::THD()
mysys_var=0;
binlog_evt_union.do_union= FALSE;
enable_slow_log= 0;
+
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
#endif
@@ -747,11 +802,14 @@ THD::THD()
thr_lock_owner_init(&main_lock_id, &lock_info);
m_internal_handler= NULL;
+
+ arena_for_cached_items= 0;
}
void THD::push_internal_handler(Internal_error_handler *handler)
{
+ DBUG_ENTER("THD::push_internal_handler");
if (m_internal_handler)
{
handler->m_prev_internal_handler= m_internal_handler;
@@ -761,6 +819,7 @@ void THD::push_internal_handler(Internal_error_handler *handler)
{
m_internal_handler= handler;
}
+ DBUG_VOID_RETURN;
}
@@ -780,10 +839,11 @@ bool THD::handle_error(uint sql_errno, const char *message,
Internal_error_handler *THD::pop_internal_handler()
{
+ DBUG_ENTER("THD::pop_internal_handler");
DBUG_ASSERT(m_internal_handler != NULL);
Internal_error_handler *popped_handler= m_internal_handler;
m_internal_handler= m_internal_handler->m_prev_internal_handler;
- return popped_handler;
+ DBUG_RETURN(popped_handler);
}
extern "C"
@@ -880,14 +940,65 @@ void THD::init(void)
update_charset();
reset_current_stmt_binlog_row_based();
bzero((char *) &status_var, sizeof(status_var));
+ bzero((char *) &org_status_var, sizeof(org_status_var));
sql_log_bin_toplevel= options & OPTION_BIN_LOG;
-
+ select_commands= update_commands= other_commands= 0;
+ /* Set to handle counting of aborted connections */
+ userstat_running= opt_userstat_running;
+ last_global_update_time= current_connect_time= time(NULL);
#if defined(ENABLED_DEBUG_SYNC)
/* Initialize the Debug Sync Facility. See debug_sync.cc. */
debug_sync_init_thread(this);
#endif /* defined(ENABLED_DEBUG_SYNC) */
}
+
+/* Updates some status variables to be used by update_global_user_stats */
+
+void THD::update_stats(void)
+{
+ /* sql_command == SQLCOM_END in case of parse errors or quit */
+ if (lex->sql_command != SQLCOM_END)
+ {
+ /* A SQL query. */
+ if (lex->sql_command == SQLCOM_SELECT)
+ select_commands++;
+ else if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
+ {
+ /* Ignore 'SHOW ' commands */
+ }
+ else if (is_update_query(lex->sql_command))
+ update_commands++;
+ else
+ other_commands++;
+ }
+}
+
+
+void THD::update_all_stats()
+{
+ time_t save_time;
+ ulonglong end_cpu_time, end_utime;
+ double busy_time, cpu_time;
+
+ /* This is set at start of query if opt_userstat_running was set */
+ if (!userstat_running)
+ return;
+
+ end_cpu_time= my_getcputime();
+ end_utime= my_micro_time_and_time(&save_time);
+ busy_time= (end_utime - start_utime) / 1000000.0;
+ cpu_time= (end_cpu_time - start_cpu_time) / 10000000.0;
+ /* In case there are bad values, 2629743 is the #seconds in a month. */
+ if (cpu_time > 2629743.0)
+ cpu_time= 0;
+ status_var_add(status_var.cpu_time, cpu_time);
+ status_var_add(status_var.busy_time, busy_time);
+
+ update_global_user_stats(this, TRUE, save_time);
+ userstat_running= 0;
+}
+
/*
Init THD for query processing.
@@ -1058,9 +1169,8 @@ THD::~THD()
from_var from this array
NOTES
- This function assumes that all variables are long/ulong.
- If this assumption will change, then we have to explictely add
- the other variables after the while loop
+ This function assumes that all variables at start are long/ulong and
+ other types are handled explicitely
*/
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
@@ -1072,6 +1182,13 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
while (to != end)
*(to++)+= *(from++);
+
+ /* Handle the not ulong variables. See end of system_status_var */
+ to_var->bytes_received= from_var->bytes_received;
+ to_var->bytes_sent+= from_var->bytes_sent;
+ to_var->binlog_bytes_written= from_var->binlog_bytes_written;
+ to_var->cpu_time+= from_var->cpu_time;
+ to_var->busy_time+= from_var->busy_time;
}
/*
@@ -1084,7 +1201,8 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
dec_var minus this array
NOTE
- This function assumes that all variables are long/ulong.
+ This function assumes that all variables at start are long/ulong and
+ other types are handled explicitely
*/
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
@@ -1097,6 +1215,14 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
while (to != end)
*(to++)+= *(from++) - *(dec++);
+
+ to_var->bytes_received= (from_var->bytes_received -
+ dec_var->bytes_received);
+ to_var->bytes_sent+= from_var->bytes_sent - dec_var->bytes_sent;
+ to_var->binlog_bytes_written= (from_var->binlog_bytes_written -
+ dec_var->binlog_bytes_written);
+ to_var->cpu_time+= from_var->cpu_time - dec_var->cpu_time;
+ to_var->busy_time+= from_var->busy_time - dec_var->busy_time;
}
#define SECONDS_TO_WAIT_FOR_KILL 2
@@ -2890,7 +3016,8 @@ void thd_increment_bytes_sent(ulong length)
{
THD *thd=current_thd;
if (likely(thd != 0))
- { /* current_thd==0 when close_connection() calls net_send_error() */
+ {
+ /* current_thd == 0 when close_connection() calls net_send_error() */
thd->status_var.bytes_sent+= length;
}
}
@@ -2916,9 +3043,9 @@ void THD::set_status_var_init()
void Security_context::init()
{
- host= user= priv_user= ip= 0;
+ host= user= ip= 0;
host_or_ip= "connecting host";
- priv_host[0]= '\0';
+ priv_user[0]= priv_host[0]= '\0';
master_access= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access= NO_ACCESS;
@@ -2942,8 +3069,7 @@ void Security_context::skip_grants()
/* privileges for the user are unknown everything is allowed */
host_or_ip= (char *)"";
master_access= ~NO_ACCESS;
- priv_user= (char *)"";
- *priv_host= '\0';
+ *priv_user= *priv_host= '\0';
}
@@ -2985,7 +3111,7 @@ bool Security_context::set_user(char *user_arg)
of a statement under credentials of a different user, e.g.
definer of a procedure, we authenticate this user in a local
instance of Security_context by means of this method (and
- ultimately by means of acl_getroot_no_password), and make the
+ ultimately by means of acl_getroot), and make the
local instance active in the thread by re-setting
thd->security_ctx pointer.
@@ -3019,19 +3145,12 @@ change_security_context(THD *thd,
DBUG_ASSERT(definer_user->str && definer_host->str);
*backup= NULL;
- /*
- The current security context may have NULL members
- if we have just started the thread and not authenticated
- any user. This use case is currently in events worker thread.
- */
- needs_change= (thd->security_ctx->priv_user == NULL ||
- strcmp(definer_user->str, thd->security_ctx->priv_user) ||
- thd->security_ctx->priv_host == NULL ||
+ needs_change= (strcmp(definer_user->str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info, definer_host->str,
thd->security_ctx->priv_host));
if (needs_change)
{
- if (acl_getroot_no_password(this, definer_user->str, definer_host->str,
+ if (acl_getroot(this, definer_user->str, definer_host->str,
definer_host->str, db->str))
{
my_error(ER_NO_SUCH_USER, MYF(0), definer_user->str,
@@ -3120,7 +3239,7 @@ extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd)
#ifdef INNODB_COMPATIBILITY_HOOKS
-extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd)
+extern "C" const struct charset_info_st *thd_charset(MYSQL_THD thd)
{
return(thd->charset());
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index fa802fea7ad..2240236a0e5 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -205,13 +205,15 @@ public:
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
+ engine_option_value *option_list;
bool generated;
Key(enum Keytype type_par, const char *name_arg,
KEY_CREATE_INFO *key_info_arg,
- bool generated_arg, List<Key_part_spec> &cols)
+ bool generated_arg, List<Key_part_spec> &cols,
+ engine_option_value *create_opt)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
- name(name_arg), generated(generated_arg)
+ name(name_arg), option_list(create_opt), generated(generated_arg)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -240,7 +242,7 @@ public:
Foreign_key(const char *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),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
@@ -252,6 +254,8 @@ public:
*/
virtual Key *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Foreign_key(*this, mem_root); }
+ /* Used to validate foreign key options */
+ bool validate(List<Create_field> &table_fields);
};
typedef struct st_mysql_lock
@@ -335,7 +339,6 @@ struct system_variables
ulong read_rnd_buff_size;
ulong div_precincrement;
ulong sortbuff_size;
- ulong thread_handling;
ulong tx_isolation;
ulong completion_type;
/* Determines which non-standard SQL behaviour should be enabled */
@@ -419,8 +422,6 @@ struct system_variables
typedef struct system_status_var
{
- ulonglong bytes_received;
- ulonglong bytes_sent;
ulong com_other;
ulong com_stat[(uint) SQLCOM_END];
ulong created_tmp_disk_tables;
@@ -459,6 +460,8 @@ typedef struct system_status_var
ulong select_range_count;
ulong select_range_check_count;
ulong select_scan_count;
+ ulong rows_read;
+ ulong rows_sent;
ulong long_query_count;
ulong filesort_merge_passes;
ulong filesort_range_count;
@@ -476,6 +479,9 @@ typedef struct system_status_var
Number of statements sent from the client
*/
ulong questions;
+ ulong empty_queries;
+ ulong access_denied_errors; /* Can only be 0 or 1 */
+ ulong lost_connections;
/*
IMPORTANT!
SEE last_system_status_var DEFINITION BELOW.
@@ -484,12 +490,16 @@ typedef struct system_status_var
Status variables which it does not make sense to add to
global status variable counter
*/
+ ulonglong bytes_received;
+ ulonglong bytes_sent;
+ ulonglong binlog_bytes_written;
double last_query_cost;
+ double cpu_time, busy_time;
} STATUS_VAR;
/*
This is used for 'SHOW STATUS'. It must be updated to the last ulong
- variable in system_status_var which is makes sens to add to the global
+ variable in system_status_var which is makes sense to add to the global
counter
*/
@@ -797,7 +807,8 @@ public:
priv_user - The user privilege we are using. May be "" for anonymous user.
ip - client IP
*/
- char *host, *user, *priv_user, *ip;
+ char *host, *user, *ip;
+ char priv_user[USERNAME_LENGTH];
/* The host privilege we are using */
char priv_host[MAX_HOSTNAME];
/* points to host if host is available, otherwise points to ip */
@@ -1339,6 +1350,7 @@ public:
struct my_rnd_struct rand; // used for authentication
struct system_variables variables; // Changeable local variables
struct system_status_var status_var; // Per thread statistic vars
+ struct system_status_var org_status_var; // For user statistics
struct system_status_var *initial_status_var; /* used by show status */
THR_LOCK_INFO lock_info; // Locking info of this thread
THR_LOCK_OWNER main_lock_id; // To use for conventional queries
@@ -1439,6 +1451,8 @@ public:
uint in_sub_stmt;
/* TRUE when the current top has SQL_LOG_BIN ON */
bool sql_log_bin_toplevel;
+ /* True when opt_userstat_running is set at start of query */
+ bool userstat_running;
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
@@ -1889,6 +1903,21 @@ public:
*/
LOG_INFO* current_linfo;
NET* slave_net; // network connection from slave -> m.
+
+ /*
+ Used to update global user stats. The global user stats are updated
+ occasionally with the 'diff' variables. After the update, the 'diff'
+ variables are reset to 0.
+ */
+ /* Time when the current thread connected to MySQL. */
+ time_t current_connect_time;
+ /* Last time when THD stats were updated in global_user_stats. */
+ time_t last_global_update_time;
+ /* Number of commands not reflected in global_user_stats yet. */
+ uint select_commands, update_commands, other_commands;
+ ulonglong start_cpu_time;
+ ulonglong start_bytes_received;
+
/* Used by the sys_var class to store temporary values */
union
{
@@ -1954,6 +1983,8 @@ public:
alloc_root.
*/
void init_for_queries();
+ void update_all_stats();
+ void update_stats(void);
void change_user(void);
void cleanup(void);
void cleanup_after_query();
@@ -2360,6 +2391,27 @@ public:
Protected with LOCK_thd_data mutex.
*/
void set_query(char *query_arg, uint32 query_length_arg);
+
+private:
+ /*
+ This reference points to the table arena when the expression
+ for a virtual column is being evaluated
+ */
+ Query_arena *arena_for_cached_items;
+
+public:
+ void reset_arena_for_cached_items(Query_arena *new_arena)
+ {
+ arena_for_cached_items= new_arena;
+ }
+ Query_arena *switch_to_arena_for_cached_items(Query_arena *backup)
+ {
+ if (!arena_for_cached_items)
+ return 0;
+ set_n_backup_active_arena(arena_for_cached_items, backup);
+ return backup;
+ }
+
private:
/** The current internal error handler for this thread, or NULL. */
Internal_error_handler *m_internal_handler;
@@ -2381,7 +2433,6 @@ private:
MEM_ROOT main_mem_root;
};
-
/** A short cut for thd->main_da.set_ok_status(). */
inline void
@@ -3117,4 +3168,150 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
STATUS_VAR *dec_var);
void mark_transaction_to_rollback(THD *thd, bool all);
+/*
+ inline handler methods that need to know TABLE and THD structures
+*/
+inline void handler::increment_statistics(ulong SSV::*offset) const
+{
+ status_var_increment(table->in_use->status_var.*offset);
+}
+
+inline void handler::decrement_statistics(ulong SSV::*offset) const
+{
+ status_var_decrement(table->in_use->status_var.*offset);
+}
+
+inline int handler::ha_index_read_map(uchar * buf, const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
+{
+ DBUG_ASSERT(inited==INDEX);
+ increment_statistics(&SSV::ha_read_key_count);
+ int error= index_read_map(buf, key, keypart_map, find_flag);
+ if (!error)
+ update_index_statistics();
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_index_read_idx_map(uchar * buf, uint index,
+ const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
+{
+ increment_statistics(&SSV::ha_read_key_count);
+ int error= index_read_idx_map(buf, index, key, keypart_map, find_flag);
+ if (!error)
+ {
+ rows_read++;
+ index_rows_read[index]++;
+ }
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_index_next(uchar * buf)
+{
+ DBUG_ASSERT(inited==INDEX);
+ increment_statistics(&SSV::ha_read_next_count);
+ int error= index_next(buf);
+ if (!error)
+ update_index_statistics();
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_index_prev(uchar * buf)
+{
+ DBUG_ASSERT(inited==INDEX);
+ increment_statistics(&SSV::ha_read_prev_count);
+ int error= index_prev(buf);
+ if (!error)
+ update_index_statistics();
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_index_first(uchar * buf)
+{
+ DBUG_ASSERT(inited==INDEX);
+ increment_statistics(&SSV::ha_read_first_count);
+ int error= index_first(buf);
+ if (!error)
+ update_index_statistics();
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_index_last(uchar * buf)
+{
+ DBUG_ASSERT(inited==INDEX);
+ increment_statistics(&SSV::ha_read_last_count);
+ int error= index_last(buf);
+ if (!error)
+ update_index_statistics();
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_index_next_same(uchar *buf, const uchar *key,
+ uint keylen)
+{
+ DBUG_ASSERT(inited==INDEX);
+ increment_statistics(&SSV::ha_read_next_count);
+ int error= index_next_same(buf, key, keylen);
+ if (!error)
+ update_index_statistics();
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_ft_read(uchar *buf)
+{
+ int error= ft_read(buf);
+ if (!error)
+ rows_read++;
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_rnd_next(uchar *buf)
+{
+ increment_statistics(&SSV::ha_read_rnd_next_count);
+ int error= rnd_next(buf);
+ if (!error)
+ rows_read++;
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_rnd_pos(uchar *buf, uchar *pos)
+{
+ increment_statistics(&SSV::ha_read_rnd_count);
+ int error= rnd_pos(buf, pos);
+ if (!error)
+ rows_read++;
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_rnd_pos_by_record(uchar *buf)
+{
+ int error= rnd_pos_by_record(buf);
+ if (!error)
+ rows_read++;
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+inline int handler::ha_read_first_row(uchar *buf, uint primary_key)
+{
+ int error= read_first_row(buf, primary_key);
+ if (!error)
+ rows_read++;
+ table->status=error ? STATUS_NOT_FOUND: 0;
+ return error;
+}
+
+
#endif /* MYSQL_SERVER */
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 67d52b26900..1c2ae915259 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -20,23 +20,12 @@
#include "mysql_priv.h"
-#ifdef HAVE_OPENSSL
-/*
- Without SSL the handshake consists of one packet. This packet
- has both client capabilites and scrambled password.
- With SSL the handshake might consist of two packets. If the first
- packet (client capabilities) has CLIENT_SSL flag set, we have to
- switch to SSL and read the second packet. The scrambled password
- is in the second packet and client_capabilites field will be ignored.
- Maybe it is better to accept flags other than CLIENT_SSL from the
- second packet?
-*/
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
-#else
-#define MIN_HANDSHAKE_SIZE 6
-#endif /* HAVE_OPENSSL */
+HASH global_user_stats, global_client_stats, global_table_stats;
+HASH global_index_stats;
+/* Protects the above global stats */
+extern pthread_mutex_t LOCK_global_user_client_stats;
+extern pthread_mutex_t LOCK_global_table_stats;
+extern pthread_mutex_t LOCK_global_index_stats;
#ifdef __WIN__
extern void win_install_sigabrt_handler();
@@ -49,9 +38,9 @@ extern void win_install_sigabrt_handler();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
static HASH hash_user_connections;
-static int get_or_create_user_conn(THD *thd, const char *user,
- const char *host,
- USER_RESOURCES *mqh)
+int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host,
+ USER_RESOURCES *mqh)
{
int return_val= 0;
size_t temp_len, user_len;
@@ -117,7 +106,6 @@ end:
1 error
*/
-static
int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
@@ -270,241 +258,6 @@ end:
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-/**
- Check if user exist and password supplied is correct.
-
- @param thd thread handle, thd->security_ctx->{host,user,ip} are used
- @param command originator of the check: now check_user is called
- during connect and change user procedures; used for
- logging.
- @param passwd scrambled password received from client
- @param passwd_len length of scrambled password
- @param db database name to connect to, may be NULL
- @param check_count TRUE if establishing a new connection. In this case
- check that we have not exceeded the global
- max_connections limist
-
- @note Host, user and passwd may point to communication buffer.
- Current implementation does not depend on that, but future changes
- should be done with this in mind; 'thd' is INOUT, all other params
- are 'IN'.
-
- @retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and
- thd->db are updated; OK is sent to the client.
- @retval 1 error, e.g. access denied or handshake error, not sent to
- the client. A message is pushed into the error stack.
-*/
-
-int
-check_user(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count)
-{
- DBUG_ENTER("check_user");
- LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
-
- /*
- Clear thd->db as it points to something, that will be freed when
- connection is closed. We don't want to accidentally free a wrong
- pointer if connect failed. Also in case of 'CHANGE USER' failure,
- current database will be switched to 'no database selected'.
- */
- thd->reset_db(NULL, 0);
-
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
- thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights
- /* Change database if necessary */
- if (db && db[0])
- {
- if (mysql_change_db(thd, &db_str, FALSE))
- DBUG_RETURN(1);
- }
- my_ok(thd);
- DBUG_RETURN(0);
-#else
-
- my_bool opt_secure_auth_local;
- pthread_mutex_lock(&LOCK_global_system_variables);
- opt_secure_auth_local= opt_secure_auth;
- pthread_mutex_unlock(&LOCK_global_system_variables);
-
- /*
- If the server is running in secure auth mode, short scrambles are
- forbidden.
- */
- if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
- {
- my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
- general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
- DBUG_RETURN(1);
- }
- if (passwd_len != 0 &&
- passwd_len != SCRAMBLE_LENGTH &&
- passwd_len != SCRAMBLE_LENGTH_323)
- {
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
-
- USER_RESOURCES ur;
- int res= acl_getroot(thd, &ur, passwd, passwd_len);
-#ifndef EMBEDDED_LIBRARY
- if (res == -1)
- {
- /*
- This happens when client (new) sends password scrambled with
- scramble(), but database holds old value (scrambled with
- scramble_323()). Here we please client to send scrambled_password
- in old format.
- */
- NET *net= &thd->net;
- if (opt_secure_auth_local)
- {
- my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip);
- general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
- /* We have to read very specific packet size */
- if (send_old_password_request(thd) ||
- my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- DBUG_RETURN(1);
- }
- /* Final attempt to check the user based on reply */
- /* So as passwd is short, errcode is always >= 0 */
- res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
- }
-#endif /*EMBEDDED_LIBRARY*/
- /* here res is always >= 0 */
- if (res == 0)
- {
- if (!(thd->main_security_ctx.master_access &
- NO_ACCESS)) // authentication is OK
- {
- DBUG_PRINT("info",
- ("Capabilities: %lu packet_length: %ld Host: '%s' "
- "Login user: '%s' Priv_user: '%s' Using password: %s "
- "Access: %lu db: '%s'",
- thd->client_capabilities,
- thd->max_client_packet_length,
- thd->main_security_ctx.host_or_ip,
- thd->main_security_ctx.user,
- thd->main_security_ctx.priv_user,
- passwd_len ? "yes": "no",
- thd->main_security_ctx.master_access,
- (thd->db ? thd->db : "*none*")));
-
- if (check_count)
- {
- bool count_ok= 1;
-
- if (!(thd->main_security_ctx.master_access & SUPER_ACL))
- {
- pthread_mutex_lock(&LOCK_connection_count);
- count_ok= (*thd->scheduler->connection_count <=
- *thd->scheduler->max_connections);
- VOID(pthread_mutex_unlock(&LOCK_connection_count));
- }
- if (!count_ok)
- { // too many connections
- my_error(ER_CON_COUNT_ERROR, MYF(0));
- DBUG_RETURN(1);
- }
- }
-
- /*
- Log the command before authentication checks, so that the user can
- check the log for the tried login tried and also to detect
- break-in attempts.
- */
- general_log_print(thd, command,
- (thd->main_security_ctx.priv_user ==
- thd->main_security_ctx.user ?
- (char*) "%s@%s on %s" :
- (char*) "%s@%s as anonymous on %s"),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- db ? db : (char*) "");
-
- /*
- This is the default access rights for the current database. It's
- set to 0 here because we don't have an active database yet (and we
- may not have an active database to set.
- */
- thd->main_security_ctx.db_access=0;
-
- /* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
- max_user_connections) &&
- get_or_create_user_conn(thd,
- (opt_old_style_user_limits ? thd->main_security_ctx.user :
- thd->main_security_ctx.priv_user),
- (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
- thd->main_security_ctx.priv_host),
- &ur))
- {
- /* The error is set by get_or_create_user_conn(). */
- DBUG_RETURN(1);
- }
- if (thd->user_connect &&
- (thd->user_connect->user_resources.conn_per_hour ||
- thd->user_connect->user_resources.user_conn ||
- max_user_connections) &&
- check_for_max_user_connections(thd, thd->user_connect))
- {
- /* The error is set in check_for_max_user_connections(). */
- DBUG_RETURN(1);
- }
-
- /* Change database if necessary */
- if (db && db[0])
- {
- if (mysql_change_db(thd, &db_str, FALSE))
- {
- /* mysql_change_db() has pushed the error message. */
- if (thd->user_connect)
- decrease_user_connections(thd->user_connect);
- DBUG_RETURN(1);
- }
- }
- my_ok(thd);
- /*
- Allow the network layer to skip big packets. Although a malicious
- authenticated session might use this to trick the server to read
- big packets indefinitely, this is a previously established behavior
- that needs to be preserved as to not break backwards compatibility.
- */
- thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
- thd->password= test(passwd_len); // remember for error messages
- /* Ready to handle queries */
- DBUG_RETURN(0);
- }
- }
- else if (res == 2) // client gave short hash, server has long hash
- {
- my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
- general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
- DBUG_RETURN(1);
- }
- my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
- general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
- thd->main_security_ctx.user,
- thd->main_security_ctx.host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
- DBUG_RETURN(1);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-}
-
-
/*
Check for maximum allowable user connections, if the mysqld server is
started with corresponding variable that is greater then 0.
@@ -527,10 +280,14 @@ 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);
+ if (hash_init(&hash_user_connections,system_charset_info,max_connections,
+ 0,0,
+ (hash_get_key) get_key_conn, (hash_free_key) free_user,
+ 0))
+ {
+ sql_print_error("Initializing hash_user_connections failed.");
+ exit(1);
+ }
#endif
}
@@ -583,6 +340,445 @@ void reset_mqh(LEX_USER *lu, bool get_them= 0)
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
+/*****************************************************************************
+ Handle users statistics
+*****************************************************************************/
+
+/* 'mysql_system_user' is used for when the user is not defined for a THD. */
+static const char mysql_system_user[]= "#mysql_system#";
+
+// Returns 'user' if it's not NULL. Returns 'mysql_system_user' otherwise.
+static const char * get_valid_user_string(char* user)
+{
+ return user ? user : mysql_system_user;
+}
+
+/*
+ Returns string as 'IP' for the client-side of the connection represented by
+ 'client'. Does not allocate memory. May return "".
+*/
+
+static const char *get_client_host(THD *client)
+{
+ return client->security_ctx->host_or_ip[0] ?
+ client->security_ctx->host_or_ip :
+ client->security_ctx->host ? client->security_ctx->host : "";
+}
+
+extern "C" uchar *get_key_user_stats(USER_STATS *user_stats, size_t *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= user_stats->user_name_length;
+ return (uchar*) user_stats->user;
+}
+
+void free_user_stats(USER_STATS* user_stats)
+{
+ my_free(user_stats, MYF(0));
+}
+
+void init_user_stats(USER_STATS *user_stats,
+ const char *user,
+ size_t user_length,
+ const char *priv_user,
+ uint total_connections,
+ uint concurrent_connections,
+ time_t connected_time,
+ double busy_time,
+ double cpu_time,
+ ulonglong bytes_received,
+ ulonglong bytes_sent,
+ ulonglong binlog_bytes_written,
+ ha_rows rows_sent,
+ ha_rows rows_read,
+ ha_rows rows_inserted,
+ ha_rows rows_deleted,
+ ha_rows rows_updated,
+ ulonglong select_commands,
+ ulonglong update_commands,
+ ulonglong other_commands,
+ ulonglong commit_trans,
+ ulonglong rollback_trans,
+ ulonglong denied_connections,
+ ulonglong lost_connections,
+ ulonglong access_denied_errors,
+ ulonglong empty_queries)
+{
+ DBUG_ENTER("init_user_stats");
+ DBUG_PRINT("enter", ("user: %s priv_user: %s", user, priv_user));
+
+ user_length= min(user_length, sizeof(user_stats->user)-1);
+ memcpy(user_stats->user, user, user_length);
+ user_stats->user[user_length]= 0;
+ user_stats->user_name_length= user_length;
+ strmake(user_stats->priv_user, priv_user, sizeof(user_stats->priv_user)-1);
+
+ user_stats->total_connections= total_connections;
+ user_stats->concurrent_connections= concurrent_connections;
+ user_stats->connected_time= connected_time;
+ user_stats->busy_time= busy_time;
+ user_stats->cpu_time= cpu_time;
+ user_stats->bytes_received= bytes_received;
+ user_stats->bytes_sent= bytes_sent;
+ user_stats->binlog_bytes_written= binlog_bytes_written;
+ user_stats->rows_sent= rows_sent;
+ user_stats->rows_updated= rows_updated;
+ user_stats->rows_read= rows_read;
+ user_stats->select_commands= select_commands;
+ user_stats->update_commands= update_commands;
+ user_stats->other_commands= other_commands;
+ user_stats->commit_trans= commit_trans;
+ user_stats->rollback_trans= rollback_trans;
+ user_stats->denied_connections= denied_connections;
+ user_stats->lost_connections= lost_connections;
+ user_stats->access_denied_errors= access_denied_errors;
+ user_stats->empty_queries= empty_queries;
+ DBUG_VOID_RETURN;
+}
+
+
+#ifdef COMPLEAT_PATCH_NOT_ADDED_YET
+
+void add_user_stats(USER_STATS *user_stats,
+ uint total_connections,
+ uint concurrent_connections,
+ time_t connected_time,
+ double busy_time,
+ double cpu_time,
+ ulonglong bytes_received,
+ ulonglong bytes_sent,
+ ulonglong binlog_bytes_written,
+ ha_rows rows_sent,
+ ha_rows rows_read,
+ ha_rows rows_inserted,
+ ha_rows rows_deleted,
+ ha_rows rows_updated,
+ ulonglong select_commands,
+ ulonglong update_commands,
+ ulonglong other_commands,
+ ulonglong commit_trans,
+ ulonglong rollback_trans,
+ ulonglong denied_connections,
+ ulonglong lost_connections,
+ ulonglong access_denied_errors,
+ ulonglong empty_queries)
+{
+ user_stats->total_connections+= total_connections;
+ user_stats->concurrent_connections+= concurrent_connections;
+ user_stats->connected_time+= connected_time;
+ user_stats->busy_time+= busy_time;
+ user_stats->cpu_time+= cpu_time;
+ user_stats->bytes_received+= bytes_received;
+ user_stats->bytes_sent+= bytes_sent;
+ user_stats->binlog_bytes_written+= binlog_bytes_written;
+ user_stats->rows_sent+= rows_sent;
+ user_stats->rows_inserted+= rows_inserted;
+ user_stats->rows_deleted+= rows_deleted;
+ user_stats->rows_updated+= rows_updated;
+ user_stats->rows_read+= rows_read;
+ user_stats->select_commands+= select_commands;
+ user_stats->update_commands+= update_commands;
+ user_stats->other_commands+= other_commands;
+ user_stats->commit_trans+= commit_trans;
+ user_stats->rollback_trans+= rollback_trans;
+ user_stats->denied_connections+= denied_connections;
+ user_stats->lost_connections+= lost_connections;
+ user_stats->access_denied_errors+= access_denied_errors;
+ user_stats->empty_queries+= empty_queries;
+}
+#endif
+
+
+void init_global_user_stats(void)
+{
+ if (hash_init(&global_user_stats, system_charset_info, max_connections,
+ 0, 0, (hash_get_key) get_key_user_stats,
+ (hash_free_key)free_user_stats, 0))
+ {
+ sql_print_error("Initializing global_user_stats failed.");
+ exit(1);
+ }
+}
+
+void init_global_client_stats(void)
+{
+ if (hash_init(&global_client_stats, system_charset_info, max_connections,
+ 0, 0, (hash_get_key) get_key_user_stats,
+ (hash_free_key)free_user_stats, 0))
+ {
+ sql_print_error("Initializing global_client_stats failed.");
+ exit(1);
+ }
+}
+
+extern "C" uchar *get_key_table_stats(TABLE_STATS *table_stats, size_t *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= table_stats->table_name_length;
+ return (uchar*) table_stats->table;
+}
+
+extern "C" void free_table_stats(TABLE_STATS* table_stats)
+{
+ my_free(table_stats, MYF(0));
+}
+
+void init_global_table_stats(void)
+{
+ if (hash_init(&global_table_stats, system_charset_info, max_connections,
+ 0, 0, (hash_get_key) get_key_table_stats,
+ (hash_free_key)free_table_stats, 0)) {
+ sql_print_error("Initializing global_table_stats failed.");
+ exit(1);
+ }
+}
+
+extern "C" uchar *get_key_index_stats(INDEX_STATS *index_stats, size_t *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= index_stats->index_name_length;
+ return (uchar*) index_stats->index;
+}
+
+extern "C" void free_index_stats(INDEX_STATS* index_stats)
+{
+ my_free(index_stats, MYF(0));
+}
+
+void init_global_index_stats(void)
+{
+ if (hash_init(&global_index_stats, system_charset_info, max_connections,
+ 0, 0, (hash_get_key) get_key_index_stats,
+ (hash_free_key)free_index_stats, 0))
+ {
+ sql_print_error("Initializing global_index_stats failed.");
+ exit(1);
+ }
+}
+
+
+void free_global_user_stats(void)
+{
+ hash_free(&global_user_stats);
+}
+
+void free_global_table_stats(void)
+{
+ hash_free(&global_table_stats);
+}
+
+void free_global_index_stats(void)
+{
+ hash_free(&global_index_stats);
+}
+
+void free_global_client_stats(void)
+{
+ hash_free(&global_client_stats);
+}
+
+/*
+ Increments the global stats connection count for an entry from
+ global_client_stats or global_user_stats. Returns 0 on success
+ and 1 on error.
+*/
+
+static bool increment_count_by_name(const char *name, size_t name_length,
+ const char *role_name,
+ HASH *users_or_clients, THD *thd)
+{
+ USER_STATS *user_stats;
+
+ if (!(user_stats= (USER_STATS*) hash_search(users_or_clients, (uchar*) name,
+ name_length)))
+ {
+ /* First connection for this user or client */
+ if (!(user_stats= ((USER_STATS*)
+ my_malloc(sizeof(USER_STATS),
+ MYF(MY_WME | MY_ZEROFILL)))))
+ return TRUE; // Out of memory
+
+ init_user_stats(user_stats, name, name_length, role_name,
+ 0, 0, // connections
+ 0, 0, 0, // time
+ 0, 0, 0, // bytes sent, received and written
+ 0, 0, // Rows sent and read
+ 0, 0, 0, // rows inserted, deleted and updated
+ 0, 0, 0, // select, update and other commands
+ 0, 0, // commit and rollback trans
+ thd->status_var.access_denied_errors,
+ 0, // lost connections
+ 0, // access denied errors
+ 0); // empty queries
+
+ if (my_hash_insert(users_or_clients, (uchar*)user_stats))
+ {
+ my_free(user_stats, 0);
+ return TRUE; // Out of memory
+ }
+ }
+ user_stats->total_connections++;
+ return FALSE;
+}
+
+
+/*
+ Increments the global user and client stats connection count.
+
+ @param use_lock if true, LOCK_global_user_client_stats will be locked
+
+ @retval 0 ok
+ @retval 1 error.
+*/
+
+#ifndef EMBEDDED_LIBRARY
+static bool increment_connection_count(THD* thd, bool use_lock)
+{
+ const char *user_string= get_valid_user_string(thd->main_security_ctx.user);
+ const char *client_string= get_client_host(thd);
+ bool return_value= FALSE;
+
+ if (!thd->userstat_running)
+ return FALSE;
+
+ if (use_lock)
+ pthread_mutex_lock(&LOCK_global_user_client_stats);
+
+ if (increment_count_by_name(user_string, strlen(user_string), user_string,
+ &global_user_stats, thd))
+ {
+ return_value= TRUE;
+ goto end;
+ }
+ if (increment_count_by_name(client_string, strlen(client_string),
+ user_string, &global_client_stats, thd))
+ {
+ return_value= TRUE;
+ goto end;
+ }
+
+end:
+ if (use_lock)
+ pthread_mutex_unlock(&LOCK_global_user_client_stats);
+ return return_value;
+}
+#endif
+
+/*
+ Used to update the global user and client stats
+*/
+
+static void update_global_user_stats_with_user(THD *thd,
+ USER_STATS *user_stats,
+ time_t now)
+{
+ DBUG_ASSERT(thd->userstat_running);
+
+ user_stats->connected_time+= now - thd->last_global_update_time;
+ user_stats->busy_time+= (thd->status_var.busy_time -
+ thd->org_status_var.busy_time);
+ user_stats->cpu_time+= (thd->status_var.cpu_time -
+ thd->org_status_var.cpu_time);
+ /*
+ This is handle specially as bytes_recieved is incremented BEFORE
+ org_status_var is copied.
+ */
+ user_stats->bytes_received+= (thd->org_status_var.bytes_received-
+ thd->start_bytes_received);
+ user_stats->bytes_sent+= (thd->status_var.bytes_sent -
+ thd->org_status_var.bytes_sent);
+ user_stats->binlog_bytes_written+=
+ (thd->status_var.binlog_bytes_written -
+ thd->org_status_var.binlog_bytes_written);
+ user_stats->rows_read+= (thd->status_var.rows_read -
+ thd->org_status_var.rows_read);
+ user_stats->rows_sent+= (thd->status_var.rows_sent -
+ thd->org_status_var.rows_sent);
+ user_stats->rows_inserted+= (thd->status_var.ha_write_count -
+ thd->org_status_var.ha_write_count);
+ user_stats->rows_deleted+= (thd->status_var.ha_delete_count -
+ thd->org_status_var.ha_delete_count);
+ user_stats->rows_updated+= (thd->status_var.ha_update_count -
+ thd->org_status_var.ha_update_count);
+ user_stats->select_commands+= thd->select_commands;
+ user_stats->update_commands+= thd->update_commands;
+ user_stats->other_commands+= thd->other_commands;
+ user_stats->commit_trans+= (thd->status_var.ha_commit_count -
+ thd->org_status_var.ha_commit_count);
+ user_stats->rollback_trans+= (thd->status_var.ha_rollback_count +
+ thd->status_var.ha_savepoint_rollback_count -
+ thd->org_status_var.ha_rollback_count -
+ thd->org_status_var.
+ ha_savepoint_rollback_count);
+ user_stats->access_denied_errors+=
+ (thd->status_var.access_denied_errors -
+ thd->org_status_var.access_denied_errors);
+ user_stats->empty_queries+= (thd->status_var.empty_queries -
+ thd->org_status_var.empty_queries);
+
+ /* The following can only contain 0 or 1 and then connection ends */
+ user_stats->denied_connections+= thd->status_var.access_denied_errors;
+ user_stats->lost_connections+= thd->status_var.lost_connections;
+}
+
+
+/* Updates the global stats of a user or client */
+void update_global_user_stats(THD *thd, bool create_user, time_t now)
+{
+ const char *user_string, *client_string;
+ USER_STATS *user_stats;
+ size_t user_string_length, client_string_length;
+ DBUG_ASSERT(thd->userstat_running);
+
+ user_string= get_valid_user_string(thd->main_security_ctx.user);
+ user_string_length= strlen(user_string);
+ client_string= get_client_host(thd);
+ client_string_length= strlen(client_string);
+
+ pthread_mutex_lock(&LOCK_global_user_client_stats);
+
+ // Update by user name
+ if ((user_stats= (USER_STATS*) hash_search(&global_user_stats,
+ (uchar*) user_string,
+ user_string_length)))
+ {
+ /* Found user. */
+ update_global_user_stats_with_user(thd, user_stats, now);
+ }
+ else
+ {
+ /* Create the entry */
+ if (create_user)
+ {
+ increment_count_by_name(user_string, user_string_length, user_string,
+ &global_user_stats, thd);
+ }
+ }
+
+ /* Update by client IP */
+ if ((user_stats= (USER_STATS*)hash_search(&global_client_stats,
+ (uchar*) client_string,
+ client_string_length)))
+ {
+ // Found by client IP
+ update_global_user_stats_with_user(thd, user_stats, now);
+ }
+ else
+ {
+ // Create the entry
+ if (create_user)
+ {
+ increment_count_by_name(client_string, client_string_length,
+ user_string, &global_client_stats, thd);
+ }
+ }
+ /* Reset variables only used for counting */
+ thd->select_commands= thd->update_commands= thd->other_commands= 0;
+ thd->last_global_update_time= now;
+
+ pthread_mutex_unlock(&LOCK_global_user_client_stats);
+}
+
void thd_init_client_charset(THD *thd, uint cs_number)
{
@@ -640,9 +836,8 @@ bool init_new_connection_handler_thread()
thd thread handle
RETURN
- 0 success, OK is sent to user, thd is updated.
- -1 error, which is sent to user
- > 0 error code (not sent to user)
+ 0 success, thd is updated.
+ 1 error
*/
#ifndef EMBEDDED_LIBRARY
@@ -650,8 +845,6 @@ static int check_connection(THD *thd)
{
uint connect_errors= 0;
NET *net= &thd->net;
- ulong pkt_len= 0;
- char *end;
DBUG_PRINT("info",
("New connection received on %s", vio_description(net->vio)));
@@ -713,200 +906,10 @@ static int check_connection(THD *thd)
}
vio_keepalive(net->vio, TRUE);
- ulong server_capabilites;
- {
- /* buff[] needs to big enough to hold the server_version variable */
- char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64];
- server_capabilites= CLIENT_BASIC_FLAGS;
-
- if (opt_using_transactions)
- server_capabilites|= CLIENT_TRANSACTIONS;
-#ifdef HAVE_COMPRESS
- server_capabilites|= CLIENT_COMPRESS;
-#endif /* HAVE_COMPRESS */
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- {
- server_capabilites |= CLIENT_SSL; /* Wow, SSL is available! */
- server_capabilites |= CLIENT_SSL_VERIFY_SERVER_CERT;
- }
-#endif /* HAVE_OPENSSL */
-
- end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
- int4store((uchar*) end, thd->thread_id);
- end+= 4;
- /*
- So as check_connection is the only entry point to authorization
- procedure, scramble is set here. This gives us new scramble for
- each handshake.
- */
- create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
- /*
- Old clients does not understand long scrambles, but can ignore packet
- tail: that's why first part of the scramble is placed here, and second
- part at the end of packet.
- */
- end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
-
- int2store(end, server_capabilites);
- /* write server characteristics: up to 16 bytes allowed */
- end[2]=(char) default_charset_info->number;
- int2store(end+3, thd->server_status);
- bzero(end+5, 13);
- end+= 18;
- /* write scramble tail */
- end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
- SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
-
- /* At this point we write connection message and read reply */
- if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
- (uchar*) buff, (size_t) (end-buff)) ||
- (pkt_len= my_net_read(net)) == packet_error ||
- pkt_len < MIN_HANDSHAKE_SIZE)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0),
- thd->main_security_ctx.host_or_ip);
- return 1;
- }
- }
-#ifdef _CUSTOMCONFIG_
-#include "_cust_sql_parse.h"
-#endif
- if (connect_errors)
- reset_host_errors(&thd->remote.sin_addr);
if (thd->packet.alloc(thd->variables.net_buffer_length))
return 1; /* The error is set by alloc(). */
- thd->client_capabilities= uint2korr(net->read_pos);
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
- thd->max_client_packet_length= uint4korr(net->read_pos+4);
- DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
- thd_init_client_charset(thd, (uint) net->read_pos[8]);
- thd->update_charset();
- end= (char*) net->read_pos+32;
- }
- else
- {
- thd->max_client_packet_length= uint3korr(net->read_pos+2);
- end= (char*) net->read_pos+5;
- }
- /*
- Disable those bits which are not supported by the server.
- This is a precautionary measure, if the client lies. See Bug#27944.
- */
- thd->client_capabilities&= server_capabilites;
-
- if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
- thd->variables.sql_mode|= MODE_IGNORE_SPACE;
-#ifdef HAVE_OPENSSL
- DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
- if (thd->client_capabilities & CLIENT_SSL)
- {
- char error_string[1024];
- /* Do the SSL layering. */
- if (!ssl_acceptor_fd)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, error_string))
- {
- DBUG_PRINT("error", ("Failed to accept new SSL connection"));
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- DBUG_PRINT("info", ("Reading user information over SSL layer"));
- if ((pkt_len= my_net_read(net)) == packet_error ||
- pkt_len < NORMAL_HANDSHAKE_SIZE)
- {
- DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
- pkt_len));
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
- }
-#endif /* HAVE_OPENSSL */
-
- if (end >= (char*) net->read_pos+ pkt_len +2)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
-
- if (thd->client_capabilities & CLIENT_INTERACTIVE)
- thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
- if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
- opt_using_transactions)
- net->return_status= &thd->server_status;
-
- char *user= end;
- char *passwd= strend(user)+1;
- uint user_len= passwd - user - 1;
- char *db= passwd;
- char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
- char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
- uint dummy_errors;
-
- /*
- Old clients send null-terminated string as password; new clients send
- the size (1 byte) + string (not null-terminated). Hence in case of empty
- password both send '\0'.
-
- This strlen() can't be easily deleted without changing protocol.
-
- Cast *passwd to an unsigned char, so that it doesn't extend the sign for
- *passwd > 127 and become 2**32-127+ after casting to uint.
- */
- uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- (uchar)(*passwd++) : strlen(passwd);
- db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
- db + passwd_len + 1 : 0;
- /* strlen() can't be easily deleted without changing protocol */
- uint db_len= db ? strlen(db) : 0;
-
- if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
- {
- inc_host_errors(&thd->remote.sin_addr);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
- return 1;
- }
-
- /* Since 4.1 all database names are stored in utf8 */
- if (db)
- {
- db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info,
- db, db_len,
- thd->charset(), &dummy_errors)]= 0;
- db= db_buff;
- }
-
- user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
- system_charset_info, user, user_len,
- thd->charset(), &dummy_errors)]= '\0';
- user= user_buff;
-
- /* If username starts and ends in "'", chop them off */
- if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
- {
- user[user_len-1]= 0;
- user++;
- user_len-= 2;
- }
-
- if (thd->main_security_ctx.user)
- x_free(thd->main_security_ctx.user);
- if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
- return 1; /* The error is set by my_strdup(). */
- return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
+ return acl_authenticate(thd, connect_errors, 0);
}
@@ -978,6 +981,14 @@ bool login_connection(THD *thd)
/* Connect completed, set read/write timeouts back to default */
my_net_set_read_timeout(net, thd->variables.net_read_timeout);
my_net_set_write_timeout(net, thd->variables.net_write_timeout);
+
+ /* Updates global user connection stats. */
+ if (increment_connection_count(thd, TRUE))
+ {
+ net_send_error(thd, ER_OUTOFMEMORY); // Out of memory
+ DBUG_RETURN(1);
+ }
+
DBUG_RETURN(0);
}
@@ -999,6 +1010,7 @@ void end_connection(THD *thd)
if (thd->killed || (net->error && net->vio != 0))
{
statistic_increment(aborted_threads,&LOCK_status);
+ status_var_increment(thd->status_var.lost_connections);
}
if (net->error && net->vio != 0)
@@ -1125,10 +1137,14 @@ pthread_handler_t handle_one_connection(void *arg)
for (;;)
{
NET *net= &thd->net;
+ bool create_user= TRUE;
lex_start(thd);
if (login_connection(thd))
+ {
+ create_user= FALSE;
goto end_thread;
+ }
prepare_new_connection_state(thd);
@@ -1142,12 +1158,14 @@ pthread_handler_t handle_one_connection(void *arg)
end_thread:
close_connection(thd, 0, 1);
+ if (thd->userstat_running)
+ update_global_user_stats(thd, create_user, time(NULL));
+
if (thd->scheduler->end_thread(thd,1))
return 0; // Probably no-threads
/*
- If end_thread() returns, we are either running with
- thread-handler=no-threads or this thread has been schedule to
+ If end_thread() returns, this thread has been schedule to
handle the next connection.
*/
thd= current_thd;
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 6f61dc40f66..e9ef5ef0cf3 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -608,7 +608,7 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
thd->set_n_backup_active_arena(this, &backup_arena);
/* Create a list of fields and start sequential scan */
rc= result->prepare(item_list, &fake_unit);
- if (!rc && !(rc= table->file->ha_rnd_init(TRUE)))
+ if (!rc && !(rc= table->file->ha_rnd_init_with_error(TRUE)))
is_rnd_inited= 1;
thd->restore_active_arena(this, &backup_arena);
@@ -655,7 +655,7 @@ void Materialized_cursor::fetch(ulong num_rows)
result->begin_dataset();
for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++)
{
- if ((res= table->file->rnd_next(table->record[0])))
+ if ((res= table->file->ha_rnd_next(table->record[0])))
break;
/* Send data only if the read was successful. */
result->send_data(item_list);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 841f250e4c9..361a5db1f2c 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -266,8 +266,15 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE);
}
- if (usable_index==MAX_KEY || (select && select->quick))
- init_read_record(&info, thd, table, select, 1, 1, FALSE);
+ if (usable_index == MAX_KEY || (select && select->quick))
+ {
+ if (init_read_record(&info, thd, table, select, 1, 1, FALSE))
+ {
+ delete select;
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
+ }
+ }
else
init_read_record_idx(&info, thd, table, 1, usable_index);
@@ -305,6 +312,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
while (!(error=info.read_record(&info)) && !thd->killed &&
! thd->is_error())
{
+ update_virtual_fields(thd, table);
thd->examined_row_count++;
// thd->is_error() is tested to disallow delete row on error
if (!select || select->skip_record(thd) > 0)
@@ -945,7 +953,10 @@ int multi_delete::do_table_deletes(TABLE *table, bool ignore)
READ_RECORD info;
ha_rows last_deleted= deleted;
DBUG_ENTER("do_deletes_for_table");
- init_read_record(&info, thd, table, NULL, 0, 1, FALSE);
+
+ if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE))
+ DBUG_RETURN(1);
+
/*
Ignore any rows not found in reference tables as they may already have
been deleted by foreign key handling
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index bbc3d0b27a4..69be8c8e9b4 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -573,11 +573,11 @@ retry:
{
/* Check if we read from the same index. */
DBUG_ASSERT((uint) keyno == table->file->get_index());
- error= table->file->index_next(table->record[0]);
+ error= table->file->ha_index_next(table->record[0]);
}
else
{
- error= table->file->rnd_next(table->record[0]);
+ error= table->file->ha_rnd_next(table->record[0]);
}
break;
}
@@ -587,13 +587,13 @@ retry:
{
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno, 1);
- error= table->file->index_first(table->record[0]);
+ error= table->file->ha_index_first(table->record[0]);
}
else
{
table->file->ha_index_or_rnd_end();
if (!(error= table->file->ha_rnd_init(1)))
- error= table->file->rnd_next(table->record[0]);
+ error= table->file->ha_rnd_next(table->record[0]);
}
mode=RNEXT;
break;
@@ -603,7 +603,7 @@ retry:
DBUG_ASSERT((uint) keyno == table->file->get_index());
if (table->file->inited != handler::NONE)
{
- error=table->file->index_prev(table->record[0]);
+ error=table->file->ha_index_prev(table->record[0]);
break;
}
/* else fall through */
@@ -611,13 +611,13 @@ retry:
DBUG_ASSERT(keyname != 0);
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno, 1);
- error= table->file->index_last(table->record[0]);
+ error= table->file->ha_index_last(table->record[0]);
mode=RPREV;
break;
case RNEXT_SAME:
/* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */
DBUG_ASSERT(keyname != 0);
- error= table->file->index_next_same(table->record[0], key, key_len);
+ error= table->file->ha_index_next_same(table->record[0], key, key_len);
break;
case RKEY:
{
@@ -657,8 +657,8 @@ retry:
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno, 1);
key_copy(key, table->record[0], table->key_info + keyno, key_len);
- error= table->file->index_read_map(table->record[0],
- key, keypart_map, ha_rkey_mode);
+ error= table->file->ha_index_read_map(table->record[0],
+ key, keypart_map, ha_rkey_mode);
mode=rkey_to_rnext[(int)ha_rkey_mode];
break;
}
@@ -680,6 +680,8 @@ retry:
}
goto ok;
}
+ /* Generate values for virtual fields */
+ update_virtual_fields(thd, table);
if (cond && !cond->val_int())
continue;
if (num_rows >= offset_limit_cnt)
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 7eff6a5e0fa..916557a46c4 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -182,11 +182,14 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields,
SQL_SELECT *select, List<String> *names,
String *name, String *description, String *example)
{
- DBUG_ENTER("search_topics");
int count= 0;
-
READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE);
+ DBUG_ENTER("search_topics");
+
+ /* Should never happen. As this is part of help, we can ignore this */
+ if (init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE))
+ DBUG_RETURN(0);
+
while (!read_record_info.read_record(&read_record_info))
{
if (!select->cond->val_int()) // Doesn't match like
@@ -222,11 +225,13 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields,
int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields,
SQL_SELECT *select, int *key_id)
{
- DBUG_ENTER("search_keyword");
int count= 0;
-
READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE);
+ DBUG_ENTER("search_keyword");
+ /* Should never happen. As this is part of help, we can ignore this */
+ if (init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE))
+ DBUG_RETURN(0);
+
while (!read_record_info.read_record(&read_record_info) && count<2)
{
if (!select->cond->val_int()) // Dosn't match like
@@ -294,13 +299,13 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
rkey_id->store((longlong) key_id, TRUE);
rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);
- int key_res= relations->file->index_read_map(relations->record[0],
- buff, (key_part_map) 1,
- HA_READ_KEY_EXACT);
+ int key_res= relations->file->ha_index_read_map(relations->record[0],
+ buff, (key_part_map) 1,
+ HA_READ_KEY_EXACT);
for ( ;
!key_res && key_id == (int16) rkey_id->val_int() ;
- key_res= relations->file->index_next(relations->record[0]))
+ key_res= relations->file->ha_index_next(relations->record[0]))
{
uchar topic_id_buff[8];
longlong topic_id= rtopic_id->val_int();
@@ -308,8 +313,8 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
field->store((longlong) topic_id, TRUE);
field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW);
- if (!topics->file->index_read_map(topics->record[0], topic_id_buff,
- (key_part_map)1, HA_READ_KEY_EXACT))
+ if (!topics->file->ha_index_read_map(topics->record[0], topic_id_buff,
+ (key_part_map)1, HA_READ_KEY_EXACT))
{
memorize_variant_topic(thd,topics,count,find_fields,
names,name,description,example);
@@ -347,10 +352,11 @@ int search_categories(THD *thd, TABLE *categories,
Field *pcat_id= find_fields[help_category_help_category_id].field;
int count= 0;
READ_RECORD read_record_info;
-
DBUG_ENTER("search_categories");
- init_read_record(&read_record_info, thd, categories, select,1,0,FALSE);
+ /* Should never happen. As this is part of help, we can ignore this */
+ if (init_read_record(&read_record_info, thd, categories, select,1,0,FALSE))
+ DBUG_RETURN(0);
while (!read_record_info.read_record(&read_record_info))
{
if (select && !select->cond->val_int())
@@ -381,10 +387,13 @@ int search_categories(THD *thd, TABLE *categories,
void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
SQL_SELECT *select, List<String> *res)
{
+ READ_RECORD read_record_info;
DBUG_ENTER("get_all_items_for_category");
- READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, items, select,1,0,FALSE);
+ /* Should never happen. As this is part of help, we can ignore this */
+ if (init_read_record(&read_record_info, thd, items, select,1,0,FALSE))
+ DBUG_VOID_RETURN;
+
while (!read_record_info.read_record(&read_record_info))
{
if (!select->cond->val_int())
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 6b5d60d8613..ea138807122 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -72,15 +72,6 @@ static void unlink_blobs(register TABLE *table);
#endif
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
-/* Define to force use of my_malloc() if the allocated memory block is big */
-
-#ifndef HAVE_ALLOCA
-#define my_safe_alloca(size, min_length) my_alloca(size)
-#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
-#else
-#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
-#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
-#endif
/*
Check that insert/update fields are from the same single table of a view.
@@ -280,6 +271,9 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
}
}
}
+ /* Mark virtual columns used in the insert statement */
+ if (table->vfield)
+ table->mark_virtual_columns_for_write(TRUE);
// For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
@@ -1273,7 +1267,6 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (mysql_prepare_insert_check_table(thd, table_list, fields, select_insert))
DBUG_RETURN(TRUE);
-
/* Prepare the fields in the statement. */
if (values)
{
@@ -1326,6 +1319,18 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (!table)
table= table_list->table;
+ if (!fields.elements && table->vfield)
+ {
+ for (Field **vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->stored_in_db)
+ {
+ thd->lex->unit.insert_table_with_stored_vcol= table;
+ break;
+ }
+ }
+ }
+
if (!select_insert)
{
Item *fake_conds= 0;
@@ -1450,7 +1455,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
goto err;
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
{
- if (table->file->rnd_pos(table->record[1],table->file->dup_ref))
+ if (table->file->ha_rnd_pos(table->record[1],table->file->dup_ref))
goto err;
}
else
@@ -1471,9 +1476,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
}
key_copy((uchar*) key,table->record[0],table->key_info+key_nr,0);
- if ((error=(table->file->index_read_idx_map(table->record[1],key_nr,
- (uchar*) key, HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))))
+ if ((error= (table->file->ha_index_read_idx_map(table->record[1],
+ key_nr, (uchar*) key,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))))
goto err;
}
if (info->handle_duplicates == DUP_UPDATE)
@@ -1774,8 +1780,10 @@ public:
table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0),
group_count(0)
{
- thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user;
+ thd.security_ctx->user=(char*) delayed_user;
thd.security_ctx->host=(char*) my_localhost;
+ strmake(thd.security_ctx->priv_user, thd.security_ctx->user,
+ USERNAME_LENGTH);
thd.current_tablenr=0;
thd.version=refresh_version;
thd.command=COM_DELAYED_INSERT;
@@ -2101,7 +2109,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
(share->fields+1)*sizeof(Field**)+
share->reclength +
- share->column_bitmap_size*2);
+ share->column_bitmap_size*3);
if (!copy)
goto error;
@@ -2111,7 +2119,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
/* Assign the pointers for the field pointers array and the record. */
field= copy->field= (Field**) (copy + 1);
bitmap= (uchar*) (field + share->fields + 1);
- copy->record[0]= (bitmap + share->column_bitmap_size * 2);
+ copy->record[0]= (bitmap + share->column_bitmap_size*3);
memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength);
/*
Make a copy of all fields.
@@ -2153,10 +2161,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
copy->def_read_set.bitmap= (my_bitmap_map*) bitmap;
copy->def_write_set.bitmap= ((my_bitmap_map*)
(bitmap + share->column_bitmap_size));
+ copy->def_vcol_set.bitmap= ((my_bitmap_map*)
+ (bitmap + 2*share->column_bitmap_size));
copy->tmp_set.bitmap= 0; // To catch errors
- bzero((char*) bitmap, share->column_bitmap_size*2);
+ bzero((char*) bitmap, share->column_bitmap_size*3);
copy->read_set= &copy->def_read_set;
copy->write_set= &copy->def_write_set;
+ copy->vcol_set= &copy->def_vcol_set;
DBUG_RETURN(copy);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1cedb0c41db..33121e5301d 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -332,6 +332,7 @@ void lex_start(THD *thd)
lex->reset_query_tables_list(FALSE);
lex->expr_allows_subselect= TRUE;
lex->use_only_table_context= FALSE;
+ lex->parse_vcol_expr= FALSE;
lex->name.str= 0;
lex->name.length= 0;
@@ -781,9 +782,9 @@ int MYSQLlex(void *arg, void *yythd)
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
LEX *lex= thd->lex;
YYSTYPE *yylval=(YYSTYPE*) arg;
- CHARSET_INFO *cs= thd->charset();
- uchar *state_map= cs->state_map;
- uchar *ident_map= cs->ident_map;
+ CHARSET_INFO *const cs= thd->charset();
+ const uchar *const state_map= cs->state_map;
+ const uchar *const ident_map= cs->ident_map;
LINT_INIT(c);
lip->yylval=yylval; // The global state
@@ -1581,6 +1582,7 @@ void st_select_lex_unit::init_query()
item_list.empty();
describe= 0;
found_rows_for_union= 0;
+ insert_table_with_stored_vcol= 0;
}
void st_select_lex::init_query()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6372970438d..2f14f3eb575 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -118,6 +118,8 @@ enum enum_sql_command {
SQLCOM_SHOW_CREATE_TRIGGER,
SQLCOM_ALTER_DB_UPGRADE,
SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
+ SQLCOM_SHOW_USER_STATS, SQLCOM_SHOW_TABLE_STATS, SQLCOM_SHOW_INDEX_STATS,
+ SQLCOM_SHOW_CLIENT_STATS,
/*
When a command is added here, be sure it's also added in mysqld.cc
@@ -530,6 +532,13 @@ public:
bool describe; /* union exec() called for EXPLAIN */
Procedure *last_procedure; /* Pointer to procedure, if such exists */
+ /*
+ Insert table with stored virtual columns.
+ This is used only in those rare cases
+ when the list of inserted values is empty.
+ */
+ TABLE *insert_table_with_stored_vcol;
+
void init_query();
st_select_lex_unit* master_unit();
st_select_lex* outer_select();
@@ -951,6 +960,8 @@ 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;
struct Sroutine_hash_entry;
@@ -1576,6 +1587,7 @@ typedef struct st_lex : public Query_tables_list
LEX_USER *grant_user;
XID *xid;
THD *thd;
+ Virtual_column_info *vcol_info;
/* maintain a list of used plugins for this LEX */
DYNAMIC_ARRAY plugins;
@@ -1659,6 +1671,14 @@ typedef struct st_lex : public Query_tables_list
syntax error back.
*/
bool expr_allows_subselect;
+ /*
+ A special command "PARSE_VCOL_EXPR" is defined for the parser
+ to translate a defining expression of a virtual column into an
+ Item object.
+ The following flag is used to prevent other applications to use
+ this command.
+ */
+ bool parse_vcol_expr;
thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
@@ -1770,6 +1790,11 @@ typedef struct st_lex : public Query_tables_list
const char *stmt_definition_end;
/**
+ Collects create options for Field and KEY
+ */
+ engine_option_value *option_list, *option_list_last;
+
+ /**
During name resolution search only in the table list given by
Name_resolution_context::first_name_resolution_table and
Name_resolution_context::last_name_resolution_table
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 572a8686c4d..af66c9447b0 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -338,10 +338,14 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CLIENT_STATS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_USER_STATS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_TABLE_STATS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_INDEX_STATS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
- CF_SHOW_TABLE_COMMAND |
- CF_REEXECUTION_FRAGILE);
+ sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
+ CF_SHOW_TABLE_COMMAND |
+ CF_REEXECUTION_FRAGILE);
sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
CF_SHOW_TABLE_COMMAND |
CF_REEXECUTION_FRAGILE);
@@ -440,9 +444,8 @@ static void handle_bootstrap_impl(THD *thd)
thd_proc_info(thd, 0);
thd->version=refresh_version;
- thd->security_ctx->priv_user=
- thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
- thd->security_ctx->priv_host[0]=0;
+ thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
+ thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0;
/*
Make the "client" handle multiple results. This is necessary
to enable stored procedures with SELECTs and Dynamic SQL
@@ -571,7 +574,6 @@ end:
return 0;
}
-
/**
@brief Check access privs for a MERGE table and fix children lock types.
@@ -833,6 +835,8 @@ bool do_command(THD *thd)
net_new_transaction(net);
+ /* Save for user statistics */
+ thd->start_bytes_received= thd->status_var.bytes_received;
packet_length= my_net_read(net);
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.start_new_query();
@@ -1109,96 +1113,34 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CHANGE_USER:
{
status_var_increment(thd->status_var.com_other);
- char *user= (char*) packet, *packet_end= packet + packet_length;
- /* Safe because there is always a trailing \0 at the end of the packet */
- char *passwd= strend(user)+1;
thd->change_user();
thd->clear_error(); // if errors from rollback
- /*
- Old clients send null-terminated string ('\0' for empty string) for
- password. New clients send the size (1 byte) + string (not null
- terminated, so also '\0' for empty string).
+ /* acl_authenticate() takes the data from net->read_pos */
+ net->read_pos= (uchar*)packet;
- Cast *passwd to an unsigned char, so that it doesn't extend the sign
- for *passwd > 127 and become 2**32-127 after casting to uint.
- */
- char db_buff[NAME_LEN+1]; // buffer to store db in utf8
- char *db= passwd;
- char *save_db;
- /*
- If there is no password supplied, the packet must contain '\0',
- in any type of handshake (4.1 or pre-4.1).
- */
- if (passwd >= packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
- uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
- (uchar)(*passwd++) : strlen(passwd));
- uint dummy_errors, save_db_length, db_length;
- int res;
+ uint save_db_length= thd->db_length;
+ char *save_db= thd->db;
+ USER_CONN *save_user_connect= thd->user_connect;
Security_context save_security_ctx= *thd->security_ctx;
- USER_CONN *save_user_connect;
-
- db+= passwd_len + 1;
- /*
- Database name is always NUL-terminated, so in case of empty database
- the packet must contain at least the trailing '\0'.
- */
- if (db >= packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
- db_length= strlen(db);
-
- char *ptr= db + db_length + 1;
- uint cs_number= 0;
+ CHARSET_INFO *save_character_set_client=
+ thd->variables.character_set_client;
+ CHARSET_INFO *save_collation_connection=
+ thd->variables.collation_connection;
+ CHARSET_INFO *save_character_set_results=
+ thd->variables.character_set_results;
- if (ptr < packet_end)
- {
- if (ptr + 2 > packet_end)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
-
- cs_number= uint2korr(ptr);
- }
-
- /* Convert database name to utf8 */
- db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
- system_charset_info, db, db_length,
- thd->charset(), &dummy_errors)]= 0;
- db= db_buff;
-
- /* Save user and privileges */
- save_db_length= thd->db_length;
- save_db= thd->db;
- save_user_connect= thd->user_connect;
-
- if (!(thd->security_ctx->user= my_strdup(user, MYF(0))))
- {
- thd->security_ctx->user= save_security_ctx.user;
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- break;
- }
-
- /* Clear variables that are allocated */
- thd->user_connect= 0;
- thd->security_ctx->priv_user= thd->security_ctx->user;
- res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
-
- if (res)
+ if (acl_authenticate(thd, 0, packet_length))
{
x_free(thd->security_ctx->user);
*thd->security_ctx= save_security_ctx;
thd->user_connect= save_user_connect;
- thd->db= save_db;
- thd->db_length= save_db_length;
+ thd->reset_db(save_db, save_db_length);
+ thd->variables.character_set_client= save_character_set_client;
+ thd->variables.collation_connection= save_collation_connection;
+ thd->variables.character_set_results= save_character_set_results;
+ thd->update_charset();
}
else
{
@@ -1209,12 +1151,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
x_free(save_db);
x_free(save_security_ctx.user);
-
- if (cs_number)
- {
- thd_init_client_charset(thd, cs_number);
- thd->update_charset();
- }
}
break;
}
@@ -1386,7 +1322,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
table_list.select_lex= &(thd->lex->select_lex);
lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
thd->lex->
select_lex.table_list.link_in_list(&table_list,
@@ -1699,6 +1635,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Free tables */
close_thread_tables(thd);
+ /* Update status; Must be done after close_thread_tables */
+ thd->update_all_stats();
+
if (sql_command_flags[thd->lex->sql_command] & CF_CHANGES_DATA)
{
net_end_statement(thd);
@@ -1874,6 +1813,12 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
thd->profiling.discard_current_query();
#endif
break;
+ case SCH_USER_STATS:
+ case SCH_CLIENT_STATS:
+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
+ DBUG_RETURN(1);
+ case SCH_TABLE_STATS:
+ case SCH_INDEX_STATS:
case SCH_OPEN_TABLES:
case SCH_VARIABLES:
case SCH_STATUS:
@@ -2315,6 +2260,10 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_COLLATIONS:
case SQLCOM_SHOW_STORAGE_ENGINES:
case SQLCOM_SHOW_PROFILE:
+ case SQLCOM_SHOW_CLIENT_STATS:
+ case SQLCOM_SHOW_USER_STATS:
+ case SQLCOM_SHOW_TABLE_STATS:
+ case SQLCOM_SHOW_INDEX_STATS:
case SQLCOM_SELECT:
thd->status_var.last_query_cost= 0.0;
if (all_tables)
@@ -4372,8 +4321,8 @@ end_with_restore_list:
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL,
- ER(ER_PROC_AUTO_GRANT_FAIL));
+ ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL));
+ thd->clear_error();
}
/*
@@ -5064,6 +5013,7 @@ create_sp_error:
break;
}
thd_proc_info(thd, "query end");
+ thd->update_stats();
/*
Binlog-related cleanup:
@@ -5157,6 +5107,10 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
delete result;
}
}
+ /* Count number of empty select queries */
+ if (!thd->sent_row_count)
+ status_var_increment(thd->status_var.empty_queries);
+ status_var_add(thd->status_var.rows_sent, thd->sent_row_count);
return res;
}
@@ -5316,6 +5270,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
{
const char *db_name= db ? db : thd->db;
+ status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host, db_name);
}
@@ -5348,12 +5303,15 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
{ // We can never grant this
DBUG_PRINT("error",("No possible access"));
if (!no_errors)
+ {
+ status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user,
sctx->priv_host,
(thd->password ?
ER(ER_YES) :
ER(ER_NO))); /* purecov: tested */
+ }
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -5379,11 +5337,14 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_PRINT("error",("Access denied"));
if (!no_errors)
+ {
+ status_var_increment(thd->status_var.access_denied_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 */
}
@@ -5412,6 +5373,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
if (!thd->col_access && check_grant_db(thd, dst_db_name))
{
+ status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
thd->security_ctx->priv_user,
thd->security_ctx->priv_host,
@@ -5474,14 +5436,14 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
{
TABLE_LIST *org_tables= tables;
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
- uint i= 0;
Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx;
+ uint i;
/*
The check that first_not_own_table is not reached is for the case when
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=0; i < number && tables != first_not_own_table;
tables= tables->next_global, i++)
{
if (tables->security_ctx)
@@ -5493,9 +5455,12 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
(want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
{
if (!no_errors)
+ {
+ status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host,
INFORMATION_SCHEMA_NAME.str);
+ }
return TRUE;
}
/*
@@ -5659,6 +5624,7 @@ bool check_global_access(THD *thd, ulong want_access)
return 0;
get_privilege_desc(command, sizeof(command), want_access);
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
+ status_var_increment(thd->status_var.access_denied_errors);
return 1;
#else
return 0;
@@ -5762,7 +5728,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
Call it after we use THD for queries, not before.
*/
-void mysql_reset_thd_for_next_command(THD *thd)
+void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat)
{
DBUG_ENTER("mysql_reset_thd_for_next_command");
DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
@@ -5807,6 +5773,15 @@ void mysql_reset_thd_for_next_command(THD *thd)
thd->total_warn_count=0; // Warnings for this query
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
+
+ /* Copy data for user stats */
+ if ((thd->userstat_running= calculate_userstat))
+ {
+ thd->start_cpu_time= my_getcputime();
+ memcpy(&thd->org_status_var, &thd->status_var, sizeof(thd->status_var));
+ thd->select_commands= thd->update_commands= thd->other_commands= 0;
+ }
+
thd->query_plan_flags= QPLAN_INIT;
thd->query_plan_fsort_passes= 0;
@@ -6005,7 +5980,6 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
const char ** found_semicolon)
{
DBUG_ENTER("mysql_parse");
-
DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
/*
@@ -6025,7 +5999,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
FIXME: cleanup the dependencies in the code to simplify this.
*/
lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0)
{
@@ -6103,10 +6077,11 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
}
else
{
+ /* Update statistics for getting the query from the cache */
+ thd->lex->sql_command= SQLCOM_SELECT;
/* There are no multi queries in the cache. */
*found_semicolon= NULL;
}
-
DBUG_VOID_RETURN;
}
@@ -6132,7 +6107,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
if (!(error= parser_state.init(thd, inBuf, length)))
{
lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
if (!parse_sql(thd, & parser_state, NULL) &&
all_tables_not_ok(thd, lex->select_lex.table_list.first))
@@ -6160,7 +6135,9 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
LEX_STRING *comment,
char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type)
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info,
+ engine_option_value *create_options)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6178,7 +6155,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::PRIMARY, NullS,
&default_key_create_info,
- 0, lex->col_list);
+ 0, lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6188,7 +6165,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
- lex->col_list);
+ lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6246,7 +6223,8 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
if (!(new_field= new Create_field()) ||
new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
default_value, on_update_value, comment, change,
- interval_list, cs, uint_geom_type))
+ interval_list, cs, uint_geom_type, vcol_info,
+ create_options))
DBUG_RETURN(1);
lex->alter_info.create_list.push_back(new_field);
@@ -6972,6 +6950,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (flush_error_log())
result=1;
}
+ if (((options & (REFRESH_SLOW_QUERY_LOG | REFRESH_LOG)) ==
+ REFRESH_SLOW_QUERY_LOG))
+ {
+ /* We are only flushing slow query log */
+ logger.flush_slow_log(thd);
+ }
+
#ifdef HAVE_QUERY_CACHE
if (options & REFRESH_QUERY_CACHE_FREE)
{
@@ -7054,29 +7039,58 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
#endif
#ifdef OPENSSL
- if (options & REFRESH_DES_KEY_FILE)
- {
- if (des_key_file && load_des_key_file(des_key_file))
- result= 1;
- }
+ if (options & REFRESH_DES_KEY_FILE)
+ {
+ if (des_key_file && load_des_key_file(des_key_file))
+ result= 1;
+ }
#endif
#ifdef HAVE_REPLICATION
- if (options & REFRESH_SLAVE)
- {
- tmp_write_to_binlog= 0;
- pthread_mutex_lock(&LOCK_active_mi);
- if (reset_slave(thd, active_mi))
- result=1;
- pthread_mutex_unlock(&LOCK_active_mi);
- }
+ if (options & REFRESH_SLAVE)
+ {
+ tmp_write_to_binlog= 0;
+ pthread_mutex_lock(&LOCK_active_mi);
+ if (reset_slave(thd, active_mi))
+ result=1;
+ pthread_mutex_unlock(&LOCK_active_mi);
+ }
#endif
- if (options & REFRESH_USER_RESOURCES)
- reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
- *write_to_binlog= tmp_write_to_binlog;
- /*
- If the query was killed then this function must fail.
- */
- return result || (thd ? thd->killed : 0);
+ if (options & REFRESH_USER_RESOURCES)
+ reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
+ if (options & REFRESH_TABLE_STATS)
+ {
+ pthread_mutex_lock(&LOCK_global_table_stats);
+ free_global_table_stats();
+ init_global_table_stats();
+ pthread_mutex_unlock(&LOCK_global_table_stats);
+ }
+ if (options & REFRESH_INDEX_STATS)
+ {
+ pthread_mutex_lock(&LOCK_global_index_stats);
+ free_global_index_stats();
+ init_global_index_stats();
+ pthread_mutex_unlock(&LOCK_global_index_stats);
+ }
+ if (options & (REFRESH_USER_STATS | REFRESH_CLIENT_STATS))
+ {
+ pthread_mutex_lock(&LOCK_global_user_client_stats);
+ if (options & REFRESH_USER_STATS)
+ {
+ free_global_user_stats();
+ init_global_user_stats();
+ }
+ if (options & REFRESH_CLIENT_STATS)
+ {
+ free_global_client_stats();
+ init_global_client_stats();
+ }
+ pthread_mutex_unlock(&LOCK_global_user_client_stats);
+ }
+ *write_to_binlog= tmp_write_to_binlog;
+ /*
+ If the query was killed then this function must fail.
+ */
+ return result || (thd ? thd->killed : 0);
}
@@ -7112,7 +7126,6 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (tmp)
{
-
/*
If we're SUPER, we can KILL anything, including system-threads.
No further checks.
@@ -7695,8 +7708,9 @@ void get_default_definer(THD *thd, LEX_USER *definer)
definer->host.str= (char *) sctx->priv_host;
definer->host.length= strlen(definer->host.str);
- definer->password.str= NULL;
- definer->password.length= 0;
+ definer->password= null_lex_str;
+ definer->plugin= empty_lex_str;
+ definer->auth= empty_lex_str;
}
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 0e717078422..3dae2d1e8b4 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -984,7 +984,8 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
saved_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func= 0;
- error= func_expr->fix_fields(thd, (Item**)&func_expr);
+ if (!(error= func_expr->fix_fields(thd, (Item**)&func_expr)))
+ func_expr->walk(&Item::vcol_in_partition_func_processor, 0, NULL);
/*
Restore full_group_by_flag and allow_sum_func,
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index c9b73413377..c80cc55df4c 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
@@ -16,10 +16,11 @@
#include "mysql_priv.h"
#include <my_pthread.h>
#include <my_getopt.h>
+#include <mysql/plugin_auth.h>
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
-extern struct st_mysql_plugin *mysqld_builtins[];
+extern struct st_maria_plugin *mariadb_builtins[];
/**
@note The order of the enumeration is critical.
@@ -36,6 +37,18 @@ static TYPELIB global_plugin_typelib=
char *opt_plugin_load= NULL;
char *opt_plugin_dir_ptr;
char opt_plugin_dir[FN_REFLEN];
+uint plugin_maturity;
+
+/*
+ not really needed now, this map will become essential when we add more
+ maturity levels. We cannot change existing maturity constants,
+ so the next value - even if it will be MariaDB_PLUGIN_MATURITY_VERY_BUGGY -
+ will inevitably be larger than MariaDB_PLUGIN_MATURITY_STABLE.
+ To be able to compare them we use this mapping array
+*/
+uint plugin_maturity_map[]=
+{ 0, 1, 2, 3, 4, 5, 6 };
+
/*
When you ad a new plugin type, add both a string and make sure that the
init and deinit array are correctly updated.
@@ -46,7 +59,10 @@ const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{ C_STRING_WITH_LEN("STORAGE ENGINE") },
{ C_STRING_WITH_LEN("FTPARSER") },
{ C_STRING_WITH_LEN("DAEMON") },
- { C_STRING_WITH_LEN("INFORMATION SCHEMA") }
+ { C_STRING_WITH_LEN("INFORMATION SCHEMA") },
+ { C_STRING_WITH_LEN("AUDIT") },
+ { C_STRING_WITH_LEN("REPLICATION") },
+ { C_STRING_WITH_LEN("AUTHENTICATION") }
};
extern int initialize_schema_table(st_plugin_int *plugin);
@@ -59,12 +75,12 @@ extern int finalize_schema_table(st_plugin_int *plugin);
*/
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
- 0,ha_initialize_handlerton,0,0,initialize_schema_table
+ 0,ha_initialize_handlerton,0,0,initialize_schema_table, 0, 0, 0
};
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
- 0,ha_finalize_handlerton,0,0,finalize_schema_table
+ 0,ha_finalize_handlerton,0,0,finalize_schema_table, 0, 0, 0
};
#ifdef HAVE_DLOPEN
@@ -74,6 +90,14 @@ static const char *sizeof_st_plugin_sym=
"_mysql_sizeof_struct_st_plugin_";
static const char *plugin_declarations_sym= "_mysql_plugin_declarations_";
static int min_plugin_interface_version= MYSQL_PLUGIN_INTERFACE_VERSION & ~0xFF;
+static const char *maria_plugin_interface_version_sym=
+ "_maria_plugin_interface_version_";
+static const char *maria_sizeof_st_plugin_sym=
+ "_maria_sizeof_struct_st_plugin_";
+static const char *maria_plugin_declarations_sym=
+ "_maria_plugin_declarations_";
+static int min_maria_plugin_interface_version=
+ MARIA_PLUGIN_INTERFACE_VERSION & ~0xFF;
#endif
/* Note that 'int version' must be the first field of every plugin
@@ -85,7 +109,10 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION,
MYSQL_DAEMON_INTERFACE_VERSION,
- MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+ 0xff00, /* audit plugins are supported in a later versions */
+ 0xff00, /* replication plugins are supported in a later versions */
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION
};
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
@@ -93,10 +120,15 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION,
MYSQL_DAEMON_INTERFACE_VERSION,
- MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+ 0x0000, /* audit plugins are supported in a later versions */
+ 0x0000, /* replication plugins are supported in a later versions */
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION
};
-static bool initialized= 0;
+/* support for Services */
+
+#include "sql_plugin_services.h"
/*
A mutex LOCK_plugin must be acquired before accessing the
@@ -110,6 +142,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
@@ -197,7 +231,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
const char *list);
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
int *, char **);
-static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
+static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(THD *thd, struct system_variables *vars);
@@ -222,6 +256,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(error), args);
+ va_end(args);
+ }
+}
/****************************************************************************
Value type thunks, allows the C world to play in the C++ world
@@ -338,11 +388,230 @@ static inline void free_plugin_mem(struct st_plugin_dl *p)
}
+/**
+ Reads data from mysql plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report What errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+#ifdef HAVE_DLOPEN
+static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+ /* Determine interface version */
+ if (!sym)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= 0;
+ plugin_dl->mysqlversion= *(int *)sym;
+ /* Versioning */
+ if (plugin_dl->mysqlversion < min_plugin_interface_version ||
+ (plugin_dl->mysqlversion >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ /* convert mysql declaration to maria one */
+ {
+ int i;
+ uint sizeof_st_plugin;
+ struct st_mysql_plugin *old;
+ struct st_maria_plugin *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ DBUG_ASSERT(min_plugin_interface_version == 0);
+ sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
+ }
+
+ for (i= 0;
+ ((struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_mysql_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ {
+
+ cur[i].type= old->type;
+ cur[i].info= old->info;
+ cur[i].name= old->name;
+ cur[i].author= old->author;
+ cur[i].descr= old->descr;
+ cur[i].license= old->license;
+ cur[i].init= old->init;
+ cur[i].deinit= old->deinit;
+ cur[i].version= old->version;
+ cur[i].status_vars= old->status_vars;
+ cur[i].system_vars= old->system_vars;
+ /*
+ Something like this should be added to process
+ new mysql plugin versions:
+ if (plugin_dl->mysqlversion > 0x0101)
+ {
+ cur[i].newfield= CONSTANT_MEANS_UNKNOWN;
+ }
+ else
+ {
+ cur[i].newfield= old->newfield;
+ }
+ */
+ /* Maria only fields */
+ cur[i].version_info= "Unknown";
+ cur[i].maturity= MariaDB_PLUGIN_MATURITY_UNKNOWN;
+ }
+ plugin_dl->allocated= true;
+ plugin_dl->plugins= (struct st_maria_plugin *)cur;
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Reads data from maria plugin interface
+
+ @param plugin_dl Structure where the data should be put
+ @param sym Reverence on version info
+ @param dlpath Path to the module
+ @param report what errors should be reported
+
+ @retval FALSE OK
+ @retval TRUE ERROR
+*/
+
+static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
+ void *sym, char *dlpath,
+ int report)
+{
+ DBUG_ENTER("read_maria_plugin_info");
+
+ /* Determine interface version */
+ if (!(sym))
+ {
+ /*
+ Actually this branch impossible because in case of absence of maria
+ version we try mysql version.
+ */
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY,
+ maria_plugin_interface_version_sym);
+ DBUG_RETURN(TRUE);
+ }
+ plugin_dl->mariaversion= *(int *)sym;
+ plugin_dl->mysqlversion= 0;
+ /* Versioning */
+ if (plugin_dl->mariaversion < min_maria_plugin_interface_version ||
+ (plugin_dl->mariaversion >> 8) > (MARIA_PLUGIN_INTERFACE_VERSION >> 8))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0,
+ "plugin interface version mismatch");
+ DBUG_RETURN(TRUE);
+ }
+ /* Find plugin declarations */
+ if (!(sym= dlsym(plugin_dl->handle, maria_plugin_declarations_sym)))
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_plugin_declarations_sym);
+ DBUG_RETURN(TRUE);
+ }
+ if (plugin_dl->mariaversion != MARIA_PLUGIN_INTERFACE_VERSION)
+ {
+ uint sizeof_st_plugin;
+ struct st_maria_plugin *old, *cur;
+ char *ptr= (char *)sym;
+
+ if ((sym= dlsym(plugin_dl->handle, maria_sizeof_st_plugin_sym)))
+ sizeof_st_plugin= *(int *)sym;
+ else
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_CANT_FIND_DL_ENTRY, maria_sizeof_st_plugin_sym);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (sizeof_st_plugin != sizeof(st_mysql_plugin))
+ {
+ int i;
+ for (i= 0;
+ ((struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ /* no op */;
+
+ cur= (struct st_maria_plugin*)
+ my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ MYF(MY_ZEROFILL|MY_WME));
+ if (!cur)
+ {
+ free_plugin_mem(plugin_dl);
+ report_error(report, ER_OUTOFMEMORY, plugin_dl->dl.length);
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ All st_plugin fields not initialized in the plugin explicitly, are
+ set to 0. It matches C standard behaviour for struct initializers that
+ have less values than the struct definition.
+ */
+ for (i=0;
+ (old= (struct st_maria_plugin *)(ptr + i * sizeof_st_plugin))->info;
+ i++)
+ memcpy(cur + i, old, min(sizeof(cur[i]), sizeof_st_plugin));
+
+ sym= cur;
+ plugin_dl->allocated= true;
+ }
+ }
+ plugin_dl->plugins= (struct st_maria_plugin *)sym;
+
+ DBUG_RETURN(FALSE);
+}
+#endif /* HAVE_DLOPEN */
+
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");
@@ -357,10 +626,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 | REPORT_TO_USER)) == REPORT_TO_LOG)
- sql_print_error("%s", ER(ER_UDF_NO_PATHS));
+ report_error(report, ER_UDF_NO_PATHS);
DBUG_RETURN(0);
}
/* If this dll is already loaded just increase ref_count. */
@@ -385,118 +651,52 @@ 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(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(ER_CANT_FIND_DL_ENTRY), plugin_interface_version_sym);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
DBUG_RETURN(0);
}
- plugin_dl.version= *(int *)sym;
- /* Versioning */
- if (plugin_dl.version < min_plugin_interface_version ||
- (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
+
+ /* Checks which plugin interface present and reads info */
+ if (!(sym= dlsym(plugin_dl.handle, maria_plugin_interface_version_sym)))
{
- 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(ER_CANT_OPEN_LIBRARY), dlpath, 0,
- "plugin interface version mismatch");
- DBUG_RETURN(0);
+ if (read_mysql_plugin_info(&plugin_dl,
+ dlsym(plugin_dl.handle,
+ plugin_interface_version_sym),
+ dlpath,
+ report))
+ DBUG_RETURN(0);
}
- /* Find plugin declarations */
- if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
+ else
{
- 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(ER_CANT_FIND_DL_ENTRY), plugin_declarations_sym);
- DBUG_RETURN(0);
+ if (read_maria_plugin_info(&plugin_dl, sym, dlpath, report))
+ DBUG_RETURN(0);
}
- if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
+ /* link the services in */
+ for (i= 0; i < array_elements(list_of_services); i++)
{
- int i;
- uint sizeof_st_plugin;
- struct st_mysql_plugin *old, *cur;
- char *ptr= (char *)sym;
-
- if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
- sizeof_st_plugin= *(int *)sym;
- 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(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym);
- DBUG_RETURN(0);
-#else
- /*
- When the following assert starts failing, we'll have to switch
- to the upper branch of the #ifdef
- */
- DBUG_ASSERT(min_plugin_interface_version == 0);
- sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
-#endif
- }
-
- if (sizeof_st_plugin != sizeof(st_mysql_plugin))
+ if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
{
- for (i= 0;
- ((struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- /* no op */;
-
- cur= (struct st_mysql_plugin*)
- my_malloc((i+1)*sizeof(struct st_mysql_plugin), MYF(MY_ZEROFILL|MY_WME));
- if (!cur)
+ uint ver= (uint)(intptr) *(void **)sym;
+ if (ver > list_of_services[i].version ||
+ (ver >> 8) < (list_of_services[i].version >> 8))
{
- 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(ER_OUTOFMEMORY), plugin_dl.dl.length);
+ 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);
}
- /*
- All st_plugin fields not initialized in the plugin explicitly, are
- set to 0. It matches C standard behaviour for struct initializers that
- have less values than the struct definition.
- */
- for (i=0;
- (old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
- i++)
- memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
-
- sym= cur;
- plugin_dl.allocated= true;
+ *(void **)sym= list_of_services[i].service;
}
}
- plugin_dl.plugins= (struct st_mysql_plugin *)sym;
/* Duplicate and convert dll name */
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
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(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,
@@ -507,19 +707,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(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(ER_FEATURE_DISABLED), "plugin", "HAVE_DLOPEN");
+ report_error(report, ER_FEATURE_DISABLED, "plugin", "HAVE_DLOPEN");
DBUG_RETURN(0);
#endif
}
@@ -638,7 +832,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);
@@ -646,7 +840,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
*plugin= pi;
#endif
pi->ref_count++;
- DBUG_PRINT("info",("thd: 0x%lx plugin: \"%s\" ref_count: %d",
+ DBUG_PRINT("lock",("thd: 0x%lx plugin: \"%s\" LOCK ref_count: %d",
(long) current_thd, pi->name.str, pi->ref_count));
if (lex)
@@ -737,14 +931,11 @@ static bool plugin_add(MEM_ROOT *tmp_root,
int *argc, char **argv, int report)
{
struct st_plugin_int tmp;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
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(ER_UDF_EXISTS), name->str);
+ report_error(report, ER_UDF_EXISTS, name->str);
DBUG_RETURN(TRUE);
}
/* Clear the whole struct to catch future extensions. */
@@ -771,10 +962,18 @@ 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(ER_CANT_OPEN_LIBRARY), dl->str, 0, buf);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
+ goto err;
+ }
+ if (plugin_maturity_map[plugin->maturity] < plugin_maturity)
+ {
+ char buf[256];
+ strxnmov(buf, sizeof(buf) - 1, "Loading of ",
+ plugin_maturity_names[plugin->maturity],
+ " plugins is prohibited by --plugin-maturity=",
+ plugin_maturity_names[plugin_maturity],
+ NullS);
+ report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
goto err;
}
tmp.plugin= plugin;
@@ -803,10 +1002,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(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);
@@ -962,8 +1158,6 @@ static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
my_free((uchar*) plugin, MYF(MY_WME));
#endif
- DBUG_PRINT("info",("unlocking plugin, name= %s, ref_count= %d",
- pi->name.str, pi->ref_count));
if (lex)
{
/*
@@ -983,6 +1177,9 @@ static void intern_plugin_unlock(LEX *lex, plugin_ref plugin)
DBUG_ASSERT(pi->ref_count);
pi->ref_count--;
+ DBUG_PRINT("lock",("thd: 0x%lx plugin: \"%s\" UNLOCK ref_count: %d",
+ (long) current_thd, pi->name.str, pi->ref_count));
+
if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
reap_needed= true;
@@ -1013,6 +1210,9 @@ void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
{
LEX *lex= thd ? thd->lex : 0;
DBUG_ENTER("plugin_unlock_list");
+ if (count == 0)
+ DBUG_VOID_RETURN;
+
DBUG_ASSERT(list);
pthread_mutex_lock(&LOCK_plugin);
while (count--)
@@ -1148,8 +1348,8 @@ int plugin_init(int *argc, char **argv, int flags)
{
uint i;
bool is_myisam;
- struct st_mysql_plugin **builtins;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin **builtins;
+ struct st_maria_plugin *plugin;
struct st_plugin_int tmp, *plugin_ptr, **reap;
MEM_ROOT tmp_root;
bool reaped_mandatory_plugin= FALSE;
@@ -1188,7 +1388,7 @@ int plugin_init(int *argc, char **argv, int flags)
/*
First we register builtin plugins
*/
- for (builtins= mysqld_builtins; *builtins; builtins++)
+ for (builtins= mariadb_builtins; *builtins; builtins++)
{
for (plugin= *builtins; plugin->info; plugin++)
{
@@ -1303,7 +1503,7 @@ err:
}
-static bool register_builtin(struct st_mysql_plugin *plugin,
+static bool register_builtin(struct st_maria_plugin *plugin,
struct st_plugin_int *tmp,
struct st_plugin_int **ptr)
{
@@ -1339,7 +1539,7 @@ static bool register_builtin(struct st_mysql_plugin *plugin,
RETURN
false - plugin registered successfully
*/
-bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin)
+bool plugin_register_builtin(THD *thd, struct st_maria_plugin *plugin)
{
struct st_plugin_int tmp, *ptr;
bool result= true;
@@ -1421,7 +1621,12 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
goto end;
}
table= tables.table;
- init_read_record(&read_record_info, new_thd, table, NULL, 1, 0, FALSE);
+ if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 0, FALSE))
+ {
+ sql_print_error("Could not initialize init_read_record; Plugins not "
+ "loaded");
+ goto end;
+ }
table->use_all_columns();
/*
there're no other threads running yet, so we don't need a mutex.
@@ -1468,7 +1673,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
char buffer[FN_REFLEN];
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
struct st_plugin_dl *plugin_dl;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
char *p= buffer;
DBUG_ENTER("plugin_load_list");
while (list)
@@ -1810,10 +2015,10 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
table->use_all_columns();
table->field[0]->store(name->str, name->length, system_charset_info);
- if (! table->file->index_read_idx_map(table->record[0], 0,
- (uchar *)table->field[0]->ptr,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (! table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar *)table->field[0]->ptr,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
int error;
/*
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 79ee296ac64..149b7e0cbb1 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -27,16 +27,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;
@@ -62,8 +52,9 @@ struct st_plugin_dl
{
LEX_STRING dl;
void *handle;
- struct st_mysql_plugin *plugins;
- int version;
+ struct st_maria_plugin *plugins;
+ int mysqlversion;
+ int mariaversion;
bool allocated;
uint ref_count; /* number of plugins loaded from the library */
};
@@ -73,7 +64,7 @@ struct st_plugin_dl
struct st_plugin_int
{
LEX_STRING name;
- struct st_mysql_plugin *plugin;
+ struct st_maria_plugin *plugin;
struct st_plugin_dl *plugin_dl;
uint state;
uint ref_count; /* number of threads using the plugin */
@@ -116,6 +107,9 @@ extern char *opt_plugin_load;
extern char *opt_plugin_dir_ptr;
extern char opt_plugin_dir[FN_REFLEN];
extern const LEX_STRING plugin_type_names[];
+extern uint plugin_maturity;
+extern TYPELIB plugin_maturity_values;
+extern const char *plugin_maturity_names[];
extern int plugin_init(int *argc, char **argv, int init_flags);
extern void plugin_shutdown(void);
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 4de7671bd1a..600c140c776 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2097,14 +2097,13 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
Prepared_statement *stmt;
bool error;
DBUG_ENTER("mysqld_stmt_prepare");
-
DBUG_PRINT("prep_query", ("%s", packet));
/* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
if (! (stmt= new Prepared_statement(thd)))
- DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
+ goto end; /* out of memory: error is set in Sql_alloc */
if (thd->stmt_map.insert(thd, stmt))
{
@@ -2112,7 +2111,7 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
The error is set in the insert. The statement itself
will be also deleted there (this is how the hash works).
*/
- DBUG_VOID_RETURN;
+ goto end;
}
/* Reset warnings from previous command */
@@ -2139,6 +2138,7 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
thd->protocol= save_protocol;
/* check_prepared_statemnt sends the metadata packet in case of success */
+end:
DBUG_VOID_RETURN;
}
@@ -2483,7 +2483,7 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
packet+= 9; /* stmt_id + 5 bytes of flags */
/* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
@@ -2582,7 +2582,8 @@ void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length)
DBUG_ENTER("mysqld_stmt_fetch");
/* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
+
status_var_increment(thd->status_var.com_stmt_fetch);
if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
@@ -2648,7 +2649,7 @@ void mysqld_stmt_reset(THD *thd, char *packet)
DBUG_ENTER("mysqld_stmt_reset");
/* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
+ mysql_reset_thd_for_next_command(thd, opt_userstat_running);
status_var_increment(thd->status_var.com_stmt_reset);
if (!(stmt= find_prepared_statement(thd, stmt_id)))
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 60da06fadf1..59d9d72e778 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2903,8 +2903,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
!table->fulltext_searched &&
!table->pos_in_table_list->embedding)
{
- if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY))
- == HA_NOSAME)
+ if (table->key_info[key].flags & HA_NOSAME)
{
if (const_ref == eq_part)
{ // Found everything for ref.
@@ -5535,7 +5534,7 @@ static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
{
uint null_fields,blobs,fields,rec_length;
Field **f_ptr,*field;
- MY_BITMAP *read_set= join_tab->table->read_set;;
+ MY_BITMAP *read_set= join_tab->table->read_set;
null_fields= blobs= fields= rec_length=0;
for (f_ptr=join_tab->table->field ; (field= *f_ptr) ; f_ptr++)
@@ -5858,8 +5857,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
DBUG_RETURN(0);
if (j->type == JT_CONST)
j->table->const_table= 1;
- else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
- HA_END_SPACE_KEY)) != HA_NOSAME) ||
+ else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) ||
keyparts != keyinfo->key_parts || null_ref_key)
{
/* Must read with repeat */
@@ -9629,6 +9627,8 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
table->s->db_create_options|= HA_OPTION_PACK_RECORD;
else if (org_field->type() == FIELD_TYPE_DOUBLE)
((Field_double *) new_field)->not_fixed= TRUE;
+ new_field->vcol_info= 0;
+ new_field->stored_in_db= TRUE;
}
return new_field;
}
@@ -9942,9 +9942,13 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
uint field_count= table->s->fields;
bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
FALSE);
- bitmap_init(&table->tmp_set,
+ bitmap_init(&table->def_vcol_set,
(my_bitmap_map*) (bitmaps+ bitmap_buffer_size(field_count)),
field_count, FALSE);
+ bitmap_init(&table->tmp_set,
+ (my_bitmap_map*) (bitmaps+ 2*bitmap_buffer_size(field_count)),
+ field_count, FALSE);
+
/* write_set and all_set are copies of read_set */
table->def_write_set= table->def_read_set;
table->s->all_set= table->def_read_set;
@@ -10097,7 +10101,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
&tmpname, (uint) strlen(tmp_table_name)+1,
&group_buff, (group && ! using_unique_constraint ?
param->group_length : 0),
- &bitmaps, bitmap_buffer_size(field_count)*2,
+ &bitmaps, bitmap_buffer_size(field_count)*3,
NullS))
{
if (temp_pool_slot != MY_BIT_NONE)
@@ -10712,7 +10716,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
&share, sizeof(*share),
&field, (field_count + 1) * sizeof(Field*),
&blob_field, (field_count+1) *sizeof(uint),
- &bitmaps, bitmap_buffer_size(field_count)*2,
+ &bitmaps, bitmap_buffer_size(field_count)*3,
NullS))
return 0;
@@ -10803,8 +10807,9 @@ error:
static bool open_tmp_table(TABLE *table)
{
int error;
- if ((error=table->file->ha_open(table, table->s->table_name.str,O_RDWR,
- HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
+ if ((error= table->file->ha_open(table, table->s->table_name.str, O_RDWR,
+ HA_OPEN_TMP_TABLE |
+ HA_OPEN_INTERNAL_TABLE)))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
table->db_stat=0;
@@ -11129,7 +11134,8 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table,
if (table->file->indexes_are_disabled())
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
table->file->ha_index_or_rnd_end();
- table->file->ha_rnd_init(1);
+ if (table->file->ha_rnd_init_with_error(1))
+ DBUG_RETURN(1);
if (table->no_rows)
{
new_table.file->extra(HA_EXTRA_NO_ROWS);
@@ -11154,7 +11160,7 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table,
is safe as this is a temporary MyISAM table without timestamp/autoincrement
or partitioning.
*/
- while (!table->file->rnd_next(new_table.record[1]))
+ while (!table->file->ha_rnd_next(new_table.record[1]))
{
write_err= new_table.file->ha_write_row(new_table.record[1]);
DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;);
@@ -11688,6 +11694,8 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
}
DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
+ update_virtual_fields(join->thd, join_tab->table);
+
if (select_cond)
{
select_cond_result= test(select_cond->val_int());
@@ -11907,6 +11915,8 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
}
int err= 0;
SQL_SELECT *select=join_tab->select;
+ if (rc == NESTED_LOOP_OK)
+ update_virtual_fields(join->thd, join_tab->table);
if (rc == NESTED_LOOP_OK &&
(!join_tab->cache.select ||
(err= join_tab->cache.select->skip_record(join->thd)) != 0 ))
@@ -11978,10 +11988,10 @@ int safe_index_read(JOIN_TAB *tab)
{
int error;
TABLE *table= tab->table;
- if ((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= table->file->ha_index_read_map(table->record[0],
+ tab->ref.key_buff,
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT)))
return report_error(table, error);
return 0;
}
@@ -12085,8 +12095,8 @@ join_read_system(JOIN_TAB *tab)
int error;
if (table->status & STATUS_GARBAGE) // If first read
{
- if ((error=table->file->read_first_row(table->record[0],
- table->s->primary_key)))
+ if ((error= table->file->ha_read_first_row(table->record[0],
+ table->s->primary_key)))
{
if (error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -12094,6 +12104,7 @@ join_read_system(JOIN_TAB *tab)
empty_record(table); // Make empty record
return -1;
}
+ update_virtual_fields(tab->join->thd, table);
store_record(table,record[1]);
}
else if (!table->status) // Only happens with left join
@@ -12128,10 +12139,10 @@ join_read_const(JOIN_TAB *tab)
error=HA_ERR_KEY_NOT_FOUND;
else
{
- error=table->file->index_read_idx_map(table->record[0],tab->ref.key,
- (uchar*) tab->ref.key_buff,
- make_prev_keypart_map(tab->ref.key_parts),
- HA_READ_KEY_EXACT);
+ error= table->file->ha_index_read_idx_map(table->record[0],tab->ref.key,
+ (uchar*) tab->ref.key_buff,
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT);
}
if (error)
{
@@ -12142,6 +12153,7 @@ join_read_const(JOIN_TAB *tab)
return report_error(table, error);
return -1;
}
+ update_virtual_fields(tab->join->thd, table);
store_record(table,record[1]);
}
else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join
@@ -12185,10 +12197,10 @@ join_read_key(JOIN_TAB *tab)
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);
+ error= table->file->ha_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);
@@ -12269,10 +12281,10 @@ join_read_always_key(JOIN_TAB *tab)
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
return -1;
- if ((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= table->file->ha_index_read_map(table->record[0],
+ tab->ref.key_buff,
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -12303,9 +12315,10 @@ join_read_last_key(JOIN_TAB *tab)
}
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
return -1;
- if ((error=table->file->index_read_last_map(table->record[0],
- tab->ref.key_buff,
- make_prev_keypart_map(tab->ref.key_parts))))
+ if ((error= table->file->ha_index_read_map(table->record[0],
+ tab->ref.key_buff,
+ make_prev_keypart_map(tab->ref.key_parts),
+ HA_READ_PREFIX_LAST)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -12330,9 +12343,9 @@ join_read_next_same(READ_RECORD *info)
TABLE *table= info->table;
JOIN_TAB *tab=table->reginfo.join_tab;
- if ((error=table->file->index_next_same(table->record[0],
- tab->ref.key_buff,
- tab->ref.key_length)))
+ if ((error= table->file->ha_index_next_same(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length)))
{
if (error != HA_ERR_END_OF_FILE)
return report_error(table, error);
@@ -12350,7 +12363,7 @@ join_read_prev_same(READ_RECORD *info)
TABLE *table= info->table;
JOIN_TAB *tab=table->reginfo.join_tab;
- if ((error=table->file->index_prev(table->record[0])))
+ if ((error= table->file->ha_index_prev(table->record[0])))
return report_error(table, error);
if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key,
tab->ref.key_length))
@@ -12375,7 +12388,7 @@ int rr_sequential(READ_RECORD *info);
int init_read_record_seq(JOIN_TAB *tab)
{
tab->read_record.read_record= rr_sequential;
- if (tab->read_record.file->ha_rnd_init(1))
+ if (tab->read_record.file->ha_rnd_init_with_error(1))
return 1;
return (*tab->read_record.read_record)(&tab->read_record);
}
@@ -12395,8 +12408,9 @@ join_init_read_record(JOIN_TAB *tab)
{
if (tab->select && tab->select->quick && tab->select->quick->reset())
return 1;
- init_read_record(&tab->read_record, tab->join->thd, tab->table,
- tab->select,1,1, FALSE);
+ if (init_read_record(&tab->read_record, tab->join->thd, tab->table,
+ tab->select,1,1, FALSE))
+ return 1;
return (*tab->read_record.read_record)(&tab->read_record);
}
@@ -12419,7 +12433,7 @@ join_read_first(JOIN_TAB *tab)
error= table->file->ha_index_init(tab->index, tab->sorted);
if (!error)
error= table->file->prepare_index_scan();
- if (error || (error=tab->table->file->index_first(tab->table->record[0])))
+ if (error || (error=tab->table->file->ha_index_first(tab->table->record[0])))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
report_error(table, error);
@@ -12433,8 +12447,9 @@ static int
join_read_next(READ_RECORD *info)
{
int error;
- if ((error=info->file->index_next(info->record)))
+ if ((error= info->file->ha_index_next(info->record)))
return report_error(info->table, error);
+
return 0;
}
@@ -12457,8 +12472,9 @@ join_read_last(JOIN_TAB *tab)
error= table->file->ha_index_init(tab->index, 1);
if (!error)
error= table->file->prepare_index_scan();
- if (error || (error= tab->table->file->index_last(tab->table->record[0])))
+ if (error || (error= tab->table->file->ha_index_last(tab->table->record[0])))
return report_error(table, error);
+
return 0;
}
@@ -12467,7 +12483,7 @@ static int
join_read_prev(READ_RECORD *info)
{
int error;
- if ((error= info->file->index_prev(info->record)))
+ if ((error= info->file->ha_index_prev(info->record)))
return report_error(info->table, error);
return 0;
}
@@ -12492,7 +12508,7 @@ join_ft_read_first(JOIN_TAB *tab)
#endif
table->file->ft_init();
- if ((error= table->file->ft_read(table->record[0])))
+ if ((error= table->file->ha_ft_read(table->record[0])))
return report_error(table, error);
return 0;
}
@@ -12501,7 +12517,7 @@ static int
join_ft_read_next(READ_RECORD *info)
{
int error;
- if ((error= info->file->ft_read(info->table->record[0])))
+ if ((error= info->file->ha_ft_read(info->table->record[0])))
return report_error(info->table, error);
return 0;
}
@@ -12793,7 +12809,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
int error;
join->found_records++;
- if ((error=table->file->ha_write_row(table->record[0])))
+ if ((error= table->file->ha_write_row(table->record[0])))
{
if (!table->file->is_fatal_error(error, HA_CHECK_DUP))
goto end;
@@ -12848,15 +12864,15 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (item->maybe_null)
group->buff[-1]= (char) group->field->is_null();
}
- if (!table->file->index_read_map(table->record[1],
- join->tmp_table_param.group_buff,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (!table->file->ha_index_read_map(table->record[1],
+ join->tmp_table_param.group_buff,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{ /* Update old record */
restore_record(table,record[1]);
update_tmptable_sum_func(join->sum_funcs,table);
- if ((error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ if ((error= table->file->ha_update_row(table->record[1],
+ table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
@@ -12879,7 +12895,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
init_tmptable_sum_functions(join->sum_funcs);
copy_funcs(join->tmp_table_param.items_to_copy);
- if ((error=table->file->ha_write_row(table->record[0])))
+ if ((error= table->file->ha_write_row(table->record[0])))
{
if (create_internal_tmp_table_from_heap(join->thd, table,
&join->tmp_table_param,
@@ -12920,7 +12936,7 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
copy_fields(&join->tmp_table_param); // Groups are copied twice.
copy_funcs(join->tmp_table_param.items_to_copy);
- if (!(error=table->file->ha_write_row(table->record[0])))
+ if (!(error= table->file->ha_write_row(table->record[0])))
join->send_records++; // New group
else
{
@@ -12929,15 +12945,15 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
- if (table->file->rnd_pos(table->record[1],table->file->dup_ref))
+ if (table->file->ha_rnd_pos(table->record[1],table->file->dup_ref))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
restore_record(table,record[1]);
update_tmptable_sum_func(join->sum_funcs,table);
- if ((error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ if ((error= table->file->ha_update_row(table->record[1],
+ table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
@@ -14324,8 +14340,10 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
org_record=(char*) (record=table->record[0])+offset;
new_record=(char*) table->record[1]+offset;
- file->ha_rnd_init(1);
- error=file->rnd_next(record);
+ if (file->ha_rnd_init_with_error(1))
+ DBUG_RETURN(1);
+
+ error= file->ha_rnd_next(record);
for (;;)
{
if (thd->killed)
@@ -14338,7 +14356,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
{
if (error == HA_ERR_RECORD_DELETED)
{
- error= file->rnd_next(record);
+ error= file->ha_rnd_next(record);
continue;
}
if (error == HA_ERR_END_OF_FILE)
@@ -14347,9 +14365,9 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
}
if (having && !having->val_int())
{
- if ((error=file->ha_delete_row(record)))
+ if ((error= file->ha_delete_row(record)))
goto err;
- error=file->rnd_next(record);
+ error= file->ha_rnd_next(record);
continue;
}
if (copy_blobs(first_field))
@@ -14364,7 +14382,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
bool found=0;
for (;;)
{
- if ((error=file->rnd_next(record)))
+ if ((error= file->ha_rnd_next(record)))
{
if (error == HA_ERR_RECORD_DELETED)
continue;
@@ -14374,7 +14392,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
}
if (compare_record(table, first_field) == 0)
{
- if ((error=file->ha_delete_row(record)))
+ if ((error= file->ha_delete_row(record)))
goto err;
}
else if (!found)
@@ -14453,7 +14471,9 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
DBUG_RETURN(1);
}
- file->ha_rnd_init(1);
+ if ((error= file->ha_rnd_init(1)))
+ goto err;
+
key_pos=key_buffer;
for (;;)
{
@@ -14464,7 +14484,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
error=0;
goto err;
}
- if ((error=file->rnd_next(record)))
+ if ((error= file->ha_rnd_next(record)))
{
if (error == HA_ERR_RECORD_DELETED)
continue;
@@ -14474,7 +14494,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
}
if (having && !having->val_int())
{
- if ((error=file->ha_delete_row(record)))
+ if ((error= file->ha_delete_row(record)))
goto err;
continue;
}
@@ -14491,7 +14511,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
if (hash_search(&hash, org_key_pos, key_length))
{
/* Duplicated found ; Remove the row */
- if ((error=file->ha_delete_row(record)))
+ if ((error= file->ha_delete_row(record)))
goto err;
}
else
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 1655426bb4a..ba4dbaacbb9 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -182,8 +182,9 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
free_root(&mem, MYF(0));
init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
- init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
- FALSE);
+ if (init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
+ FALSE))
+ DBUG_RETURN(1);
while (!(read_record_info.read_record(&read_record_info)))
{
/* return_val is already TRUE, so no need to set */
@@ -526,10 +527,10 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
system_charset_info);
/* read index until record is that specified in server_name */
- if ((error= table->file->index_read_idx_map(table->record[0], 0,
- (uchar *)table->field[0]->ptr,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar *)table->field[0]->ptr,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT)))
{
/* if not found, err */
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@@ -869,10 +870,10 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
server->server_name_length,
system_charset_info);
- if ((error= table->file->index_read_idx_map(table->record[0], 0,
- (uchar *)table->field[0]->ptr,
- ~(longlong)0,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar *)table->field[0]->ptr,
+ ~(longlong)0,
+ HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
table->file->print_error(error, MYF(0));
@@ -926,10 +927,10 @@ delete_server_record(TABLE *table,
/* set the field that's the PK to the value we're looking for */
table->field[0]->store(server_name, server_name_length, system_charset_info);
- if ((error= table->file->index_read_idx_map(table->record[0], 0,
- (uchar *)table->field[0]->ptr,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT)))
+ if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar *)table->field[0]->ptr,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT)))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
table->file->print_error(error, MYF(0));
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index b79e01f5ef4..e1d223eadad 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -18,6 +18,7 @@
#include "mysql_priv.h"
#include "sql_select.h" // For select_describe
+#include "create_options.h"
#include "sql_show.h"
#include "repl_failsafe.h"
#include "sp.h"
@@ -95,11 +96,21 @@ static int make_version_string(char *buf, int buf_length, uint version)
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
}
+
+static const LEX_STRING maturity_name[]={
+ { C_STRING_WITH_LEN("Unknown") },
+ { C_STRING_WITH_LEN("Experimental") },
+ { C_STRING_WITH_LEN("Alpha") },
+ { C_STRING_WITH_LEN("Beta") },
+ { C_STRING_WITH_LEN("Gamma") },
+ { C_STRING_WITH_LEN("Stable") }};
+
+
static my_bool show_plugins(THD *thd, plugin_ref plugin,
void *arg)
{
TABLE *table= (TABLE*) arg;
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
CHARSET_INFO *cs= system_charset_info;
char version_buf[20];
@@ -144,7 +155,7 @@ static my_bool show_plugins(THD *thd, plugin_ref plugin,
table->field[5]->set_notnull();
table->field[6]->store(version_buf,
make_version_string(version_buf, sizeof(version_buf),
- plugin_dl->version),
+ plugin_dl->mariaversion),
cs);
table->field[6]->set_notnull();
}
@@ -187,6 +198,26 @@ static my_bool show_plugins(THD *thd, plugin_ref plugin,
}
table->field[9]->set_notnull();
+ if ((uint) plug->maturity <= MariaDB_PLUGIN_MATURITY_STABLE)
+ table->field[10]->store(maturity_name[plug->maturity].str,
+ maturity_name[plug->maturity].length,
+ cs);
+ else
+ {
+ DBUG_ASSERT(0);
+ table->field[10]->store("Unknown", 7, cs);
+ }
+ table->field[10]->set_notnull();
+
+ if (plug->version_info)
+ {
+ table->field[11]->store(plug->version_info,
+ strlen(plug->version_info), cs);
+ table->field[11]->set_notnull();
+ }
+ else
+ table->field[11]->set_null();
+
return schema_table_store_record(thd, table);
}
@@ -822,6 +853,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
sctx->master_access);
if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname))
{
+ status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->host_or_ip, dbname);
general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
@@ -1013,7 +1045,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
/*
The identifier must be quoted as it includes a quote character or
- it's a keyword
+ it's a keyword
*/
VOID(packet->reserve(length*2 + 2));
@@ -1173,6 +1205,31 @@ static bool get_field_default_value(THD *thd, TABLE *table,
return has_default;
}
+
+/**
+ Appends list of options to string
+
+ @param thd thread handler
+ @param packet string to append
+ @param opt list of options
+*/
+
+static void append_create_options(THD *thd, String *packet,
+ engine_option_value *opt)
+{
+ for(; opt; opt= opt->next)
+ {
+ DBUG_ASSERT(opt->value.str);
+ packet->append(' ');
+ append_identifier(thd, packet, opt->name.str, opt->name.length);
+ packet->append('=');
+ if (opt->quoted_value)
+ append_unescaped(packet, opt->value.str, opt->value.length);
+ else
+ packet->append(opt->value.str, opt->value.length);
+ }
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1311,6 +1368,19 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
}
}
+ if (field->vcol_info)
+ {
+ packet->append(STRING_WITH_LEN(" AS ("));
+ packet->append(field->vcol_info->expr_str.str,
+ field->vcol_info->expr_str.length,
+ system_charset_info);
+ packet->append(STRING_WITH_LEN(")"));
+ if (field->stored_in_db)
+ packet->append(STRING_WITH_LEN(" PERSISTENT"));
+ else
+ packet->append(STRING_WITH_LEN(" VIRTUAL"));
+ }
+
if (flags & NOT_NULL_FLAG)
packet->append(STRING_WITH_LEN(" NOT NULL"));
else if (field->type() == MYSQL_TYPE_TIMESTAMP)
@@ -1322,7 +1392,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" NULL"));
}
- if (get_field_default_value(thd, table, field, &def_value, 1))
+ if (!field->vcol_info &&
+ get_field_default_value(thd, table, field, &def_value, 1))
{
packet->append(STRING_WITH_LEN(" DEFAULT "));
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
@@ -1341,6 +1412,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
+ append_create_options(thd, packet, field->option_list);
}
key_info= table->key_info;
@@ -1412,6 +1484,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
}
+ append_create_options(thd, packet, key_info->option_list);
}
/*
@@ -1571,6 +1644,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
+ append_create_options(thd, packet, share->option_list);
append_directory(thd, packet, "DATA", create_info.data_file_name);
append_directory(thd, packet, "INDEX", create_info.index_file_name);
}
@@ -2207,12 +2281,36 @@ void remove_status_vars(SHOW_VAR *list)
}
}
-inline void make_upper(char *buf)
+
+
+static void update_key_cache_stat_var(KEY_CACHE *key_cache, size_t ofs)
{
- for (; *buf; buf++)
- *buf= my_toupper(system_charset_info, *buf);
+ uint var_no;
+ if (ofs == offsetof(KEY_CACHE, blocks_used) ||
+ ofs == offsetof(KEY_CACHE, blocks_unused) ||
+ ofs == offsetof(KEY_CACHE, global_blocks_changed))
+ {
+ var_no= (ofs-offsetof(KEY_CACHE, blocks_used))/sizeof(ulong);
+ *(ulong *)((char *) key_cache + ofs)=
+ (ulong) get_key_cache_stat_value(key_cache, var_no);
+ return;
+ }
+
+ if (ofs == offsetof(KEY_CACHE, global_cache_r_requests) ||
+ ofs == offsetof(KEY_CACHE, global_cache_read) ||
+ ofs == offsetof(KEY_CACHE, global_cache_w_requests) ||
+ ofs == offsetof(KEY_CACHE, global_cache_write))
+ {
+ var_no= NUM_LONG_KEY_CACHE_STAT_VARIABLES +
+ (ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
+ sizeof(ulonglong);
+ *(ulonglong *)((char *) key_cache + ofs)=
+ get_key_cache_stat_value(key_cache, var_no);
+ return;
+ }
}
+
static bool show_status_array(THD *thd, const char *wild,
SHOW_VAR *variables,
enum enum_var_type value_type,
@@ -2250,7 +2348,7 @@ static bool show_status_array(THD *thd, const char *wild,
strnmov(prefix_end, variables->name, len);
name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
if (ucase_names)
- make_upper(name_buffer);
+ my_caseup_str(system_charset_info, name_buffer);
restore_record(table, s->default_values);
table->field[0]->store(name_buffer, strlen(name_buffer),
@@ -2345,10 +2443,12 @@ static bool show_status_array(THD *thd, const char *wild,
break;
}
case SHOW_KEY_CACHE_LONG:
+ update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_KEY_CACHE_LONGLONG:
+ update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
@@ -2377,6 +2477,323 @@ end:
DBUG_RETURN(res);
}
+#ifdef COMPLEAT_PATCH_NOT_ADDED_YET
+/*
+ Aggregate values for mapped_user entries by their role.
+
+ SYNOPSIS
+ aggregate_user_stats
+ all_user_stats - input to aggregate
+ agg_user_stats - returns aggregated values
+
+ RETURN
+ 0 - OK
+ 1 - error
+*/
+
+static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats)
+{
+ DBUG_ENTER("aggregate_user_stats");
+ if (hash_init(agg_user_stats, system_charset_info,
+ max(all_user_stats->records, 1),
+ 0, 0, (hash_get_key)get_key_user_stats,
+ (hash_free_key)free_user_stats, 0))
+ {
+ sql_print_error("Malloc in aggregate_user_stats failed");
+ DBUG_RETURN(1);
+ }
+
+ for (uint i= 0; i < all_user_stats->records; i++)
+ {
+ USER_STATS *user= (USER_STATS*)hash_element(all_user_stats, i);
+ USER_STATS *agg_user;
+ uint name_length= strlen(user->priv_user);
+
+ if (!(agg_user= (USER_STATS*) hash_search(agg_user_stats,
+ (uchar*)user->priv_user,
+ name_length)))
+ {
+ // First entry for this role.
+ if (!(agg_user= (USER_STATS*) my_malloc(sizeof(USER_STATS),
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ sql_print_error("Malloc in aggregate_user_stats failed");
+ DBUG_RETURN(1);
+ }
+
+ init_user_stats(agg_user, user->priv_user, name_length,
+ user->priv_user,
+ user->total_connections, user->concurrent_connections,
+ user->connected_time, user->busy_time, user->cpu_time,
+ user->bytes_received, user->bytes_sent,
+ user->binlog_bytes_written,
+ user->rows_sent, user->rows_read,
+ user->rows_inserted, user->rows_deleted,
+ user->rows_updated,
+ user->select_commands, user->update_commands,
+ user->other_commands,
+ user->commit_trans, user->rollback_trans,
+ user->denied_connections, user->lost_connections,
+ user->access_denied_errors, user->empty_queries);
+
+ if (my_hash_insert(agg_user_stats, (uchar*) agg_user))
+ {
+ /* Out of memory */
+ my_free(agg_user, 0);
+ sql_print_error("Malloc in aggregate_user_stats failed");
+ DBUG_RETURN(1);
+ }
+ }
+ else
+ {
+ /* Aggregate with existing values for this role. */
+ add_user_stats(agg_user,
+ user->total_connections, user->concurrent_connections,
+ user->connected_time, user->busy_time, user->cpu_time,
+ user->bytes_received, user->bytes_sent,
+ user->binlog_bytes_written,
+ user->rows_sent, user->rows_read,
+ user->rows_inserted, user->rows_deleted,
+ user->rows_updated,
+ user->select_commands, user->update_commands,
+ user->other_commands,
+ user->commit_trans, user->rollback_trans,
+ user->denied_connections, user->lost_connections,
+ user->access_denied_errors, user->empty_queries);
+ }
+ }
+ DBUG_PRINT("exit", ("aggregated %lu input into %lu output entries",
+ all_user_stats->records, agg_user_stats->records));
+ DBUG_RETURN(0);
+}
+#endif
+
+/*
+ Write result to network for SHOW USER_STATISTICS
+
+ SYNOPSIS
+ send_user_stats
+ all_user_stats - values to return
+ table - I_S table
+
+ RETURN
+ 0 - OK
+ 1 - error
+*/
+
+int send_user_stats(THD* thd, HASH *all_user_stats, TABLE *table)
+{
+ DBUG_ENTER("send_user_stats");
+
+ for (uint i= 0; i < all_user_stats->records; i++)
+ {
+ uint j= 0;
+ USER_STATS *user_stats= (USER_STATS*) hash_element(all_user_stats, i);
+
+ table->field[j++]->store(user_stats->user, user_stats->user_name_length,
+ system_charset_info);
+ table->field[j++]->store((longlong)user_stats->total_connections,TRUE);
+ table->field[j++]->store((longlong)user_stats->concurrent_connections, TRUE);
+ table->field[j++]->store((longlong)user_stats->connected_time, TRUE);
+ table->field[j++]->store((double)user_stats->busy_time);
+ table->field[j++]->store((double)user_stats->cpu_time);
+ table->field[j++]->store((longlong)user_stats->bytes_received, TRUE);
+ table->field[j++]->store((longlong)user_stats->bytes_sent, TRUE);
+ table->field[j++]->store((longlong)user_stats->binlog_bytes_written, TRUE);
+ table->field[j++]->store((longlong)user_stats->rows_read, TRUE);
+ table->field[j++]->store((longlong)user_stats->rows_sent, TRUE);
+ table->field[j++]->store((longlong)user_stats->rows_deleted, TRUE);
+ table->field[j++]->store((longlong)user_stats->rows_inserted, TRUE);
+ table->field[j++]->store((longlong)user_stats->rows_updated, TRUE);
+ table->field[j++]->store((longlong)user_stats->select_commands, TRUE);
+ table->field[j++]->store((longlong)user_stats->update_commands, TRUE);
+ table->field[j++]->store((longlong)user_stats->other_commands, TRUE);
+ table->field[j++]->store((longlong)user_stats->commit_trans, TRUE);
+ table->field[j++]->store((longlong)user_stats->rollback_trans, TRUE);
+ table->field[j++]->store((longlong)user_stats->denied_connections, TRUE);
+ table->field[j++]->store((longlong)user_stats->lost_connections, TRUE);
+ table->field[j++]->store((longlong)user_stats->access_denied_errors, TRUE);
+ table->field[j++]->store((longlong)user_stats->empty_queries, TRUE);
+ if (schema_table_store_record(thd, table))
+ {
+ DBUG_PRINT("error", ("store record error"));
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ Process SHOW USER_STATISTICS
+
+ SYNOPSIS
+ mysqld_show_user_stats
+ thd - current thread
+ wild - limit results to the entry for this user
+ with_roles - when true, display role for mapped users
+
+ RETURN
+ 0 - OK
+ 1 - error
+*/
+
+int fill_schema_user_stats(THD* thd, TABLE_LIST* tables, COND* cond)
+{
+ TABLE *table= tables->table;
+ int result;
+ DBUG_ENTER("fill_schema_user_stats");
+
+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
+ DBUG_RETURN(1);
+
+ /*
+ Iterates through all the global stats and sends them to the client.
+ Pattern matching on the client IP is supported.
+ */
+
+ pthread_mutex_lock(&LOCK_global_user_client_stats);
+ result= send_user_stats(thd, &global_user_stats, table) != 0;
+ pthread_mutex_unlock(&LOCK_global_user_client_stats);
+
+ DBUG_PRINT("exit", ("result: %d", result));
+ DBUG_RETURN(result);
+}
+
+/*
+ Process SHOW CLIENT_STATISTICS
+
+ SYNOPSIS
+ mysqld_show_client_stats
+ thd - current thread
+ wild - limit results to the entry for this client
+
+ RETURN
+ 0 - OK
+ 1 - error
+*/
+
+int fill_schema_client_stats(THD* thd, TABLE_LIST* tables, COND* cond)
+{
+ TABLE *table= tables->table;
+ int result;
+ DBUG_ENTER("fill_schema_client_stats");
+
+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
+ DBUG_RETURN(1);
+
+ /*
+ Iterates through all the global stats and sends them to the client.
+ Pattern matching on the client IP is supported.
+ */
+
+ pthread_mutex_lock(&LOCK_global_user_client_stats);
+ result= send_user_stats(thd, &global_client_stats, table) != 0;
+ pthread_mutex_unlock(&LOCK_global_user_client_stats);
+
+ DBUG_PRINT("exit", ("result: %d", result));
+ DBUG_RETURN(result);
+}
+
+
+/* Fill information schema table with table statistics */
+
+int fill_schema_table_stats(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_table_stats");
+
+ pthread_mutex_lock(&LOCK_global_table_stats);
+ for (uint i= 0; i < global_table_stats.records; i++)
+ {
+ char *end_of_schema;
+ TABLE_STATS *table_stats=
+ (TABLE_STATS*)hash_element(&global_table_stats, i);
+ TABLE_LIST tmp_table;
+ size_t schema_length, table_name_length;
+
+ end_of_schema= strend(table_stats->table);
+ schema_length= (size_t) (end_of_schema - table_stats->table);
+ table_name_length= strlen(table_stats->table + schema_length + 1);
+
+ bzero((char*) &tmp_table,sizeof(tmp_table));
+ tmp_table.db= table_stats->table;
+ tmp_table.table_name= end_of_schema+1;
+ tmp_table.grant.privilege= 0;
+ if (check_access(thd, SELECT_ACL | EXTRA_ACL, tmp_table.db,
+ &tmp_table.grant.privilege, 0, 0,
+ is_schema_db(tmp_table.db)) ||
+ check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX,
+ 1))
+ continue;
+
+ table->field[0]->store(table_stats->table, schema_length,
+ system_charset_info);
+ table->field[1]->store(table_stats->table + schema_length+1,
+ table_name_length, system_charset_info);
+ table->field[2]->store((longlong)table_stats->rows_read, TRUE);
+ table->field[3]->store((longlong)table_stats->rows_changed, TRUE);
+ table->field[4]->store((longlong)table_stats->rows_changed_x_indexes,
+ TRUE);
+ if (schema_table_store_record(thd, table))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_global_table_stats));
+ DBUG_RETURN(1);
+ }
+ }
+ pthread_mutex_unlock(&LOCK_global_table_stats);
+ DBUG_RETURN(0);
+}
+
+
+/* Fill information schema table with index statistics */
+
+int fill_schema_index_stats(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_index_stats");
+
+ pthread_mutex_lock(&LOCK_global_index_stats);
+ for (uint i= 0; i < global_index_stats.records; i++)
+ {
+ INDEX_STATS *index_stats =
+ (INDEX_STATS*) hash_element(&global_index_stats, i);
+ TABLE_LIST tmp_table;
+ char *index_name;
+ size_t schema_name_length, table_name_length, index_name_length;
+
+ bzero((char*) &tmp_table,sizeof(tmp_table));
+ tmp_table.db= index_stats->index;
+ tmp_table.table_name= strend(index_stats->index)+1;
+ tmp_table.grant.privilege= 0;
+ if (check_access(thd, SELECT_ACL | EXTRA_ACL, tmp_table.db,
+ &tmp_table.grant.privilege, 0, 0,
+ is_schema_db(tmp_table.db)) ||
+ check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, 1))
+ continue;
+
+ index_name= strend(tmp_table.table_name)+1;
+ schema_name_length= (tmp_table.table_name - index_stats->index) -1;
+ table_name_length= (index_name - tmp_table.table_name)-1;
+ index_name_length= (index_stats->index_name_length - schema_name_length -
+ table_name_length - 3);
+
+ table->field[0]->store(tmp_table.db, schema_name_length,
+ system_charset_info);
+ table->field[1]->store(tmp_table.table_name, table_name_length,
+ system_charset_info);
+ table->field[2]->store(index_name, index_name_length, system_charset_info);
+ table->field[3]->store((longlong)index_stats->rows_read, TRUE);
+
+ if (schema_table_store_record(thd, table))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_global_index_stats));
+ DBUG_RETURN(1);
+ }
+ }
+ pthread_mutex_unlock(&LOCK_global_index_stats);
+ DBUG_RETURN(0);
+}
+
/* collect status for all running threads */
@@ -4019,6 +4436,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
cs);
+ if (field->vcol_info)
+ table->field[16]->store(STRING_WITH_LEN("VIRTUAL"), cs);
table->field[18]->store(field->comment.str, field->comment.length, cs);
if (schema_table_store_record(thd, table))
@@ -4075,7 +4494,7 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin,
if (plugin_state(plugin) != PLUGIN_IS_READY)
{
- struct st_mysql_plugin *plug= plugin_decl(plugin);
+ struct st_maria_plugin *plug= plugin_decl(plugin);
if (!(wild && wild[0] &&
wild_case_compare(scs, plug->name,wild)))
{
@@ -4317,7 +4736,7 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(1);
}
proc_table->file->ha_index_init(0, 1);
- if ((res= proc_table->file->index_first(proc_table->record[0])))
+ if ((res= proc_table->file->ha_index_first(proc_table->record[0])))
{
res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
goto err;
@@ -4327,7 +4746,7 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
res= 1;
goto err;
}
- while (!proc_table->file->index_next(proc_table->record[0]))
+ while (!proc_table->file->ha_index_next(proc_table->record[0]))
{
if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
{
@@ -5573,6 +5992,81 @@ struct schema_table_ref
ST_SCHEMA_TABLE *schema_table;
};
+ST_FIELD_INFO user_stats_fields_info[]=
+{
+ {"USER", USERNAME_LENGTH, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
+ {"TOTAL_CONNECTIONS", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Total_connections",SKIP_OPEN_TABLE},
+ {"CONCURRENT_CONNECTIONS", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Concurrent_connections",SKIP_OPEN_TABLE},
+ {"CONNECTED_TIME", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Connected_time",SKIP_OPEN_TABLE},
+ {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Busy_time",SKIP_OPEN_TABLE},
+ {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Cpu_time",SKIP_OPEN_TABLE},
+ {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Bytes_received",SKIP_OPEN_TABLE},
+ {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Bytes_sent",SKIP_OPEN_TABLE},
+ {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Binlog_bytes_written",SKIP_OPEN_TABLE},
+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE},
+ {"ROWS_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_sent",SKIP_OPEN_TABLE},
+ {"ROWS_DELETED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_deleted",SKIP_OPEN_TABLE},
+ {"ROWS_INSERTED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_inserted",SKIP_OPEN_TABLE},
+ {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_updated",SKIP_OPEN_TABLE},
+ {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Select_commands",SKIP_OPEN_TABLE},
+ {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Update_commands",SKIP_OPEN_TABLE},
+ {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Other_commands",SKIP_OPEN_TABLE},
+ {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Commit_transactions",SKIP_OPEN_TABLE},
+ {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rollback_transactions",SKIP_OPEN_TABLE},
+ {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Denied_connections",SKIP_OPEN_TABLE},
+ {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE},
+ {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE},
+ {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
+};
+
+ST_FIELD_INFO client_stats_fields_info[]=
+{
+ {"CLIENT", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Client",SKIP_OPEN_TABLE},
+ {"TOTAL_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Total_connections",SKIP_OPEN_TABLE},
+ {"CONCURRENT_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Concurrent_connections",SKIP_OPEN_TABLE},
+ {"CONNECTED_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Connected_time",SKIP_OPEN_TABLE},
+ {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Busy_time",SKIP_OPEN_TABLE},
+ {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_DOUBLE, 0, 0, "Cpu_time",SKIP_OPEN_TABLE},
+ {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Bytes_received",SKIP_OPEN_TABLE},
+ {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Bytes_sent",SKIP_OPEN_TABLE},
+ {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Binlog_bytes_written",SKIP_OPEN_TABLE},
+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE},
+ {"ROWS_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_sent",SKIP_OPEN_TABLE},
+ {"ROWS_DELETED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_deleted",SKIP_OPEN_TABLE},
+ {"ROWS_INSERTED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_inserted",SKIP_OPEN_TABLE},
+ {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_updated",SKIP_OPEN_TABLE},
+ {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Select_commands",SKIP_OPEN_TABLE},
+ {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Update_commands",SKIP_OPEN_TABLE},
+ {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Other_commands",SKIP_OPEN_TABLE},
+ {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Commit_transactions",SKIP_OPEN_TABLE},
+ {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rollback_transactions",SKIP_OPEN_TABLE},
+ {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Denied_connections",SKIP_OPEN_TABLE},
+ {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE},
+ {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE},
+ {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_stats_fields_info[]=
+{
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_schema",SKIP_OPEN_TABLE},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_name",SKIP_OPEN_TABLE},
+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE},
+ {"ROWS_CHANGED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_changed",SKIP_OPEN_TABLE},
+ {"ROWS_CHANGED_X_INDEXES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_changed_x_#indexes",SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
+};
+
+ST_FIELD_INFO index_stats_fields_info[]=
+{
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_schema",SKIP_OPEN_TABLE},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_name",SKIP_OPEN_TABLE},
+ {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Index_name",SKIP_OPEN_TABLE},
+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Rows_read",SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0,0}
+};
/*
Find schema_tables elment by name
@@ -6212,6 +6706,90 @@ int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond)
}
+static
+int store_key_cache_table_record(THD *thd, TABLE *table,
+ const char *name, uint name_length,
+ KEY_CACHE *key_cache,
+ uint partitions, uint partition_no)
+{
+ KEY_CACHE_STATISTICS keycache_stats;
+ uint err;
+ DBUG_ENTER("store_key_cache_table_record");
+
+ get_key_cache_statistics(key_cache, partition_no, &keycache_stats);
+
+ if (!key_cache->key_cache_inited || keycache_stats.mem_size == 0)
+ DBUG_RETURN(0);
+
+ restore_record(table, s->default_values);
+ table->field[0]->store(name, name_length, system_charset_info);
+ if (partitions == 0)
+ table->field[1]->set_null();
+ else
+ {
+ table->field[1]->set_notnull();
+ table->field[1]->store((long) partitions, TRUE);
+ }
+
+ if (partition_no == 0)
+ table->field[2]->set_null();
+ else
+ {
+ table->field[2]->set_notnull();
+ table->field[2]->store((long) partition_no, TRUE);
+ }
+ table->field[3]->store(keycache_stats.mem_size, TRUE);
+ table->field[4]->store(keycache_stats.block_size, TRUE);
+ table->field[5]->store(keycache_stats.blocks_used, TRUE);
+ table->field[6]->store(keycache_stats.blocks_unused, TRUE);
+ table->field[7]->store(keycache_stats.blocks_changed, TRUE);
+ table->field[8]->store(keycache_stats.read_requests, TRUE);
+ table->field[9]->store(keycache_stats.reads, TRUE);
+ table->field[10]->store(keycache_stats.write_requests, TRUE);
+ table->field[11]->store(keycache_stats.writes, TRUE);
+
+ err= schema_table_store_record(thd, table);
+ DBUG_RETURN(err);
+}
+
+
+int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ TABLE *table= tables->table;
+ I_List_iterator<NAMED_LIST> it(key_caches);
+ NAMED_LIST *element;
+ DBUG_ENTER("fill_key_cache_tables");
+
+ while ((element= it++))
+ {
+ KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
+
+ if (!key_cache->key_cache_inited)
+ continue;
+
+ uint partitions= key_cache->partitions;
+ DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
+
+ if (partitions)
+ {
+ for (uint i= 0; i < partitions; i++)
+ {
+ if (store_key_cache_table_record(thd, table,
+ element->name, element->name_length,
+ key_cache, partitions, i+1))
+ DBUG_RETURN(1);
+ }
+ }
+
+ if (store_key_cache_table_record(thd, table,
+ element->name, element->name_length,
+ key_cache, partitions, 0))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
ST_FIELD_INFO schema_fields_info[]=
{
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
@@ -6697,6 +7275,8 @@ ST_FIELD_INFO plugin_fields_info[]=
{"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
+ {"PLUGIN_MATURITY", 12, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
+ {"PLUGIN_AUTH_VERSION", 80, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
@@ -6789,6 +7369,35 @@ ST_FIELD_INFO referential_constraints_fields_info[]=
};
+ST_FIELD_INFO keycache_fields_info[]=
+{
+ {"KEY_CACHE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
+ {"SEGMENTS", 3, MYSQL_TYPE_LONG, 0,
+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED) , 0, SKIP_OPEN_TABLE},
+ {"SEGMENT_NUMBER", 3, MYSQL_TYPE_LONG, 0,
+ (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
+ {"FULL_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
+ {"BLOCK_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE },
+ {"USED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_blocks_used", SKIP_OPEN_TABLE},
+ {"UNUSED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_blocks_unused", SKIP_OPEN_TABLE},
+ {"DIRTY_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_blocks_not_flushed", SKIP_OPEN_TABLE},
+ {"READ_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_read_requests", SKIP_OPEN_TABLE},
+ {"READS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_reads", SKIP_OPEN_TABLE},
+ {"WRITE_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_write_requests", SKIP_OPEN_TABLE},
+ {"WRITES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
+ (MY_I_S_UNSIGNED), "Key_writes", SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+};
+
+
/*
Description of ST_FIELD_INFO in table.h
@@ -6800,6 +7409,8 @@ ST_SCHEMA_TABLE schema_tables[]=
{
{"CHARACTER_SETS", charsets_fields_info, create_schema_table,
fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
+ {"CLIENT_STATISTICS", client_stats_fields_info, create_schema_table,
+ fill_schema_client_stats, make_old_format, 0, -1, -1, 0, 0},
{"COLLATIONS", collation_fields_info, create_schema_table,
fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
{"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
@@ -6824,6 +7435,10 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_status, make_old_format, 0, 0, -1, 0, 0},
{"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
fill_variables, make_old_format, 0, 0, -1, 0, 0},
+ {"INDEX_STATISTICS", index_stats_fields_info, create_schema_table,
+ fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0},
+ {"KEY_CACHES", keycache_fields_info, create_schema_table,
+ fill_key_cache_tables, make_old_format, 0, -1,-1, 0, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
OPEN_TABLE_ONLY},
@@ -6865,11 +7480,15 @@ ST_SCHEMA_TABLE schema_tables[]=
get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
{"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
+ {"TABLE_STATISTICS", table_stats_fields_info, create_schema_table,
+ fill_schema_table_stats, make_old_format, 0, -1, -1, 0, 0},
{"TRIGGERS", triggers_fields_info, create_schema_table,
get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0,
OPEN_TABLE_ONLY},
{"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
fill_schema_user_privileges, 0, 0, -1, -1, 0, 0},
+ {"USER_STATISTICS", user_stats_fields_info, create_schema_table,
+ fill_schema_user_stats, make_old_format, 0, -1, -1, 0, 0},
{"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
make_old_format, 0, 0, -1, 1, 0},
{"VIEWS", view_fields_info, create_schema_table,
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index bdecabd782b..db3d07a28a4 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -26,9 +26,11 @@
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
-
#include "sql_string.h"
+#ifdef MYSQL_CLIENT
+#error Attempt to use server-side sql_string on client. Use client/sql_string.cc
+#endif
/*****************************************************************************
** String functions
*****************************************************************************/
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 9e22f7b6a27..a9df0dc2620 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -1,3 +1,5 @@
+#ifndef MYSQL_SQL_STRING_H_INCLUDED
+#define MYSQL_SQL_STRING_H_INCLUDED
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -23,6 +25,10 @@
#define NOT_FIXED_DEC 31
#endif
+#ifdef MYSQL_CLIENT
+#error Attempt to use server-side sql_string on client. Use client/sql_string.h
+#endif
+
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
@@ -394,3 +400,5 @@ static inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str,
{
return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
}
+
+#endif // MYSQL_SQL_STRING_H_INCLUDED
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 88bcd092dfa..b9b5ff47cf6 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -19,6 +19,7 @@
#include <hash.h>
#include <myisam.h>
#include <my_dir.h>
+#include "create_options.h"
#include "sp_head.h"
#include "sql_trigger.h"
#include "sql_show.h"
@@ -43,17 +44,10 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
-static int
-mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
- Alter_info *alter_info,
- bool tmp_table,
- uint *db_options,
- handler *file, KEY **key_info_buffer,
- uint *key_count, int select_field_count);
-static bool
-mysql_prepare_alter_table(THD *thd, TABLE *table,
- HA_CREATE_INFO *create_info,
- Alter_info *alter_info);
+static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *,
+ bool, uint *, handler *, KEY **, uint *, int);
+static bool mysql_prepare_alter_table(THD *, TABLE *, HA_CREATE_INFO *,
+ Alter_info *);
#ifndef DBUG_OFF
@@ -2255,10 +2249,10 @@ static int sort_keys(KEY *a, KEY *b)
{
if (!(b_flags & HA_NOSAME))
return -1;
- if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
+ if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
{
/* Sort NOT NULL keys before other keys */
- return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
+ return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
}
if (a->name == primary_key_name)
return -1;
@@ -2539,7 +2533,12 @@ int prepare_create_field(Create_field *sql_field,
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
}
- if (!(sql_field->flags & NOT_NULL_FLAG))
+ if (sql_field->flags & NOT_NULL_FLAG)
+ DBUG_PRINT("info", ("1"));
+ if (sql_field->vcol_info)
+ DBUG_PRINT("info", ("2"));
+ if (!(sql_field->flags & NOT_NULL_FLAG) ||
+ (sql_field->vcol_info)) /* Make virtual columns allow NULL values */
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
@@ -2853,6 +2852,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
null_fields--;
sql_field->flags= dup_field->flags;
sql_field->interval= dup_field->interval;
+ sql_field->vcol_info= dup_field->vcol_info;
+ sql_field->stored_in_db= dup_field->stored_in_db;
it2.remove(); // Remove first (create) definition
select_field_pos--;
break;
@@ -2885,7 +2886,28 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
- record_offset+= sql_field->pack_length;
+ if (parse_option_list(thd, &sql_field->option_struct,
+ sql_field->option_list,
+ create_info->db_type->field_options, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
+ /*
+ For now skip fields that are not physically stored in the database
+ (virtual fields) and update their offset later
+ (see the next loop).
+ */
+ if (sql_field->stored_in_db)
+ record_offset+= sql_field->pack_length;
+ }
+ /* Update virtual fields' offset*/
+ it.rewind();
+ while ((sql_field=it++))
+ {
+ if (!sql_field->stored_in_db)
+ {
+ sql_field->offset= record_offset;
+ record_offset+= sql_field->pack_length;
+ }
}
if (timestamps_with_niladic > 1)
{
@@ -2935,6 +2957,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (key->type == Key::FOREIGN_KEY)
{
fk_key_count++;
+ if (((Foreign_key *)key)->validate(alter_info->create_list))
+ DBUG_RETURN(TRUE);
Foreign_key *fk_key= (Foreign_key*) key;
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
@@ -3065,6 +3089,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
key_info->algorithm= key->key_create_info.algorithm;
+ key_info->option_list= key->option_list;
+ if (parse_option_list(thd, &key_info->option_struct,
+ key_info->option_list,
+ create_info->db_type->index_options, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
if (key->type == Key::FULLTEXT)
{
@@ -3221,6 +3251,17 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
#endif
+ if (!sql_field->stored_in_db)
+ {
+ /* Key fields must always be physically stored. */
+ my_error(ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (key->type == Key::PRIMARY && sql_field->vcol_info)
+ {
+ my_error(ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
if (!(sql_field->flags & NOT_NULL_FLAG))
{
if (key->type == Key::PRIMARY)
@@ -3431,6 +3472,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
+ if (parse_option_list(thd, &create_info->option_struct,
+ create_info->option_list,
+ file->partition_ht()->table_options, FALSE,
+ thd->mem_root))
+ DBUG_RETURN(TRUE);
+
DBUG_RETURN(FALSE);
}
@@ -5717,6 +5764,7 @@ compare_tables(TABLE *table,
KEY_PART_INFO *key_part;
KEY_PART_INFO *end;
THD *thd= table->in_use;
+ uint i;
/*
Remember if the new definition has new VARCHAR column;
create_info->varchar will be reset in mysql_prepare_create_table.
@@ -5807,6 +5855,12 @@ compare_tables(TABLE *table,
DBUG_RETURN(0);
}
+ if ((create_info->fileds_option_struct=
+ (void**)thd->calloc(sizeof(void*) * table->s->fields)) == NULL ||
+ (create_info->indexes_option_struct=
+ (void**)thd->calloc(sizeof(void*) * table->s->keys)) == NULL)
+ DBUG_RETURN(1);
+
/*
Use transformed info to evaluate possibility of fast ALTER TABLE
but use the preserved field to persist modifications.
@@ -5814,15 +5868,19 @@ compare_tables(TABLE *table,
new_field_it.init(alter_info->create_list);
tmp_new_field_it.init(tmp_alter_info.create_list);
- /* Go through fields and check if the original ones are compatible
+ /*
+ Go through fields and check if the original ones are compatible
with new table.
*/
- for (f_ptr= table->field, new_field= new_field_it++,
+ for (i= 0, f_ptr= table->field, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++;
(field= *f_ptr);
- f_ptr++, new_field= new_field_it++,
+ i++, f_ptr++, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++)
{
+ DBUG_ASSERT(i < table->s->fields);
+ create_info->fileds_option_struct[i]= tmp_new_field->option_struct;
+
/* Make sure we have at least the default charset in use. */
if (!new_field->charset)
new_field->charset= create_info->default_table_charset;
@@ -5836,6 +5894,19 @@ compare_tables(TABLE *table,
DBUG_RETURN(0);
}
+ /*
+ Check if the altered column is computed and either
+ is stored or is used in the partitioning expression.
+ TODO: Mark such a column with an alter flag only if
+ the defining expression has changed.
+ */
+ if (field->vcol_info &&
+ (field->stored_in_db || field->vcol_info->is_in_partitioning_expr()))
+ {
+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
+ DBUG_RETURN(0);
+ }
+
/* Don't pack rows in old tables if the user has requested this. */
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
(tmp_new_field->flags & BLOB_FLAG) ||
@@ -5963,7 +6034,9 @@ compare_tables(TABLE *table,
for (new_key= *key_info_buffer; new_key < new_key_end; new_key++)
{
/* Search an old key with the same name. */
- for (table_key= table->key_info; table_key < table_key_end; table_key++)
+ for (i= 0, table_key= table->key_info;
+ table_key < table_key_end;
+ i++, table_key++)
{
if (! strcmp(table_key->name, new_key->name))
break;
@@ -5982,6 +6055,11 @@ compare_tables(TABLE *table,
}
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
}
+ else
+ {
+ DBUG_ASSERT(i < table->s->keys);
+ create_info->indexes_option_struct[i]= new_key->option_struct;
+ }
}
/* Check if changes are compatible with current handler without a copy */
@@ -6157,6 +6235,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
restore_record(table, s->default_values); // Empty record for DEFAULT
+ create_info->option_list= merge_engine_table_options(table->s->option_list,
+ create_info->option_list, thd->mem_root);
/*
First collect all fields from table which isn't in drop_list
*/
@@ -6198,6 +6278,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (def)
{ // Field is changed
def->field=field;
+ if (field->stored_in_db != def->stored_in_db)
+ {
+ my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
+ MYF(0),
+ "Changing the STORED status");
+ goto err;
+ }
if (!def->after)
{
new_create_list.push_back(def);
@@ -6402,7 +6489,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key= new Key(key_type, key_name,
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts);
+ key_parts, key_info->option_list);
new_key_list.push_back(key);
}
}
@@ -6410,6 +6497,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
Key *key;
while ((key=key_it++)) // Add new keys
{
+ if (key->type == Key::FOREIGN_KEY &&
+ ((Foreign_key *)key)->validate(new_create_list))
+ goto err;
if (key->type != Key::FOREIGN_KEY)
new_key_list.push_back(key);
if (key->name &&
@@ -7606,27 +7696,6 @@ view_err:
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
DBUG_RETURN(TRUE);
- if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
- {
- /*
- For the alter table to be properly flushed to the logs, we
- have to open the new table. If not, we get a problem on server
- shutdown. But we do not need to attach MERGE children.
- */
- char path[FN_REFLEN];
- TABLE *t_table;
- build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0);
- t_table= open_temporary_table(thd, path, new_db, tmp_name, 0);
- if (t_table)
- {
- intern_close_table(t_table);
- my_free(t_table, MYF(0));
- }
- else
- sql_print_warning("Could not open table %s.%s after rename\n",
- new_db,table_name);
- ha_flush_logs(old_db_type);
- }
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
@@ -7835,7 +7904,9 @@ copy_data_between_tables(TABLE *from,TABLE *to,
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
- init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
+ to->mark_virtual_columns_for_write(TRUE);
+ if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE))
+ goto err;
errpos= 4;
if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -7849,6 +7920,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
error= 1;
break;
}
+ update_virtual_fields(thd, from);
thd->row_count++;
/* Return error if source table isn't empty. */
if (error_if_not_empty)
@@ -7869,6 +7941,12 @@ copy_data_between_tables(TABLE *from,TABLE *to,
copy_ptr->do_copy(copy_ptr);
}
prev_insert_id= to->file->next_insert_id;
+ update_virtual_fields(thd, to, TRUE);
+ if (thd->is_error())
+ {
+ error= 1;
+ break;
+ }
error=to->file->ha_write_row(to->record[0]);
to->auto_increment_field_not_null= FALSE;
if (error)
@@ -8050,7 +8128,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
goto err;
}
ha_checksum row_crc= 0;
- int error= t->file->rnd_next(t->record[0]);
+ int error= t->file->ha_rnd_next(t->record[0]);
if (unlikely(error))
{
if (error == HA_ERR_RECORD_DELETED)
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 5de8301fd05..5c9077f86ea 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -445,7 +445,8 @@ static int print_key_cache_status(const char *name, KEY_CACHE *key_cache)
Buffer_size: %10lu\n\
Block_size: %10lu\n\
Division_limit: %10lu\n\
-Age_limit: %10lu\n\
+Age_threshold: %10lu\n\
+Partitions: %10lu\n\
blocks used: %10lu\n\
not flushed: %10lu\n\
w_requests: %10s\n\
@@ -455,6 +456,7 @@ reads: %10s\n\n",
name,
(ulong) key_cache->param_buff_size, key_cache->param_block_size,
key_cache->param_division_limit, key_cache->param_age_threshold,
+ key_cache->param_partitions,
key_cache->blocks_used,key_cache->global_blocks_changed,
llstr(key_cache->global_cache_w_requests,llbuff1),
llstr(key_cache->global_cache_write,llbuff2),
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index d455a66c4f2..7aa7571d5ee 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -152,7 +152,13 @@ void udf_init()
}
table= tables.table;
- init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE);
+ if (init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE))
+ {
+ sql_print_error("Could not initialize init_read_record; udf's not "
+ "loaded");
+ goto end;
+ }
+
table->use_all_columns();
while (!(error= read_record_info.read_record(&read_record_info)))
{
@@ -577,10 +583,10 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
goto err;
table->use_all_columns();
table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin);
- if (!table->file->index_read_idx_map(table->record[0], 0,
- (uchar*) table->field[0]->ptr,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
+ if (!table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar*) table->field[0]->ptr,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT))
{
int error;
if ((error = table->file->ha_delete_row(table->record[0])))
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index fc45b3d31a2..15251e956be 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -143,7 +143,7 @@ static void prepare_record_for_error_message(int error, TABLE *table)
/* Tell the engine about the new set. */
table->file->column_bitmaps_signal();
/* Read record that is identified by table->file->ref. */
- (void) table->file->rnd_pos(table->record[1], table->file->ref);
+ (void) table->file->ha_rnd_pos(table->record[1], table->file->ref);
/* Copy the newly read columns into the new record. */
for (field_p= table->field; (field= *field_p); field_p++)
if (bitmap_is_set(&unique_map, field->field_index))
@@ -460,7 +460,10 @@ int mysql_update(THD *thd,
*/
if (used_index == MAX_KEY || (select && select->quick))
- init_read_record(&info, thd, table, select, 0, 1, FALSE);
+ {
+ if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
+ goto err;
+ }
else
init_read_record_idx(&info, thd, table, 1, used_index);
@@ -470,6 +473,7 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) &&
!thd->killed && !thd->is_error())
{
+ update_virtual_fields(thd, table);
thd->examined_row_count++;
if (!select || select->skip_record(thd) > 0)
{
@@ -528,7 +532,8 @@ int mysql_update(THD *thd,
if (select && select->quick && select->quick->reset())
goto err;
table->file->try_semi_consistent_read(1);
- init_read_record(&info, thd, table, select, 0, 1, FALSE);
+ if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
+ goto err;
updated= found= 0;
/*
@@ -577,6 +582,7 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) && !thd->killed)
{
+ update_virtual_fields(thd, table);
thd->examined_row_count++;
if (!select || select->skip_record(thd) > 0)
{
@@ -1955,7 +1961,7 @@ int multi_update::do_updates()
TABLE_LIST *cur_table;
int local_error= 0;
ha_rows org_updated;
- TABLE *table, *tmp_table;
+ TABLE *table, *tmp_table, *err_table;
List_iterator_fast<TABLE> check_opt_it(unupdated_check_opt_tables);
DBUG_ENTER("multi_update::do_updates");
@@ -1973,14 +1979,21 @@ int multi_update::do_updates()
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
- (void) table->file->ha_rnd_init(0);
+ if ((local_error= table->file->ha_rnd_init(0)))
+ {
+ err_table= table;
+ goto err;
+ }
table->file->extra(HA_EXTRA_NO_CACHE);
check_opt_it.rewind();
while(TABLE *tbl= check_opt_it++)
{
- if (tbl->file->ha_rnd_init(1))
+ if ((local_error= tbl->file->ha_rnd_init(1)))
+ {
+ err_table= tbl;
goto err;
+ }
tbl->file->extra(HA_EXTRA_CACHE);
}
@@ -2000,8 +2013,11 @@ int multi_update::do_updates()
}
copy_field_end=copy_field_ptr;
- if ((local_error = tmp_table->file->ha_rnd_init(1)))
+ if ((local_error= tmp_table->file->ha_rnd_init(1)))
+ {
+ err_table= tmp_table;
goto err;
+ }
can_compare_record= (!(table->file->ha_table_flags() &
HA_PARTIAL_COLUMN_READ) ||
@@ -2011,13 +2027,17 @@ int multi_update::do_updates()
for (;;)
{
if (thd->killed && trans_safe)
- goto err;
- if ((local_error=tmp_table->file->rnd_next(tmp_table->record[0])))
+ {
+ thd->fatal_error();
+ goto err2;
+ }
+ if ((local_error= tmp_table->file->ha_rnd_next(tmp_table->record[0])))
{
if (local_error == HA_ERR_END_OF_FILE)
break;
if (local_error == HA_ERR_RECORD_DELETED)
continue; // May happen on dup key
+ err_table= tmp_table;
goto err;
}
@@ -2027,12 +2047,15 @@ int multi_update::do_updates()
uint field_num= 0;
do
{
- if((local_error=
- tbl->file->rnd_pos(tbl->record[0],
- (uchar *) tmp_table->field[field_num]->ptr)))
+ if ((local_error=
+ tbl->file->ha_rnd_pos(tbl->record[0],
+ (uchar*) tmp_table->field[field_num]->ptr)))
+ {
+ err_table= tbl;
goto err;
+ }
field_num++;
- } while((tbl= check_opt_it++));
+ } while ((tbl= check_opt_it++));
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
@@ -2057,7 +2080,10 @@ int multi_update::do_updates()
if (error == VIEW_CHECK_SKIP)
continue;
else if (error == VIEW_CHECK_ERROR)
- goto err;
+ {
+ thd->fatal_error();
+ goto err2;
+ }
}
if ((local_error=table->file->ha_update_row(table->record[1],
table->record[0])) &&
@@ -2065,7 +2091,10 @@ int multi_update::do_updates()
{
if (!ignore ||
table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY))
+ {
+ err_table= table;
goto err;
+ }
}
if (local_error != HA_ERR_RECORD_IS_THE_SAME)
updated++;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 280d33aa654..2112d9b1e1c 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1215,7 +1215,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
+ MODE_PIPES_AS_CONCAT affect expression parsing
+ MODE_ANSI_QUOTES affect expression parsing
+ MODE_IGNORE_SPACE affect expression parsing
- - MODE_NOT_USED not used :)
+ - MODE_IGNORE_BAD_TABLE_OPTIONS affect only CREATE/ALTER TABLE parsing
* MODE_ONLY_FULL_GROUP_BY affect execution
* MODE_NO_UNSIGNED_SUBTRACTION affect execution
- MODE_NO_DIR_IN_CREATE affect table creation only
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index b06178b5889..e01289ad087 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -44,6 +44,7 @@
#include "sp_rcontext.h"
#include "sp.h"
#include "event_parse_data.h"
+#include "create_options.h"
#include <myisam.h>
#include <myisammrg.h>
@@ -56,6 +57,7 @@
int yylex(void *yylval, void *yythd);
const LEX_STRING null_lex_str= {0,0};
+const LEX_STRING empty_lex_str= { (char*) "", 0 };
#define yyoverflow(A,B,C,D,E,F) \
{ \
@@ -606,6 +608,7 @@ static bool add_create_index_prepare (LEX *lex, Table_ident *table)
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change= NullS;
+ lex->option_list= NULL;
return FALSE;
}
@@ -615,7 +618,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type, const char *name,
{
Key *key;
key= new Key(type, name, info ? info : &lex->key_create_info, generated,
- lex->col_list);
+ lex->col_list, lex->option_list);
if (key == NULL)
return TRUE;
@@ -709,6 +712,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ALGORITHM_SYM
%token ALL /* SQL-2003-R */
%token ALTER /* SQL-2003-R */
+%token ALWAYS_SYM
%token ANALYZE_SYM
%token AND_AND_SYM /* OPERATOR */
%token AND_SYM /* SQL-2003-R */
@@ -758,6 +762,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CHECK_SYM /* SQL-2003-R */
%token CIPHER_SYM
%token CLIENT_SYM
+%token CLIENT_STATS_SYM
%token CLOSE_SYM /* SQL-2003-R */
%token COALESCE /* SQL-2003-N */
%token CODE_SYM
@@ -875,6 +880,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token FULLTEXT_SYM
%token FUNCTION_SYM /* SQL-2003-R */
%token GE
+%token GENERATED_SYM
%token GEOMETRYCOLLECTION
%token GEOMETRY_SYM
%token GET_FORMAT /* MYSQL-FUNC */
@@ -904,6 +910,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token IMPORT
%token INDEXES
%token INDEX_SYM
+%token INDEX_STATS_SYM
%token INFILE
%token INITIAL_SIZE_SYM
%token INNER_SYM /* SQL-2003-R */
@@ -1052,11 +1059,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PAGE_CHECKSUM_SYM
%token PARAM_MARKER
%token PARSER_SYM
+%token PARSE_VCOL_EXPR_SYM
%token PARTIAL /* SQL-2003-N */
%token PARTITIONING_SYM
%token PARTITIONS_SYM
%token PARTITION_SYM /* SQL-2003-R */
%token PASSWORD
+%token PERSISTENT_SYM
%token PHASE_SYM
%token PLUGINS_SYM
%token PLUGIN_SYM
@@ -1145,6 +1154,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SIGNED_SYM
%token SIMPLE_SYM /* SQL-2003-N */
%token SLAVE
+%token SLOW_SYM
%token SMALLINT /* SQL-2003-R */
%token SNAPSHOT_SYM
%token SOCKET_SYM
@@ -1189,6 +1199,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TABLES
%token TABLESPACE
%token TABLE_REF_PRIORITY
+%token TABLE_STATS_SYM
%token TABLE_SYM /* SQL-2003-R */
%token TABLE_CHECKSUM_SYM
%token TEMPORARY /* SQL-2003-N */
@@ -1236,6 +1247,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UPGRADE_SYM
%token USAGE /* SQL-2003-N */
%token USER /* SQL-2003-R */
+%token USER_STATS_SYM
%token USE_FRM
%token USE_SYM
%token USING /* SQL-2003-R */
@@ -1250,7 +1262,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token VARIANCE_SYM
%token VARYING /* SQL-2003-R */
%token VAR_SAMP_SYM
+%token VIA_SYM
%token VIEW_SYM /* SQL-2003-N */
+%token VIRTUAL_SYM
%token WAIT_SYM
%token WARNINGS
%token WEEK_SYM
@@ -1309,7 +1323,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
text_string opt_gconcat_separator
%type <num>
- type int_type real_type order_dir lock_option
+ type int_type real_type order_dir lock_option field_def
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog
delete_option opt_temporary all_or_any opt_distinct
@@ -1468,6 +1482,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
key_using_alg
server_def server_options_list server_option
definer_opt no_definer definer
+ parse_vcol_expr vcol_opt_specifier vcol_opt_attribute
+ vcol_opt_attribute_list vcol_attribute
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1599,6 +1615,7 @@ statement:
| lock
| optimize
| keycache
+ | parse_vcol_expr
| partition_entry
| preload
| prepare
@@ -2326,6 +2343,7 @@ sp_init_param:
lex->interval_list.empty();
lex->uint_geom_type= 0;
+ lex->vcol_info= 0;
}
;
@@ -3881,7 +3899,11 @@ create2:
;
create2a:
- field_list ')' opt_create_table_options
+ field_list ')'
+ {
+ Lex->create_info.option_list= NULL;
+ }
+ opt_create_table_options
opt_partitioning
create3 {}
| opt_partitioning
@@ -4732,6 +4754,30 @@ create_table_option:
Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
Lex->create_info.transactional= $3;
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, true, &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, false, &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal real_ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, &Lex->create_info.option_list,
+ &Lex->option_list_last, YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
;
default_charset:
@@ -4853,25 +4899,33 @@ column_def:
;
key_def:
- normal_key_type opt_ident key_alg '(' key_list ')' normal_key_options
+ normal_key_type opt_ident key_alg '(' key_list ')'
+ { Lex->option_list= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $1, $2))
MYSQL_YYABORT;
}
| fulltext opt_key_or_index opt_ident init_key_options
- '(' key_list ')' fulltext_key_options
+ '(' key_list ')'
+ { Lex->option_list= NULL; }
+ fulltext_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| spatial opt_key_or_index opt_ident init_key_options
- '(' key_list ')' spatial_key_options
+ '(' key_list ')'
+ { Lex->option_list= NULL; }
+ spatial_key_options
{
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
| opt_constraint constraint_key_type opt_ident key_alg
- '(' key_list ')' normal_key_options
+ '(' key_list ')'
+ { Lex->option_list= NULL; }
+ normal_key_options
{
if (add_create_index (Lex, $2, $3 ? $3 : $1))
MYSQL_YYABORT;
@@ -4890,6 +4944,7 @@ key_def:
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
+ lex->option_list= NULL;
if (add_create_index (lex, Key::MULTIPLE, key_name,
&default_key_create_info, 1))
MYSQL_YYABORT;
@@ -4933,8 +4988,10 @@ field_spec:
lex->default_value= lex->on_update_value= 0;
lex->comment=null_lex_str;
lex->charset=NULL;
+ lex->vcol_info= 0;
+ lex->option_list= NULL;
}
- type opt_attribute
+ field_def
{
LEX *lex=Lex;
if (add_field_to_list(lex->thd, &$1, (enum enum_field_types) $3,
@@ -4942,8 +4999,98 @@ field_spec:
lex->default_value, lex->on_update_value,
&lex->comment,
lex->change,&lex->interval_list,lex->charset,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info, lex->option_list))
+ MYSQL_YYABORT;
+ }
+ ;
+
+field_def:
+ type opt_attribute {}
+ | type opt_generated_always AS '(' virtual_column_func ')'
+ vcol_opt_specifier
+ vcol_opt_attribute
+ {
+ $$= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
+ Lex->vcol_info->set_field_type((enum enum_field_types) $1);
+ }
+ ;
+
+opt_generated_always:
+ /* empty */
+ | GENERATED_SYM ALWAYS_SYM {}
+ ;
+
+vcol_opt_specifier:
+ /* empty */
+ {
+ Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ }
+ | VIRTUAL_SYM
+ {
+ Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ }
+ | PERSISTENT_SYM
+ {
+ Lex->vcol_info->set_stored_in_db_flag(TRUE);
+ }
+ ;
+
+vcol_opt_attribute:
+ /* empty */ {}
+ | vcol_opt_attribute_list {}
+ ;
+
+vcol_opt_attribute_list:
+ vcol_opt_attribute_list vcol_attribute {}
+ | vcol_attribute
+ ;
+
+vcol_attribute:
+ UNIQUE_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= UNIQUE_FLAG;
+ lex->alter_info.flags|= ALTER_ADD_INDEX;
+ }
+ | UNIQUE_SYM KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= UNIQUE_KEY_FLAG;
+ lex->alter_info.flags|= ALTER_ADD_INDEX;
+ }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
+ ;
+
+parse_vcol_expr:
+ PARSE_VCOL_EXPR_SYM '(' virtual_column_func ')'
+ {
+ /*
+ "PARSE_VCOL_EXPR" can only be used by the SQL server
+ when reading a '*.frm' file.
+ Prevent the end user from invoking this command.
+ */
+ if (!Lex->parse_vcol_expr)
+ {
+ my_message(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0));
MYSQL_YYABORT;
+ }
+ }
+ ;
+
+virtual_column_func:
+ remember_name expr remember_end
+ {
+ Lex->vcol_info= new Virtual_column_info();
+ if (!Lex->vcol_info)
+ {
+ mem_alloc_error(sizeof(Virtual_column_info));
+ MYSQL_YYABORT;
+ }
+ uint expr_len= (uint)($3 - $1) - 1;
+ Lex->vcol_info->expr_str.str= (char* ) sql_memdup($1 + 1, expr_len);
+ Lex->vcol_info->expr_str.length= expr_len;
+ Lex->vcol_info->expr_item= $2;
}
;
@@ -5273,6 +5420,29 @@ attribute:
Lex->charset=$2;
}
}
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, true, &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, false, &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal real_ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, &Lex->option_list,
+ &Lex->option_list_last, YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
+ }
;
now_or_signed_literal:
@@ -5562,6 +5732,29 @@ key_using_alg:
all_key_opt:
KEY_BLOCK_SIZE opt_equal ulong_num
{ Lex->key_create_info.block_size= $3; }
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, true, &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, false, &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal real_ulonglong_num
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, $3, &Lex->option_list,
+ &Lex->option_list_last, YYTHD->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (YYTHD->mem_root)
+ engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
+ }
;
normal_key_opt:
@@ -6050,6 +6243,7 @@ alter_list_item:
LEX *lex=Lex;
lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->option_list= NULL;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -6060,8 +6254,10 @@ alter_list_item:
lex->comment=null_lex_str;
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->vcol_info= 0;
+ lex->option_list= NULL;
}
- type opt_attribute
+ field_def
{
LEX *lex=Lex;
if (add_field_to_list(lex->thd,&$3,
@@ -6070,7 +6266,8 @@ alter_list_item:
lex->default_value, lex->on_update_value,
&lex->comment,
$3.str, &lex->interval_list, lex->charset,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
}
opt_place
@@ -6177,8 +6374,7 @@ alter_list_item:
}
| create_table_options_space_separated
{
- LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_OPTIONS;
+ Lex->alter_info.flags|= ALTER_OPTIONS;
}
| FORCE_SYM
{
@@ -9272,6 +9468,7 @@ ulonglong_num:
real_ulonglong_num:
NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
| ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ | HEX_NUM { $$= strtoull($1.str, (char**) 0, 16); }
| LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
| dec_num_error { MYSQL_YYABORT; }
;
@@ -10334,6 +10531,34 @@ show_param:
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
}
+ | CLIENT_STATS_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_CLIENT_STATS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_CLIENT_STATS))
+ MYSQL_YYABORT;
+ }
+ | USER_STATS_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_USER_STATS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_USER_STATS))
+ MYSQL_YYABORT;
+ }
+ | TABLE_STATS_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_TABLE_STATS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_STATS))
+ MYSQL_YYABORT;
+ }
+ | INDEX_STATS_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_INDEX_STATS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_INDEX_STATS))
+ MYSQL_YYABORT;
+ }
| CREATE PROCEDURE sp_name
{
LEX *lex= Lex;
@@ -10542,6 +10767,16 @@ flush_option:
{ Lex->type|= REFRESH_STATUS; }
| SLAVE
{ Lex->type|= REFRESH_SLAVE; }
+ | SLOW_SYM QUERY_SYM LOGS_SYM
+ { Lex->type |= REFRESH_SLOW_QUERY_LOG; }
+ | CLIENT_STATS_SYM
+ { Lex->type|= REFRESH_CLIENT_STATS; }
+ | USER_STATS_SYM
+ { Lex->type|= REFRESH_USER_STATS; }
+ | TABLE_STATS_SYM
+ { Lex->type|= REFRESH_TABLE_STATS; }
+ | INDEX_STATS_SYM
+ { Lex->type|= REFRESH_INDEX_STATS; }
| MASTER_SYM
{ Lex->type|= REFRESH_MASTER; }
| DES_KEY_FILE
@@ -11524,6 +11759,9 @@ user:
$$->user = $1;
$$->host.str= (char *) "%";
$$->host.length= 1;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
if (check_string_char_length(&$$->user, ER(ER_USERNAME),
USERNAME_CHAR_LENGTH,
@@ -11536,6 +11774,9 @@ user:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1; $$->host=$3;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
if (check_string_char_length(&$$->user, ER(ER_USERNAME),
USERNAME_CHAR_LENGTH,
@@ -11623,6 +11864,7 @@ keyword_sp:
| AGAINST {}
| AGGREGATE_SYM {}
| ALGORITHM_SYM {}
+ | ALWAYS_SYM {}
| ANY_SYM {}
| AT_SYM {}
| AUTHORS_SYM {}
@@ -11640,6 +11882,7 @@ keyword_sp:
| CHAIN_SYM {}
| CHANGED {}
| CIPHER_SYM {}
+ | CLIENT_STATS_SYM {}
| CLIENT_SYM {}
| COALESCE {}
| CODE_SYM {}
@@ -11692,6 +11935,7 @@ keyword_sp:
| FIRST_SYM {}
| FIXED_SYM {}
| FRAC_SECOND_SYM {}
+ | GENERATED_SYM {}
| GEOMETRY_SYM {}
| GEOMETRYCOLLECTION {}
| GET_FORMAT {}
@@ -11701,6 +11945,7 @@ keyword_sp:
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
+ | INDEX_STATS_SYM {}
| INVOKER_SYM {}
| IMPORT {}
| INDEXES {}
@@ -11779,6 +12024,7 @@ keyword_sp:
| PARTITIONING_SYM {}
| PARTITIONS_SYM {}
| PASSWORD {}
+ | PERSISTENT_SYM {}
| PHASE_SYM {}
| PLUGIN_SYM {}
| PLUGINS_SYM {}
@@ -11824,6 +12070,7 @@ keyword_sp:
| SIMPLE_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
+ | SLOW_SYM {}
| SNAPSHOT_SYM {}
| SOUNDS_SYM {}
| SOURCE_SYM {}
@@ -11843,6 +12090,7 @@ keyword_sp:
| SUSPEND_SYM {}
| SWAPS_SYM {}
| SWITCHES_SYM {}
+ | TABLE_STATS_SYM {}
| TABLES {}
| TABLE_CHECKSUM_SYM {}
| TABLESPACE {}
@@ -11868,9 +12116,11 @@ keyword_sp:
| UNKNOWN_SYM {}
| UNTIL_SYM {}
| USER {}
+ | USER_STATS_SYM {}
| USE_FRM {}
| VARIABLES {}
| VIEW_SYM {}
+ | VIRTUAL_SYM {}
| VALUE_SYM {}
| WARNINGS {}
| WAIT_SYM {}
@@ -12783,6 +13033,18 @@ grant_user:
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$= $1; $1->password= $5; }
+ | user IDENTIFIED_SYM VIA_SYM ident_or_text
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= empty_lex_str;
+ }
+ | user IDENTIFIED_SYM VIA_SYM ident_or_text USING TEXT_STRING_sys
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= $6;
+ }
| user
{ $$= $1; $1->password= null_lex_str; }
;
@@ -13471,6 +13733,7 @@ sf_tail:
lex->length= lex->dec= NULL;
lex->interval_list.empty();
lex->type= 0;
+ lex->vcol_info= 0;
}
type /* $11 */
{ /* $12 */
diff --git a/sql/structs.h b/sql/structs.h
index 2546d241059..64e69fca0d0 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -68,6 +68,7 @@ typedef struct st_key_part_info { /* Info about a key part */
uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;
+class engine_option_value;
typedef struct st_key {
uint key_length; /* Tot length of key */
@@ -76,6 +77,7 @@ typedef struct st_key {
uint extra_length;
uint usable_key_parts; /* Should normally be = key_parts */
uint block_size;
+ uint name_length;
enum ha_key_alg algorithm;
/*
Note that parser is used when the table is opened for use, and
@@ -88,6 +90,8 @@ typedef struct st_key {
};
KEY_PART_INFO *key_part;
char *name; /* Name of key */
+ /* Unique name for cache; db + \0 + table_name + \0 + key_name + \0 */
+ uchar *cache_name;
/*
Array of AVG(#records with the same field value) for 1st ... Nth key part.
0 means 'not known'.
@@ -98,6 +102,9 @@ typedef struct st_key {
int bdb_return_if_eq;
} handler;
struct st_table *table;
+ /** reference to the list of options or NULL */
+ engine_option_value *option_list;
+ void *option_struct; /* structure with parsed options */
} KEY;
@@ -175,7 +182,7 @@ extern const char *show_comp_option_name[];
typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
typedef struct st_lex_user {
- LEX_STRING user, host, password;
+ LEX_STRING user, host, password, plugin, auth;
} LEX_USER;
/*
@@ -237,6 +244,111 @@ typedef struct user_conn {
USER_RESOURCES user_resources;
} USER_CONN;
+typedef struct st_user_stats
+{
+ char user[max(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1];
+ // Account name the user is mapped to when this is a user from mapped_user.
+ // Otherwise, the same value as user.
+ char priv_user[max(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1];
+ uint user_name_length;
+ uint total_connections;
+ uint concurrent_connections;
+ time_t connected_time; // in seconds
+ double busy_time; // in seconds
+ double cpu_time; // in seconds
+ ulonglong bytes_received;
+ ulonglong bytes_sent;
+ ulonglong binlog_bytes_written;
+ ha_rows rows_read, rows_sent;
+ ha_rows rows_updated, rows_deleted, rows_inserted;
+ ulonglong select_commands, update_commands, other_commands;
+ ulonglong commit_trans, rollback_trans;
+ ulonglong denied_connections, lost_connections;
+ ulonglong access_denied_errors;
+ ulonglong empty_queries;
+} USER_STATS;
+
+/* Lookup function for hash tables with USER_STATS entries */
+extern "C" uchar *get_key_user_stats(USER_STATS *user_stats, size_t *length,
+ my_bool not_used __attribute__((unused)));
+
+/* Free all memory for a hash table with USER_STATS entries */
+extern void free_user_stats(USER_STATS* user_stats);
+
+/* Intialize an instance of USER_STATS */
+extern void
+init_user_stats(USER_STATS *user_stats,
+ const char *user,
+ size_t user_length,
+ const char *priv_user,
+ uint total_connections,
+ uint concurrent_connections,
+ time_t connected_time,
+ double busy_time,
+ double cpu_time,
+ ulonglong bytes_received,
+ ulonglong bytes_sent,
+ ulonglong binlog_bytes_written,
+ ha_rows rows_sent,
+ ha_rows rows_read,
+ ha_rows rows_inserted,
+ ha_rows rows_deleted,
+ ha_rows rows_updated,
+ ulonglong select_commands,
+ ulonglong update_commands,
+ ulonglong other_commands,
+ ulonglong commit_trans,
+ ulonglong rollback_trans,
+ ulonglong denied_connections,
+ ulonglong lost_connections,
+ ulonglong access_denied_errors,
+ ulonglong empty_queries);
+
+/* Increment values of an instance of USER_STATS */
+extern void
+add_user_stats(USER_STATS *user_stats,
+ uint total_connections,
+ uint concurrent_connections,
+ time_t connected_time,
+ double busy_time,
+ double cpu_time,
+ ulonglong bytes_received,
+ ulonglong bytes_sent,
+ ulonglong binlog_bytes_written,
+ ha_rows rows_sent,
+ ha_rows rows_read,
+ ha_rows rows_inserted,
+ ha_rows rows_deleted,
+ ha_rows rows_updated,
+ ulonglong select_commands,
+ ulonglong update_commands,
+ ulonglong other_commands,
+ ulonglong commit_trans,
+ ulonglong rollback_trans,
+ ulonglong denied_connections,
+ ulonglong lost_connections,
+ ulonglong access_denied_errors,
+ ulonglong empty_queries);
+
+typedef struct st_table_stats
+{
+ char table[NAME_LEN * 2 + 2]; // [db] + '\0' + [table] + '\0'
+ uint table_name_length;
+ ulonglong rows_read, rows_changed;
+ ulonglong rows_changed_x_indexes;
+ /* Stores enum db_type, but forward declarations cannot be done */
+ int engine_type;
+} TABLE_STATS;
+
+typedef struct st_index_stats
+{
+ // [db] + '\0' + [table] + '\0' + [index] + '\0'
+ char index[NAME_LEN * 3 + 3];
+ uint index_name_length; /* Length of 'index' */
+ ulonglong rows_read;
+} INDEX_STATS;
+
+
/* Bits in form->update */
#define REG_MAKE_DUPP 1 /* Make a copy of record when read */
#define REG_NEW_RECORD 2 /* Write a new record if not found */
diff --git a/sql/table.cc b/sql/table.cc
index 2129da90a29..988e082addf 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -18,6 +18,7 @@
#include "mysql_priv.h"
#include "sql_trigger.h"
+#include "create_options.h"
#include <m_ctype.h>
#include "my_md5.h"
@@ -33,6 +34,12 @@ LEX_STRING GENERAL_LOG_NAME= {C_STRING_WITH_LEN("general_log")};
/* SLOW_LOG name */
LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
+/*
+ Keyword added as a prefix when parsing the defining expression for a
+ virtual column read from the column definition saved in the frm file
+*/
+LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
+
/* Functions defined in this file */
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
@@ -672,12 +679,14 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
uint interval_count, interval_parts, read_length, int_length;
uint db_create_options, keys, key_parts, n_length;
uint key_info_length, com_length, null_bit_pos;
- uint extra_rec_buf_length;
+ uint vcol_screen_length;
+ uint extra_rec_buf_length, options_len;
uint i,j;
bool use_hash;
- char *keynames, *names, *comment_pos;
+ char *keynames, *names, *comment_pos, *vcol_screen_pos;
uchar *record;
- uchar *disk_buff, *strpos, *null_flags, *null_pos;
+ uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+ uchar *buff= 0;
ulong pos, record_offset, *rec_per_key, rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -795,7 +804,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
for (i=0 ; i < keys ; i++, keyinfo++)
{
- keyinfo->table= 0; // Updated in open_frm
if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -847,6 +855,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
share->reclength = uint2korr((head+16));
+ share->stored_rec_length= share->reclength;
if (*(head+26) == 1)
share->system= 1; /* one-record-database */
#ifdef HAVE_CRYPTED_FRM
@@ -864,15 +873,14 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if ((n_length= uint4korr(head+55)))
{
/* Read extra data segment */
- uchar *buff, *next_chunk, *buff_end;
+ uchar *next_chunk, *buff_end;
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
goto err;
if (my_pread(file, buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
share->connect_string.length= uint2korr(buff);
if (!(share->connect_string.str= strmake_root(&share->mem_root,
@@ -880,8 +888,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
share->connect_string.
length)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
next_chunk+= share->connect_string.length + 2;
buff_end= buff + n_length;
@@ -901,8 +908,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
plugin_data(tmp_plugin, handlerton *)))
{
/* bad file, legacy_db_type did not match the name */
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
/*
tmp_plugin is locked with a local lock.
@@ -931,8 +937,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
error= 8;
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
@@ -946,8 +951,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
/* purecov: begin inspected */
error= 8;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
/* purecov: end */
}
next_chunk+= str_db_type_length + 2;
@@ -963,40 +967,26 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
memdup_root(&share->mem_root, next_chunk + 4,
partition_info_len + 1)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
#else
if (partition_info_len)
{
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
#endif
next_chunk+= 5 + partition_info_len;
}
-#if MYSQL_VERSION_ID < 50200
- if (share->mysql_version >= 50106 && share->mysql_version <= 50109)
- {
- /*
- Partition state array was here in version 5.1.6 to 5.1.9, this code
- makes it possible to load a 5.1.6 table in later versions. Can most
- likely be removed at some point in time. Will only be used for
- upgrades within 5.1 series of versions. Upgrade to 5.2 can only be
- done from newer 5.1 versions.
- */
- next_chunk+= 4;
- }
- else if (share->mysql_version >= 50110)
-#endif
+ if (share->mysql_version >= 50110)
{
/* New auto_partitioned indicator introduced in 5.1.11 */
#ifdef WITH_PARTITION_STORAGE_ENGINE
share->auto_partitioned= *next_chunk;
#endif
next_chunk++;
+ DBUG_ASSERT(next_chunk <= buff_end);
}
keyinfo= share->key_info;
for (i= 0; i < keys; i++, keyinfo++)
@@ -1008,8 +998,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
{
DBUG_PRINT("error",
("fulltext key uses parser that is not defined in .frm"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
parser_name.str= (char*) next_chunk;
parser_name.length= strlen((char*) next_chunk);
@@ -1019,12 +1008,22 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (! keyinfo->parser)
{
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
}
- my_free(buff, MYF(0));
+ DBUG_ASSERT(next_chunk <= buff_end);
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ /*
+ store options position, but skip till the time we will
+ know number of fields
+ */
+ options_len= uint4korr(next_chunk);
+ options= next_chunk + 4;
+ next_chunk+= options_len + 4;
+ }
+ DBUG_ASSERT(next_chunk <= buff_end);
}
share->key_block_size= uint2korr(head+62);
@@ -1034,21 +1033,21 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
share->rec_buff_length= rec_buff_length;
if (!(record= (uchar *) alloc_root(&share->mem_root,
rec_buff_length)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->default_values= record;
if (my_pread(file, record, (size_t) share->reclength,
record_offset, MYF(MY_NABP)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file, head,288,MYF(MY_NABP)))
- goto err;
+ goto free_and_err;
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err; // Wrong password
+ goto free_and_err; // Wrong password
}
#endif
@@ -1060,11 +1059,15 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
int_length= uint2korr(head+274);
share->null_fields= uint2korr(head+282);
com_length= uint2korr(head+284);
+ vcol_screen_length= uint2korr(head+286);
+ share->vfields= 0;
+ share->stored_fields= share->fields;
share->comment.length= (int) (head[46]);
share->comment.str= strmake_root(&share->mem_root, (char*) head+47,
share->comment.length);
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
+
if (!(field_ptr = (Field **)
alloc_root(&share->mem_root,
@@ -1072,14 +1075,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
interval_count*sizeof(TYPELIB)+
(share->fields+interval_parts+
keys+3)*sizeof(char *)+
- (n_length+int_length+com_length)))))
- goto err; /* purecov: inspected */
+ (n_length+int_length+com_length+
+ vcol_screen_length)))))
+ goto free_and_err; /* purecov: inspected */
share->field= field_ptr;
read_length=(uint) (share->fields * field_pack_length +
- pos+ (uint) (n_length+int_length+com_length));
+ pos+ (uint) (n_length+int_length+com_length+
+ vcol_screen_length));
if (read_string(file,(uchar**) &disk_buff,read_length))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
@@ -1098,11 +1103,15 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
memcpy((char*) names, strpos+(share->fields*field_pack_length),
(uint) (n_length+int_length));
comment_pos= names+(n_length+int_length);
- memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
+ memcpy(comment_pos, disk_buff+read_length-com_length-vcol_screen_length,
+ com_length);
+ vcol_screen_pos= names+(n_length+int_length+com_length);
+ memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
+ vcol_screen_length);
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
if (share->fieldnames.count != share->fields)
- goto err;
+ goto free_and_err;
fix_type_pointers(&interval_array, share->intervals, interval_count,
&names);
@@ -1116,7 +1125,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
count)))
- goto err;
+ goto free_and_err;
for (count= 0; count < interval->count; count++)
{
char *val= (char*) interval->type_names[count];
@@ -1132,7 +1141,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
/* Allocate handler */
if (!(handler_file= get_new_handler(share, thd->mem_root,
share->db_type())))
- goto err;
+ goto free_and_err;
record= share->default_values-1; /* Fieldstart = 1 */
null_bits_are_used= share->null_fields != 0;
@@ -1167,10 +1176,14 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
uint pack_flag, interval_nr, unireg_type, recpos, field_length;
+ uint vcol_info_length=0;
+ uint vcol_expr_length=0;
enum_field_types field_type;
CHARSET_INFO *charset=NULL;
Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
LEX_STRING comment;
+ Virtual_column_info *vcol_info= 0;
+ bool fld_stored_in_db= TRUE;
if (new_frm_ver >= 3)
{
@@ -1191,7 +1204,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
charset= &my_charset_bin;
#else
error= 4; // unsupported field type
- goto err;
+ goto free_and_err;
#endif
}
else
@@ -1202,9 +1215,21 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
{
error= 5; // Unknown or unavailable charset
errarg= (int) strpos[14];
- goto err;
+ goto free_and_err;
}
}
+
+ if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ {
+ DBUG_ASSERT(interval_nr); // Expect non-null expression
+ /*
+ The interval_id byte in the .frm file stores the length of the
+ expression statement for a virtual column.
+ */
+ vcol_info_length= interval_nr;
+ interval_nr= 0;
+ }
+
if (!comment_length)
{
comment.str= (char*) "";
@@ -1216,6 +1241,34 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
comment.length= comment_length;
comment_pos+= comment_length;
}
+
+ if (vcol_info_length)
+ {
+ /*
+ Get virtual column data stored in the .frm file as follows:
+ byte 1 = 1 (always 1 to allow for future extensions)
+ byte 2 = sql_type
+ byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
+ byte 4-... = virtual column expression (text data)
+ */
+ vcol_info= new Virtual_column_info();
+ if ((uint)vcol_screen_pos[0] != 1)
+ {
+ error= 4;
+ goto free_and_err;
+ }
+ field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
+ fld_stored_in_db= (bool) (uint) vcol_screen_pos[2];
+ vcol_expr_length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE;
+ if (!(vcol_info->expr_str.str=
+ (char *)memdup_root(&share->mem_root,
+ vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE,
+ vcol_expr_length)))
+ goto free_and_err;
+ vcol_info->expr_str.length= vcol_expr_length;
+ vcol_screen_pos+= vcol_info_length;
+ share->vfields++;
+ }
}
else
{
@@ -1301,11 +1354,13 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (!reg_field) // Not supported field type
{
error= 4;
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
}
reg_field->field_index= i;
reg_field->comment=comment;
+ reg_field->vcol_info= vcol_info;
+ reg_field->stored_in_db= fld_stored_in_db;
if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
{
null_bits_are_used= 1;
@@ -1329,7 +1384,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
share->timestamp_field_offset= i;
if (use_hash)
- if (my_hash_insert(&share->name_hash, (uchar*) field_ptr) )
+ {
+ if (my_hash_insert(&share->name_hash,
+ (uchar*) field_ptr))
{
/*
Set return code 8 here to indicate that an error has
@@ -1337,10 +1394,20 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
sent (OOM).
*/
error= 8;
- goto err;
+ goto free_and_err;
}
+ }
+ if (!reg_field->stored_in_db)
+ {
+ share->stored_fields--;
+ if (share->stored_rec_length>=recpos)
+ share->stored_rec_length= recpos-1;
+ }
}
*field_ptr=0; // End marker
+ /* Sanity checks: */
+ DBUG_ASSERT(share->fields>=share->stored_fields);
+ DBUG_ASSERT(share->reclength>=share->stored_rec_length);
/* Fix key->name and key_part->field */
if (key_parts)
@@ -1355,6 +1422,19 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
{
uint usable_parts= 0;
keyinfo->name=(char*) share->keynames.type_names[key];
+ keyinfo->name_length= strlen(keyinfo->name);
+ keyinfo->cache_name=
+ (uchar*) alloc_root(&share->mem_root,
+ share->table_cache_key.length+
+ keyinfo->name_length + 1);
+ if (keyinfo->cache_name) // If not out of memory
+ {
+ uchar *pos= keyinfo->cache_name;
+ memcpy(pos, share->table_cache_key.str, share->table_cache_key.length);
+ memcpy(pos + share->table_cache_key.length, keyinfo->name,
+ keyinfo->name_length+1);
+ }
+
/* Fix fulltext keys for old .frm files */
if (share->key_info[key].flags & HA_FULLTEXT)
share->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
@@ -1391,7 +1471,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (!key_part->fieldnr)
{
error= 4; // Wrong file
- goto err;
+ goto free_and_err;
}
field= key_part->field= share->field[key_part->fieldnr-1];
key_part->type= field->key_type();
@@ -1417,12 +1497,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
key_part->store_length+=HA_KEY_BLOB_LENGTH;
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
- /*
- Mark that there may be many matching values for one key
- combination ('a', 'a ', 'a '...)
- */
- if (!(field->flags & BINARY_FLAG))
- keyinfo->flags|= HA_END_SPACE_KEY;
}
if (field->type() == MYSQL_TYPE_BIT)
key_part->key_part_flag|= HA_BIT_PART;
@@ -1508,6 +1582,15 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
*/
if (field->real_maybe_null())
key_part->key_part_flag|= HA_NULL_PART;
+ /*
+ Sometimes we can compare key parts for equality with memcmp.
+ But not always.
+ */
+ if (!(key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
+ HA_BIT_PART)) &&
+ key_part->type != HA_KEYTYPE_FLOAT &&
+ key_part->type == HA_KEYTYPE_DOUBLE)
+ key_part->key_part_flag|= HA_CAN_MEMCMP;
}
keyinfo->usable_key_parts= usable_parts; // Filesort
@@ -1556,6 +1639,16 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
null_length, 255);
}
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ DBUG_ASSERT(options_len);
+ if (engine_table_options_frm_read(options, options_len, share))
+ goto free_and_err;
+ }
+ if (parse_engine_table_options(thd, handler_file->partition_ht(), share))
+ goto free_and_err;
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
if (share->found_next_number_field)
{
reg_field= *share->found_next_number_field;
@@ -1617,6 +1710,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
#endif
DBUG_RETURN (0);
+ free_and_err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
err:
share->error= error;
share->open_errno= my_errno;
@@ -1630,6 +1725,315 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
DBUG_RETURN(error);
} /* open_binary_frm */
+/*
+ @brief
+ Clear GET_FIXED_FIELDS_FLAG in all fields of a table
+
+ @param
+ table The table for whose fields the flags are to be cleared
+
+ @note
+ This routine is used for error handling purposes.
+
+ @return
+ none
+*/
+
+static void clear_field_flag(TABLE *table)
+{
+ Field **ptr;
+ DBUG_ENTER("clear_field_flag");
+
+ for (ptr= table->field; *ptr; ptr++)
+ (*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ @brief
+ Perform semantic analysis of the defining expression for a virtual column
+
+ @param
+ thd The thread object
+ @param
+ table The table containing the virtual column
+ @param
+ vcol_field The virtual field whose defining expression is to be analyzed
+
+ @details
+ The function performs semantic analysis of the defining expression for
+ the virtual column vcol_field. The expression is used to compute the
+ values of this column.
+
+ @note
+ The function exploits the fact that the fix_fields method sets the flag
+ GET_FIXED_FIELDS_FLAG for all fields in the item tree.
+ This flag must always be unset before returning from this function
+ since it is used for other purposes as well.
+
+ @retval
+ TRUE An error occurred, something was wrong with the function
+ @retval
+ FALSE Otherwise
+*/
+
+bool fix_vcol_expr(THD *thd,
+ TABLE *table,
+ Field *vcol_field)
+{
+ Virtual_column_info *vcol_info= vcol_field->vcol_info;
+ Item* func_expr= vcol_info->expr_item;
+ 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;
+ Field **ptr, *field;
+ enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
+ DBUG_ASSERT(func_expr);
+ DBUG_ENTER("fix_vcol_expr");
+
+ /*
+ 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.
+ */
+
+ 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;
+ 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;
+
+ thd->mark_used_columns= MARK_COLUMNS_NONE;
+
+ context= thd->lex->current_context();
+ 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);
+ save_where= thd->where;
+ thd->where= "virtual column function";
+
+ /* Save the context before fixing the fields*/
+ save_use_only_table_context= thd->lex->use_only_table_context;
+ thd->lex->use_only_table_context= TRUE;
+ /* Fix fields referenced to by the virtual column function */
+ error= func_expr->fix_fields(thd, (Item**)0);
+ /* Restore the original context*/
+ 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 virtual column expression does not belong to the table"));
+ goto end;
+ }
+ thd->where= save_where;
+ if (unlikely(func_expr->result_type() == ROW_RESULT))
+ {
+ my_error(ER_ROW_EXPR_FOR_VCOL, MYF(0));
+ goto end;
+ }
+#ifdef PARANOID
+ /*
+ Walk through the Item tree checking if all items are valid
+ to be part of the virtual column
+ */
+ error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
+ if (error)
+ {
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
+ goto end;
+ }
+#endif
+ if (unlikely(func_expr->const_item()))
+ {
+ my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
+ goto end;
+ }
+ /* Ensure that this virtual column is not based on another virtual field. */
+ ptr= table->field;
+ while ((field= *(ptr++)))
+ {
+ if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
+ (field->vcol_info))
+ {
+ my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
+ goto end;
+ }
+ }
+ result= FALSE;
+
+end:
+
+ /* Clear GET_FIXED_FIELDS_FLAG for the fields of the table */
+ clear_field_flag(table);
+
+ table->get_fields_in_item_tree= FALSE;
+ thd->mark_used_columns= save_mark_used_columns;
+ table->map= 0; //Restore old value
+
+ DBUG_RETURN(result);
+}
+
+/*
+ @brief
+ Unpack the definition of a virtual column from its linear representation
+
+ @parm
+ thd The thread object
+ @param
+ table The table containing the virtual column
+ @param
+ field The field for the virtual
+ @param
+ vcol_expr The string representation of the defining expression
+ @param[out]
+ error_reported The flag to inform the caller that no other error
+ messages are to be generated
+
+ @details
+ The function takes string representation 'vcol_expr' of the defining
+ expression for the virtual field 'field' of the table 'table' and
+ parses it, building an item object for it. The pointer to this item is
+ placed into in field->vcol_info.expr_item. After this the function performs
+ semantic analysis of the item by calling the the function fix_vcol_expr.
+ Since the defining expression is part of the table definition the item for
+ it is created in table->memroot within the special arena TABLE::expr_arena.
+
+ @note
+ Before passing 'vcol_expr" to the parser the function embraces it in
+ parenthesis and prepands it a special keyword.
+
+ @retval
+ FALSE If a success
+ @retval
+ TRUE Otherwise
+*/
+bool unpack_vcol_info_from_frm(THD *thd,
+ TABLE *table,
+ Field *field,
+ LEX_STRING *vcol_expr,
+ bool *error_reported)
+{
+ bool rc;
+ char *vcol_expr_str;
+ int str_len;
+ CHARSET_INFO *old_character_set_client;
+ Query_arena *backup_stmt_arena_ptr;
+ Query_arena backup_arena;
+ Query_arena *vcol_arena;
+ Parser_state parser_state;
+ DBUG_ENTER("unpack_vcol_info_from_frm");
+ DBUG_ASSERT(vcol_expr);
+
+ /*
+ Step 1: Construct the input string for the parser.
+ The string to be parsed has to be of the following format:
+ "PARSE_VCOL_EXPR (<expr_string_from_frm>)".
+ */
+
+ if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
+ vcol_expr->length +
+ parse_vcol_keyword.length + 3)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ memcpy(vcol_expr_str,
+ (char*) parse_vcol_keyword.str,
+ parse_vcol_keyword.length);
+ str_len= parse_vcol_keyword.length;
+ memcpy(vcol_expr_str + str_len, "(", 1);
+ str_len++;
+ memcpy(vcol_expr_str + str_len,
+ (char*) vcol_expr->str,
+ vcol_expr->length);
+ str_len+= vcol_expr->length;
+ memcpy(vcol_expr_str + str_len, ")", 1);
+ str_len++;
+ memcpy(vcol_expr_str + str_len, "\0", 1);
+ str_len++;
+
+ if (parser_state.init(thd, vcol_expr_str, str_len))
+ goto err;
+
+ /*
+ Step 2: Setup thd for parsing.
+ */
+ backup_stmt_arena_ptr= thd->stmt_arena;
+ vcol_arena= table->expr_arena;
+ if (!vcol_arena)
+ {
+ Query_arena expr_arena(&table->mem_root, Query_arena::INITIALIZED);
+ if (!(vcol_arena= (Query_arena *) alloc_root(&table->mem_root,
+ sizeof(Query_arena))))
+ goto err;
+ *vcol_arena= expr_arena;
+ table->expr_arena= vcol_arena;
+ }
+ thd->set_n_backup_active_arena(vcol_arena, &backup_arena);
+ thd->stmt_arena= vcol_arena;
+
+ thd->lex->parse_vcol_expr= TRUE;
+ old_character_set_client= thd->variables.character_set_client;
+
+ /*
+ Step 3: Use the parser to build an Item object from vcol_expr_str.
+ */
+ if (parse_sql(thd, &parser_state, NULL))
+ {
+ goto err;
+ }
+ /* From now on use vcol_info generated by the parser. */
+ field->vcol_info= thd->lex->vcol_info;
+
+ /* Validate the Item tree. */
+ if (fix_vcol_expr(thd, table, field))
+ {
+ *error_reported= TRUE;
+ field->vcol_info= 0;
+ goto err;
+ }
+ rc= FALSE;
+ goto end;
+
+err:
+ rc= TRUE;
+ thd->lex->parse_vcol_expr= FALSE;
+ thd->free_items();
+end:
+ thd->stmt_arena= backup_stmt_arena_ptr;
+ if (vcol_arena)
+ thd->restore_active_arena(vcol_arena, &backup_arena);
+ thd->variables.character_set_client= old_character_set_client;
+
+ DBUG_RETURN(rc);
+}
+
+/*
+ Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
+*/
/*
Open a table based on a TABLE_SHARE
@@ -1664,7 +2068,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
uint records, i, bitmap_size;
bool error_reported= FALSE;
uchar *record, *bitmaps;
- Field **field_ptr;
+ Field **field_ptr, **vfield_ptr;
DBUG_ENTER("open_table_from_share");
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
share->table_name.str, (long) outparam));
@@ -1818,6 +2222,34 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
}
}
+ /*
+ Process virtual columns, if any.
+ */
+ if (!(vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
+ (uint) ((share->vfields+1)*
+ sizeof(Field*)))))
+ goto err;
+
+ outparam->vfield= vfield_ptr;
+
+ for (field_ptr= outparam->field; *field_ptr; field_ptr++)
+ {
+ if ((*field_ptr)->vcol_info)
+ {
+ if (unpack_vcol_info_from_frm(thd,
+ outparam,
+ *field_ptr,
+ &(*field_ptr)->vcol_info->expr_str,
+ &error_reported))
+ {
+ error= 4; // in case no error is reported
+ goto err;
+ }
+ *(vfield_ptr++)= *field_ptr;
+ }
+ }
+ *vfield_ptr= 0; // End marker
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (share->partition_info_len && outparam->file)
{
@@ -1885,17 +2317,33 @@ partititon_err:
}
#endif
+ /* Check virtual columns against table's storage engine. */
+ if (share->vfields &&
+ ((outparam->file &&
+ !outparam->file->check_if_supported_virtual_columns()) ||
+ (!outparam->file && share->db_type() &&
+ share->db_type()->db_type == DB_TYPE_CSV_DB))) // Workaround for CSV
+ {
+ my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
+ MYF(0),
+ "Specified storage engine");
+ error_reported= TRUE;
+ goto err;
+ }
+
/* Allocate bitmaps */
bitmap_size= share->column_bitmap_size;
- if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*3)))
+ if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*4)))
goto err;
bitmap_init(&outparam->def_read_set,
(my_bitmap_map*) bitmaps, share->fields, FALSE);
bitmap_init(&outparam->def_write_set,
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE);
- bitmap_init(&outparam->tmp_set,
+ bitmap_init(&outparam->def_vcol_set,
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE);
+ bitmap_init(&outparam->tmp_set,
+ (my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE);
outparam->default_column_bitmaps();
/* The table struct is now initialized; Open the table */
@@ -2000,10 +2448,14 @@ int closefrm(register TABLE *table, bool free_share)
}
my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR));
table->alias= 0;
+ if (table->expr_arena)
+ table->expr_arena->free_items();
if (table->field)
{
for (Field **ptr=table->field ; *ptr ; ptr++)
+ {
delete *ptr;
+ }
table->field= 0;
}
delete table->file;
@@ -2467,6 +2919,7 @@ File create_frm(THD *thd, const char *name, const char *db,
ulong length;
uchar fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
+ DBUG_ENTER("create_frm");
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2548,7 +3001,7 @@ File create_frm(THD *thd, const char *name, const char *db,
{
VOID(my_close(file,MYF(0)));
VOID(my_delete(name,MYF(0)));
- return(-1);
+ DBUG_RETURN(-1);
}
}
}
@@ -2559,7 +3012,7 @@ File create_frm(THD *thd, const char *name, const char *db,
else
my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
}
- return (file);
+ DBUG_RETURN(file);
} /* create_frm */
@@ -2578,6 +3031,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
create_info->comment= share->comment;
create_info->transactional= share->transactional;
create_info->page_checksum= share->page_checksum;
+ create_info->option_list= share->option_list;
DBUG_VOID_RETURN;
}
@@ -3735,11 +4189,8 @@ bool TABLE_LIST::prepare_view_securety_context(THD *thd)
{
DBUG_PRINT("info", ("This table is suid view => load contest"));
DBUG_ASSERT(view && view_sctx);
- if (acl_getroot_no_password(view_sctx,
- definer.user.str,
- definer.host.str,
- definer.host.str,
- thd->db))
+ if (acl_getroot(view_sctx, definer.user.str, definer.host.str,
+ definer.host.str, thd->db))
{
if ((thd->lex->sql_command == SQLCOM_SHOW_CREATE) ||
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS))
@@ -4332,9 +4783,10 @@ void st_table::clear_column_bitmaps()
Reset column read/write usage. It's identical to:
bitmap_clear_all(&table->def_read_set);
bitmap_clear_all(&table->def_write_set);
+ bitmap_clear_all(&table->def_vcol_set);
*/
- bzero((char*) def_read_set.bitmap, s->column_bitmap_size*2);
- column_bitmaps_set(&def_read_set, &def_write_set);
+ bzero((char*) def_read_set.bitmap, s->column_bitmap_size*3);
+ column_bitmaps_set(&def_read_set, &def_write_set, &def_vcol_set);
}
@@ -4439,7 +4891,14 @@ void st_table::mark_columns_used_by_index_no_reset(uint index,
KEY_PART_INFO *key_part_end= (key_part +
key_info[index].key_parts);
for (;key_part != key_part_end; key_part++)
+ {
bitmap_set_bit(bitmap, key_part->fieldnr-1);
+ if (key_part->field->vcol_info &&
+ key_part->field->vcol_info->expr_item)
+ key_part->field->vcol_info->
+ expr_item->walk(&Item::register_field_in_bitmap,
+ 1, (uchar *) bitmap);
+ }
}
@@ -4566,6 +5025,8 @@ void st_table::mark_columns_needed_for_update()
file->column_bitmaps_signal();
}
}
+ /* Mark all virtual columns needed for update */
+ mark_virtual_columns_for_write(FALSE);
DBUG_VOID_RETURN;
}
@@ -4592,9 +5053,109 @@ void st_table::mark_columns_needed_for_insert()
}
if (found_next_number_field)
mark_auto_increment_column();
+ /* Mark virtual columns for insert */
+ mark_virtual_columns_for_write(TRUE);
+}
+
+
+/*
+ @brief Mark a column as virtual used by the query
+
+ @param field the field for the column to be marked
+
+ @details
+ The function marks the column for 'field' as virtual (computed)
+ in the bitmap vcol_set.
+ If the column is marked for the first time the expression to compute
+ the column is traversed and all columns that are occurred there are
+ marked in the read_set of the table.
+
+ @retval
+ TRUE if column is marked for the first time
+ @retval
+ FALSE otherwise
+*/
+
+bool st_table::mark_virtual_col(Field *field)
+{
+ bool res;
+ DBUG_ASSERT(field->vcol_info);
+ if (!(res= bitmap_fast_test_and_set(vcol_set, field->field_index)))
+ {
+ Item *vcol_item= field->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ }
+ return res;
}
+/*
+ @brief Mark virtual columns for update/insert commands
+
+ @param insert_fl <-> virtual columns are marked for insert command
+
+ @details
+ The function marks virtual columns used in a update/insert commands
+ in the vcol_set bitmap.
+ For an insert command a virtual column is always marked in write_set if
+ it is a stored column.
+ If a virtual column is from write_set it is always marked in vcol_set.
+ If a stored virtual column is not from write_set but it is computed
+ through columns from write_set it is also marked in vcol_set, and,
+ besides, it is added to write_set.
+
+ @return void
+
+ @note
+ Let table t1 have columns a,b,c and let column c be a stored virtual
+ column computed through columns a and b. Then for the query
+ UPDATE t1 SET a=1
+ column c will be placed into vcol_set and into write_set while
+ column b will be placed into read_set.
+ If column c was a virtual column, but not a stored virtual column
+ then it would not be added to any of the sets. Column b would not
+ be added to read_set either.
+*/
+
+void st_table::mark_virtual_columns_for_write(bool insert_fl)
+{
+ Field **vfield_ptr, *tmp_vfield;
+ bool bitmap_updated= FALSE;
+
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ tmp_vfield= *vfield_ptr;
+ if (bitmap_is_set(write_set, tmp_vfield->field_index))
+ bitmap_updated= mark_virtual_col(tmp_vfield);
+ else if (tmp_vfield->stored_in_db)
+ {
+ bool mark_fl= insert_fl;
+ if (!mark_fl)
+ {
+ MY_BITMAP *save_read_set;
+ Item *vcol_item= tmp_vfield->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ bitmap_clear_all(&tmp_set);
+ save_read_set= read_set;
+ read_set= &tmp_set;
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ read_set= save_read_set;
+ bitmap_intersect(&tmp_set, write_set);
+ mark_fl= !bitmap_is_clear_all(&tmp_set);
+ }
+ if (mark_fl)
+ {
+ bitmap_set_bit(write_set, tmp_vfield->field_index);
+ mark_virtual_col(tmp_vfield);
+ bitmap_updated= TRUE;
+ }
+ }
+ }
+ if (bitmap_updated)
+ file->column_bitmaps_signal();
+}
+
/**
@brief Check if this is part of a MERGE table with attached children.
@@ -4602,7 +5163,7 @@ void st_table::mark_columns_needed_for_insert()
@retval TRUE children are attached
@retval FALSE no MERGE part or children not attached
- @detail
+ @details
A MERGE table consists of a parent TABLE and zero or more child
TABLEs. Each of these TABLEs is called a part of a MERGE table.
*/
@@ -4863,6 +5424,57 @@ size_t max_row_length(TABLE *table, const uchar *data)
return length;
}
+/*
+ @brief Compute values for virtual columns used in query
+
+ @param thd Thread handle
+ @param table The TABLE object
+ @param for_write Requests to compute only fields needed for write
+
+ @details
+ The function computes the values of the virtual columns of the table and
+ stores them in the table record buffer.
+ Only fields from vcol_set are computed, and, when the flag for_write is not
+ set to TRUE, a virtual field is computed only if it's not stored.
+ The flag for_write is set to TRUE for row insert/update operations.
+
+ @retval
+ 0 Success
+ @retval
+ >0 Error occurred when storing a virtual field value
+*/
+
+int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
+{
+ DBUG_ENTER("update_virtual_fields");
+ Field **vfield_ptr, *vfield;
+ int error= 0;
+ if (!table || !table->vfield)
+ DBUG_RETURN(0);
+
+ thd->reset_arena_for_cached_items(table->expr_arena);
+ /* Iterate over virtual fields in the table */
+ for (vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++)
+ {
+ vfield= (*vfield_ptr);
+ DBUG_ASSERT(vfield->vcol_info && vfield->vcol_info->expr_item);
+ /* Only update those fields that are marked in the vcol_set bitmap */
+ if (bitmap_is_set(table->vcol_set, vfield->field_index) &&
+ (for_write || !vfield->stored_in_db))
+ {
+ /* Compute the actual value of the virtual fields */
+ error= vfield->vcol_info->expr_item->save_in_field(vfield, 0);
+ DBUG_PRINT("info", ("field '%s' - updated", vfield->field_name));
+ }
+ else
+ {
+ DBUG_PRINT("info", ("field '%s' - skipped", vfield->field_name));
+ }
+ }
+ thd->reset_arena_for_cached_items(0);
+ DBUG_RETURN(0);
+}
+
/*****************************************************************************
** Instansiate templates
*****************************************************************************/
diff --git a/sql/table.h b/sql/table.h
index 0a25ee75d4e..9f6006c9adc 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -13,6 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifndef SQL_TABLE_INCLUDED
+#define SQL_TABLE_INCLUDED
/* Structs that defines the TABLE */
@@ -25,6 +27,7 @@ class st_select_lex;
class partition_info;
class COND_EQUAL;
class Security_context;
+class Query_arena;
/*************************************************************************/
@@ -340,6 +343,8 @@ typedef struct st_table_share
#ifdef NOT_YET
struct st_table *open_tables; /* link to open tables */
#endif
+ engine_option_value *option_list; /* text options for table */
+ void *option_struct; /* structure with parsed options */
/* The following is copied to each TABLE on OPEN */
Field **field;
@@ -382,6 +387,8 @@ typedef struct st_table_share
ulong version, mysql_version;
ulong timestamp_offset; /* Set to offset+1 of record */
ulong reclength; /* Recordlength */
+ /* Stored record length. No generated-only virtual fields are included */
+ ulong stored_rec_length;
plugin_ref db_plugin; /* storage engine plugin */
inline handlerton *db_type() const /* table_type for handler */
@@ -407,6 +414,8 @@ typedef struct st_table_share
*/
uint null_bytes_for_compare;
uint fields; /* Number of fields */
+ /* Number of stored fields, generated-only virtual fields are not included */
+ uint stored_fields;
uint rec_buff_length; /* Size of table->record[] buffer */
uint keys, key_parts;
uint max_key_length, max_unique_length, total_key_length;
@@ -428,6 +437,7 @@ typedef struct st_table_share
uint error, open_errno, errarg; /* error from open_table_def() */
uint column_bitmap_size;
uchar frm_version;
+ uint vfields; /* Number of computed (virtual) fields */
bool null_field_first;
bool system; /* Set if system table (one record) */
bool crypted; /* If .frm file is crypted */
@@ -705,6 +715,7 @@ struct st_table {
Field *next_number_field; /* Set if next_number is activated */
Field *found_next_number_field; /* Set on open */
Field_timestamp *timestamp_field;
+ Field **vfield; /* Pointer to virtual fields*/
/* Table's triggers, 0 if there are no of them */
Table_triggers_list *triggers;
@@ -713,8 +724,8 @@ struct st_table {
const char *alias; /* alias or table name */
uchar *null_flags;
my_bitmap_map *bitmap_init_value;
- MY_BITMAP def_read_set, def_write_set, tmp_set; /* containers */
- MY_BITMAP *read_set, *write_set; /* Active column sets */
+ MY_BITMAP def_read_set, def_write_set, def_vcol_set, tmp_set;
+ MY_BITMAP *read_set, *write_set, *vcol_set; /* Active column sets */
/*
The ID of the query that opened and is using this table. Has different
meanings depending on the table type.
@@ -863,6 +874,14 @@ struct st_table {
MEM_ROOT mem_root;
GRANT_INFO grant;
FILESORT_INFO sort;
+ /*
+ The arena which the items for expressions from the table definition
+ are associated with.
+ Currently only the items of the expressions for virtual columns are
+ associated with this arena.
+ TODO: To attach the partitioning expressions to this arena.
+ */
+ Query_arena *expr_arena;
#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info; /* Partition related information */
bool no_partitions_used; /* If true, all partitions have been pruned away */
@@ -880,6 +899,8 @@ struct st_table {
void mark_columns_needed_for_update(void);
void mark_columns_needed_for_delete(void);
void mark_columns_needed_for_insert(void);
+ bool mark_virtual_col(Field *field);
+ void mark_virtual_columns_for_write(bool insert_fl);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{
@@ -888,12 +909,30 @@ struct st_table {
if (file)
file->column_bitmaps_signal();
}
+ inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
+ MY_BITMAP *write_set_arg,
+ MY_BITMAP *vcol_set_arg)
+ {
+ read_set= read_set_arg;
+ write_set= write_set_arg;
+ vcol_set= vcol_set_arg;
+ if (file)
+ file->column_bitmaps_signal();
+ }
inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{
read_set= read_set_arg;
write_set= write_set_arg;
}
+ inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg,
+ MY_BITMAP *write_set_arg,
+ MY_BITMAP *vcol_set_arg)
+ {
+ read_set= read_set_arg;
+ write_set= write_set_arg;
+ vcol_set= vcol_set_arg;
+ }
inline void use_all_columns()
{
column_bitmaps_set(&s->all_set, &s->all_set);
@@ -902,6 +941,7 @@ struct st_table {
{
read_set= &def_read_set;
write_set= &def_write_set;
+ vcol_set= &def_vcol_set;
}
/* Is table open or should be treated as such by name-locking? */
inline bool is_name_opened() { return db_stat || open_placeholder; }
@@ -957,6 +997,7 @@ typedef struct st_foreign_key_info
enum enum_schema_tables
{
SCH_CHARSETS= 0,
+ SCH_CLIENT_STATS,
SCH_COLLATIONS,
SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
SCH_COLUMNS,
@@ -966,6 +1007,8 @@ enum enum_schema_tables
SCH_FILES,
SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES,
+ SCH_INDEX_STATS,
+ SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARTITIONS,
@@ -984,8 +1027,10 @@ enum enum_schema_tables
SCH_TABLE_CONSTRAINTS,
SCH_TABLE_NAMES,
SCH_TABLE_PRIVILEGES,
+ SCH_TABLE_STATS,
SCH_TRIGGERS,
SCH_USER_PRIVILEGES,
+ SCH_USER_STATS,
SCH_VARIABLES,
SCH_VIEWS
};
@@ -1822,3 +1867,4 @@ static inline void dbug_tmp_restore_column_maps(MY_BITMAP *read_set,
size_t max_row_length(TABLE *table, const uchar *data);
+#endif
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index 1fbab74554f..da0c25b54dd 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -63,11 +63,13 @@ void init_sql_alloc(MEM_ROOT *mem_root, uint block_size, uint pre_alloc)
}
+#ifndef MYSQL_CLIENT
void *sql_alloc(size_t Size)
{
MEM_ROOT *root= *my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC);
return alloc_root(root,Size);
}
+#endif
void *sql_calloc(size_t size)
diff --git a/sql/tztime.cc b/sql/tztime.cc
index cd6e63be039..3f3060fbc10 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1676,7 +1676,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_leapcnt= 0;
- res= table->file->index_first(table->record[0]);
+ res= table->file->ha_index_first(table->record[0]);
while (!res)
{
@@ -1698,7 +1698,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans,
tz_lsis[tz_leapcnt-1].ls_corr));
- res= table->file->index_next(table->record[0]);
+ res= table->file->ha_index_next(table->record[0]);
}
(void)table->file->ha_index_end();
@@ -1813,6 +1813,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
uint tzid, ttid;
my_time_t ttime;
char buff[MAX_FIELD_WIDTH];
+ uchar keybuff[32];
+ Field *field;
String abbr(buff, sizeof(buff), &my_charset_latin1);
char *alloc_buff, *tz_name_buff;
/*
@@ -1865,8 +1867,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
*/
(void)table->file->ha_index_init(0, 1);
- if (table->file->index_read_map(table->record[0], table->field[0]->ptr,
- HA_WHOLE_KEY, HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr,
+ HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
#ifdef EXTRA_DEBUG
/*
@@ -1890,11 +1892,16 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
*/
table= tz_tables->table;
tz_tables= tz_tables->next_local;
- table->field[0]->store((longlong) tzid, TRUE);
+ field= table->field[0];
+ field->store((longlong) tzid, TRUE);
+ DBUG_ASSERT(field->key_length() <= sizeof(keybuff));
+ field->get_key_image(keybuff,
+ min(field->key_length(), sizeof(keybuff)),
+ Field::itRAW);
(void)table->file->ha_index_init(0, 1);
- if (table->file->index_read_map(table->record[0], table->field[0]->ptr,
- HA_WHOLE_KEY, HA_READ_KEY_EXACT))
+ if (table->file->ha_index_read_map(table->record[0], keybuff,
+ HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
sql_print_error("Can't find description of time zone '%u'", tzid);
goto end;
@@ -1917,11 +1924,16 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
*/
table= tz_tables->table;
tz_tables= tz_tables->next_local;
- table->field[0]->store((longlong) tzid, TRUE);
+ field= table->field[0];
+ field->store((longlong) tzid, TRUE);
+ DBUG_ASSERT(field->key_length() <= sizeof(keybuff));
+ field->get_key_image(keybuff,
+ min(field->key_length(), sizeof(keybuff)),
+ Field::itRAW);
(void)table->file->ha_index_init(0, 1);
- res= table->file->index_read_map(table->record[0], table->field[0]->ptr,
- (key_part_map)1, HA_READ_KEY_EXACT);
+ res= table->file->ha_index_read_map(table->record[0], keybuff,
+ (key_part_map)1, HA_READ_KEY_EXACT);
while (!res)
{
ttid= (uint)table->field[1]->val_int();
@@ -1968,8 +1980,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
tmp_tz_info.typecnt= ttid + 1;
- res= table->file->index_next_same(table->record[0],
- table->field[0]->ptr, 4);
+ res= table->file->ha_index_next_same(table->record[0], keybuff, 4);
}
if (res != HA_ERR_END_OF_FILE)
@@ -1991,8 +2002,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
table->field[0]->store((longlong) tzid, TRUE);
(void)table->file->ha_index_init(0, 1);
- res= table->file->index_read_map(table->record[0], table->field[0]->ptr,
- (key_part_map)1, HA_READ_KEY_EXACT);
+ res= table->file->ha_index_read_map(table->record[0], keybuff,
+ (key_part_map)1, HA_READ_KEY_EXACT);
while (!res)
{
ttime= (my_time_t)table->field[1]->val_int();
@@ -2021,8 +2032,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u",
tzid, (ulong) ttime, ttid));
- res= table->file->index_next_same(table->record[0],
- table->field[0]->ptr, 4);
+ res= table->file->ha_index_next_same(table->record[0], keybuff, 4);
}
/*
diff --git a/sql/unireg.cc b/sql/unireg.cc
index f0aeb0e5530..9859d27dd3b 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -24,11 +24,15 @@
*/
#include "mysql_priv.h"
+#include "create_options.h"
#include <m_ctype.h>
#include <assert.h>
#define FCOMP 17 /* Bytes for a packed field */
+/* threshold for safe_alloca */
+#define ALLOCA_THRESHOLD 2048
+
static uchar * pack_screens(List<Create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
@@ -107,6 +111,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
ulong key_buff_length;
File file;
ulong filepos, data_offset;
+ uint options_len;
uchar fileinfo[64],forminfo[288],*keybuff;
uchar *screen_buff;
char buff[128];
@@ -182,6 +187,18 @@ bool mysql_create_frm(THD *thd, const char *file_name,
create_info->extra_size+= key_info[i].parser_name->length + 1;
}
+ options_len= engine_table_options_frm_length(create_info->option_list,
+ create_fields,
+ keys, key_info);
+ DBUG_PRINT("info", ("Options length: %u", options_len));
+ if (options_len)
+ {
+ create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+ create_info->extra_size+= (options_len + 4);
+ }
+ else
+ create_info->table_options&= ~HA_OPTION_TEXT_CREATE_OPTIONS;
+
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
{
@@ -300,6 +317,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
if (my_write(file, (uchar*) buff, 6, MYF_RW))
goto err;
}
+
for (i= 0; i < keys; i++)
{
if (key_info[i].parser_name)
@@ -310,6 +328,24 @@ bool mysql_create_frm(THD *thd, const char *file_name,
}
}
+ if (options_len)
+ {
+ uchar *optbuff= (uchar *)my_safe_alloca(options_len + 4, ALLOCA_THRESHOLD);
+ my_bool error;
+ DBUG_PRINT("info", ("Create options length: %u", options_len));
+ if (!optbuff)
+ goto err;
+ int4store(optbuff, options_len);
+ engine_table_options_frm_image(optbuff + 4,
+ create_info->option_list,
+ create_fields,
+ keys, key_info);
+ error= my_write(file, optbuff, options_len + 4, MYF_RW);
+ my_safe_afree(optbuff, options_len + 4, ALLOCA_THRESHOLD);
+ if (error)
+ goto err;
+ }
+
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
if (my_write(file, forminfo, 288, MYF_RW) ||
my_write(file, screen_buff, info_length, MYF_RW) ||
@@ -589,7 +625,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
{
uint length,int_count,int_length,no_empty, int_parts;
uint time_stamp_pos,null_fields;
- ulong reclength, totlength, n_length, com_length;
+ ulong reclength, totlength, n_length, com_length, vcol_info_length;
DBUG_ENTER("pack_header");
if (create_fields.elements > MAX_FIELDS)
@@ -600,8 +636,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
totlength= 0L;
reclength= data_offset;
- no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
- com_length=0;
+ no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
+ com_length=vcol_info_length=0;
n_length=2L;
/* Check fields */
@@ -629,6 +665,30 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
field->field_name, tmp_len);
field->comment.length= tmp_len;
}
+ if (field->vcol_info)
+ {
+ tmp_len=
+ system_charset_info->cset->charpos(system_charset_info,
+ field->vcol_info->expr_str.str,
+ field->vcol_info->expr_str.str +
+ field->vcol_info->expr_str.length,
+ VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
+
+ if (tmp_len < field->vcol_info->expr_str.length)
+ {
+ my_error(ER_WRONG_STRING_LENGTH, MYF(0),
+ field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION",
+ (uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
+ DBUG_RETURN(1);
+ }
+ /*
+ Sum up the length of the expression string and the length of the
+ mandatory header to the total length of info on the defining
+ expressions saved in the frm file for virtual columns.
+ */
+ vcol_info_length+= field->vcol_info->expr_str.length+
+ (uint)FRM_VCOL_HEADER_SIZE;
+ }
totlength+= field->length;
com_length+= field->comment.length;
@@ -648,8 +708,6 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
!time_stamp_pos)
time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
length=field->pack_length;
- /* Ensure we don't have any bugs when generating offsets */
- DBUG_ASSERT(reclength == field->offset + data_offset);
if ((uint) field->offset+ (uint) data_offset+ length > reclength)
reclength=(uint) (field->offset+ data_offset + length);
n_length+= (ulong) strlen(field->field_name)+1;
@@ -716,7 +774,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
/* Hack to avoid bugs with small static rows in MySQL */
reclength=max(file->min_record_length(table_options),reclength);
if (info_length+(ulong) create_fields.elements*FCOMP+288+
- n_length+int_length+com_length > 65535L || int_count > 255)
+ n_length+int_length+com_length+vcol_info_length > 65535L ||
+ int_count > 255)
{
my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
DBUG_RETURN(1);
@@ -724,7 +783,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
bzero((char*)forminfo,288);
length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
- com_length);
+ com_length+vcol_info_length);
int2store(forminfo,length);
forminfo[256] = (uint8) screens;
int2store(forminfo+258,create_fields.elements);
@@ -741,7 +800,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length);
- /* Up to forminfo+288 is free to use for additional information */
+ int2store(forminfo+286,vcol_info_length);
+ /* forminfo+288 is free to use for additional information */
DBUG_RETURN(0);
} /* pack_header */
@@ -780,7 +840,7 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
ulong data_offset)
{
reg2 uint i;
- uint int_count, comment_length=0;
+ uint int_count, comment_length= 0, vcol_info_length=0;
uchar buff[MAX_FIELD_WIDTH];
Create_field *field;
DBUG_ENTER("pack_fields");
@@ -793,6 +853,7 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
while ((field=it++))
{
uint recpos;
+ uint cur_vcol_expr_len= 0;
buff[0]= (uchar) field->row;
buff[1]= (uchar) field->col;
buff[2]= (uchar) field->sc_length;
@@ -815,6 +876,17 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
buff[14]= (uchar) field->charset->number;
else
buff[14]= 0; // Numerical
+ if (field->vcol_info)
+ {
+ /*
+ Use the interval_id place in the .frm file to store the length of
+ the additional data saved for the virtual field
+ */
+ buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length +
+ (uint)FRM_VCOL_HEADER_SIZE;
+ vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE;
+ buff[13]= (uchar) MYSQL_TYPE_VIRTUAL;
+ }
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
@@ -909,6 +981,34 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
DBUG_RETURN(1);
}
}
+ if (vcol_info_length)
+ {
+ it.rewind();
+ int_count=0;
+ while ((field=it++))
+ {
+ /*
+ Pack each virtual field as follows:
+ byte 1 = 1 (always 1 to allow for future extensions)
+ byte 2 = sql_type
+ byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
+ byte 4-... = virtual column expression (text data)
+ */
+ if (field->vcol_info && field->vcol_info->expr_str.length)
+ {
+ buff[0]= (uchar)1;
+ buff[1]= (uchar) field->sql_type;
+ buff[2]= (uchar) field->stored_in_db;
+ if (my_write(file, buff, 3, MYF_RW))
+ DBUG_RETURN(1);
+ if (my_write(file,
+ (uchar*) field->vcol_info->expr_str.str,
+ field->vcol_info->expr_str.length,
+ MYF_RW))
+ DBUG_RETURN(1);
+ }
+ }
+ }
DBUG_RETURN(0);
}
diff --git a/sql/unireg.h b/sql/unireg.h
index 4fbde3b8631..ec4ecf6a10f 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -212,6 +212,13 @@
#define DEFAULT_KEY_CACHE_NAME "default"
+/* The length of the header part for each virtual column in the .frm file */
+#define FRM_VCOL_HEADER_SIZE 3
+
+/* Maximum length of the defining expression for a virtual columns */
+#define VIRTUAL_COLUMN_EXPRESSION_MAXLEN 255 - FRM_VCOL_HEADER_SIZE
+
+
/* Include prototypes for unireg */
#include "mysqld_error.h"
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 988337ec50e..922db30c9d9 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1290,10 +1290,11 @@ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
*/
int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
- DBUG_ENTER("ha_archive::optimize");
int rc= 0;
azio_stream writer;
char writer_filename[FN_REFLEN];
+ char* frm_string;
+ DBUG_ENTER("ha_archive::optimize");
init_archive_reader();
@@ -1304,12 +1305,28 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
share->archive_write_open= FALSE;
}
+ if (!(frm_string= (char*) malloc(archive.frm_length)))
+ return ENOMEM;
+
+ azread_frm(&archive, frm_string);
+
/* Lets create a file to contain the new data */
fn_format(writer_filename, share->table_name, "", ARN,
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY)))
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ {
+ free(frm_string);
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ }
+
+ rc= azwrite_frm(&writer, frm_string, archive.frm_length);
+ free(frm_string);
+ if (rc)
+ {
+ rc= HA_ERR_CRASHED_ON_USAGE;
+ goto error;
+ }
/*
An extended rebuild is a lot more effort. We open up each row and re-record it.
@@ -1387,7 +1404,6 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
// make the file we just wrote be our data file
rc = my_rename(writer_filename,share->data_file_name,MYF(0));
-
DBUG_RETURN(rc);
error:
DBUG_PRINT("ha_archive", ("Failed to recover, error was %d", rc));
@@ -1666,4 +1682,21 @@ mysql_declare_plugin(archive)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_storage_engine,
+ "ARCHIVE",
+ "Brian Aker, MySQL AB",
+ "Archive storage engine",
+ PLUGIN_LICENSE_GPL,
+ archive_db_init, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0300 /* 3.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index e3ba111043b..19651a370cc 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -369,3 +369,20 @@ mysql_declare_plugin(blackhole)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_storage_engine,
+ "BLACKHOLE",
+ "MySQL AB",
+ "/dev/null storage engine (anything you write to it disappears)",
+ PLUGIN_LICENSE_GPL,
+ blackhole_init, /* Plugin Init */
+ blackhole_fini, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 4a9754922e5..4ca3e029cbc 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -1655,4 +1655,20 @@ mysql_declare_plugin(csv)
NULL /* config options */
}
mysql_declare_plugin_end;
-
+maria_declare_plugin(csv)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &csv_storage_engine,
+ "CSV",
+ "Brian Aker, MySQL AB",
+ "CSV storage engine",
+ PLUGIN_LICENSE_GPL,
+ tina_init_func, /* Plugin Init */
+ tina_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am
index 4b2f165377c..10163e307b1 100644
--- a/storage/example/Makefile.am
+++ b/storage/example/Makefile.am
@@ -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
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index 604722c3c8c..e8ef0b72bc8 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
@@ -113,6 +113,76 @@ static HASH example_open_tables;
/* The mutex used to init the hash; variable for example share methods */
pthread_mutex_t example_mutex;
+
+/**
+ structure for CREATE TABLE options (table options)
+
+ These can be specified in the CREATE TABLE:
+ CREATE TABLE ( ... ) {...here...}
+*/
+
+struct example_table_options_struct
+{
+ const char *strparam;
+ ulonglong ullparam;
+ uint enumparam;
+ bool boolparam;
+};
+
+
+/**
+ structure for CREATE TABLE options (field options)
+
+ These can be specified in the CREATE TABLE per field:
+ CREATE TABLE ( field ... {...here...}, ... )
+*/
+
+struct example_field_options_struct
+{
+ const char *compex_param_to_parse_it_in_engine;
+};
+
+/* HA_TOPTION_* macros expect the structure called ha_table_option_struct */
+#define ha_table_option_struct example_table_options_struct
+ha_create_table_option example_table_option_list[]=
+{
+ /*
+ one numeric option, with the default of UINT_MAX32, valid
+ range of values 0..UINT_MAX32, and a "block size" of 10
+ (any value must be divisible by 10).
+ */
+ HA_TOPTION_NUMBER("ULL", ullparam, UINT_MAX32, 0, UINT_MAX32, 10),
+ /*
+ one option that takes an arbitrary string
+ */
+ HA_TOPTION_STRING("STR", strparam),
+ /*
+ one enum option. a valid values are strings ONE and TWO.
+ A default value is 0, that is "one".
+ */
+ HA_TOPTION_ENUM("one_or_two", enumparam, "one,two", 0),
+ /*
+ one boolean option, the valid values are YES/NO, ON/OFF, 1/0.
+ The default is 1, that is true, yes, on.
+ */
+ HA_TOPTION_BOOL("YESNO", boolparam, 1),
+ HA_TOPTION_END
+};
+
+/* HA_FOPTION_* macros expect the structure called ha_field_option_struct */
+#define ha_field_option_struct example_field_options_struct
+ha_create_table_option example_field_option_list[]=
+{
+ /*
+ If the engine wants something more complex than a string, number, enum,
+ or boolean - for example a list - it needs to specify the option
+ as a string and parse it internally.
+ */
+ HA_FOPTION_STRING("COMPLEX", compex_param_to_parse_it_in_engine),
+ HA_FOPTION_END
+};
+
+
/**
@brief
Function we use in the creation of our hash to get key.
@@ -138,6 +208,8 @@ static int example_init_func(void *p)
example_hton->state= SHOW_OPTION_YES;
example_hton->create= example_create_handler;
example_hton->flags= HTON_CAN_RECREATE;
+ example_hton->table_options= example_table_option_list;
+ example_hton->field_options= example_field_option_list;
DBUG_RETURN(0);
}
@@ -295,6 +367,17 @@ int ha_example::open(const char *name, int mode, uint test_if_locked)
DBUG_RETURN(1);
thr_lock_data_init(&share->lock,&lock,NULL);
+#ifndef DBUG_OFF
+ example_table_options_struct *options=
+ (example_table_options_struct *)table->s->option_struct;
+
+ DBUG_ASSERT(options);
+ DBUG_PRINT("info", ("strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (options->strparam ? options->strparam : "<NULL>"),
+ options->ullparam, options->enumparam, options->boolparam));
+#endif
+
DBUG_RETURN(0);
}
@@ -507,7 +590,7 @@ int ha_example::index_last(uchar *buf)
int ha_example::rnd_init(bool scan)
{
DBUG_ENTER("ha_example::rnd_init");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ DBUG_RETURN(0);
}
int ha_example::rnd_end()
@@ -774,27 +857,6 @@ int ha_example::delete_table(const char *name)
/**
@brief
- Renames a table from one name to another via an alter table call.
-
- @details
- If you do not implement this, the default rename_table() is called from
- handler.cc and it will delete all files with the file extensions returned
- by bas_ext().
-
- Called from sql_table.cc by mysql_rename_table().
-
- @see
- mysql_rename_table() in sql_table.cc
-*/
-int ha_example::rename_table(const char * from, const char * to)
-{
- DBUG_ENTER("ha_example::rename_table ");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/**
- @brief
Given a starting key and an ending key, estimate the number of rows that
will exist between the two keys.
@@ -836,15 +898,105 @@ ha_rows ha_example::records_in_range(uint inx, key_range *min_key,
int ha_example::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
+#ifndef DBUG_OFF
+ example_table_options_struct *options=
+ (example_table_options_struct *)table_arg->s->option_struct;
DBUG_ENTER("ha_example::create");
/*
- This is not implemented but we want someone to be able to see that it
- works.
+ This example shows how to support custom engine specific table and field
+ options.
*/
+ DBUG_ASSERT(options);
+ DBUG_PRINT("info", ("strparam: '%-.64s' ullparam: %llu enumparam: %u "\
+ "boolparam: %u",
+ (options->strparam ? options->strparam : "<NULL>"),
+ options->ullparam, options->enumparam, options->boolparam));
+ for (Field **field= table_arg->s->field; *field; field++)
+ {
+ example_field_options_struct *field_options=
+ (example_field_options_struct *)(*field)->option_struct;
+ DBUG_ASSERT(field_options);
+ DBUG_PRINT("info", ("field: %s complex: '%-.64s'",
+ (*field)->field_name,
+ (field_options->compex_param_to_parse_it_in_engine ?
+ field_options->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ }
+#endif
DBUG_RETURN(0);
}
+/**
+ check_if_incompatible_data() called if ALTER TABLE can't detect otherwise
+ if new and old definition are compatible
+
+ @details If there are no other explicit signs like changed number of
+ fields this function will be called by compare_tables()
+ (sql/sql_tables.cc) to decide should we rewrite whole table or only .frm
+ file.
+
+*/
+
+bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes)
+{
+ example_table_options_struct *param_old, *param_new;
+ uint i;
+ DBUG_ENTER("ha_example::check_if_incompatible_data");
+ /*
+ This example shows how custom engine specific table and field
+ options can be accessed from this function to be compared.
+ */
+ param_new= (example_table_options_struct *)info->option_struct;
+ DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "
+ "boolparam: %u",
+ (param_new->strparam ? param_new->strparam : "<NULL>"),
+ param_new->ullparam, param_new->enumparam,
+ param_new->boolparam));
+
+ param_old= (example_table_options_struct *)table->s->option_struct;
+ DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "
+ "boolparam: %u",
+ (param_old->strparam ? param_old->strparam : "<NULL>"),
+ param_old->ullparam, param_old->enumparam,
+ param_old->boolparam));
+
+ /*
+ check important parameters:
+ for this example engine, we'll assume that changing ullparam or
+ boolparam requires a table to be rebuilt, while changing strparam
+ or enumparam - does not.
+ */
+ if (param_new->ullparam != param_old->ullparam ||
+ param_new->boolparam != param_old->boolparam)
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+
+ for (i= 0; i < table->s->fields; i++)
+ {
+ example_field_options_struct *f_old, *f_new;
+ f_old= (example_field_options_struct *)table->s->field[i]->option_struct;
+ DBUG_ASSERT(f_old);
+ DBUG_PRINT("info", ("old field: %u old complex: '%-.64s'", i,
+ (f_old->compex_param_to_parse_it_in_engine ?
+ f_old->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ if (info->fileds_option_struct[i])
+ {
+ f_new= (example_field_options_struct *)info->fileds_option_struct[i];
+ DBUG_PRINT("info", ("old field: %u new complex: '%-.64s'", i,
+ (f_new->compex_param_to_parse_it_in_engine ?
+ f_new->compex_param_to_parse_it_in_engine :
+ "<NULL>")));
+ }
+ else
+ DBUG_PRINT("info", ("old field %i did not changed", i));
+ }
+
+ DBUG_RETURN(COMPATIBLE_DATA_YES);
+}
+
+
struct st_mysql_storage_engine example_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
@@ -890,6 +1042,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,
@@ -901,8 +1071,25 @@ 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 */
}
mysql_declare_plugin_end;
+maria_declare_plugin(example)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &example_storage_engine,
+ "EXAMPLE",
+ "Brian Aker, MySQL AB",
+ "Example storage engine",
+ PLUGIN_LICENSE_GPL,
+ example_init_func, /* Plugin Init */
+ example_done_func, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ func_status, /* status variables */
+ example_system_variables, /* system variables */
+ "0.1", /* string version */
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index fad44f34615..dc47fac1f17 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -243,9 +243,10 @@ public:
ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
- int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required
+ bool check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 619393289a9..4d597d6d7a9 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -3416,3 +3416,20 @@ mysql_declare_plugin(federated)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ "Federated MySQL storage engine",
+ PLUGIN_LICENSE_GPL,
+ federated_db_init, /* Plugin Init */
+ federated_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index a88c60efb74..04ba9984492 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -3506,9 +3506,26 @@ mysql_declare_plugin(federatedx)
PLUGIN_LICENSE_GPL,
federatedx_db_init, /* Plugin Init */
federatedx_done, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
+ 0x0200 /* 2.0 */,
NULL, /* status variables */
NULL, /* system variables */
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(federatedx)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federatedx_storage_engine,
+ "FEDERATED",
+ "Patrick Galbraith",
+ "FederatedX pluggable storage engine",
+ PLUGIN_LICENSE_GPL,
+ federatedx_db_init, /* Plugin Init */
+ federatedx_done, /* Plugin Deinit */
+ 0x0200 /* 2.0 */,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "2.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_BETA /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index fb7c13e4e41..42437a22614 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -767,3 +767,20 @@ mysql_declare_plugin(heap)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_storage_engine,
+ "MEMORY",
+ "MySQL AB",
+ "Hash based, stored in memory, useful for temporary tables",
+ PLUGIN_LICENSE_GPL,
+ heap_init,
+ NULL,
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c
index b6814fc1614..bc8183bf777 100644
--- a/storage/heap/hp_create.c
+++ b/storage/heap/hp_create.c
@@ -85,8 +85,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
/* fall_through */
case HA_KEYTYPE_VARTEXT1:
- if (!my_binary_compare(keyinfo->seg[j].charset))
- keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
length+= 2;
/* Save number of bytes used to store length */
@@ -96,8 +94,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
/* Case-insensitiveness is handled in coll->hash_sort */
/* fall_through */
case HA_KEYTYPE_VARTEXT2:
- if (!my_binary_compare(keyinfo->seg[j].charset))
- keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
length+= 2;
/* Save number of bytes used to store length */
@@ -111,8 +107,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
default:
break;
}
- if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
- keyinfo->flag|= HA_END_SPACE_KEY;
}
keyinfo->length= length;
length+= keyinfo->rb_tree.size_of_element +
diff --git a/storage/heap/hp_rkey.c b/storage/heap/hp_rkey.c
index 6eeac6acd7b..27d1114770e 100644
--- a/storage/heap/hp_rkey.c
+++ b/storage/heap/hp_rkey.c
@@ -63,7 +63,7 @@ int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key,
info->update= 0;
DBUG_RETURN(my_errno);
}
- if (!(keyinfo->flag & HA_NOSAME) || (keyinfo->flag & HA_END_SPACE_KEY))
+ if (!(keyinfo->flag & HA_NOSAME))
memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
memcpy(record, pos, (size_t) share->reclength);
diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc
index 39096be7848..f77927421d2 100644
--- a/storage/ibmdb2i/ha_ibmdb2i.cc
+++ b/storage/ibmdb2i/ha_ibmdb2i.cc
@@ -1158,9 +1158,7 @@ int ha_ibmdb2i::rnd_init(bool scan)
rrnAssocHandle= 0;
- DBUG_RETURN(0); // MySQL sometimes does not check the return code, causing
- // an assert in ha_rnd_end later on if we return a non-zero
- // value here.
+ DBUG_RETURN(0);
}
int ha_ibmdb2i::rnd_end()
@@ -3357,3 +3355,20 @@ mysql_declare_plugin(ibmdb2i)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(ibmdb2i)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ibmdb2i_storage_engine,
+ "IBMDB2I",
+ "The IBM development team in Rochester, Minnesota",
+ "IBM DB2 for i Storage Engine",
+ PLUGIN_LICENSE_GPL,
+ ibmdb2i_init_func, /* Plugin Init */
+ ibmdb2i_done_func, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ NULL, /* status variables */
+ ibmdb2i_system_variables, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_UNKNOWN /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/innodb_plugin/Makefile.am b/storage/innodb_plugin/Makefile.am
index 1d0dd936895..807be18b2a2 100644
--- a/storage/innodb_plugin/Makefile.am
+++ b/storage/innodb_plugin/Makefile.am
@@ -331,7 +331,7 @@ libinnobase_a_CFLAGS= $(AM_CFLAGS)
EXTRA_LTLIBRARIES= ha_innodb_plugin.la
pkgplugin_LTLIBRARIES= @plugin_innodb_plugin_shared_target@
-ha_innodb_plugin_la_LDFLAGS= -module -rpath $(pkgplugindir)
+ha_innodb_plugin_la_LDFLAGS= -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
ha_innodb_plugin_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_plugin_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_plugin_la_SOURCES= $(libinnobase_a_SOURCES)
diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt
index 22e0211f052..12bd3d063b5 100644
--- a/storage/maria/CMakeLists.txt
+++ b/storage/maria/CMakeLists.txt
@@ -45,7 +45,7 @@ SET(MARIA_SOURCES ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c
ma_sp_key.c ma_control_file.c ma_loghandler.c
ma_pagecache.c ma_pagecaches.c
ma_checkpoint.c ma_recovery.c ma_commit.c ma_pagecrc.c
- ha_maria.h maria_def.h ma_recovery_util.c
+ ha_maria.h maria_def.h ma_recovery_util.c ma_servicethread.c
)
MYSQL_STORAGE_ENGINE(MARIA)
diff --git a/storage/maria/Makefile.am b/storage/maria/Makefile.am
index d38abe01bdc..fe674fb2837 100644
--- a/storage/maria/Makefile.am
+++ b/storage/maria/Makefile.am
@@ -73,7 +73,8 @@ noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h \
ma_loghandler.h ma_loghandler_lsn.h ma_pagecache.h \
ma_checkpoint.h ma_recovery.h ma_commit.h ma_state.h \
trnman_public.h ma_check_standalone.h \
- ma_key_recover.h ma_recovery_util.h
+ ma_key_recover.h ma_recovery_util.h \
+ ma_servicethread.h
ma_test1_DEPENDENCIES= $(LIBRARIES)
ma_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
@@ -135,7 +136,7 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_pagecache.c ma_pagecaches.c \
ma_checkpoint.c ma_recovery.c ma_commit.c \
ma_pagecrc.c ma_recovery_util.c \
- ha_maria.cc
+ ha_maria.cc ma_servicethread.c
CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA? maria_log_control maria_log.0000*
SUFFIXES = .sh
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index da23f76f143..9176e99c912 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -102,22 +102,40 @@ TYPELIB maria_translog_purge_type_typelib=
array_elements(maria_translog_purge_type_names) - 1, "",
maria_translog_purge_type_names, NULL
};
+
+/* transactional log directory sync */
const char *maria_sync_log_dir_names[]=
{
"NEVER", "NEWFILE", "ALWAYS", NullS
};
-
TYPELIB maria_sync_log_dir_typelib=
{
array_elements(maria_sync_log_dir_names) - 1, "",
maria_sync_log_dir_names, NULL
};
+/* transactional log group commit */
+const char *maria_group_commit_names[]=
+{
+ "none", "hard", "soft", NullS
+};
+TYPELIB maria_group_commit_typelib=
+{
+ array_elements(maria_group_commit_names) - 1, "",
+ maria_group_commit_names, NULL
+};
+
/** Interval between background checkpoints in seconds */
static ulong checkpoint_interval;
static void update_checkpoint_interval(MYSQL_THD thd,
struct st_mysql_sys_var *var,
void *var_ptr, const void *save);
+static void update_maria_group_commit(MYSQL_THD thd,
+ struct st_mysql_sys_var *var,
+ void *var_ptr, const void *save);
+static void update_maria_group_commit_interval(MYSQL_THD thd,
+ struct st_mysql_sys_var *var,
+ void *var_ptr, const void *save);
/** After that many consecutive recovery failures, remove logs */
static ulong force_start_after_recovery_failures;
static void update_log_file_size(MYSQL_THD thd,
@@ -164,6 +182,24 @@ static MYSQL_SYSVAR_ULONG(log_file_size, log_file_size,
NULL, update_log_file_size, TRANSLOG_FILE_SIZE,
TRANSLOG_MIN_FILE_SIZE, 0xffffffffL, TRANSLOG_PAGE_SIZE);
+static MYSQL_SYSVAR_ENUM(group_commit, maria_group_commit,
+ PLUGIN_VAR_RQCMDARG,
+ "Specifies maria group commit mode. "
+ "Possible values are \"none\" (no group commit), "
+ "\"hard\" (with waiting to actual commit), "
+ "\"soft\" (no wait for commit (DANGEROUS!!!))",
+ NULL, update_maria_group_commit,
+ TRANSLOG_GCOMMIT_NONE, &maria_group_commit_typelib);
+
+static MYSQL_SYSVAR_ULONG(group_commit_interval, maria_group_commit_interval,
+ PLUGIN_VAR_RQCMDARG,
+ "Interval between commite in microseconds (1/1000000c)."
+ " 0 stands for no waiting"
+ " for other threads to come and do a commit in \"hard\" mode and no"
+ " sync()/commit at all in \"soft\" mode. Option has only an effect"
+ " if maria_group_commit is used",
+ NULL, update_maria_group_commit_interval, 0, 0, UINT_MAX, 1);
+
static MYSQL_SYSVAR_ENUM(log_purge_type, log_purge_type,
PLUGIN_VAR_RQCMDARG,
"Specifies how maria transactional log will be purged. "
@@ -432,7 +468,7 @@ static int table2maria(TABLE *table_arg, data_file_type row_type,
recinfo_pos= recinfo;
create_info->null_bytes= table_arg->s->null_bytes;
- while (recpos < (uint) share->reclength)
+ while (recpos < (uint) share->stored_rec_length)
{
Field **field, *found= 0;
minpos= share->reclength;
@@ -3318,6 +3354,8 @@ static struct st_mysql_sys_var* system_variables[]= {
MYSQL_SYSVAR(block_size),
MYSQL_SYSVAR(checkpoint_interval),
MYSQL_SYSVAR(force_start_after_recovery_failures),
+ MYSQL_SYSVAR(group_commit),
+ MYSQL_SYSVAR(group_commit_interval),
MYSQL_SYSVAR(log_dir_path),
MYSQL_SYSVAR(log_file_size),
MYSQL_SYSVAR(log_purge_type),
@@ -3349,6 +3387,92 @@ static void update_checkpoint_interval(MYSQL_THD thd,
}
/**
+ @brief Updates group commit mode
+*/
+
+static void update_maria_group_commit(MYSQL_THD thd,
+ struct st_mysql_sys_var *var,
+ void *var_ptr, const void *save)
+{
+ ulong value= (ulong)*((long *)var_ptr);
+ DBUG_ENTER("update_maria_group_commit");
+ DBUG_PRINT("enter", ("old value: %lu new value %lu rate %lu",
+ value, (ulong)(*(long *)save),
+ maria_group_commit_interval));
+ /* old value */
+ switch (value) {
+ case TRANSLOG_GCOMMIT_NONE:
+ break;
+ case TRANSLOG_GCOMMIT_HARD:
+ translog_hard_group_commit(FALSE);
+ break;
+ case TRANSLOG_GCOMMIT_SOFT:
+ translog_soft_sync(FALSE);
+ if (maria_group_commit_interval)
+ translog_soft_sync_end();
+ break;
+ default:
+ DBUG_ASSERT(0); /* impossible */
+ }
+ value= *(ulong *)var_ptr= (ulong)(*(long *)save);
+ translog_sync();
+ /* new value */
+ switch (value) {
+ case TRANSLOG_GCOMMIT_NONE:
+ break;
+ case TRANSLOG_GCOMMIT_HARD:
+ translog_hard_group_commit(TRUE);
+ break;
+ case TRANSLOG_GCOMMIT_SOFT:
+ translog_soft_sync(TRUE);
+ /* variable change made under global lock so we can just read it */
+ if (maria_group_commit_interval)
+ translog_soft_sync_start();
+ break;
+ default:
+ DBUG_ASSERT(0); /* impossible */
+ }
+ DBUG_VOID_RETURN;
+}
+
+/**
+ @brief Updates group commit interval
+*/
+
+static void update_maria_group_commit_interval(MYSQL_THD thd,
+ struct st_mysql_sys_var *var,
+ void *var_ptr, const void *save)
+{
+ ulong new_value= (ulong)*((long *)save);
+ ulong *value_ptr= (ulong*) var_ptr;
+ DBUG_ENTER("update_maria_group_commit_interval");
+ DBUG_PRINT("enter", ("old value: %lu new value %lu group commit %lu",
+ *value_ptr, new_value, maria_group_commit));
+
+ /* variable change made under global lock so we can just read it */
+ switch (maria_group_commit) {
+ case TRANSLOG_GCOMMIT_NONE:
+ *value_ptr= new_value;
+ translog_set_group_commit_interval(new_value);
+ break;
+ case TRANSLOG_GCOMMIT_HARD:
+ *value_ptr= new_value;
+ translog_set_group_commit_interval(new_value);
+ break;
+ case TRANSLOG_GCOMMIT_SOFT:
+ if (*value_ptr)
+ translog_soft_sync_end();
+ translog_set_group_commit_interval(new_value);
+ if ((*value_ptr= new_value))
+ translog_soft_sync_start();
+ break;
+ default:
+ DBUG_ASSERT(0); /* impossible */
+ }
+ DBUG_VOID_RETURN;
+}
+
+/**
@brief Updates the transaction log file limit.
*/
@@ -3370,6 +3494,7 @@ static SHOW_VAR status_variables[]= {
{"Maria_pagecache_reads", (char*) &maria_pagecache_var.global_cache_read, SHOW_LONGLONG},
{"Maria_pagecache_write_requests", (char*) &maria_pagecache_var.global_cache_w_requests, SHOW_LONGLONG},
{"Maria_pagecache_writes", (char*) &maria_pagecache_var.global_cache_write, SHOW_LONGLONG},
+ {"Maria_transaction_log_syncs", (char*) &translog_syncs, SHOW_LONGLONG},
{NullS, NullS, SHOW_LONG}
};
@@ -3386,9 +3511,26 @@ mysql_declare_plugin(maria)
PLUGIN_LICENSE_GPL,
ha_maria_init, /* Plugin Init */
NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
+ 0x0105, /* 1.5 */
status_variables, /* status variables */
system_variables, /* system variables */
NULL
}
mysql_declare_plugin_end;
+maria_declare_plugin(maria)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &maria_storage_engine,
+ "MARIA",
+ "MySQL AB",
+ "Crash-safe tables with MyISAM heritage",
+ PLUGIN_LICENSE_GPL,
+ ha_maria_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0105, /* 1.5 */
+ status_variables, /* status variables */
+ system_variables, /* system variables */
+ "1.5", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
index 6ca1f6ca797..6402571f043 100644
--- a/storage/maria/ha_maria.h
+++ b/storage/maria/ha_maria.h
@@ -149,6 +149,7 @@ public:
int assign_to_keycache(THD * thd, HA_CHECK_OPT * check_opt);
int preload_keys(THD * thd, HA_CHECK_OPT * check_opt);
bool check_if_incompatible_data(HA_CREATE_INFO * info, uint table_changes);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
#ifdef HAVE_REPLICATION
int dump(THD * thd, int fd);
int net_read_dump(NET * net);
diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c
index 6d1a6332c54..b75267f81f1 100644
--- a/storage/maria/ma_checkpoint.c
+++ b/storage/maria/ma_checkpoint.c
@@ -35,6 +35,7 @@
#include "ma_blockrec.h"
#include "ma_checkpoint.h"
#include "ma_loghandler_lsn.h"
+#include "ma_servicethread.h"
/** @brief type of checkpoint currently running */
@@ -43,10 +44,9 @@ static CHECKPOINT_LEVEL checkpoint_in_progress= CHECKPOINT_NONE;
static pthread_mutex_t LOCK_checkpoint;
/** @brief for killing the background checkpoint thread */
static pthread_cond_t COND_checkpoint;
-/** @brief if checkpoint module was inited or not */
-static my_bool checkpoint_inited= FALSE;
-/** @brief 'kill' flag for the background checkpoint thread */
-static int checkpoint_thread_die;
+/** @brief control structure for checkpoint background thread */
+static MA_SERVICE_THREAD_CONTROL checkpoint_control=
+ {THREAD_DEAD, FALSE, &LOCK_checkpoint, &COND_checkpoint};
/* is ulong like pagecache->blocks_changed */
static ulong pages_to_flush_before_next_checkpoint;
static PAGECACHE_FILE *dfiles, /**< data files to flush in background */
@@ -99,7 +99,7 @@ int ma_checkpoint_execute(CHECKPOINT_LEVEL level, my_bool no_wait)
int result= 0;
DBUG_ENTER("ma_checkpoint_execute");
- if (!checkpoint_inited)
+ if (!checkpoint_control.inited)
{
/*
If ha_maria failed to start, maria_panic_hton is called, we come here.
@@ -326,17 +326,17 @@ int ma_checkpoint_init(ulong interval)
pthread_t th;
int res= 0;
DBUG_ENTER("ma_checkpoint_init");
- checkpoint_inited= TRUE;
- checkpoint_thread_die= 2; /* not yet born == dead */
- if (pthread_mutex_init(&LOCK_checkpoint, MY_MUTEX_INIT_SLOW) ||
- pthread_cond_init(&COND_checkpoint, 0))
+ if (ma_service_thread_control_init(&checkpoint_control))
res= 1;
else if (interval > 0)
{
compile_time_assert(sizeof(void *) >= sizeof(ulong));
if (!(res= pthread_create(&th, NULL, ma_checkpoint_background,
(void *)interval)))
- checkpoint_thread_die= 0; /* thread lives, will have to be killed */
+ {
+ /* thread lives, will have to be killed */
+ checkpoint_control.status= THREAD_RUNNING;
+ }
}
DBUG_RETURN(res);
}
@@ -425,30 +425,12 @@ void ma_checkpoint_end(void)
DBUG_EXECUTE_IF("maria_crash",
{ DBUG_PRINT("maria_crash", ("now")); DBUG_ABORT(); });
- if (checkpoint_inited)
+ if (checkpoint_control.inited)
{
- pthread_mutex_lock(&LOCK_checkpoint);
- if (checkpoint_thread_die != 2) /* thread was started ok */
- {
- DBUG_PRINT("info",("killing Maria background checkpoint thread"));
- checkpoint_thread_die= 1; /* kill it */
- do /* and wait for it to be dead */
- {
- /* wake it up if it was in a sleep */
- pthread_cond_broadcast(&COND_checkpoint);
- DBUG_PRINT("info",("waiting for Maria background checkpoint thread"
- " to die"));
- pthread_cond_wait(&COND_checkpoint, &LOCK_checkpoint);
- }
- while (checkpoint_thread_die != 2);
- }
- pthread_mutex_unlock(&LOCK_checkpoint);
+ ma_service_thread_control_end(&checkpoint_control);
my_free((uchar *)dfiles, MYF(MY_ALLOW_ZERO_PTR));
my_free((uchar *)kfiles, MYF(MY_ALLOW_ZERO_PTR));
dfiles= kfiles= NULL;
- pthread_mutex_destroy(&LOCK_checkpoint);
- pthread_cond_destroy(&COND_checkpoint);
- checkpoint_inited= FALSE;
}
DBUG_VOID_RETURN;
}
@@ -588,7 +570,6 @@ pthread_handler_t ma_checkpoint_background(void *arg)
#if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */
sleeps=0;
#endif
- struct timespec abstime;
switch (sleeps % interval)
{
case 0:
@@ -701,25 +682,11 @@ pthread_handler_t ma_checkpoint_background(void *arg)
sleep_time= interval - (sleeps % interval);
}
}
- pthread_mutex_lock(&LOCK_checkpoint);
- if (checkpoint_thread_die == 1)
+ if (my_service_thread_sleep(&checkpoint_control,
+ sleep_time * 1000000000ULL))
break;
-#if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */
- pthread_mutex_unlock(&LOCK_checkpoint);
- my_sleep(100000); /* a tenth of a second */
- pthread_mutex_lock(&LOCK_checkpoint);
-#else
- /* To have a killable sleep, we use timedwait like our SQL GET_LOCK() */
- DBUG_PRINT("info", ("sleeping %u seconds", sleep_time));
- set_timespec(abstime, sleep_time);
- pthread_cond_timedwait(&COND_checkpoint, &LOCK_checkpoint, &abstime);
-#endif
- if (checkpoint_thread_die == 1)
- break;
- pthread_mutex_unlock(&LOCK_checkpoint);
sleeps+= sleep_time;
}
- pthread_mutex_unlock(&LOCK_checkpoint);
DBUG_PRINT("info",("Maria background checkpoint thread ends"));
{
CHECKPOINT_LEVEL level= CHECKPOINT_FULL;
@@ -730,12 +697,7 @@ pthread_handler_t ma_checkpoint_background(void *arg)
DBUG_EXECUTE_IF("maria_checkpoint_indirect", level= CHECKPOINT_INDIRECT;);
ma_checkpoint_execute(level, FALSE);
}
- pthread_mutex_lock(&LOCK_checkpoint);
- checkpoint_thread_die= 2; /* indicate that we are dead */
- /* wake up ma_checkpoint_end() which may be waiting for our death */
- pthread_cond_broadcast(&COND_checkpoint);
- /* broadcast was inside unlock because ma_checkpoint_end() destroys mutex */
- pthread_mutex_unlock(&LOCK_checkpoint);
+ my_service_thread_signal_end(&checkpoint_control);
my_thread_end();
return 0;
}
diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c
index 6cd23558784..d302892ce05 100644
--- a/storage/maria/ma_ft_boolean_search.c
+++ b/storage/maria/ma_ft_boolean_search.c
@@ -592,7 +592,7 @@ FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr,
sizeof(FTB_WORD *)*ftb->queue.elements);
memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements);
my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *),
- (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset);
+ (qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset);
if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC;
ftb->state=READY;
return ftb;
diff --git a/storage/maria/ma_ft_parser.c b/storage/maria/ma_ft_parser.c
index 9c988c41c7b..b35c2227ca2 100644
--- a/storage/maria/ma_ft_parser.c
+++ b/storage/maria/ma_ft_parser.c
@@ -254,7 +254,8 @@ void maria_ft_parse_init(TREE *wtree, CHARSET_INFO *cs)
{
DBUG_ENTER("maria_ft_parse_init");
if (!is_tree_inited(wtree))
- init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL, cs);
+ init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0, NULL,
+ (void*) cs);
DBUG_VOID_RETURN;
}
diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c
index 9cec978166f..838e9814c89 100644
--- a/storage/maria/ma_init.c
+++ b/storage/maria/ma_init.c
@@ -88,6 +88,11 @@ void maria_end(void)
maria_inited= maria_multi_threaded= FALSE;
ft_free_stopwords();
ma_checkpoint_end();
+ if (translog_status == TRANSLOG_OK)
+ {
+ translog_soft_sync_end();
+ translog_sync();
+ }
if ((trid= trnman_get_max_trid()) > max_trid_in_control_file)
{
/*
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index be86740d822..482a4e9071f 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -18,6 +18,7 @@
#include "ma_blockrec.h" /* for some constants and in-write hooks */
#include "ma_key_recover.h" /* For some in-write hooks */
#include "ma_checkpoint.h"
+#include "ma_servicethread.h"
/*
On Windows, neither my_open() nor my_sync() work for directories.
@@ -47,6 +48,15 @@
#include <m_ctype.h>
#endif
+/** @brief protects checkpoint_in_progress */
+static pthread_mutex_t LOCK_soft_sync;
+/** @brief for killing the background checkpoint thread */
+static pthread_cond_t COND_soft_sync;
+/** @brief control structure for checkpoint background thread */
+static MA_SERVICE_THREAD_CONTROL soft_sync_control=
+ {THREAD_DEAD, FALSE, &LOCK_soft_sync, &COND_soft_sync};
+
+
/* transaction log file descriptor */
typedef struct st_translog_file
{
@@ -124,10 +134,24 @@ struct st_translog_buffer
/* Previous buffer offset to detect it flush finish */
TRANSLOG_ADDRESS prev_buffer_offset;
/*
+ If the buffer was forced to close it save value of its horizon
+ otherwise LSN_IMPOSSIBLE
+ */
+ TRANSLOG_ADDRESS pre_force_close_horizon;
+ /*
How much is written (or will be written when copy_to_buffer_in_progress
become 0) to this buffer
*/
translog_size_t size;
+ /*
+ When moving from one log buffer to another, we write the last of the
+ previous buffer to file and then move to start using the new log
+ buffer. In the case of a part filed last page, this page is not moved
+ to the start of the new buffer but instead we set the 'skip_data'
+ variable to tell us how much data at the beginning of the buffer is not
+ relevant.
+ */
+ uint skipped_data;
/* File handler for this buffer */
TRANSLOG_FILE *file;
/* Threads which are waiting for buffer filling/freeing */
@@ -304,6 +328,7 @@ struct st_translog_descriptor
*/
pthread_mutex_t log_flush_lock;
pthread_cond_t log_flush_cond;
+ pthread_cond_t new_goal_cond;
/* Protects changing of headers of finished files (max_lsn) */
pthread_mutex_t file_header_lock;
@@ -344,13 +369,39 @@ static struct st_translog_descriptor log_descriptor;
ulong log_purge_type= TRANSLOG_PURGE_IMMIDIATE;
ulong log_file_size= TRANSLOG_FILE_SIZE;
+/* sync() of log files directory mode */
ulong sync_log_dir= TRANSLOG_SYNC_DIR_NEWFILE;
+ulong maria_group_commit= TRANSLOG_GCOMMIT_NONE;
+ulong maria_group_commit_interval= 0;
/* Marker for end of log */
static uchar end_of_log= 0;
#define END_OF_LOG &end_of_log
+/**
+ Switch for "soft" sync (no real sync() but periodical sync by service
+ thread)
+*/
+static volatile my_bool soft_sync= FALSE;
+/**
+ Switch for "hard" group commit mode
+*/
+static volatile my_bool hard_group_commit= FALSE;
+/**
+ File numbers interval which have to be sync()
+*/
+static uint32 soft_sync_min= 0;
+static uint32 soft_sync_max= 0;
+static uint32 soft_need_sync= 1;
+/**
+ stores interval in microseconds
+*/
+static uint32 group_commit_wait= 0;
enum enum_translog_status translog_status= TRANSLOG_UNINITED;
+ulonglong translog_syncs= 0; /* Number of sync()s */
+
+/* time of last flush */
+static ulonglong flush_start= 0;
/* chunk types */
#define TRANSLOG_CHUNK_LSN 0x00 /* 0 chunk refer as LSN (head or tail */
@@ -980,12 +1031,17 @@ static TRANSLOG_FILE *get_logfile_by_number(uint32 file_no)
static TRANSLOG_FILE *get_current_logfile()
{
TRANSLOG_FILE *file;
+ DBUG_ENTER("get_current_logfile");
rw_rdlock(&log_descriptor.open_files_lock);
+ DBUG_PRINT("info", ("max_file: %lu min_file: %lu open_files: %lu",
+ (ulong) log_descriptor.max_file,
+ (ulong) log_descriptor.min_file,
+ (ulong) log_descriptor.open_files.elements));
DBUG_ASSERT(log_descriptor.max_file - log_descriptor.min_file + 1 ==
log_descriptor.open_files.elements);
file= *dynamic_element(&log_descriptor.open_files, 0, TRANSLOG_FILE **);
rw_unlock(&log_descriptor.open_files_lock);
- return (file);
+ DBUG_RETURN(file);
}
uchar NEAR maria_trans_file_magic[]=
@@ -1069,6 +1125,7 @@ static my_bool translog_write_file_header()
static my_bool translog_max_lsn_to_header(File file, LSN lsn)
{
uchar lsn_buff[LSN_STORE_SIZE];
+ my_bool rc;
DBUG_ENTER("translog_max_lsn_to_header");
DBUG_PRINT("enter", ("File descriptor: %ld "
"lsn: (%lu,0x%lx)",
@@ -1077,11 +1134,17 @@ static my_bool translog_max_lsn_to_header(File file, LSN lsn)
lsn_store(lsn_buff, lsn);
- DBUG_RETURN(my_pwrite(file, lsn_buff,
- LSN_STORE_SIZE,
- (LOG_HEADER_DATA_SIZE - LSN_STORE_SIZE),
- log_write_flags) != 0 ||
- my_sync(file, MYF(MY_WME)) != 0);
+ rc= (my_pwrite(file, lsn_buff,
+ LSN_STORE_SIZE,
+ (LOG_HEADER_DATA_SIZE - LSN_STORE_SIZE),
+ log_write_flags) != 0 ||
+ my_sync(file, MYF(MY_WME)) != 0);
+ /*
+ We should not increase counter in case of error above, but it is so
+ unlikely that we can ignore this case
+ */
+ translog_syncs++;
+ DBUG_RETURN(rc);
}
@@ -1397,7 +1460,7 @@ LSN translog_get_file_max_lsn_stored(uint32 file)
{
LOGHANDLER_FILE_INFO info;
- File fd;
+ File fd;
LINT_INIT_STRUCT(info);
fd= open_logfile_by_number_no_cache(file);
if ((fd < 0) ||
@@ -1428,7 +1491,9 @@ LSN translog_get_file_max_lsn_stored(uint32 file)
static my_bool translog_buffer_init(struct st_translog_buffer *buffer, int num)
{
DBUG_ENTER("translog_buffer_init");
- buffer->prev_last_lsn= buffer->last_lsn= LSN_IMPOSSIBLE;
+ buffer->pre_force_close_horizon=
+ buffer->prev_last_lsn= buffer->last_lsn=
+ LSN_IMPOSSIBLE;
DBUG_PRINT("info", ("last_lsn and prev_last_lsn set to 0 buffer: 0x%lx",
(ulong) buffer));
@@ -1440,6 +1505,7 @@ static my_bool translog_buffer_init(struct st_translog_buffer *buffer, int num)
memset(buffer->buffer, TRANSLOG_FILLER, TRANSLOG_WRITE_BUFFER);
/* Buffer size */
buffer->size= 0;
+ buffer->skipped_data= 0;
/* cond of thread which is waiting for buffer filling */
if (pthread_cond_init(&buffer->waiting_filling_buffer, 0))
DBUG_RETURN(1);
@@ -1494,7 +1560,10 @@ static my_bool translog_close_log_file(TRANSLOG_FILE *file)
TODO: sync only we have changed the log
*/
if (!file->is_sync)
+ {
rc= my_sync(file->handler.file, MYF(MY_WME));
+ translog_syncs++;
+ }
rc|= my_close(file->handler.file, MYF(MY_WME));
my_free(file, MYF(0));
return test(rc);
@@ -2049,7 +2118,8 @@ static void translog_start_buffer(struct st_translog_buffer *buffer,
(ulong) LSN_OFFSET(log_descriptor.horizon),
(ulong) LSN_OFFSET(log_descriptor.horizon)));
DBUG_ASSERT(buffer_no == buffer->buffer_no);
- buffer->prev_last_lsn= buffer->last_lsn= LSN_IMPOSSIBLE;
+ buffer->pre_force_close_horizon=
+ buffer->prev_last_lsn= buffer->last_lsn= LSN_IMPOSSIBLE;
DBUG_PRINT("info", ("last_lsn and prev_last_lsn set to 0 buffer: 0x%lx",
(ulong) buffer));
buffer->offset= log_descriptor.horizon;
@@ -2057,6 +2127,7 @@ static void translog_start_buffer(struct st_translog_buffer *buffer,
buffer->file= get_current_logfile();
buffer->overlay= 0;
buffer->size= 0;
+ buffer->skipped_data= 0;
translog_cursor_init(cursor, buffer, buffer_no);
DBUG_PRINT("info", ("file: #%ld (%d) init cursor #%u: 0x%lx "
"chaser: %d Size: %lu (%lu)",
@@ -2528,6 +2599,7 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
TRANSLOG_ADDRESS offset= buffer->offset;
TRANSLOG_FILE *file= buffer->file;
uint8 ver= buffer->ver;
+ uint skipped_data;
DBUG_ENTER("translog_buffer_flush");
DBUG_PRINT("enter",
("Buffer: #%u 0x%lx file: %d offset: (%lu,0x%lx) size: %lu",
@@ -2562,6 +2634,8 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
disk
*/
file= buffer->file;
+ skipped_data= buffer->skipped_data;
+ DBUG_ASSERT(skipped_data < TRANSLOG_PAGE_SIZE);
for (i= 0, pg= LSN_OFFSET(buffer->offset) / TRANSLOG_PAGE_SIZE;
i < buffer->size;
i+= TRANSLOG_PAGE_SIZE, pg++)
@@ -2578,13 +2652,16 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
DBUG_ASSERT(i + TRANSLOG_PAGE_SIZE <= buffer->size);
if (translog_status != TRANSLOG_OK && translog_status != TRANSLOG_SHUTDOWN)
DBUG_RETURN(1);
- if (pagecache_inject(log_descriptor.pagecache,
+ if (pagecache_write_part(log_descriptor.pagecache,
&file->handler, pg, 3,
buffer->buffer + i,
PAGECACHE_PLAIN_PAGE,
PAGECACHE_LOCK_LEFT_UNLOCKED,
- PAGECACHE_PIN_LEFT_UNPINNED, 0,
- LSN_IMPOSSIBLE))
+ PAGECACHE_PIN_LEFT_UNPINNED,
+ PAGECACHE_WRITE_DONE, 0,
+ LSN_IMPOSSIBLE,
+ skipped_data,
+ TRANSLOG_PAGE_SIZE - skipped_data))
{
DBUG_PRINT("error",
("Can't write page (%lu,0x%lx) to pagecache, error: %d",
@@ -2594,10 +2671,12 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
translog_stop_writing();
DBUG_RETURN(1);
}
+ skipped_data= 0;
}
file->is_sync= 0;
- if (my_pwrite(file->handler.file, buffer->buffer,
- buffer->size, LSN_OFFSET(buffer->offset),
+ if (my_pwrite(file->handler.file, buffer->buffer + buffer->skipped_data,
+ buffer->size - buffer->skipped_data,
+ LSN_OFFSET(buffer->offset) + buffer->skipped_data,
log_write_flags))
{
DBUG_PRINT("error", ("Can't write buffer (%lu,0x%lx) size %lu "
@@ -2990,6 +3069,7 @@ restart:
uchar *from, *table= NULL;
int is_last_unfinished_page;
uint last_protected_sector= 0;
+ uint skipped_data= curr_buffer->skipped_data;
TRANSLOG_FILE file_copy;
uint8 ver= curr_buffer->ver;
translog_wait_for_writers(curr_buffer);
@@ -3002,7 +3082,38 @@ restart:
}
DBUG_ASSERT(LSN_FILE_NO(addr) == LSN_FILE_NO(curr_buffer->offset));
from= curr_buffer->buffer + (addr - curr_buffer->offset);
- memcpy(buffer, from, TRANSLOG_PAGE_SIZE);
+ if (skipped_data && addr == curr_buffer->offset)
+ {
+ /*
+ We read page part of which is not present in buffer,
+ so we should read absent part from file (page cache actually)
+ */
+ file= get_logfile_by_number(file_no);
+ DBUG_ASSERT(file != NULL);
+ /*
+ it's ok to not lock the page because:
+ - The log handler has it's own page cache.
+ - There is only one thread that can access the log
+ cache at a time
+ */
+ if (!(buffer= pagecache_read(log_descriptor.pagecache,
+ &file->handler,
+ LSN_OFFSET(addr) / TRANSLOG_PAGE_SIZE,
+ 3, buffer,
+ PAGECACHE_PLAIN_PAGE,
+ PAGECACHE_LOCK_LEFT_UNLOCKED,
+ NULL)))
+ DBUG_RETURN(NULL);
+ }
+ else
+ skipped_data= 0; /* Read after skipped in buffer data */
+ /*
+ Now we have correct data in buffer up to 'skipped_data'. The
+ following memcpy() will move the data from the internal buffer
+ that was not yet on disk.
+ */
+ memcpy(buffer + skipped_data, from + skipped_data,
+ TRANSLOG_PAGE_SIZE - skipped_data);
/*
We can use copy then in translog_page_validator() because it
do not put it permanently somewhere.
@@ -3296,6 +3407,7 @@ static my_bool translog_truncate_log(TRANSLOG_ADDRESS addr)
uint32 next_page_offset, page_rest;
uint32 i;
File fd;
+ int rc;
TRANSLOG_VALIDATOR_DATA data;
char path[FN_REFLEN];
uchar page_buff[TRANSLOG_PAGE_SIZE];
@@ -3321,14 +3433,19 @@ static my_bool translog_truncate_log(TRANSLOG_ADDRESS addr)
TRANSLOG_PAGE_SIZE);
page_rest= next_page_offset - LSN_OFFSET(addr);
memset(page_buff, TRANSLOG_FILLER, page_rest);
- if ((fd= open_logfile_by_number_no_cache(LSN_FILE_NO(addr))) < 0 ||
- ((my_chsize(fd, next_page_offset, TRANSLOG_FILLER, MYF(MY_WME)) ||
- (page_rest && my_pwrite(fd, page_buff, page_rest, LSN_OFFSET(addr),
- log_write_flags)) ||
- my_sync(fd, MYF(MY_WME))) |
- my_close(fd, MYF(MY_WME))) ||
- (sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS &&
- sync_dir(log_descriptor.directory_fd, MYF(MY_WME | MY_IGNORE_BADFD))))
+ rc= ((fd= open_logfile_by_number_no_cache(LSN_FILE_NO(addr))) < 0 ||
+ ((my_chsize(fd, next_page_offset, TRANSLOG_FILLER, MYF(MY_WME)) ||
+ (page_rest && my_pwrite(fd, page_buff, page_rest, LSN_OFFSET(addr),
+ log_write_flags)) ||
+ my_sync(fd, MYF(MY_WME)))));
+ translog_syncs++;
+ rc|= (fd > 0 && my_close(fd, MYF(MY_WME)));
+ if (sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS)
+ {
+ rc|= sync_dir(log_descriptor.directory_fd, MYF(MY_WME | MY_IGNORE_BADFD));
+ translog_syncs++;
+ }
+ if (rc)
DBUG_RETURN(1);
/* fix the horizon */
@@ -3488,7 +3605,10 @@ my_bool translog_init_with_table(const char *directory,
my_bool version_changed= 0;
DBUG_ENTER("translog_init_with_table");
+ translog_syncs= 0;
+ flush_start= 0;
id_to_share= NULL;
+
log_descriptor.directory_fd= -1;
log_descriptor.is_everything_flushed= 1;
log_descriptor.flush_in_progress= 0;
@@ -3516,6 +3636,7 @@ my_bool translog_init_with_table(const char *directory,
pthread_mutex_init(&log_descriptor.dirty_buffer_mask_lock,
MY_MUTEX_INIT_FAST) ||
pthread_cond_init(&log_descriptor.log_flush_cond, 0) ||
+ pthread_cond_init(&log_descriptor.new_goal_cond, 0) ||
my_rwlock_init(&log_descriptor.open_files_lock,
NULL) ||
my_init_dynamic_array(&log_descriptor.open_files,
@@ -3849,7 +3970,7 @@ my_bool translog_init_with_table(const char *directory,
if (!old_log_was_recovered && old_flags == flags)
{
LOGHANDLER_FILE_INFO info;
- LINT_INIT(info.maria_version);
+ LINT_INIT_STRUCT(info);
/*
Accessing &log_descriptor.open_files without mutex is safe
@@ -3919,7 +4040,6 @@ my_bool translog_init_with_table(const char *directory,
log_descriptor.flushed= log_descriptor.horizon;
log_descriptor.in_buffers_only= log_descriptor.bc.buffer->offset;
log_descriptor.max_lsn= LSN_IMPOSSIBLE; /* set to 0 */
- log_descriptor.previous_flush_horizon= log_descriptor.horizon;
/*
Now 'flushed' is set to 'horizon' value, but 'horizon' is (potentially)
address of the next LSN and we want indicate that all LSNs that are
@@ -4002,6 +4122,10 @@ my_bool translog_init_with_table(const char *directory,
It is beginning of the log => there is no LSNs in the log =>
There is no harm in leaving it "as-is".
*/
+ log_descriptor.previous_flush_horizon= log_descriptor.horizon;
+ DBUG_PRINT("info", ("previous_flush_horizon: (%lu,0x%lx)",
+ LSN_IN_PARTS(log_descriptor.
+ previous_flush_horizon)));
DBUG_RETURN(0);
}
file_no--;
@@ -4077,6 +4201,9 @@ my_bool translog_init_with_table(const char *directory,
translog_free_record_header(&rec);
}
}
+ log_descriptor.previous_flush_horizon= log_descriptor.horizon;
+ DBUG_PRINT("info", ("previous_flush_horizon: (%lu,0x%lx)",
+ LSN_IN_PARTS(log_descriptor.previous_flush_horizon)));
DBUG_RETURN(0);
err:
ma_message_no_user(0, "log initialization failed");
@@ -4164,6 +4291,7 @@ void translog_destroy()
pthread_mutex_destroy(&log_descriptor.log_flush_lock);
pthread_mutex_destroy(&log_descriptor.dirty_buffer_mask_lock);
pthread_cond_destroy(&log_descriptor.log_flush_cond);
+ pthread_cond_destroy(&log_descriptor.new_goal_cond);
rwlock_destroy(&log_descriptor.open_files_lock);
delete_dynamic(&log_descriptor.open_files);
delete_dynamic(&log_descriptor.unfinished_files);
@@ -6892,11 +7020,11 @@ int translog_read_record_header_from_buffer(uchar *page,
{
translog_size_t res;
DBUG_ENTER("translog_read_record_header_from_buffer");
+ DBUG_PRINT("info", ("page byte: 0x%x offset: %u",
+ (uint) page[page_offset], (uint) page_offset));
DBUG_ASSERT(translog_is_LSN_chunk(page[page_offset]));
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
- DBUG_PRINT("info", ("page byte: 0x%x offset: %u",
- (uint) page[page_offset], (uint) page_offset));
buff->type= (page[page_offset] & TRANSLOG_REC_TYPE);
buff->short_trid= uint2korr(page + page_offset + 1);
DBUG_PRINT("info", ("Type %u, Short TrID %u, LSN (%lu,0x%lx)",
@@ -7363,27 +7491,27 @@ static void translog_force_current_buffer_to_finish()
"Buffer addr: (%lu,0x%lx) "
"Page addr: (%lu,0x%lx) "
"size: %lu (%lu) Pg: %u left: %u in progress %u",
- (uint) log_descriptor.bc.buffer_no,
- (ulong) log_descriptor.bc.buffer,
- LSN_IN_PARTS(log_descriptor.bc.buffer->offset),
+ (uint) old_buffer_no,
+ (ulong) old_buffer,
+ LSN_IN_PARTS(old_buffer->offset),
(ulong) LSN_FILE_NO(log_descriptor.horizon),
(ulong) (LSN_OFFSET(log_descriptor.horizon) -
log_descriptor.bc.current_page_fill),
- (ulong) log_descriptor.bc.buffer->size,
+ (ulong) old_buffer->size,
(ulong) (log_descriptor.bc.ptr -log_descriptor.bc.
buffer->buffer),
(uint) log_descriptor.bc.current_page_fill,
(uint) left,
- (uint) log_descriptor.bc.buffer->
+ (uint) old_buffer->
copy_to_buffer_in_progress));
translog_lock_assert_owner();
LINT_INIT(current_page_fill);
- new_buff_beginning= log_descriptor.bc.buffer->offset;
- new_buff_beginning+= log_descriptor.bc.buffer->size; /* increase offset */
+ new_buff_beginning= old_buffer->offset;
+ new_buff_beginning+= old_buffer->size; /* increase offset */
DBUG_ASSERT(log_descriptor.bc.ptr !=NULL);
DBUG_ASSERT(LSN_FILE_NO(log_descriptor.horizon) ==
- LSN_FILE_NO(log_descriptor.bc.buffer->offset));
+ LSN_FILE_NO(old_buffer->offset));
translog_check_cursor(&log_descriptor.bc);
DBUG_ASSERT(left < TRANSLOG_PAGE_SIZE);
if (left)
@@ -7394,18 +7522,20 @@ static void translog_force_current_buffer_to_finish()
*/
DBUG_PRINT("info", ("left: %u", (uint) left));
+ old_buffer->pre_force_close_horizon=
+ old_buffer->offset + old_buffer->size;
/* decrease offset */
new_buff_beginning-= log_descriptor.bc.current_page_fill;
current_page_fill= log_descriptor.bc.current_page_fill;
memset(log_descriptor.bc.ptr, TRANSLOG_FILLER, left);
- log_descriptor.bc.buffer->size+= left;
+ old_buffer->size+= left;
DBUG_PRINT("info", ("Finish Page buffer #%u: 0x%lx "
"Size: %lu",
- (uint) log_descriptor.bc.buffer->buffer_no,
- (ulong) log_descriptor.bc.buffer,
- (ulong) log_descriptor.bc.buffer->size));
- DBUG_ASSERT(log_descriptor.bc.buffer->buffer_no ==
+ (uint) old_buffer->buffer_no,
+ (ulong) old_buffer,
+ (ulong) old_buffer->size));
+ DBUG_ASSERT(old_buffer->buffer_no ==
log_descriptor.bc.buffer_no);
}
else
@@ -7516,11 +7646,21 @@ static void translog_force_current_buffer_to_finish()
if (left)
{
- /*
- TODO: do not copy beginning of the page if we have no CRC or sector
- checks on
- */
- memcpy(new_buffer->buffer, data, current_page_fill);
+ if (log_descriptor.flags &
+ (TRANSLOG_PAGE_CRC | TRANSLOG_SECTOR_PROTECTION))
+ memcpy(new_buffer->buffer, data, current_page_fill);
+ else
+ {
+ /*
+ This page header does not change if we add more data to the page so
+ we can not copy it and will not overwrite later
+ */
+ new_buffer->skipped_data= current_page_fill;
+#ifndef DBUG_OFF
+ memset(new_buffer->buffer, 0xa5, current_page_fill);
+#endif
+ DBUG_ASSERT(new_buffer->skipped_data < TRANSLOG_PAGE_SIZE);
+ }
}
old_buffer->next_buffer_offset= new_buffer->offset;
translog_buffer_lock(new_buffer);
@@ -7568,6 +7708,7 @@ void translog_flush_set_new_goal_and_wait(TRANSLOG_ADDRESS lsn)
{
log_descriptor.next_pass_max_lsn= lsn;
log_descriptor.max_lsn_requester= pthread_self();
+ pthread_cond_broadcast(&log_descriptor.new_goal_cond);
}
while (flush_no == log_descriptor.flush_no)
{
@@ -7579,67 +7720,79 @@ void translog_flush_set_new_goal_and_wait(TRANSLOG_ADDRESS lsn)
/**
- @brief Flush the log up to given LSN (included)
+ @brief sync() range of files (inclusive) and directory (by request)
- @param lsn log record serial number up to which (inclusive)
- the log has to be flushed
+ @param min min internal file number to flush
+ @param max max internal file number to flush
+ @param sync_dir need sync directory
- @return Operation status
+ return Operation status
@retval 0 OK
@retval 1 Error
-
*/
-my_bool translog_flush(TRANSLOG_ADDRESS lsn)
+static my_bool translog_sync_files(uint32 min, uint32 max,
+ my_bool sync_dir)
{
- LSN sent_to_disk= LSN_IMPOSSIBLE;
- TRANSLOG_ADDRESS flush_horizon;
- uint fn, i;
- dirty_buffer_mask_t dirty_buffer_mask;
- uint8 last_buffer_no, start_buffer_no;
+ uint fn;
my_bool rc= 0;
- DBUG_ENTER("translog_flush");
- DBUG_PRINT("enter", ("Flush up to LSN: (%lu,0x%lx)", LSN_IN_PARTS(lsn)));
- DBUG_ASSERT(translog_status == TRANSLOG_OK ||
- translog_status == TRANSLOG_READONLY);
- LINT_INIT(sent_to_disk);
+ ulonglong flush_interval;
+ DBUG_ENTER("translog_sync_files");
+ DBUG_PRINT("info", ("min: %lu max: %lu sync dir: %d",
+ (ulong) min, (ulong) max, (int) sync_dir));
+ DBUG_ASSERT(min <= max);
- pthread_mutex_lock(&log_descriptor.log_flush_lock);
- DBUG_PRINT("info", ("Everything is flushed up to (%lu,0x%lx)",
- LSN_IN_PARTS(log_descriptor.flushed)));
- if (cmp_translog_addr(log_descriptor.flushed, lsn) >= 0)
+ flush_interval= group_commit_wait;
+ if (flush_interval)
+ flush_start= my_micro_time();
+ for (fn= min; fn <= max; fn++)
{
- pthread_mutex_unlock(&log_descriptor.log_flush_lock);
- DBUG_RETURN(0);
- }
- if (log_descriptor.flush_in_progress)
- {
- translog_flush_set_new_goal_and_wait(lsn);
- if (!pthread_equal(log_descriptor.max_lsn_requester, pthread_self()))
+ TRANSLOG_FILE *file= get_logfile_by_number(fn);
+ DBUG_ASSERT(file != NULL);
+ if (!file->is_sync)
{
- /* fix lsn if it was horizon */
- if (cmp_translog_addr(lsn, log_descriptor.bc.buffer->last_lsn) > 0)
- lsn= BUFFER_MAX_LSN(log_descriptor.bc.buffer);
- translog_flush_wait_for_end(lsn);
- pthread_mutex_unlock(&log_descriptor.log_flush_lock);
- DBUG_RETURN(0);
+ if (my_sync(file->handler.file, MYF(MY_WME)))
+ {
+ rc= 1;
+ translog_stop_writing();
+ DBUG_RETURN(rc);
+ }
+ translog_syncs++;
+ file->is_sync= 1;
}
- log_descriptor.next_pass_max_lsn= LSN_IMPOSSIBLE;
}
- log_descriptor.flush_in_progress= 1;
- flush_horizon= log_descriptor.previous_flush_horizon;
- DBUG_PRINT("info", ("flush_in_progress is set"));
- pthread_mutex_unlock(&log_descriptor.log_flush_lock);
- translog_lock();
- if (log_descriptor.is_everything_flushed)
+ if (sync_dir)
{
- DBUG_PRINT("info", ("everything is flushed"));
- rc= (translog_status == TRANSLOG_READONLY);
- translog_unlock();
- goto out;
+ if (!(rc= sync_dir(log_descriptor.directory_fd,
+ MYF(MY_WME | MY_IGNORE_BADFD))))
+ translog_syncs++;
}
+ DBUG_RETURN(rc);
+}
+
+
+/*
+ @brief Flushes buffers with LSNs in them less or equal address <lsn>
+
+ @param lsn address up to which all LSNs should be flushed,
+ can be reset to real last LSN address
+ @parem sent_to_disk returns 'sent to disk' position
+ @param flush_horizon returns horizon of the flush
+
+ @note About terminology see comment to translog_flush().
+*/
+
+void translog_flush_buffers(TRANSLOG_ADDRESS *lsn,
+ TRANSLOG_ADDRESS *sent_to_disk,
+ TRANSLOG_ADDRESS *flush_horizon)
+{
+ dirty_buffer_mask_t dirty_buffer_mask;
+ uint i;
+ uint8 last_buffer_no, start_buffer_no;
+ DBUG_ENTER("translog_flush_buffers");
+
/*
We will recheck information when will lock buffers one by
one so we can use unprotected read here (this is just for
@@ -7663,15 +7816,15 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn)
/*
if LSN up to which we have to flush bigger then maximum LSN of previous
buffer and at least one LSN was saved in the current buffer (last_lsn !=
- LSN_IMPOSSIBLE) then we better finish the current buffer.
+ LSN_IMPOSSIBLE) then we have to close the current buffer.
*/
- if (cmp_translog_addr(lsn, log_descriptor.bc.buffer->prev_last_lsn) > 0 &&
+ if (cmp_translog_addr(*lsn, log_descriptor.bc.buffer->prev_last_lsn) > 0 &&
log_descriptor.bc.buffer->last_lsn != LSN_IMPOSSIBLE)
{
struct st_translog_buffer *buffer= log_descriptor.bc.buffer;
- lsn= log_descriptor.bc.buffer->last_lsn; /* fix lsn if it was horizon */
+ *lsn= log_descriptor.bc.buffer->last_lsn; /* fix lsn if it was horizon */
DBUG_PRINT("info", ("LSN to flush fixed to last lsn: (%lu,0x%lx)",
- LSN_IN_PARTS(log_descriptor.bc.buffer->last_lsn)));
+ LSN_IN_PARTS(log_descriptor.bc.buffer->last_lsn)));
last_buffer_no= log_descriptor.bc.buffer_no;
log_descriptor.is_everything_flushed= 1;
translog_force_current_buffer_to_finish();
@@ -7683,8 +7836,10 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn)
TRANSLOG_BUFFERS_NO);
translog_unlock();
}
- sent_to_disk= translog_get_sent_to_disk();
- if (cmp_translog_addr(lsn, sent_to_disk) > 0)
+
+ /* flush buffers */
+ *sent_to_disk= translog_get_sent_to_disk();
+ if (cmp_translog_addr(*lsn, *sent_to_disk) > 0)
{
DBUG_PRINT("info", ("Start buffer #: %u last buffer #: %u",
@@ -7704,53 +7859,235 @@ my_bool translog_flush(TRANSLOG_ADDRESS lsn)
LSN_IN_PARTS(buffer->last_lsn),
(buffer->file ?
"dirty" : "closed")));
- if (buffer->prev_last_lsn <= lsn &&
+ if (buffer->prev_last_lsn <= *lsn &&
buffer->file != NULL)
{
- DBUG_ASSERT(flush_horizon <= buffer->offset + buffer->size);
- flush_horizon= buffer->offset + buffer->size;
+ DBUG_ASSERT(*flush_horizon <= buffer->offset + buffer->size);
+ *flush_horizon= (buffer->pre_force_close_horizon != LSN_IMPOSSIBLE ?
+ buffer->pre_force_close_horizon :
+ buffer->offset + buffer->size);
+ /* pre_force_close_horizon is reset during new buffer start */
+ DBUG_PRINT("info", ("flush_horizon: (%lu,0x%lx)",
+ LSN_IN_PARTS(*flush_horizon)));
+ DBUG_ASSERT(*flush_horizon <= log_descriptor.horizon);
+
translog_buffer_flush(buffer);
}
translog_buffer_unlock(buffer);
i= (i + 1) % TRANSLOG_BUFFERS_NO;
} while (i != last_buffer_no);
- sent_to_disk= translog_get_sent_to_disk();
+ *sent_to_disk= translog_get_sent_to_disk();
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+/**
+ @brief Flush the log up to given LSN (included)
+
+ @param lsn log record serial number up to which (inclusive)
+ the log has to be flushed
+
+ @return Operation status
+ @retval 0 OK
+ @retval 1 Error
+
+ @note
+
+ - Non group commit logic: Commits made in passes. Thread which started
+ flush first is performing actual flush, other threads sets new goal (LSN)
+ of the next pass (if it is maximum) and waits for the pass end or just
+ wait for the pass end.
+
+ - If hard group commit enabled and rate set to zero:
+ The first thread sends all changed buffers to disk. This is repeated
+ as long as there are new LSNs added. The process can not loop
+ forever because we have limited number of threads and they will wait
+ for the data to be synced.
+ Pseudo code:
+
+ do
+ send changed buffers to disk
+ while new_goal
+ sync
+
+ - If hard group commit switched ON and less than rate microseconds has
+ passed from last sync, then after buffers have been sent to disk
+ wait until rate microseconds has passed since last sync, do sync and return.
+ This ensures that if we call sync infrequently we don't do any waits.
+
+ - If soft group commit enabled everything works as with 'non group commit'
+ but the thread doesn't do any real sync(). If rate is not zero the
+ sync() will be performed by a service thread with the given rate
+ when needed (new LSN appears).
+
+ @note Terminology:
+ 'sent to disk' means written to disk but not sync()ed,
+ 'flushed' mean sent to disk and synced().
+*/
+
+my_bool translog_flush(TRANSLOG_ADDRESS lsn)
+{
+ struct timespec abstime;
+ ulonglong flush_interval;
+ ulonglong time_spent;
+ LSN sent_to_disk= LSN_IMPOSSIBLE;
+ TRANSLOG_ADDRESS flush_horizon;
+ my_bool rc= 0;
+ my_bool hgroup_commit_at_start;
+ DBUG_ENTER("translog_flush");
+ DBUG_PRINT("enter", ("Flush up to LSN: (%lu,0x%lx)", LSN_IN_PARTS(lsn)));
+ DBUG_ASSERT(translog_status == TRANSLOG_OK ||
+ translog_status == TRANSLOG_READONLY);
+ LINT_INIT(sent_to_disk);
+ LINT_INIT(flush_interval);
+
+ pthread_mutex_lock(&log_descriptor.log_flush_lock);
+ DBUG_PRINT("info", ("Everything is flushed up to (%lu,0x%lx)",
+ LSN_IN_PARTS(log_descriptor.flushed)));
+ if (cmp_translog_addr(log_descriptor.flushed, lsn) >= 0)
+ {
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
+ DBUG_RETURN(0);
+ }
+ if (log_descriptor.flush_in_progress)
+ {
+ translog_lock();
+ /* fix lsn if it was horizon */
+ if (cmp_translog_addr(lsn, log_descriptor.bc.buffer->last_lsn) > 0)
+ lsn= BUFFER_MAX_LSN(log_descriptor.bc.buffer);
+ translog_unlock();
+ translog_flush_set_new_goal_and_wait(lsn);
+ if (!pthread_equal(log_descriptor.max_lsn_requester, pthread_self()))
+ {
+ /*
+ translog_flush_wait_for_end() release log_flush_lock while is
+ waiting then acquire it again
+ */
+ translog_flush_wait_for_end(lsn);
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
+ DBUG_RETURN(0);
+ }
+ log_descriptor.next_pass_max_lsn= LSN_IMPOSSIBLE;
}
+ log_descriptor.flush_in_progress= 1;
+ flush_horizon= log_descriptor.previous_flush_horizon;
+ DBUG_PRINT("info", ("flush_in_progress is set, flush_horizon: (%lu,0x%lx)",
+ LSN_IN_PARTS(flush_horizon)));
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
+
+ hgroup_commit_at_start= hard_group_commit;
+ if (hgroup_commit_at_start)
+ flush_interval= group_commit_wait;
- /* sync files from previous flush till current one */
- for (fn= LSN_FILE_NO(log_descriptor.flushed); fn <= LSN_FILE_NO(lsn); fn++)
+ translog_lock();
+ if (log_descriptor.is_everything_flushed)
{
- TRANSLOG_FILE *file= get_logfile_by_number(fn);
- DBUG_ASSERT(file != NULL);
- if (!file->is_sync)
+ DBUG_PRINT("info", ("everything is flushed"));
+ translog_unlock();
+ pthread_mutex_lock(&log_descriptor.log_flush_lock);
+ goto out;
+ }
+
+ for (;;)
+ {
+ /* Following function flushes buffers and makes translog_unlock() */
+ translog_flush_buffers(&lsn, &sent_to_disk, &flush_horizon);
+
+ if (!hgroup_commit_at_start)
+ break; /* flush pass is ended */
+
+retest:
+ /*
+ We do not check time here because pthread_mutex_lock rarely takes
+ a lot of time so we can sacrifice a bit precision to performance
+ (taking into account that my_micro_time() might be expensive call).
+ */
+ if (flush_interval == 0)
+ break; /* flush pass is ended */
+
+ pthread_mutex_lock(&log_descriptor.log_flush_lock);
+ if (log_descriptor.next_pass_max_lsn == LSN_IMPOSSIBLE)
{
- if (my_sync(file->handler.file, MYF(MY_WME)))
+ if (flush_interval == 0 ||
+ (time_spent= (my_micro_time() - flush_start)) >= flush_interval)
{
- rc= 1;
- translog_stop_writing();
- sent_to_disk= LSN_IMPOSSIBLE;
- goto out;
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
+ break;
}
- file->is_sync= 1;
+ DBUG_PRINT("info", ("flush waits: %llu interval: %llu spent: %llu",
+ flush_interval - time_spent,
+ flush_interval, time_spent));
+ /* wait time or next goal */
+ set_timespec_nsec(abstime, flush_interval - time_spent);
+ pthread_cond_timedwait(&log_descriptor.new_goal_cond,
+ &log_descriptor.log_flush_lock,
+ &abstime);
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
+ DBUG_PRINT("info", ("retest conditions"));
+ goto retest;
+ }
+
+ /* take next goal */
+ lsn= log_descriptor.next_pass_max_lsn;
+ log_descriptor.next_pass_max_lsn= LSN_IMPOSSIBLE;
+ /* prevent other thread from continue */
+ log_descriptor.max_lsn_requester= pthread_self();
+ DBUG_PRINT("info", ("flush took next goal: (%lu,0x%lx)",
+ LSN_IN_PARTS(lsn)));
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
+
+ /* next flush pass */
+ DBUG_PRINT("info", ("next flush pass"));
+ translog_lock();
+ }
+
+ /*
+ sync() files from previous flush till current one
+ */
+ if (!soft_sync || hgroup_commit_at_start)
+ {
+ if ((rc=
+ translog_sync_files(LSN_FILE_NO(log_descriptor.flushed),
+ LSN_FILE_NO(lsn),
+ sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS &&
+ (LSN_FILE_NO(log_descriptor.
+ previous_flush_horizon) !=
+ LSN_FILE_NO(flush_horizon) ||
+ (LSN_OFFSET(log_descriptor.
+ previous_flush_horizon) /
+ TRANSLOG_PAGE_SIZE) !=
+ (LSN_OFFSET(flush_horizon) /
+ TRANSLOG_PAGE_SIZE)))))
+ {
+ sent_to_disk= LSN_IMPOSSIBLE;
+ pthread_mutex_lock(&log_descriptor.log_flush_lock);
+ goto out;
+ }
+ /* keep values for soft sync() and forced sync() actual */
+ {
+ uint32 fileno= LSN_FILE_NO(lsn);
+ soft_sync_min= fileno;
+ soft_sync_max= fileno;
}
}
+ else
+ {
+ soft_sync_max= lsn;
+ soft_need_sync= 1;
+ }
- if (sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS &&
- (LSN_FILE_NO(log_descriptor.previous_flush_horizon) !=
- LSN_FILE_NO(flush_horizon) ||
- ((LSN_OFFSET(log_descriptor.previous_flush_horizon) - 1) /
- TRANSLOG_PAGE_SIZE) !=
- ((LSN_OFFSET(flush_horizon) - 1) / TRANSLOG_PAGE_SIZE)))
- rc|= sync_dir(log_descriptor.directory_fd, MYF(MY_WME | MY_IGNORE_BADFD));
+ DBUG_ASSERT(flush_horizon <= log_descriptor.horizon);
+
+ pthread_mutex_lock(&log_descriptor.log_flush_lock);
log_descriptor.previous_flush_horizon= flush_horizon;
out:
- pthread_mutex_lock(&log_descriptor.log_flush_lock);
if (sent_to_disk != LSN_IMPOSSIBLE)
log_descriptor.flushed= sent_to_disk;
log_descriptor.flush_in_progress= 0;
log_descriptor.flush_no++;
DBUG_PRINT("info", ("flush_in_progress is dropped"));
- pthread_mutex_unlock(&log_descriptor.log_flush_lock);\
+ pthread_mutex_unlock(&log_descriptor.log_flush_lock);
pthread_cond_broadcast(&log_descriptor.log_flush_cond);
DBUG_RETURN(rc);
}
@@ -8120,6 +8457,8 @@ LSN translog_first_theoretical_lsn()
my_bool translog_purge(TRANSLOG_ADDRESS low)
{
uint32 last_need_file= LSN_FILE_NO(low);
+ uint32 min_unsync;
+ int soft;
TRANSLOG_ADDRESS horizon= translog_get_horizon();
int rc= 0;
DBUG_ENTER("translog_purge");
@@ -8127,12 +8466,24 @@ my_bool translog_purge(TRANSLOG_ADDRESS low)
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
+ soft= soft_sync;
+ min_unsync= soft_sync_min;
+ DBUG_PRINT("info", ("min_unsync: %lu", (ulong) min_unsync));
+ if (soft && min_unsync < last_need_file)
+ {
+ last_need_file= min_unsync;
+ DBUG_PRINT("info", ("last_need_file set to %lu", (ulong)last_need_file));
+ }
+
pthread_mutex_lock(&log_descriptor.purger_lock);
+ DBUG_PRINT("info", ("last_lsn_checked file: %lu:",
+ (ulong) log_descriptor.last_lsn_checked));
if (LSN_FILE_NO(log_descriptor.last_lsn_checked) < last_need_file)
{
uint32 i;
uint32 min_file= translog_first_file(horizon, 1);
DBUG_ASSERT(min_file != 0); /* log is already started */
+ DBUG_PRINT("info", ("min_file: %lu:",(ulong) min_file));
for(i= min_file; i < last_need_file && rc == 0; i++)
{
LSN lsn= translog_get_file_max_lsn_stored(i);
@@ -8363,6 +8714,153 @@ my_bool translog_log_debug_info(TRN *trn __attribute__((unused)),
}
+
+/**
+ Sets soft sync mode
+
+ @param mode TRUE if we need switch soft sync on else off
+*/
+
+void translog_soft_sync(my_bool mode)
+{
+ soft_sync= mode;
+}
+
+
+/**
+ Sets hard group commit
+
+ @param mode TRUE if we need switch hard group commit on else off
+*/
+
+void translog_hard_group_commit(my_bool mode)
+{
+ hard_group_commit= mode;
+}
+
+
+/**
+ @brief forced log sync (used when we are switching modes)
+*/
+
+void translog_sync()
+{
+ uint32 max= get_current_logfile()->number;
+ uint32 min;
+ DBUG_ENTER("ma_translog_sync");
+
+ min= soft_sync_min;
+ if (!min)
+ min= max;
+
+ translog_sync_files(min, max, sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief set rate for group commit
+
+ @param interval interval to set.
+
+ @note We use this function with additional variable because have to
+ restart service thread with new value which we can't make inside changing
+ variable routine (update_maria_group_commit_interval)
+*/
+
+void translog_set_group_commit_interval(uint32 interval)
+{
+ DBUG_ENTER("translog_set_group_commit_interval");
+ group_commit_wait= interval;
+ DBUG_PRINT("info", ("wait: %llu",
+ (ulonglong)group_commit_wait));
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief syncing service thread
+*/
+
+static pthread_handler_t
+ma_soft_sync_background( void *arg __attribute__((unused)))
+{
+
+ my_thread_init();
+ {
+ DBUG_ENTER("ma_soft_sync_background");
+ for(;;)
+ {
+ ulonglong prev_loop= my_micro_time();
+ ulonglong time, sleep;
+ uint32 min, max, sync_request;
+ min= soft_sync_min;
+ max= soft_sync_max;
+ sync_request= soft_need_sync;
+ soft_sync_min= max;
+ soft_need_sync= 0;
+
+ sleep= group_commit_wait;
+ if (sync_request)
+ translog_sync_files(min, max, FALSE);
+ time= my_micro_time() - prev_loop;
+ if (time > sleep)
+ sleep= 0;
+ else
+ sleep-= time;
+ if (my_service_thread_sleep(&soft_sync_control, sleep))
+ break;
+ }
+ my_service_thread_signal_end(&soft_sync_control);
+ my_thread_end();
+ DBUG_RETURN(0);
+ }
+}
+
+
+/**
+ @brief Starts syncing thread
+*/
+
+int translog_soft_sync_start(void)
+{
+ pthread_t th;
+ int res= 0;
+ uint32 min, max;
+ DBUG_ENTER("translog_soft_sync_start");
+
+ /* check and init variables */
+ min= soft_sync_min;
+ max= soft_sync_max;
+ if (!max)
+ soft_sync_max= max= get_current_logfile()->number;
+ if (!min)
+ soft_sync_min= max;
+ soft_need_sync= 1;
+
+ if (!(res= ma_service_thread_control_init(&soft_sync_control)))
+ if (!(res= pthread_create(&th, NULL, ma_soft_sync_background, NULL)))
+ soft_sync_control.status= THREAD_RUNNING;
+ DBUG_RETURN(res);
+}
+
+
+/**
+ @brief Stops syncing thread
+*/
+
+void translog_soft_sync_end(void)
+{
+ DBUG_ENTER("translog_soft_sync_end");
+ if (soft_sync_control.inited)
+ {
+ ma_service_thread_control_end(&soft_sync_control);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
#ifdef MARIA_DUMP_LOG
#include <my_getopt.h>
extern void translog_example_table_init();
@@ -8482,6 +8980,7 @@ static void dump_header_page(uchar *buff)
{
LOGHANDLER_FILE_INFO desc;
char strbuff[21];
+ LINT_INIT_STRUCT(desc);
translog_interpret_file_header(&desc, buff);
printf(" This can be header page:\n"
" Timestamp: %s\n"
diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h
index dba6283e303..224d93fb24b 100644
--- a/storage/maria/ma_loghandler.h
+++ b/storage/maria/ma_loghandler.h
@@ -342,6 +342,14 @@ enum enum_translog_status
TRANSLOG_SHUTDOWN /* going to shutdown the loghandler */
};
extern enum enum_translog_status translog_status;
+extern ulonglong translog_syncs; /* Number of sync()s */
+
+void translog_soft_sync(my_bool mode);
+void translog_hard_group_commit(my_bool mode);
+int translog_soft_sync_start(void);
+void translog_soft_sync_end(void);
+void translog_sync();
+void translog_set_group_commit_interval(uint32 interval);
/*
all the rest added because of recovery; should we make
@@ -441,6 +449,14 @@ extern LOG_DESC log_record_type_descriptor[LOGREC_NUMBER_OF_TYPES];
typedef enum
{
+ TRANSLOG_GCOMMIT_NONE,
+ TRANSLOG_GCOMMIT_HARD,
+ TRANSLOG_GCOMMIT_SOFT
+} enum_maria_group_commit;
+extern ulong maria_group_commit;
+extern ulong maria_group_commit_interval;
+typedef enum
+{
TRANSLOG_PURGE_IMMIDIATE,
TRANSLOG_PURGE_EXTERNAL,
TRANSLOG_PURGE_ONDEMAND
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index a5b9bf18aa9..9d8113cb049 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -428,7 +428,7 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
uint length_pack;
MARIA_KEYDEF *keyinfo= key->keyinfo;
MARIA_SHARE *share= keyinfo->share;
- uchar *sort_order= keyinfo->seg->charset->sort_order;
+ const uchar *sort_order= keyinfo->seg->charset->sort_order;
DBUG_ENTER("_ma_prefix_search");
LINT_INIT(length);
@@ -1922,7 +1922,7 @@ _ma_calc_var_pack_key_length(const MARIA_KEY *int_key, uint nod_flag,
uint key_length,ref_length,org_key_length=0,
length_pack,new_key_length,diff_flag,pack_marker;
const uchar *key, *start, *end, *key_end;
- uchar *sort_order;
+ const uchar *sort_order;
my_bool same_length;
MARIA_KEYDEF *keyinfo= int_key->keyinfo;
diff --git a/storage/maria/ma_servicethread.c b/storage/maria/ma_servicethread.c
new file mode 100644
index 00000000000..a8099c998e9
--- /dev/null
+++ b/storage/maria/ma_servicethread.c
@@ -0,0 +1,134 @@
+#include "maria_def.h"
+#include "ma_servicethread.h"
+
+/**
+ Initializes the service thread
+
+ @param control control block
+
+ @return Operation status
+ @retval 0 OK
+ @retval 1 error
+*/
+
+int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control)
+{
+ int res= 0;
+ DBUG_ENTER("ma_service_thread_control_init");
+ DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+ control->inited= TRUE;
+ control->status= THREAD_DEAD; /* not yet born == dead */
+ res= (pthread_mutex_init(control->LOCK_control, MY_MUTEX_INIT_SLOW) ||
+ pthread_cond_init(control->COND_control, 0));
+ DBUG_PRINT("info", ("init: %s", (res ? "Error" : "OK")));
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Kill the service thread
+
+ @param control control block
+
+ @note The service thread should react on condition and status equal
+ THREAD_DYING, by setting status THREAD_DEAD, and issuing message to
+ control thread via condition and exiting. The base way to do so is using
+ my_service_thread_sleep() and my_service_thread_signal_end()
+*/
+
+void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control)
+{
+ DBUG_ENTER("ma_service_thread_control_end");
+ DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+ DBUG_ASSERT(control->inited);
+ pthread_mutex_lock(control->LOCK_control);
+ if (control->status != THREAD_DEAD) /* thread was started OK */
+ {
+ DBUG_PRINT("info",("killing Maria background thread"));
+ control->status= THREAD_DYING; /* kill it */
+ do /* and wait for it to be dead */
+ {
+ /* wake it up if it was in a sleep */
+ pthread_cond_broadcast(control->COND_control);
+ DBUG_PRINT("info",("waiting for Maria background thread to die"));
+ pthread_cond_wait(control->COND_control, control->LOCK_control);
+ }
+ while (control->status != THREAD_DEAD);
+ }
+ pthread_mutex_unlock(control->LOCK_control);
+ pthread_mutex_destroy(control->LOCK_control);
+ pthread_cond_destroy(control->COND_control);
+ control->inited= FALSE;
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ Sleep for given number of nanoseconds with reaction on thread kill
+
+ @param control control block
+ @param sleep_time time of sleeping
+
+ @return Operation status
+ @retval FALSE Time out
+ @retval TRUE Thread should be killed
+*/
+
+my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
+ ulonglong sleep_time)
+{
+ struct timespec abstime;
+ my_bool res= FALSE;
+ DBUG_ENTER("my_service_thread_sleep");
+ DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+ pthread_mutex_lock(control->LOCK_control);
+ if (control->status == THREAD_DYING)
+ {
+ pthread_mutex_unlock(control->LOCK_control);
+ DBUG_RETURN(TRUE);
+ }
+#if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */
+ pthread_mutex_unlock(&control->LOCK_control);
+ my_sleep(100000); /* a tenth of a second */
+ pthread_mutex_lock(&control->LOCK_control);
+#else
+ /* To have a killable sleep, we use timedwait like our SQL GET_LOCK() */
+ DBUG_PRINT("info", ("sleeping %llu nano seconds", sleep_time));
+ if (sleep_time)
+ {
+ set_timespec_nsec(abstime, sleep_time);
+ pthread_cond_timedwait(control->COND_control,
+ control->LOCK_control, &abstime);
+ }
+#endif
+ if (control->status == THREAD_DYING)
+ res= TRUE;
+ pthread_mutex_unlock(control->LOCK_control);
+ DBUG_RETURN(res);
+}
+
+
+/**
+ inform about thread exiting
+
+ @param control control block
+*/
+
+void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control)
+{
+ DBUG_ENTER("my_service_thread_signal_end");
+ DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+ pthread_mutex_lock(control->LOCK_control);
+ control->status = THREAD_DEAD; /* indicate that we are dead */
+ /*
+ wake up ma_service_thread_control_end which may be waiting for
+ our death
+ */
+ pthread_cond_broadcast(control->COND_control);
+ /*
+ broadcast was inside unlock because ma_service_thread_control_end
+ destroys mutex
+ */
+ pthread_mutex_unlock(control->LOCK_control);
+ DBUG_VOID_RETURN;
+}
diff --git a/storage/maria/ma_servicethread.h b/storage/maria/ma_servicethread.h
new file mode 100644
index 00000000000..153ff9ebd14
--- /dev/null
+++ b/storage/maria/ma_servicethread.h
@@ -0,0 +1,22 @@
+#include <my_pthread.h>
+
+enum ma_service_thread_state {THREAD_RUNNING, THREAD_DYING, THREAD_DEAD};
+
+typedef struct st_ma_service_thread_control
+{
+ /** 'kill' flag for the background thread */
+ enum ma_service_thread_state status;
+ /** if thread module was inited or not */
+ my_bool inited;
+ /** for killing the background thread */
+ pthread_mutex_t *LOCK_control;
+ /** for killing the background thread */
+ pthread_cond_t *COND_control;
+} MA_SERVICE_THREAD_CONTROL;
+
+
+int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control);
+void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control);
+my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
+ ulonglong sleep_time);
+void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control);
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 8846a5c3c1a..3a6368f338d 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -602,7 +602,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, uchar *query,
sizeof(FTB_WORD *)*ftb->queue.elements);
memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements);
my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *),
- (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset);
+ (qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset);
if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC;
ftb->state=READY;
return ftb;
diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c
index 3c3efbf0906..0609157f1a0 100644
--- a/storage/myisam/ft_parser.c
+++ b/storage/myisam/ft_parser.c
@@ -252,7 +252,8 @@ void ft_parse_init(TREE *wtree, CHARSET_INFO *cs)
{
DBUG_ENTER("ft_parse_init");
if (!is_tree_inited(wtree))
- init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL, cs);
+ init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL,
+ (void*) cs);
DBUG_VOID_RETURN;
}
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 5f807be2374..748c65f334b 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -260,7 +260,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
record= table_arg->record[0];
recpos= 0;
recinfo_pos= recinfo;
- while (recpos < (uint) share->reclength)
+ while (recpos < (uint) share->stored_rec_length)
{
Field **field, *found= 0;
minpos= share->reclength;
@@ -776,8 +776,6 @@ int ha_myisam::close(void)
int ha_myisam::write_row(uchar *buf)
{
- ha_statistic_increment(&SSV::ha_write_count);
-
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
@@ -1663,7 +1661,6 @@ bool ha_myisam::is_crashed() const
int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
{
- ha_statistic_increment(&SSV::ha_update_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return mi_update(file,old_data,new_data);
@@ -1671,7 +1668,6 @@ int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
int ha_myisam::delete_row(const uchar *buf)
{
- ha_statistic_increment(&SSV::ha_delete_count);
return mi_delete(file,buf);
}
@@ -1679,84 +1675,48 @@ int ha_myisam::index_read_map(uchar *buf, const uchar *key,
key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_key_count);
- int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
}
int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
- ha_statistic_increment(&SSV::ha_read_key_count);
- int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
-}
-
-int ha_myisam::index_read_last_map(uchar *buf, const uchar *key,
- key_part_map keypart_map)
-{
- DBUG_ENTER("ha_myisam::index_read_last");
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_key_count);
- int error=mi_rkey(file, buf, active_index, key, keypart_map,
- HA_READ_PREFIX_LAST);
- table->status=error ? STATUS_NOT_FOUND: 0;
- DBUG_RETURN(error);
+ return mi_rkey(file, buf, index, key, keypart_map, find_flag);
}
int ha_myisam::index_next(uchar *buf)
{
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_next_count);
- int error=mi_rnext(file,buf,active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_rnext(file,buf,active_index);
}
int ha_myisam::index_prev(uchar *buf)
{
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_prev_count);
- int error=mi_rprev(file,buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_rprev(file,buf, active_index);
}
int ha_myisam::index_first(uchar *buf)
{
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_first_count);
- int error=mi_rfirst(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_rfirst(file, buf, active_index);
}
int ha_myisam::index_last(uchar *buf)
{
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_last_count);
- int error=mi_rlast(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_rlast(file, buf, active_index);
}
int ha_myisam::index_next_same(uchar *buf,
const uchar *key __attribute__((unused)),
uint length __attribute__((unused)))
{
+ DBUG_ENTER("ha_myisam::index_next_same");
int error;
- DBUG_ASSERT(inited==INDEX);
- ha_statistic_increment(&SSV::ha_read_next_count);
do
{
error= mi_rnext_same(file,buf);
} while (error == HA_ERR_RECORD_DELETED);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ DBUG_PRINT("return",("%i", error));
+ DBUG_RETURN(error);
}
@@ -1769,10 +1729,7 @@ int ha_myisam::rnd_init(bool scan)
int ha_myisam::rnd_next(uchar *buf)
{
- ha_statistic_increment(&SSV::ha_read_rnd_next_count);
- int error=mi_scan(file, buf);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_scan(file, buf);
}
int ha_myisam::remember_rnd_pos()
@@ -1788,10 +1745,7 @@ int ha_myisam::restart_rnd_next(uchar *buf)
int ha_myisam::rnd_pos(uchar *buf, uchar *pos)
{
- ha_statistic_increment(&SSV::ha_read_rnd_count);
- int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
- table->status=error ? STATUS_NOT_FOUND: 0;
- return error;
+ return mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
}
void ha_myisam::position(const uchar *record)
@@ -2092,8 +2046,6 @@ int ha_myisam::ft_read(uchar *buf)
&LOCK_status); // why ?
error=ft_handler->please->read_next(ft_handler,(char*) buf);
-
- table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -2182,6 +2134,23 @@ mysql_declare_plugin(myisam)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_storage_engine,
+ "MyISAM",
+ "MySQL AB",
+ "Default engine as of MySQL 3.23 with great performance",
+ PLUGIN_LICENSE_GPL,
+ myisam_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
#ifdef HAVE_QUERY_CACHE
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index b7d15a6e8b7..9d8791c7eff 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -71,7 +71,6 @@ class ha_myisam: public handler
int index_read_idx_map(uchar *buf, uint index, const uchar *key,
key_part_map keypart_map,
enum ha_rkey_function find_flag);
- int index_read_last_map(uchar *buf, const uchar *key, key_part_map keypart_map);
int index_next(uchar * buf);
int index_prev(uchar * buf);
int index_first(uchar * buf);
@@ -133,6 +132,7 @@ class ha_myisam: public handler
int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
#ifdef HAVE_REPLICATION
int dump(THD* thd, int fd);
int net_read_dump(NET* net);
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 7096c03cf7d..6df148857c5 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -332,7 +332,8 @@ int chk_size(HA_CHECK *param, register MI_INFO *info)
/* The following is needed if called externally (not from myisamchk) */
flush_key_blocks(info->s->key_cache,
- info->s->kfile, FLUSH_FORCE_WRITE);
+ info->s->kfile, &info->s->dirty_part_map,
+ FLUSH_FORCE_WRITE);
size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size)
@@ -1474,6 +1475,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force)
*/
DBUG_PRINT("repair", ("all disabled are empty: create missing"));
error= flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
FLUSH_FORCE_WRITE);
goto end;
}
@@ -1488,6 +1490,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force)
/* Remove all key blocks of this index file from key cache. */
if ((error= flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
FLUSH_IGNORE_CHANGED)))
goto end; /* purecov: inspected */
@@ -1549,7 +1552,7 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info,
if (!param->using_global_keycache)
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
- (size_t) param->use_buffers, 0, 0));
+ (size_t) param->use_buffers, 0, 0, 0));
if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
@@ -1762,7 +1765,8 @@ err:
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache));
- got_error|=flush_blocks(param, share->key_cache, share->kfile);
+ got_error|=flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
if (!got_error && param->testflag & T_UNPACK)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
@@ -1908,9 +1912,10 @@ void lock_memory(HA_CHECK *param __attribute__((unused)))
/* Flush all changed blocks to disk */
-int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file)
+int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
+ ulonglong *dirty_part_map)
{
- if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
+ if (flush_key_blocks(key_cache, file, dirty_part_map, FLUSH_RELEASE))
{
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1);
@@ -1977,7 +1982,8 @@ int mi_sort_index(HA_CHECK *param, register MI_INFO *info, char * name)
}
/* Flush key cache for this file if we are calling this outside myisamchk */
- flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */
@@ -2534,7 +2540,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param, share->key_cache, share->kfile);
+ got_error|= flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@@ -3058,7 +3065,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param, share->key_cache, share->kfile);
+ got_error|= flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
/*
Destroy the write cache. The master thread did already detach from
the share by remove_io_thread() or it was not yet started (if the
diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c
index fbd24237286..a8d678494f5 100644
--- a/storage/myisam/mi_close.c
+++ b/storage/myisam/mi_close.c
@@ -64,6 +64,7 @@ int mi_close(register MI_INFO *info)
if (share->kfile >= 0) abort(););
if (share->kfile >= 0 &&
flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
((share->temporary || share->deleting) ?
FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE)))
diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c
index 7c3ed178c4c..f1c654b0396 100644
--- a/storage/myisam/mi_delete_all.c
+++ b/storage/myisam/mi_delete_all.c
@@ -52,7 +52,8 @@ int mi_delete_all_rows(MI_INFO *info)
If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache
*/
- flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_IGNORE_CHANGED);
#ifdef HAVE_MMAP
if (share->file_map)
mi_munmap_file(info);
diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c
index 3b14e5eb98e..7352b75096e 100644
--- a/storage/myisam/mi_extra.c
+++ b/storage/myisam/mi_extra.c
@@ -268,6 +268,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
pthread_mutex_lock(&share->intern_lock);
/* Flush pages that we don't need anymore */
if (flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map,
(function == HA_EXTRA_PREPARE_FOR_DROP ?
FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)))
{
@@ -326,7 +327,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break;
case HA_EXTRA_FLUSH:
if (!share->temporary)
- flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP);
+ flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_KEEP);
#ifdef HAVE_PWRITE
_mi_decrement_open_count(info);
#endif
diff --git a/storage/myisam/mi_keycache.c b/storage/myisam/mi_keycache.c
index 5cf3fede1ae..be0cdc470f1 100644
--- a/storage/myisam/mi_keycache.c
+++ b/storage/myisam/mi_keycache.c
@@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
in the old key cache.
*/
- if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_RELEASE))
{
error= my_errno;
mi_print_error(info->s, HA_ERR_CRASHED);
@@ -90,7 +91,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
(This can never fail as there is never any not written data in the
new key cache)
*/
- (void) flush_key_blocks(key_cache, share->kfile, FLUSH_RELEASE);
+ (void) flush_key_blocks(key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_RELEASE);
/*
ensure that setting the key cache and changing the multi_key_cache
@@ -102,6 +104,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
This should be seen at the lastes for the next call to an myisam function.
*/
share->key_cache= key_cache;
+ share->dirty_part_map= 0;
/* store the key cache in the global hash structure for future opens */
if (multi_key_cache_set((uchar*) share->unique_file_name,
diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c
index baa87fc05ee..860c9c57889 100644
--- a/storage/myisam/mi_locking.c
+++ b/storage/myisam/mi_locking.c
@@ -68,7 +68,9 @@ int mi_lock_database(MI_INFO *info, int lock_type)
--share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->key_cache,
- share->kfile,FLUSH_KEEP))
+ share->kfile,
+ &share->dirty_part_map,
+ FLUSH_KEEP))
{
error=my_errno;
mi_print_error(info->s, HA_ERR_CRASHED);
@@ -513,7 +515,8 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process)
- VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
+ VOID(flush_key_blocks(share->key_cache, share->kfile,
+ &share->dirty_part_map, FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;
diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c
index dd00d15b77d..17a5820d768 100644
--- a/storage/myisam/mi_page.c
+++ b/storage/myisam/mi_page.c
@@ -87,10 +87,11 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
info->state->key_file_length != page+length)
length= ((mi_getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1));
DBUG_RETURN((key_cache_write(info->s->key_cache,
- info->s->kfile,page, level, (uchar*) buff,length,
- (uint) keyinfo->block_length,
- (int) ((info->lock_type != F_UNLCK) ||
- info->s->delay_key_write))));
+ info->s->kfile, &info->s->dirty_part_map,
+ page, level, (uchar*) buff, length,
+ (uint) keyinfo->block_length,
+ (int) ((info->lock_type != F_UNLCK) ||
+ info->s->delay_key_write))));
} /* mi_write_keypage */
@@ -109,7 +110,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->key_cache,
- info->s->kfile, pos , level, buff,
+ info->s->kfile, &info->s->dirty_part_map,
+ pos , level, buff,
sizeof(buff),
(uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK)));
diff --git a/storage/myisam/mi_panic.c b/storage/myisam/mi_panic.c
index 74c93761b61..2d06b66f834 100644
--- a/storage/myisam/mi_panic.c
+++ b/storage/myisam/mi_panic.c
@@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
- if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(info->s->key_cache, info->s->kfile,
+ &info->s->dirty_part_map, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
diff --git a/storage/myisam/mi_preload.c b/storage/myisam/mi_preload.c
index 60ab55106cb..115f0f0c70c 100644
--- a/storage/myisam/mi_preload.c
+++ b/storage/myisam/mi_preload.c
@@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
}
}
else
- block_length= share->key_cache->key_cache_block_size;
+ block_length= share->key_cache->param_block_size;
length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length);
@@ -73,7 +73,8 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
- if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE))
+ if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
+ FLUSH_RELEASE))
goto err;
do
diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c
index 52d2eb6e10c..03e0c72d7e0 100644
--- a/storage/myisam/mi_search.c
+++ b/storage/myisam/mi_search.c
@@ -300,7 +300,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
uint prefix_len,suffix_len;
int key_len_skip, seg_len_pack, key_len_left;
uchar *end, *kseg, *vseg;
- uchar *sort_order=keyinfo->seg->charset->sort_order;
+ const uchar *sort_order= keyinfo->seg->charset->sort_order;
uchar tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
uchar *UNINIT_VAR(saved_from), *UNINIT_VAR(saved_to);
uchar *UNINIT_VAR(saved_vseg);
@@ -1471,7 +1471,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
int length;
uint key_length,ref_length,org_key_length=0,
length_pack,new_key_length,diff_flag,pack_marker;
- uchar *start,*end,*key_end,*sort_order;
+ uchar *start,*end,*key_end;
+ const uchar *sort_order;
my_bool same_length;
length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c
index a6e870f3cde..39303fb80e5 100644
--- a/storage/myisam/mi_test1.c
+++ b/storage/myisam/mi_test1.c
@@ -49,7 +49,8 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
if (key_cacheing)
- init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0);
+ init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0,
+ DEFAULT_KEY_CACHE_PARTITIONS);
get_options(argc,argv);
exit(run_test("test1"));
diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c
index 9844126e7dd..67da89e55ef 100644
--- a/storage/myisam/mi_test2.c
+++ b/storage/myisam/mi_test2.c
@@ -215,7 +215,8 @@ int main(int argc, char *argv[])
if (!silent)
printf("- Writing key:s\n");
if (key_cacheing)
- init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
+ init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0,
+ DEFAULT_KEY_CACHE_PARTITIONS);
if (do_locking)
mi_lock_database(file,F_WRLCK);
if (write_cacheing)
diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c
index e792612a313..e4527bf441d 100644
--- a/storage/myisam/mi_test3.c
+++ b/storage/myisam/mi_test3.c
@@ -177,7 +177,8 @@ void start_test(int id)
exit(1);
}
if (key_cacheing && rnd(2) == 0)
- init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0);
+ init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0,
+ DEFAULT_KEY_CACHE_PARTITIONS);
printf("Process %d, pid: %ld\n", id, (long) getpid());
fflush(stdout);
diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c
index 3eecb08bd99..4436d06e36b 100644
--- a/storage/myisam/myisam_ftdump.c
+++ b/storage/myisam/myisam_ftdump.c
@@ -83,7 +83,7 @@ int main(int argc,char *argv[])
usage();
}
- init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0);
+ init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0, 0);
if (!(info=mi_open(argv[0], O_RDONLY,
HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))
diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c
index 9ecbe76369f..c7ab2baa87c 100644
--- a/storage/myisam/myisamchk.c
+++ b/storage/myisam/myisamchk.c
@@ -1102,7 +1102,7 @@ static int myisamchk(HA_CHECK *param, char * filename)
{
if (param->testflag & (T_EXTEND | T_MEDIUM))
VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size,
- (size_t) param->use_buffers, 0, 0));
+ (size_t) param->use_buffers, 0, 0, 0));
VOID(init_io_cache(&param->read_cache,datafile,
(uint) param->read_buffer_length,
READ_CACHE,
@@ -1116,7 +1116,8 @@ static int myisamchk(HA_CHECK *param, char * filename)
HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM)))
error|=chk_data_link(param, info, test(param->testflag & T_EXTEND));
- error|=flush_blocks(param, share->key_cache, share->kfile);
+ error|=flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map);
VOID(end_io_cache(&param->read_cache));
}
if (!error)
@@ -1526,7 +1527,7 @@ static int mi_sort_records(HA_CHECK *param,
DBUG_RETURN(0); /* Nothing to do */
init_key_cache(dflt_key_cache, opt_key_cache_block_size,
- (size_t) param->use_buffers, 0, 0);
+ (size_t) param->use_buffers, 0, 0, 0);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
@@ -1641,8 +1642,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0;
share->state.sortkey=sort_key;
- DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) |
- got_error);
+ DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile,
+ &share->dirty_part_map) | got_error);
} /* sort_records */
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index 3262808803c..7be59b96ec1 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -174,6 +174,8 @@ typedef struct st_mi_isam_share
*index_file_name;
uchar *file_map; /* mem-map of file if possible */
KEY_CACHE *key_cache; /* ref to the current key cache */
+ /* To mark the key cache partitions containing dirty pages for this file */
+ ulonglong dirty_part_map;
MI_DECODE_TREE *decode_trees;
uint16 *decode_tables;
/* Function to use for a row checksum. */
@@ -733,7 +735,8 @@ void mi_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...));
#ifdef THREAD
pthread_handler_t thr_find_all_keys(void *arg);
#endif
-int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file);
+int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
+ ulonglong *dirty_part_map);
#ifdef __cplusplus
}
#endif
diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c
index f43c6e332ed..c441acf6c3f 100644
--- a/storage/myisam/myisamlog.c
+++ b/storage/myisam/myisamlog.c
@@ -333,7 +333,7 @@ static int examine_log(char * file_name, char **table_names)
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL);
VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
- 0, 0));
+ 0, 0, 0));
files_open=0; access_time=0;
while (access_time++ != number_of_commands &&
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index e036e0e6c59..c6e5c24590a 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1326,3 +1326,20 @@ mysql_declare_plugin(myisammrg)
NULL /* config options */
}
mysql_declare_plugin_end;
+maria_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_storage_engine,
+ "MRG_MYISAM",
+ "MySQL AB",
+ "Collection of identical MyISAM tables",
+ PLUGIN_LICENSE_GPL,
+ myisammrg_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake
index 3aba9773202..5424beca33a 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/oqgraph/CMakeFiles.txt b/storage/oqgraph/CMakeFiles.txt
new file mode 100644
index 00000000000..b039c1ddb44
--- /dev/null
+++ b/storage/oqgraph/CMakeFiles.txt
@@ -0,0 +1,22 @@
+# 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
+
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/regex
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ADD_LIBRARY(oqgraph ha_oqgraph.cc)
diff --git a/storage/oqgraph/Makefile.am b/storage/oqgraph/Makefile.am
new file mode 100644
index 00000000000..56eea4cb87a
--- /dev/null
+++ b/storage/oqgraph/Makefile.am
@@ -0,0 +1,98 @@
+# Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+#
+# 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, or
+# (at your option) any later version.
+#
+# 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 */
+
+# ======================================================================
+# Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+# Mk.II implementation by Antony Curtis & Arjen Lentz
+# For more information, documentation, support, enhancement engineering,
+# and non-GPL licensing, see http://openquery.com/graph
+# or contact graph@openquery.com
+# For packaged binaries, see http://ourdelta.org
+# ======================================================================
+
+mysqlplugindir= $(pkglibdir)/plugin
+
+BOOST_CXXFLAGS = -frtti -fexceptions -fimplicit-templates
+#BOOST_CXXFLAGS+= -g
+#original flags before 2009-11-10
+#BOOST_CXXFLAGS+= -O3 -fomit-frame-pointer -fstrict-aliasing
+#BOOST_CXXFLAGS+= -momit-leaf-frame-pointer -falign-loops
+#modified flags:
+# - remove omit-frame-pointer, x86 specific (fails on PPC) + hinders debugging
+# Option details from gcc man:
+# Don't keep the frame pointer in a register for functions that don't need one.
+# This avoids the instructions to save, set up and restore frame pointers;
+# it also makes an extra register available in many functions.
+# It also makes debugging impossible on some machines.
+# (automatically gets enabled anyway by -O* on some architectures)
+BOOST_CXXFLAGS+= -O3 -fstrict-aliasing
+BOOST_CXXFLAGS+= -falign-loops
+if HAVE_FVISIBILITY_INLINES_HIDDEN
+BOOST_CXXFLAGS+= -fvisibility-inlines-hidden
+endif
+BOOST_CXXFLAGS+= -funroll-loops -fno-trapping-math
+
+EXTRA_DIST = ha_oqgraph.h ha_oqgraph.cc graphcore.cc \
+ graphcore-graph.h graphcore-types.h graphcore.h \
+ CMakeFiles.txt plug.in oqgraph_probes.d
+
+# DTRACE = @DTRACE@
+# DTRACEFLAGS = @DTRACEFLAGS@
+# DTRACEFILES = .libs/liboqgraph_engine_la-ha_oqgraph.o
+
+ORIG_CXXFLAGS = @CXXFLAGS@
+CXXFLAGS=
+noinst_HEADERS = ha_oqgraph.h \
+ graphcore-graph.h graphcore-types.h graphcore.h
+# oqgraph_probes.h
+
+noinst_LTLIBRARIES = libgraphcore.la
+libgraphcore_la_SOURCES = graphcore.cc
+libgraphcore_la_CXXFLAGS = $(ORIG_CXXFLAGS) $(BOOST_CXXFLAGS)
+
+if BUILD_OQGRAPH_FOR_MYSQL
+
+if BUILD_OQGRAPH_STANDALONE
+INCLUDES = -DDBUG_ON -DSAFE_MUTEX -DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX -DHAVE_OQGRAPH $(MYSQL_INC)
+else
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/regex -I$(top_srcdir)/sql -I$(srcdir) -DHAVE_OQGRAPH
+endif !BUILD_OQGRAPH_STANDALONE
+
+EXTRA_LTLIBRARIES = oqgraph_engine.la
+mysqlplugin_LTLIBRARIES = @plugin_oqgraph_shared_target@
+oqgraph_engine_la_SOURCES = ha_oqgraph.cc
+oqgraph_engine_la_LIBADD = libgraphcore.la
+
+# if HAVE_DTRACE
+# oqgraph_engine_la_LIBADD += oqgraph_probes.o
+# endif
+
+oqgraph_engine_la_LDFLAGS = -module -rpath $(mysqlplugindir)
+oqgraph_engine_la_CFLAGS = $(ORIG_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+oqgraph_engine_la_CXXFLAGS = $(ORIG_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+
+# oqgraph_probes.h: oqgraph_probes.d
+# $(DTRACE) $(DTRACEFLAGS) -h -s oqgraph_probes.d
+# mv oqgraph_probes.h oqgraph_probes.h.bak
+# sed "s/#include <unistd.h>//g" oqgraph_probes.h.bak > oqgraph_probes.h
+# rm oqgraph_probes.h.bak
+
+# oqgraph_probes.o:
+# $(DTRACE) $(DTRACEFLAGS) -G -s oqgraph_probes.d $(DTRACEFILES)
+
+endif BUILD_OQGRAPH_FOR_MYSQL
+
+# End
diff --git a/storage/oqgraph/README b/storage/oqgraph/README
new file mode 100644
index 00000000000..cb4fba7295b
--- /dev/null
+++ b/storage/oqgraph/README
@@ -0,0 +1,16 @@
+OQGraph storage engine
+Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+The Open Query GRAPH engine (OQGRAPH) is a computation engine allowing
+hierarchies and more complex graph structures to be handled in a
+relational fashion. In a nutshell, tree structures and
+friend-of-a-friend style searches can now be done using standard SQL
+syntax, and results joined onto other tables.
+
+See http://openquery.com/graph for more information.
+
+
+INSTALLATION
+
+OQGraph requires at least version 1.40.0 of the Boost library. To
+obtain a copy of the Boost library, see http://www.boost.org/
diff --git a/storage/oqgraph/graphcore-graph.h b/storage/oqgraph/graphcore-graph.h
new file mode 100644
index 00000000000..46ddfb5335b
--- /dev/null
+++ b/storage/oqgraph/graphcore-graph.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ 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, or
+ (at your option) any later version.
+
+ 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 */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph@openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifndef oq_graphcore_graph_h_
+#define oq_graphcore_graph_h_
+
+typedef adjacency_list
+<
+ vecS,
+ vecS,
+ bidirectionalS,
+ VertexInfo,
+ EdgeInfo
+> Graph;
+
+#define GRAPH_WEIGHTMAP(G) get(&EdgeInfo::weight, G)
+typedef property_map<Graph, EdgeWeight EdgeInfo::*>::type weightmap_type;
+
+#define GRAPH_INDEXMAP(G) get(vertex_index, G)
+typedef property_map<Graph, vertex_index_t>::type indexmap_type;
+
+#define GRAPH_IDMAP(G) get(&VertexInfo::id, G)
+typedef property_map<Graph, VertexID VertexInfo::*>::type idmap_type;
+
+#endif
diff --git a/storage/oqgraph/graphcore-types.h b/storage/oqgraph/graphcore-types.h
new file mode 100644
index 00000000000..7a7e4c62729
--- /dev/null
+++ b/storage/oqgraph/graphcore-types.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ 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, or
+ (at your option) any later version.
+
+ 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 */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph@openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifndef oq_graphcore_types_h_
+#define oq_graphcore_types_h_
+namespace open_query
+{
+
+ typedef unsigned long long VertexID;
+ typedef double EdgeWeight;
+
+}
+#endif
diff --git a/storage/oqgraph/graphcore.cc b/storage/oqgraph/graphcore.cc
new file mode 100644
index 00000000000..f19f99d0756
--- /dev/null
+++ b/storage/oqgraph/graphcore.cc
@@ -0,0 +1,1101 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ 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, or
+ (at your option) any later version.
+
+ 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 */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph@openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#include <strings.h>
+
+#define BOOST_ALL_NO_LIB 1
+
+#include <boost/config.hpp>
+
+#include <set>
+#include <stack>
+
+#include <boost/property_map/property_map.hpp>
+
+#include <boost/graph/graph_concepts.hpp>
+#include <boost/graph/graph_archetypes.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/breadth_first_search.hpp>
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+#include <boost/graph/iteration_macros.hpp>
+#include <boost/graph/reverse_graph.hpp>
+#include <boost/graph/graph_utility.hpp>
+
+#include "graphcore.h"
+
+using namespace open_query;
+using namespace boost;
+
+static const row empty_row = { 0 };
+
+namespace open_query
+{
+ enum vertex_id_t { vertex_id };
+
+ struct VertexInfo {
+ inline VertexInfo() { }
+
+ inline VertexInfo(VertexID _id)
+ : id(_id) { }
+
+ VertexID id;
+ };
+
+ struct EdgeInfo {
+ EdgeWeight weight;
+ };
+}
+
+namespace boost
+{
+ BOOST_INSTALL_PROPERTY(vertex, id);
+
+ namespace graph
+ {
+ template<>
+ struct internal_vertex_name<VertexInfo>
+ {
+ typedef multi_index::member<VertexInfo, VertexID, &VertexInfo::id> type;
+ };
+
+ template<>
+ struct internal_vertex_constructor<VertexInfo>
+ {
+ typedef vertex_from_name<VertexInfo> type;
+ };
+ }
+}
+
+namespace open_query
+{
+
+ #include "graphcore-graph.h"
+
+ typedef graph_traits<Graph>::vertex_descriptor Vertex;
+ typedef graph_traits<Graph>::edge_descriptor Edge;
+
+ typedef std::list<std::pair<Vertex,optional<EdgeWeight> > > shortest_path_list;
+ typedef shortest_path_list::iterator shortest_path_iterator;
+
+ template<typename ID, typename IDMap>
+ class id_equals_t
+ {
+ public:
+ id_equals_t(ID id, IDMap map)
+ : m_id(id), m_map(map)
+ { }
+ template<typename V>
+ bool operator()(V u) const
+ {
+ return m_map[u] == m_id;
+ }
+ private:
+ ID m_id;
+ IDMap m_map;
+ };
+
+ template<typename ID, typename IDMap>
+ inline id_equals_t<ID,IDMap>
+ id_equals(ID id, IDMap idmap)
+ {
+ return id_equals_t<ID,IDMap>(id, idmap);
+ }
+
+ template<typename T, typename Graph>
+ class target_equals_t
+ {
+ public:
+ target_equals_t(T target, Graph &g)
+ : m_target(target), m_g(g)
+ { }
+ template<typename V>
+ bool operator()(V u) const
+ {
+ return target(u, m_g) == m_target;
+ }
+ private:
+ T m_target;
+ Graph &m_g;
+ };
+
+ template<typename T, typename Graph>
+ inline target_equals_t<T,Graph>
+ target_equals(T target, Graph &g)
+ {
+ return target_equals_t<T,Graph>(target, g);
+ }
+
+ template<typename T, typename Graph>
+ class source_equals_t
+ {
+ public:
+ source_equals_t(T source, Graph &g)
+ : m_source(source), m_g(g)
+ { }
+ template<typename V>
+ bool operator()(V u) const
+ {
+ return source(u, m_g) == m_source;
+ }
+ private:
+ T m_source;
+ Graph &m_g;
+ };
+
+ template<typename T, typename Graph>
+ inline source_equals_t<T,Graph>
+ source_equals(T source, Graph &g)
+ {
+ return source_equals_t<T,Graph>(source, g);
+ }
+
+ struct reference
+ {
+ int m_flags;
+ int m_sequence;
+ Vertex m_vertex;
+ Edge m_edge;
+ EdgeWeight m_weight;
+
+ enum
+ {
+ HAVE_SEQUENCE = 1,
+ HAVE_WEIGHT = 2,
+ HAVE_EDGE = 4,
+ };
+
+ inline reference()
+ : m_flags(0), m_sequence(0),
+ m_vertex(graph_traits<Graph>::null_vertex()),
+ m_edge(), m_weight(0)
+ { }
+
+ inline reference(int s, Edge e)
+ : m_flags(HAVE_SEQUENCE | HAVE_EDGE), m_sequence(s),
+ m_vertex(graph_traits<Graph>::null_vertex()),
+ m_edge(e), m_weight(0)
+ { }
+
+ inline reference(int s, Vertex v, const optional<Edge> &e,
+ const optional<EdgeWeight> &w)
+ : m_flags(HAVE_SEQUENCE | (w ? HAVE_WEIGHT : 0) | (e ? HAVE_EDGE : 0)),
+ m_sequence(s), m_vertex(v)
+ {
+ if (w) m_weight= *w;
+ if (e) m_edge= *e;
+ }
+
+ inline reference(int s, Vertex v, Edge e, EdgeWeight w)
+ : m_flags(HAVE_SEQUENCE | HAVE_WEIGHT | HAVE_EDGE),
+ m_sequence(s), m_vertex(v), m_edge(e), m_weight(w)
+ { }
+
+ inline reference(int s, Vertex v, EdgeWeight w)
+ : m_flags(HAVE_SEQUENCE | HAVE_WEIGHT),
+ m_sequence(s), m_vertex(v), m_edge(), m_weight(w)
+ { }
+
+ inline reference(int s, Vertex v)
+ : m_flags(HAVE_SEQUENCE), m_sequence(s), m_vertex(v), m_edge(),
+ m_weight(0)
+ { }
+
+ optional<int> sequence() const
+ {
+ if (m_flags & HAVE_SEQUENCE)
+ {
+ return m_sequence;
+ }
+ return optional<int>();
+ }
+
+ optional<Vertex> vertex() const
+ {
+ if (m_vertex != graph_traits<Graph>::null_vertex())
+ return m_vertex;
+ return optional<Vertex>();
+ }
+
+ optional<Edge> edge() const
+ {
+ if (m_flags & HAVE_EDGE)
+ return m_edge;
+ return optional<Edge>();
+ };
+
+ optional<EdgeWeight> weight() const
+ {
+ if (m_flags & HAVE_WEIGHT)
+ return m_weight;
+ return optional<EdgeWeight>();
+ }
+ };
+}
+
+namespace open_query {
+ class GRAPHCORE_INTERNAL oqgraph_share
+ {
+ public:
+ Graph g;
+
+ weightmap_type weightmap;
+ idmap_type idmap;
+ indexmap_type indexmap;
+
+ optional<Vertex> find_vertex(VertexID id) const;
+ optional<Edge> find_edge(Vertex, Vertex) const;
+
+ inline oqgraph_share() throw()
+ : g(),
+ weightmap(GRAPH_WEIGHTMAP(g)),
+ idmap(GRAPH_IDMAP(g)),
+ indexmap(GRAPH_INDEXMAP(g))
+ { }
+ inline ~oqgraph_share()
+ { }
+ };
+
+ class GRAPHCORE_INTERNAL oqgraph_cursor
+ {
+ public:
+ oqgraph_share *const share;
+
+ inline oqgraph_cursor(oqgraph_share *arg)
+ : share(arg)
+ { }
+ virtual ~oqgraph_cursor()
+ { }
+
+ virtual int fetch_row(const row &, row&) = 0;
+ virtual int fetch_row(const row &, row&, const reference&) = 0;
+ virtual void current(reference& ref) const = 0;
+ };
+}
+
+namespace open_query {
+ class GRAPHCORE_INTERNAL stack_cursor : public oqgraph_cursor
+ {
+ private:
+ optional<EdgeWeight> no_weight;
+ public:
+ int sequence;
+ std::stack<reference> results;
+ reference last;
+
+ inline stack_cursor(oqgraph_share *arg)
+ : oqgraph_cursor(arg), no_weight(), sequence(0), results(), last()
+ { }
+
+ int fetch_row(const row &, row&);
+ int fetch_row(const row &, row&, const reference&);
+
+ void current(reference& ref) const
+ {
+ ref= last;
+ }
+ };
+
+ class GRAPHCORE_INTERNAL vertices_cursor : public oqgraph_cursor
+ {
+ typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
+
+ size_t position;
+ reference last;
+ public:
+ inline vertices_cursor(oqgraph_share *arg)
+ : oqgraph_cursor(arg), position(0)
+ { }
+
+ int fetch_row(const row &, row&);
+ int fetch_row(const row &, row&, const reference&);
+
+ void current(reference& ref) const
+ {
+ ref= last;
+ }
+
+ };
+
+ class GRAPHCORE_INTERNAL edges_cursor : public oqgraph_cursor
+ {
+ typedef graph_traits<Graph>::edge_iterator edge_iterator;
+ typedef edge_iterator::difference_type edge_difference;
+
+ edge_difference position;
+ reference last;
+ public:
+ inline edges_cursor(oqgraph_share *arg)
+ : oqgraph_cursor(arg), position(0), last()
+ { }
+
+ int fetch_row(const row &, row&);
+ int fetch_row(const row &, row&, const reference&);
+
+ void current(reference& ref) const
+ {
+ ref= last;
+ }
+ };
+
+ struct GRAPHCORE_INTERNAL oqgraph_visit_dist
+ : public base_visitor<oqgraph_visit_dist>
+ {
+ typedef on_finish_vertex event_filter;
+
+ oqgraph_visit_dist(std::vector<Vertex>::iterator p,
+ std::vector<EdgeWeight>::iterator d,
+ stack_cursor *cursor)
+ : seq(0), m_cursor(*cursor), m_p(p), m_d(d)
+ { assert(cursor); }
+
+ template<class T, class Graph>
+ void operator()(T u, Graph &g)
+ {
+ m_cursor.results.push(reference(++seq, u, m_d[GRAPH_INDEXMAP(g)[u]]));
+ }
+ private:
+ int seq;
+ stack_cursor &m_cursor;
+ std::vector<Vertex>::iterator m_p;
+ std::vector<EdgeWeight>::iterator m_d;
+ };
+
+ template<bool record_weight, typename goal_filter>
+ struct GRAPHCORE_INTERNAL oqgraph_goal
+ : public base_visitor<oqgraph_goal<record_weight,goal_filter> >
+ {
+ typedef goal_filter event_filter;
+
+ oqgraph_goal(Vertex goal, std::vector<Vertex>::iterator p,
+ stack_cursor *cursor)
+ : m_goal(goal), m_cursor(*cursor), m_p(p)
+ { assert(cursor); }
+
+ template<class T, class Graph>
+ void operator()(T u, Graph &g)
+ {
+ if (u == m_goal)
+ {
+ int seq= 0;
+ indexmap_type indexmap= GRAPH_INDEXMAP(g);
+
+ for (Vertex q, v= u;; v = q, seq++)
+ if ((q= m_p[ indexmap[v] ]) == v)
+ break;
+
+ for (Vertex v= u;; u= v)
+ {
+ optional<Edge> edge;
+ optional<EdgeWeight> weight;
+ v= m_p[ indexmap[u] ];
+ if (record_weight && u != v)
+ {
+ typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end)= out_edges(v, g); ei != ei_end; ++ei)
+ {
+ if (target(*ei, g) == u)
+ {
+ edge= *ei;
+ weight= GRAPH_WEIGHTMAP(g)[*ei];
+ break;
+ }
+ }
+ }
+ else if (u != v)
+ weight= 1;
+ m_cursor.results.push(reference(seq--, u, edge, weight));
+ if (u == v)
+ break;
+ }
+ throw this;
+ }
+ }
+
+ private:
+ Vertex m_goal;
+ stack_cursor &m_cursor;
+ std::vector<Vertex>::iterator m_p;
+ };
+}
+
+namespace open_query
+{
+ inline oqgraph::oqgraph(oqgraph_share *arg) throw()
+ : share(arg), cursor(0)
+ { }
+
+ inline oqgraph::~oqgraph() throw()
+ {
+ delete cursor;
+ }
+
+ unsigned oqgraph::edges_count() const throw()
+ {
+ return num_edges(share->g);
+ }
+
+ unsigned oqgraph::vertices_count() const throw()
+ {
+ return num_vertices(share->g);
+ }
+
+ oqgraph* oqgraph::create(oqgraph_share *share) throw()
+ {
+ assert(share != NULL);
+ return new (std::nothrow) oqgraph(share);
+ }
+
+ oqgraph_share* oqgraph::create() throw()
+ {
+ return new (std::nothrow) oqgraph_share();
+ }
+
+ optional<Edge>
+ oqgraph_share::find_edge(Vertex orig, Vertex dest) const
+ {
+ if (in_degree(dest, g) >= out_degree(orig, g))
+ {
+ graph_traits<Graph>::out_edge_iterator ei, ei_end;
+ tie(ei, ei_end)= out_edges(orig, g);
+ if ((ei= find_if(ei, ei_end, target_equals(dest, g))) != ei_end)
+ return *ei;
+ }
+ else
+ {
+ graph_traits<Graph>::in_edge_iterator ei, ei_end;
+ tie(ei, ei_end)= in_edges(dest, g);
+ if ((ei= find_if(ei, ei_end, source_equals(orig, g))) != ei_end)
+ return *ei;
+ }
+ return optional<Edge>();
+ }
+
+ optional<Vertex>
+ oqgraph_share::find_vertex(VertexID id) const
+ {
+ return boost::graph::find_vertex(id, g);
+ }
+
+ int oqgraph::delete_all() throw()
+ {
+ share->g.clear();
+ return 0;
+ }
+
+ int oqgraph::insert_edge(
+ VertexID orig_id, VertexID dest_id, EdgeWeight weight, bool replace) throw()
+ {
+ optional<Vertex> orig, dest;
+ optional<Edge> edge;
+ bool inserted= 0;
+
+ if (weight < 0)
+ return INVALID_WEIGHT;
+ if (!(orig= share->find_vertex(orig_id)))
+ {
+ try
+ {
+ orig= add_vertex(VertexInfo(orig_id), share->g);
+ if (orig == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (!(dest= share->find_vertex(dest_id)))
+ {
+ try
+ {
+ dest= add_vertex(VertexInfo(dest_id), share->g);
+ if (dest == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (!(edge= share->find_edge(*orig, *dest)))
+ {
+ try
+ {
+ tie(edge, inserted)= add_edge(*orig, *dest, share->g);
+ if (!inserted)
+ return CANNOT_ADD_EDGE;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_EDGE;
+ }
+ }
+ else
+ {
+ if (!replace)
+ return DUPLICATE_EDGE;
+ }
+ share->weightmap[*edge]= weight;
+ return OK;
+ }
+
+ int oqgraph::delete_edge(current_row_st) throw()
+ {
+ reference ref;
+ if (cursor)
+ return EDGE_NOT_FOUND;
+ cursor->current(ref);
+ optional<Edge> edge;
+ if (!(edge= ref.edge()))
+ return EDGE_NOT_FOUND;
+ Vertex orig= source(*edge, share->g);
+ Vertex dest= target(*edge, share->g);
+ remove_edge(*edge, share->g);
+ if (!degree(orig, share->g))
+ remove_vertex(orig, share->g);
+ if (!degree(dest, share->g))
+ remove_vertex(dest, share->g);
+ return OK;
+ }
+
+ int oqgraph::modify_edge(current_row_st,
+ VertexID *orig_id, VertexID *dest_id, EdgeWeight *weight,
+ bool replace) throw()
+ {
+ if (!cursor)
+ return EDGE_NOT_FOUND;
+ reference ref;
+ cursor->current(ref);
+ optional<Edge> edge;
+ if (!(edge= ref.edge()))
+ return EDGE_NOT_FOUND;
+ if (weight && *weight < 0)
+ return INVALID_WEIGHT;
+
+ optional<Vertex> orig= source(*edge, share->g),
+ dest= target(*edge, share->g);
+
+ bool orig_neq= orig_id ? share->idmap[*orig] != *orig_id : 0;
+ bool dest_neq= dest_id ? share->idmap[*dest] != *dest_id : 0;
+ if (orig_neq || dest_neq)
+ {
+ optional<Edge> new_edge;
+ if (orig_neq && !(orig= share->find_vertex(*orig_id)))
+ {
+ try
+ {
+ orig= add_vertex(VertexInfo(*orig_id), share->g);
+ if (orig == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (dest_neq && !(dest= share->find_vertex(*dest_id)))
+ {
+ try
+ {
+ dest= add_vertex(VertexInfo(*dest_id), share->g);
+ if (dest == graph_traits<Graph>::null_vertex())
+ return CANNOT_ADD_VERTEX;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_VERTEX;
+ }
+ }
+ if (!(new_edge= share->find_edge(*orig, *dest)))
+ {
+ try
+ {
+ bool inserted;
+ tie(new_edge, inserted)= add_edge(*orig, *dest, share->g);
+ if (!inserted)
+ return CANNOT_ADD_EDGE;
+ }
+ catch (...)
+ {
+ return CANNOT_ADD_EDGE;
+ }
+ }
+ else
+ {
+ if (!replace)
+ return DUPLICATE_EDGE;
+ }
+ share->weightmap[*new_edge]= share->weightmap[*edge];
+ remove_edge(*edge, share->g);
+ edge= new_edge;
+ }
+ if (weight)
+ share->weightmap[*edge]= *weight;
+ return OK;
+ }
+
+ int oqgraph::modify_edge(
+ VertexID orig_id, VertexID dest_id, EdgeWeight weight) throw()
+ {
+ optional<Vertex> orig, dest;
+ optional<Edge> edge;
+
+ if (weight < 0)
+ return INVALID_WEIGHT;
+ if (!(orig= share->find_vertex(orig_id)))
+ return EDGE_NOT_FOUND;
+ if (!(dest= share->find_vertex(dest_id)))
+ return EDGE_NOT_FOUND;
+ if (!(edge= share->find_edge(*orig, *dest)))
+ return EDGE_NOT_FOUND;
+ share->weightmap[*edge]= weight;
+ return OK;
+ }
+
+
+ int oqgraph::delete_edge(VertexID orig_id, VertexID dest_id) throw()
+ {
+ optional<Vertex> orig, dest;
+ optional<Edge> edge;
+
+ if (!(orig= share->find_vertex(orig_id)))
+ return EDGE_NOT_FOUND;
+ if (!(dest= share->find_vertex(dest_id)))
+ return EDGE_NOT_FOUND;
+ if (!(edge= share->find_edge(*orig, *dest)))
+ return EDGE_NOT_FOUND;
+ remove_edge(*edge, share->g);
+ if (!degree(*orig, share->g))
+ remove_vertex(*orig, share->g);
+ if (!degree(*dest, share->g))
+ remove_vertex(*dest, share->g);
+ return OK;
+ }
+
+
+ int oqgraph::search(int *latch, VertexID *orig_id, VertexID *dest_id) throw()
+ {
+ optional<Vertex> orig, dest;
+ int op= 0, seq= 0;
+ enum {
+ NO_SEARCH = 0,
+ DIJKSTRAS = 1,
+ BREADTH_FIRST = 2,
+
+ ALGORITHM = 0x0ffff,
+ HAVE_ORIG = 0x10000,
+ HAVE_DEST = 0x20000,
+ };
+
+ delete cursor; cursor= 0;
+ row_info= empty_row;
+ if ((row_info.latch_indicator= latch))
+ op= ALGORITHM & (row_info.latch= *latch);
+ if ((row_info.orig_indicator= orig_id) && (op|= HAVE_ORIG))
+ orig= share->find_vertex((row_info.orig= *orig_id));
+ if ((row_info.dest_indicator= dest_id) && (op|= HAVE_DEST))
+ dest= share->find_vertex((row_info.dest= *dest_id));
+ //try
+ //{
+ switch (op)
+ {
+ case NO_SEARCH | HAVE_ORIG | HAVE_DEST:
+ case NO_SEARCH | HAVE_ORIG:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && orig)
+ {
+ graph_traits<Graph>::out_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end)= out_edges(*orig, share->g); ei != ei_end; ++ei)
+ {
+ Vertex v= target(*ei, share->g);
+ static_cast<stack_cursor*>(cursor)->
+ results.push(reference(++seq, v, *ei, share->weightmap[*ei]));
+ }
+ }
+ /* fall through */
+ case NO_SEARCH | HAVE_DEST:
+ if ((op & HAVE_DEST) &&
+ (cursor || (cursor= new (std::nothrow) stack_cursor(share))) &&
+ dest)
+ {
+ graph_traits<Graph>::in_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end)= in_edges(*dest, share->g); ei != ei_end; ++ei)
+ {
+ Vertex v= source(*ei, share->g);
+ static_cast<stack_cursor*>(cursor)->
+ results.push(reference(++seq, v, *ei, share->weightmap[*ei]));
+ }
+ }
+ break;
+
+ case NO_SEARCH:
+ cursor= new (std::nothrow) vertices_cursor(share);
+ break;
+
+ case DIJKSTRAS | HAVE_ORIG | HAVE_DEST:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && orig && dest)
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ std::vector<EdgeWeight> d(num_vertices(share->g));
+ oqgraph_goal<true, on_finish_vertex>
+ vis(*dest, p.begin(), static_cast<stack_cursor*>(cursor));
+ p[share->indexmap[*orig]]= *orig;
+ try
+ {
+ dijkstra_shortest_paths(share->g, *orig,
+ weight_map(
+ share->weightmap
+ ).
+ distance_map(
+ make_iterator_property_map(d.begin(), share->indexmap)
+ ).
+ predecessor_map(
+ make_iterator_property_map(p.begin(), share->indexmap)
+ ).
+ visitor(
+ make_dijkstra_visitor(vis)
+ )
+ );
+ }
+ catch (...)
+ { /* printf("found\n"); */ }
+ }
+ break;
+
+ case BREADTH_FIRST | HAVE_ORIG | HAVE_DEST:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && orig && dest)
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ oqgraph_goal<false, on_discover_vertex>
+ vis(*dest, p.begin(), static_cast<stack_cursor*>(cursor));
+ p[share->indexmap[*orig]]= *orig;
+ try
+ {
+ breadth_first_search(share->g, *orig,
+ visitor(make_bfs_visitor(
+ std::make_pair(
+ record_predecessors(
+ make_iterator_property_map(p.begin(), share->indexmap),
+ on_tree_edge()
+ ),
+ vis)
+ )
+ )
+ );
+ }
+ catch (...)
+ { /* printf("found\n"); */ }
+ }
+ break;
+
+ case DIJKSTRAS | HAVE_ORIG:
+ case BREADTH_FIRST | HAVE_ORIG:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ std::vector<EdgeWeight> d(num_vertices(share->g));
+ oqgraph_visit_dist vis(p.begin(), d.begin(),
+ static_cast<stack_cursor*>(cursor));
+ p[share->indexmap[*orig]]= *orig;
+ switch (ALGORITHM & op)
+ {
+ case DIJKSTRAS:
+ dijkstra_shortest_paths(share->g, *orig,
+ weight_map(
+ share->weightmap
+ ).
+ distance_map(
+ make_iterator_property_map(d.begin(), share->indexmap)
+ ).
+ predecessor_map(
+ make_iterator_property_map(p.begin(), share->indexmap)
+ ).
+ visitor(
+ make_dijkstra_visitor(vis)
+ )
+ );
+ break;
+ case BREADTH_FIRST:
+ breadth_first_search(share->g, *orig,
+ visitor(make_bfs_visitor(
+ std::make_pair(
+ record_predecessors(
+ make_iterator_property_map(p.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ std::make_pair(
+ record_distances(
+ make_iterator_property_map(d.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ vis
+ ))
+ ))
+ );
+ break;
+ default:
+ abort();
+ }
+ }
+ break;
+
+ case BREADTH_FIRST | HAVE_DEST:
+ case DIJKSTRAS | HAVE_DEST:
+ if ((cursor= new (std::nothrow) stack_cursor(share)) && (orig || dest))
+ {
+ std::vector<Vertex> p(num_vertices(share->g));
+ std::vector<EdgeWeight> d(num_vertices(share->g));
+ oqgraph_visit_dist vis(p.begin(), d.begin(),
+ static_cast<stack_cursor*>(cursor));
+ reverse_graph<Graph> r(share->g);
+ p[share->indexmap[*dest]]= *dest;
+ switch (ALGORITHM & op)
+ {
+ case DIJKSTRAS:
+ dijkstra_shortest_paths(r, *dest,
+ weight_map(
+ share->weightmap
+ ).
+ distance_map(
+ make_iterator_property_map(d.begin(), share->indexmap)
+ ).
+ predecessor_map(
+ make_iterator_property_map(p.begin(), share->indexmap)
+ ).
+ visitor(
+ make_dijkstra_visitor(vis)
+ )
+ );
+ break;
+ case BREADTH_FIRST:
+ breadth_first_search(r, *dest,
+ visitor(make_bfs_visitor(
+ std::make_pair(
+ record_predecessors(
+ make_iterator_property_map(p.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ std::make_pair(
+ record_distances(
+ make_iterator_property_map(d.begin(),
+ share->indexmap),
+ on_tree_edge()
+ ),
+ vis
+ ))
+ ))
+ );
+ break;
+ default:
+ abort();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+ //}
+ //catch (...)
+ //{
+ // return MISC_FAIL;
+ //}
+ }
+
+ int oqgraph::fetch_row(row& result) throw()
+ {
+ if (!cursor)
+ return NO_MORE_DATA;
+ return cursor->fetch_row(row_info, result);
+ }
+
+ int oqgraph::fetch_row(row& result, const void* ref_ptr) throw()
+ {
+ const reference &ref= *(const reference*) ref_ptr;
+ if (!cursor)
+ return NO_MORE_DATA;
+ return cursor->fetch_row(row_info, result, ref);
+ }
+
+ void oqgraph::row_ref(void *ref_ptr) throw()
+ {
+ reference &ref= *(reference*) ref_ptr;
+ if (cursor)
+ cursor->current(ref);
+ else
+ ref= reference();
+ }
+
+ int oqgraph::random(bool scan) throw()
+ {
+ if (scan || !cursor)
+ {
+ delete cursor; cursor= 0;
+ if (!(cursor= new (std::nothrow) edges_cursor(share)))
+ return MISC_FAIL;
+ }
+ row_info= empty_row;
+ return OK;
+ }
+
+ void oqgraph::free(oqgraph *graph) throw()
+ {
+ delete graph;
+ }
+
+ void oqgraph::free(oqgraph_share *graph) throw()
+ {
+ delete graph;
+ }
+
+ const size_t oqgraph::sizeof_ref= sizeof(reference);
+}
+
+int stack_cursor::fetch_row(const row &row_info, row &result)
+{
+ if (!results.empty())
+ {
+ if (int res= fetch_row(row_info, result, results.top()))
+ return res;
+ results.pop();
+ return oqgraph::OK;
+ }
+ else
+ {
+ last= reference();
+ return oqgraph::NO_MORE_DATA;
+ }
+}
+
+int stack_cursor::fetch_row(const row &row_info, row &result,
+ const reference &ref)
+{
+ last= ref;
+ if (optional<Vertex> v= last.vertex())
+ {
+ optional<int> seq;
+ optional<EdgeWeight> w;
+ optional<Vertex> v;
+ result= row_info;
+ if ((result.seq_indicator= seq= last.sequence()))
+ result.seq= *seq;
+ if ((result.link_indicator= v= last.vertex()))
+ result.link= share->idmap[*v];
+ if ((result.weight_indicator= w= last.weight()))
+ result.weight= *w;
+ return oqgraph::OK;
+ }
+ else
+ return oqgraph::NO_MORE_DATA;
+}
+
+
+int vertices_cursor::fetch_row(const row &row_info, row &result)
+{
+ vertex_iterator it, end;
+ reference ref;
+ size_t count= position;
+ for (tie(it, end)= vertices(share->g); count && it != end; ++it, --count)
+ ;
+ if (it != end)
+ ref= reference(position+1, *it);
+ if (int res= fetch_row(row_info, result, ref))
+ return res;
+ position++;
+ return oqgraph::OK;
+}
+
+int vertices_cursor::fetch_row(const row &row_info, row &result,
+ const reference &ref)
+{
+ last= ref;
+ optional<Vertex> v= last.vertex();
+ result= row_info;
+ if (v)
+ {
+ result.link_indicator= 1;
+ result.link= share->idmap[*v];
+#ifdef DISPLAY_VERTEX_INFO
+ result.seq_indicator= 1;
+ if ((result.seq= degree(*v, share->g)))
+ {
+ EdgeWeight weight= 0;
+ graph_traits<Graph>::in_edge_iterator iei, iei_end;
+ for (tie(iei, iei_end)= in_edges(*v, share->g); iei != iei_end; ++iei)
+ weight+= share->weightmap[*iei];
+ graph_traits<Graph>::out_edge_iterator oei, oei_end;
+ for (tie(oei, oei_end)= out_edges(*v, share->g); oei != oei_end; ++oei)
+ weight+= share->weightmap[*oei];
+ result.weight_indicator= 1;
+ result.weight= weight / result.seq;
+ }
+#endif
+ return oqgraph::OK;
+ }
+ else
+ return oqgraph::NO_MORE_DATA;
+}
+
+int edges_cursor::fetch_row(const row &row_info, row &result)
+{
+ edge_iterator it, end;
+ reference ref;
+ size_t count= position;
+ for (tie(it, end)= edges(share->g); count && it != end; ++it, --count)
+ ;
+ if (it != end)
+ ref= reference(position+1, *it);
+ if (int res= fetch_row(row_info, result, ref))
+ return res;
+ ++position;
+ return oqgraph::OK;
+}
+
+int edges_cursor::fetch_row(const row &row_info, row &result,
+ const reference &ref)
+{
+ optional<Edge> edge;
+ if ((edge= (last= ref).edge()))
+ {
+ result= row_info;
+ result.orig_indicator= result.dest_indicator= result.weight_indicator= 1;
+ result.orig= share->idmap[ source( *edge, share->g ) ];
+ result.dest= share->idmap[ target( *edge, share->g ) ];
+ result.weight= share->weightmap[ *edge ];
+ return oqgraph::OK;
+ }
+ return oqgraph::NO_MORE_DATA;
+}
+
+namespace boost {
+ GRAPHCORE_INTERNAL void throw_exception(std::exception const&)
+ {
+ abort();
+ }
+}
diff --git a/storage/oqgraph/graphcore.h b/storage/oqgraph/graphcore.h
new file mode 100644
index 00000000000..4aaddb2796f
--- /dev/null
+++ b/storage/oqgraph/graphcore.h
@@ -0,0 +1,116 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+
+ 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, or
+ (at your option) any later version.
+
+ 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 */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph@openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifndef oq_graphcore_h_
+#define oq_graphcore_h_
+
+/* #define GRAPHCORE_INTERNAL __attribute__((visibility("hidden"))) */
+#define GRAPHCORE_INTERNAL
+
+#include "graphcore-types.h"
+
+namespace open_query
+{
+ class oqgraph_share;
+ class oqgraph_cursor;
+
+ struct row
+ {
+ bool latch_indicator;
+ bool orig_indicator;
+ bool dest_indicator;
+ bool weight_indicator;
+ bool seq_indicator;
+ bool link_indicator;
+
+ int latch;
+ VertexID orig;
+ VertexID dest;
+ EdgeWeight weight;
+ unsigned seq;
+ VertexID link;
+ };
+
+ class oqgraph
+ {
+ oqgraph_share *const share;
+ oqgraph_cursor *cursor;
+ row row_info;
+
+ inline oqgraph(oqgraph_share*) throw();
+ inline ~oqgraph() throw();
+ public:
+
+ enum error_code
+ {
+ OK= 0,
+ NO_MORE_DATA,
+ EDGE_NOT_FOUND,
+ INVALID_WEIGHT,
+ DUPLICATE_EDGE,
+ CANNOT_ADD_VERTEX,
+ CANNOT_ADD_EDGE,
+ MISC_FAIL
+ };
+
+ struct current_row_st {};
+ static inline current_row_st current_row()
+ { return current_row_st(); }
+
+ unsigned vertices_count() const throw();
+ unsigned edges_count() const throw();
+
+ int delete_all(void) throw();
+
+ int insert_edge(VertexID, VertexID, EdgeWeight, bool=0) throw();
+ int modify_edge(VertexID, VertexID, EdgeWeight) throw();
+ int delete_edge(VertexID, VertexID) throw();
+
+ int modify_edge(current_row_st,
+ VertexID*, VertexID*, EdgeWeight*, bool=0) throw();
+ int delete_edge(current_row_st) throw();
+
+ int replace_edge(VertexID orig, VertexID dest, EdgeWeight weight) throw()
+ { return insert_edge(orig, dest, weight, true); }
+
+ int search(int*, VertexID*, VertexID*) throw();
+ int random(bool) throw();
+
+ int fetch_row(row&) throw();
+ int fetch_row(row&, const void*) throw();
+ void row_ref(void*) throw();
+
+ static oqgraph* create(oqgraph_share*) throw();
+ static oqgraph_share *create() throw();
+
+ static void free(oqgraph*) throw();
+ static void free(oqgraph_share*) throw();
+
+ static const size_t sizeof_ref;
+ };
+
+}
+#endif
diff --git a/storage/oqgraph/graphstore.c b/storage/oqgraph/graphstore.c
new file mode 100644
index 00000000000..c5478b56ca5
--- /dev/null
+++ b/storage/oqgraph/graphstore.c
@@ -0,0 +1,356 @@
+/*
+ * Graph Engine - Copyright (C) 2007 by Arjen Lentz (arjen@openquery.com.au)
+ * graphstore.c internal storage system
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <my_global.h>
+#include <my_sys.h>
+#include "graphstore.h"
+
+
+/*
+ create a new vertex, and add it to the list (or start a list)
+ NOTE! gspp is ptr to base ptr
+
+ returns 1 for ok, 0 for error
+*/
+static int _add_vertex (GRAPHSTORE **gspp, GRAPH_VERTEXID id)
+{
+ GRAPHSTORE *newgsp;
+ GRAPHSTORE *gscurp;
+
+ if (gspp == NULL)
+ return 0;
+
+ /* not allowing 0 */
+ if (!id)
+ return 0;
+
+ if (*gspp != NULL) {
+ for (gscurp = *gspp; gscurp != NULL; gscurp = gscurp->next) {
+ if (gscurp->vertex->id == id)
+ return 1; /* we can ignore, id already exists */
+ }
+ }
+
+ /* allocate and initialise */
+ if ((newgsp = my_malloc(sizeof (GRAPHSTORE),MYF(MY_ZEROFILL))) == NULL)
+ return 0;
+
+ if ((newgsp->vertex = my_malloc(sizeof (GRAPH_VERTEX),MYF(MY_ZEROFILL))) == NULL) {
+ my_free(newgsp,MYF(0));
+ return 0;
+ }
+
+ newgsp->vertex->id = id;
+ /* add new vertex to end of list */
+ if (*gspp != NULL) {
+ for (gscurp = *gspp; gscurp->next != NULL; gscurp = gscurp->next);
+ gscurp->next = newgsp;
+ }
+ else /* new list */
+ *gspp = newgsp;
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ find a vertex by id
+
+ returns ptr or NULL
+*/
+static GRAPH_VERTEX *_find_vertex (GRAPHSTORE *gsp, GRAPH_VERTEXID id)
+{
+ /* just loop through the list to find id */
+ while (gsp != NULL && gsp->vertex->id != id)
+ gsp = gsp->next;
+
+ /* return ptr to vertex, or NULL */
+ return (gsp != NULL ? gsp->vertex : NULL);
+}
+
+
+/*
+ add edge
+ both vertices must already exist; graphstore_insert() does this
+
+ return 1 for ok, 0 for error (already exists, alloc error, etc)
+*/
+static int _add_edge (GRAPHSTORE *gsp, GRAPH_VERTEXID origid, GRAPH_VERTEXID destid, GRAPH_WEIGHT weight)
+{
+ GRAPH_VERTEX *origvp, *destvp;
+ GRAPH_EDGE *ep, *newep;
+
+ /* find both vertices */
+ if ((origvp = _find_vertex(gsp,origid)) == NULL ||
+ (destvp = _find_vertex(gsp,destid)) == NULL)
+ return 0;
+
+ /* check if edge already exists */
+ for (ep = origvp->forward_edge; ep != NULL; ep = ep->next_edge) {
+ if (ep->vertex->id == destid)
+ return 0;
+ }
+
+ /* allocate and initialise new edge */
+ if ((newep = my_malloc(sizeof (GRAPH_EDGE),MYF(MY_ZEROFILL))) == NULL)
+ return 0;
+
+ newep->vertex = destvp;
+ newep->weight = weight;
+
+ /* insert new edge at start of chain, that's easiest */
+ ep = origvp->forward_edge;
+ origvp->forward_edge = newep;
+ newep->next_edge = ep;
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ create a new row, and add it to the graph set (or start set)
+ NOTE! gsetpp is ptr to base ptr
+
+ returns 1 for ok, 0 for error
+*/
+static int _add_graph_set (GRAPH_SET **gsetpp, GRAPH_TUPLE *gtp)
+{
+ GRAPH_SET *newgsetp;
+ GRAPH_SET *gsetcurp;
+
+ if (gsetpp == NULL || gtp == NULL)
+ return 0;
+
+ /* allocate and initialise */
+ if ((newgsetp = my_malloc(sizeof (GRAPH_SET),MYF(MY_ZEROFILL))) == NULL)
+ return 0;
+
+ /* put in the data */
+ memcpy(&newgsetp->tuple,gtp,sizeof (GRAPH_TUPLE));
+
+ /* add new row to end of set */
+ if (*gsetpp != NULL) {
+ for (gsetcurp = *gsetpp; gsetcurp->next != NULL; gsetcurp = gsetcurp->next);
+ gsetcurp->next = newgsetp;
+ }
+ else { /* new set */
+ *gsetpp = newgsetp;
+ }
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ free a graph set (release memory)
+
+ returns 1 for ok, 0 for error
+*/
+int free_graph_set (GRAPH_SET *gsetp)
+{
+ GRAPH_SET *nextgsetp;
+
+ if (gsetp == NULL)
+ return 0;
+
+ while (gsetp != NULL) {
+ nextgsetp = gsetp->next;
+ /* free() is a void function, nothing to check */
+ my_free(gsetp,MYF(0));
+ gsetp = nextgsetp;
+ }
+
+ /* ok */
+ return 1;
+}
+
+
+/*
+ insert new data into graphstore
+ this can be either a vertex or an edge, depending on the params
+ NOTE! gspp is ptr to base ptr
+
+ returns 1 for ok, 0 for error
+*/
+int graphstore_insert (GRAPHSTORE **gspp, GRAPH_TUPLE *gtp)
+{
+ if (gspp == NULL)
+ return 0;
+
+ /* if nada or no orig vertex, we can't do anything */
+ if (gtp == NULL || !gtp->origid)
+ return 0;
+
+#if 0
+printf("inserting: origid=%lu destid=%lu weight=%lu\n",gtp->origid,gtp->destid,gtp->weight);
+#endif
+
+ if (!gtp->destid) /* no edge param so just adding vertex */
+ return _add_vertex(gspp,gtp->origid);
+
+ /*
+ add an edge
+ first add both vertices just in case they didn't yet exist...
+ not checking result there: if there's a prob, _add_edge() will catch.
+ */
+ _add_vertex(gspp,gtp->origid);
+ _add_vertex(gspp,gtp->destid);
+ return _add_edge(*gspp,gtp->origid,gtp->destid,gtp->weight);
+}
+
+
+/*
+ this is an internal function used by graphstore_query()
+
+ find any path from originating vertex to destid
+ if found, add to the result set on the way back
+ NOTE: recursive function!
+
+ returns 1 for hit, 0 for nothing, -1 for error
+*/
+int _find_any_path(GRAPH_SET **gsetpp, GRAPH_VERTEXID origid, GRAPH_VERTEXID destid, GRAPH_VERTEX *gvp, GRAPH_SEQ depth)
+{
+ GRAPH_EDGE *gep;
+ GRAPH_TUPLE tup;
+ int res;
+
+ if (gvp->id == destid) {
+ /* found target! */
+ bzero(&tup,sizeof (GRAPH_TUPLE));
+ tup.origid = origid;
+ tup.destid = destid;
+ tup.seq = depth;
+ tup.linkid = gvp->id;
+ return (_add_graph_set(gsetpp,&tup) ? 1 : -1);
+ }
+
+ /* walk through all edges for this vertex */
+ for (gep = gvp->forward_edge; gep; gep = gep->next_edge) {
+ /* recurse */
+ res = _find_any_path(gsetpp,origid,destid,gep->vertex,depth+1);
+ if (res < 0)
+ return res;
+ if (res > 0) {
+ /* found somewhere below this one, insert ourselves and return */
+ bzero(&tup,sizeof (GRAPH_TUPLE));
+ tup.origid = origid;
+ tup.destid = destid;
+ tup.weight = gep->weight;
+ tup.seq = depth;
+ tup.linkid = gvp->id;
+ return (_add_graph_set(gsetpp,&tup) ? 1 : -1);
+ }
+ }
+
+ /* nothing found but no error */
+ return 0;
+}
+
+
+/*
+ query graphstore
+ latch specifies what operation to perform
+
+ we need to feed the conditions in... (through engine condition pushdown)
+ for now we just presume one condition per field so we just feed in a tuple
+ this also means we can just find constants, not ranges
+
+ return ptr to GRAPH_SET
+ caller must free with free_graph_set()
+*/
+GRAPH_SET *graphstore_query (GRAPHSTORE *gsp, GRAPH_TUPLE *gtp)
+{
+ GRAPH_SET *gsetp = NULL;
+ GRAPH_SET *gsetcurp;
+ GRAPH_SET *newgsetp;
+
+ if (gsp == NULL || gtp == NULL)
+ return (NULL);
+
+ switch (gtp->latch) {
+ case 0: /* return all vertices/edges */
+ {
+ GRAPHSTORE *gscurp;
+ GRAPH_EDGE *gep;
+ GRAPH_TUPLE tup;
+
+ /* walk through all vertices */
+ for (gscurp = gsp; gscurp != NULL; gscurp = gscurp->next) {
+ /* check for condition */
+ if (gtp->origid && gscurp->vertex->id != gtp->origid)
+ continue;
+
+ bzero(&tup,sizeof (GRAPH_TUPLE));
+ tup.origid = gscurp->vertex->id;
+
+ /* no edges? */
+ if (gscurp->vertex->forward_edge == NULL) {
+ /* just add vertex to set */
+ if (!_add_graph_set(&gsetp,&tup)) {
+ if (gsetp != NULL) /* clean up */
+ my_free(gsetp,MYF(0));
+ return (NULL);
+ }
+ }
+ else {
+ /* walk through all edges */
+ for (gep = gscurp->vertex->forward_edge; gep; gep = gep->next_edge) {
+ tup.destid = gep->vertex->id;
+ tup.weight = gep->weight;
+
+ /* just add vertex to set */
+ if (!_add_graph_set(&gsetp,&tup)) {
+ if (gsetp != NULL) /* clean up */
+ my_free(gsetp,MYF(0));
+ return (NULL);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case 1: /* find a path between origid and destid */
+ /* yes it'll just go with the first path it finds! */
+ {
+ GRAPHSTORE *gscurp;
+ GRAPH_VERTEX *origvp;
+ GRAPH_TUPLE tup;
+
+ if (!gtp->origid || !gtp->destid)
+ return NULL;
+
+ /* find both vertices */
+ if ((origvp = _find_vertex(gsp,gtp->origid)) == NULL ||
+ _find_vertex(gsp,gtp->destid) == NULL)
+ return NULL;
+
+ if (_find_any_path(&gsetp,gtp->origid,gtp->destid,origvp,0) < 0) { /* error? */
+ if (gsetp != NULL) /* clean up */
+ my_free(gsetp,MYF(0));
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ /* this ends up being an empty set */
+ break;
+ }
+
+ /* Fix up latch column with the proper value - to be relationally correct */
+ for (gsetcurp = gsetp; gsetcurp != NULL; gsetcurp = gsetcurp->next)
+ gsetcurp->tuple.latch = gtp->latch;
+
+ return gsetp;
+}
+
+
+
+/* end of graphstore.c */ \ No newline at end of file
diff --git a/storage/oqgraph/graphstore.h b/storage/oqgraph/graphstore.h
new file mode 100644
index 00000000000..61862221455
--- /dev/null
+++ b/storage/oqgraph/graphstore.h
@@ -0,0 +1,90 @@
+/*
+ * Graph Engine - Copyright (C) 2007 by Arjen Lentz (arjen@openquery.com.au)
+ * graphstore.h internal storage system
+ */
+//typedef unsigned short uint16;
+//typedef unsigned long long uint64;
+
+
+/*
+ This is essentially what a GRAPH engine table looks like on the MySQL end:
+ CREATE TABLE foo (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight BIGINT UNSIGNED NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL
+ ) ENGINE=OQGRAPH
+*/
+
+
+/*
+ We represent the above in C in the following way:
+*/
+typedef uint16 GRAPH_LATCH;
+typedef uint64 GRAPH_VERTEXID;
+typedef uint64 GRAPH_WEIGHT;
+typedef uint64 GRAPH_SEQ;
+
+typedef struct graph_tuple {
+ GRAPH_LATCH latch; /* function */
+ GRAPH_VERTEXID origid; /* vertex (should be != 0) */
+ GRAPH_VERTEXID destid; /* edge */
+ GRAPH_WEIGHT weight; /* weight */
+ GRAPH_SEQ seq; /* seq# within (origid) */
+ GRAPH_VERTEXID linkid; /* current step between origid/destid */
+} GRAPH_TUPLE;
+
+typedef struct graph_set {
+ GRAPH_TUPLE tuple;
+ struct graph_set *next;
+} GRAPH_SET;
+
+
+/*
+ Internally, sets look nothing like the above
+
+ - We have vertices, connected by edges.
+ - Each vertex' edges are maintained in a linked list.
+ - Edges can be weighted.
+
+ There are some issues with this structure, it'd be a pest to do a delete
+ So for now, let's just not support deletes!
+*/
+/* the below is half-gross and will likely change */
+typedef struct graph_edge {
+ struct graph_vertex {
+ GRAPH_VERTEXID id;
+ struct graph_edge *forward_edge;
+ } *vertex;
+ GRAPH_WEIGHT weight;
+ struct graph_edge *next_edge;
+} GRAPH_EDGE;
+
+typedef struct graph_vertex GRAPH_VERTEX;
+
+
+/*
+ A rough internal storage system for a set
+*/
+/* this below is fully gross and will definitely change */
+typedef struct graphstore {
+ GRAPH_VERTEX *vertex; /* changed to ptr when integrating into MySQL */
+ struct graphstore *next;
+} GRAPHSTORE;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* public function declarations */
+int graphstore_insert (GRAPHSTORE **gspp, GRAPH_TUPLE *gtp);
+GRAPH_SET *graphstore_query (GRAPHSTORE *gsp, GRAPH_TUPLE *gtp);
+int free_graph_set (GRAPH_SET *gsetp);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* end of graphstore.h */ \ No newline at end of file
diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc
new file mode 100644
index 00000000000..e0c66134858
--- /dev/null
+++ b/storage/oqgraph/ha_oqgraph.cc
@@ -0,0 +1,1041 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+ Portions of this file copyright (C) 2000-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph@openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#define MYSQL_SERVER // to have THD
+#include "mysql_priv.h"
+#if MYSQL_VERSION_ID >= 50100
+#include <mysql/plugin.h>
+#endif
+
+#ifdef HAVE_OQGRAPH
+
+#include "ha_oqgraph.h"
+#include "graphcore.h"
+
+#define OQGRAPH_STATS_UPDATE_THRESHOLD 10
+
+using namespace open_query;
+
+
+struct oqgraph_info_st
+{
+ THR_LOCK lock;
+ oqgraph_share *graph;
+ uint use_count;
+ uint key_stat_version;
+ uint records;
+ bool dropped;
+ char name[FN_REFLEN+1];
+};
+
+static const char oqgraph_description[]=
+ "Open Query Graph Computation Engine, stored in memory "
+ "(http://openquery.com/graph)";
+
+#if MYSQL_VERSION_ID < 50100
+static bool oqgraph_init();
+
+handlerton oqgraph_hton= {
+ "OQGRAPH",
+ SHOW_OPTION_YES,
+ oqgraph_description,
+ DB_TYPE_OQGRAPH,
+ oqgraph_init,
+ 0, /* slot */
+ 0, /* savepoint size. */
+ NULL, /* close_connection */
+ NULL, /* savepoint */
+ NULL, /* rollback to savepoint */
+ NULL, /* release savepoint */
+ NULL, /* commit */
+ NULL, /* rollback */
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_NO_FLAGS
+};
+
+#define STATISTIC_INCREMENT(X) \
+statistic_increment(table->in_use->status_var.X, &LOCK_status)
+#define MOVE(X) move_field(X)
+#define RECORDS records
+#else
+#define STATISTIC_INCREMENT(X) ha_statistic_increment(&SSV::X)
+#define MOVE(X) move_field_offset(X)
+#define RECORDS stats.records
+#endif
+
+static HASH oqgraph_open_tables;
+static pthread_mutex_t LOCK_oqgraph;
+static bool oqgraph_init_done= 0;
+
+#if MYSQL_VERSION_ID >= 50130
+#define HASH_KEY_LENGTH size_t
+#else
+#define HASH_KEY_LENGTH uint
+#endif
+
+static uchar* get_key(const uchar *ptr, HASH_KEY_LENGTH *length,
+ my_bool)
+{
+ const OQGRAPH_INFO *share= (const OQGRAPH_INFO*) ptr;
+ *length= strlen(share->name);
+ return (uchar*) share->name;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+static handler* oqgraph_create_handler(handlerton *hton, TABLE_SHARE *table,
+ MEM_ROOT *mem_root)
+{
+ return new (mem_root) ha_oqgraph(hton, table);
+}
+
+static int oqgraph_init(handlerton *hton)
+{
+#else
+static bool oqgraph_init()
+{
+ if (have_oqgraph == SHOW_OPTION_DISABLED)
+ return 1;
+#endif
+ if (pthread_mutex_init(&LOCK_oqgraph, MY_MUTEX_INIT_FAST))
+ goto error;
+ if (hash_init(&oqgraph_open_tables, &my_charset_bin, 32, 0, 0,
+ get_key, 0, 0))
+ {
+ pthread_mutex_destroy(&LOCK_oqgraph);
+ goto error;
+ }
+#if MYSQL_VERSION_ID >= 50100
+ hton->state= SHOW_OPTION_YES;
+ hton->db_type= DB_TYPE_AUTOASSIGN;
+ hton->create= oqgraph_create_handler;
+ hton->flags= HTON_NO_FLAGS;
+#endif
+ oqgraph_init_done= TRUE;
+ return 0;
+error:
+#if MYSQL_VERSION_ID < 50100
+ have_oqgraph= SHOW_OPTION_DISABLED;
+#endif
+ return 1;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+static int oqgraph_fini(void *)
+{
+ hash_free(&oqgraph_open_tables);
+ pthread_mutex_destroy(&LOCK_oqgraph);
+ oqgraph_init_done= FALSE;
+ return 0;
+}
+#endif
+
+static OQGRAPH_INFO *get_share(const char *name, TABLE *table=0)
+{
+ OQGRAPH_INFO *share;
+ uint length= strlen(name);
+
+ safe_mutex_assert_owner(&LOCK_oqgraph);
+ if (!(share= (OQGRAPH_INFO*) hash_search(&oqgraph_open_tables,
+ (byte*) name, length)))
+ {
+ if (!table ||
+ !(share= new OQGRAPH_INFO))
+ return 0;
+ share->use_count= share->key_stat_version= share->records= 0;
+ share->dropped= 0;
+ strmov(share->name, name);
+ if (!(share->graph= oqgraph::create()))
+ {
+ delete share;
+ return 0;
+ }
+ if (my_hash_insert(&oqgraph_open_tables, (byte*) share))
+ {
+ oqgraph::free(share->graph);
+ delete share;
+ return 0;
+ }
+ thr_lock_init(&share->lock);
+ }
+ share->use_count++;
+ return share;
+}
+
+static int free_share(OQGRAPH_INFO *share, bool drop=0)
+{
+ safe_mutex_assert_owner(&LOCK_oqgraph);
+ if (!share)
+ return 0;
+ if (drop)
+ {
+ share->dropped= true;
+ hash_delete(&oqgraph_open_tables, (byte*) share);
+ }
+ if (!--share->use_count)
+ {
+ if (share->dropped)
+ {
+ thr_lock_delete(&share->lock);
+ oqgraph::free(share->graph);
+ delete share;
+ }
+ }
+ return 0;
+}
+
+static int error_code(int res)
+{
+ switch (res)
+ {
+ case oqgraph::OK:
+ return 0;
+ case oqgraph::NO_MORE_DATA:
+ return HA_ERR_END_OF_FILE;
+ case oqgraph::EDGE_NOT_FOUND:
+ return HA_ERR_KEY_NOT_FOUND;
+ case oqgraph::INVALID_WEIGHT:
+ return HA_ERR_AUTOINC_ERANGE;
+ case oqgraph::DUPLICATE_EDGE:
+ return HA_ERR_FOUND_DUPP_KEY;
+ case oqgraph::CANNOT_ADD_VERTEX:
+ case oqgraph::CANNOT_ADD_EDGE:
+ return HA_ERR_RECORD_FILE_FULL;
+ case oqgraph::MISC_FAIL:
+ default:
+ return HA_ERR_CRASHED_ON_USAGE;
+ }
+}
+
+/**
+ * Check if table complies with our designated structure
+ *
+ * ColName Type Attributes
+ * ======= ======== =============
+ * latch SMALLINT UNSIGNED NULL
+ * origid BIGINT UNSIGNED NULL
+ * destid BIGINT UNSIGNED NULL
+ * weight DOUBLE NULL
+ * seq BIGINT UNSIGNED NULL
+ * linkid BIGINT UNSIGNED NULL
+ * =================================
+ *
+ CREATE TABLE foo (
+ latch SMALLINT UNSIGNED NULL,
+ origid BIGINT UNSIGNED NULL,
+ destid BIGINT UNSIGNED NULL,
+ weight DOUBLE NULL,
+ seq BIGINT UNSIGNED NULL,
+ linkid BIGINT UNSIGNED NULL,
+ KEY (latch, origid, destid) USING HASH,
+ KEY (latch, destid, origid) USING HASH
+ ) ENGINE=OQGRAPH
+
+ */
+static int oqgraph_check_table_structure (TABLE *table_arg)
+{
+ int i;
+ struct { const char *colname; int coltype; } skel[] = {
+ { "latch" , MYSQL_TYPE_SHORT },
+ { "origid", MYSQL_TYPE_LONGLONG },
+ { "destid", MYSQL_TYPE_LONGLONG },
+ { "weight", MYSQL_TYPE_DOUBLE },
+ { "seq" , MYSQL_TYPE_LONGLONG },
+ { "linkid", MYSQL_TYPE_LONGLONG },
+ { NULL , 0}
+ };
+
+ DBUG_ENTER("ha_oqgraph::table_structure_ok");
+
+ Field **field= table_arg->field;
+ for (i= 0; *field && skel[i].colname; i++, field++) {
+ /* Check Column Type */
+ if ((*field)->type() != skel[i].coltype)
+ DBUG_RETURN(-1);
+ if (skel[i].coltype != MYSQL_TYPE_DOUBLE) {
+ /* Check Is UNSIGNED */
+ if (!((*field)->flags & UNSIGNED_FLAG ))
+ DBUG_RETURN(-1);
+ }
+ /* Check THAT NOT NULL isn't set */
+ if ((*field)->flags & NOT_NULL_FLAG)
+ DBUG_RETURN(-1);
+ /* Check the column name */
+ if (strcmp(skel[i].colname,(*field)->field_name))
+ DBUG_RETURN(-1);
+ }
+
+ if (skel[i].colname || *field || !table_arg->key_info || !table_arg->s->keys)
+ DBUG_RETURN(-1);
+
+ KEY *key= table_arg->key_info;
+ for (uint i= 0; i < table_arg->s->keys; ++i, ++key)
+ {
+ Field **field= table_arg->field;
+ /* check that the first key part is the latch and it is a hash key */
+ if (!(field[0] == key->key_part[0].field &&
+ HA_KEY_ALG_HASH == key->algorithm))
+ DBUG_RETURN(-1);
+ if (key->key_parts == 3)
+ {
+ /* KEY (latch, origid, destid) USING HASH */
+ /* KEY (latch, destid, origid) USING HASH */
+ if (!(field[1] == key->key_part[1].field &&
+ field[2] == key->key_part[2].field) &&
+ !(field[1] == key->key_part[2].field &&
+ field[2] == key->key_part[1].field))
+ DBUG_RETURN(-1);
+ }
+ else
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+/*****************************************************************************
+** OQGRAPH tables
+*****************************************************************************/
+
+#if MYSQL_VERSION_ID >= 50100
+ha_oqgraph::ha_oqgraph(handlerton *hton, TABLE_SHARE *table_arg)
+ : handler(hton, table_arg),
+#else
+ha_oqgraph::ha_oqgraph(TABLE *table_arg)
+ : handler(&oqgraph_hton, table_arg),
+#endif
+ share(0), graph(0), records_changed(0), key_stat_version(0)
+{ }
+
+
+static const char *ha_oqgraph_exts[] =
+{
+ NullS
+};
+
+const char **ha_oqgraph::bas_ext() const
+{
+ return ha_oqgraph_exts;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+ulonglong ha_oqgraph::table_flags() const
+#else
+ulong ha_oqgraph::table_flags() const
+#endif
+{
+ return (HA_NO_BLOBS | HA_NULL_IN_KEY |
+ HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED |
+ HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE);
+}
+
+ulong ha_oqgraph::index_flags(uint inx, uint part, bool all_parts) const
+{
+ return HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR;
+}
+
+int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
+{
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if ((share = get_share(name, table)))
+ {
+ ref_length= oqgraph::sizeof_ref;
+ }
+
+ if (share)
+ {
+ /* Initialize variables for the opened table */
+ thr_lock_data_init(&share->lock, &lock, NULL);
+
+ graph= oqgraph::create(share->graph);
+
+ /*
+ We cannot run update_key_stats() here because we do not have a
+ lock on the table. The 'records' count might just be changed
+ temporarily at this moment and we might get wrong statistics (Bug
+ #10178). Instead we request for update. This will be done in
+ ha_oqgraph::info(), which is always called before key statistics are
+ used.
+ */
+ key_stat_version= share->key_stat_version-1;
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+
+ return (share ? 0 : 1);
+}
+
+int ha_oqgraph::close(void)
+{
+ pthread_mutex_lock(&LOCK_oqgraph);
+ oqgraph::free(graph); graph= 0;
+ int res= free_share(share);
+ pthread_mutex_unlock(&LOCK_oqgraph);
+ return error_code(res);
+}
+
+void ha_oqgraph::update_key_stats()
+{
+ for (uint i= 0; i < table->s->keys; i++)
+ {
+ KEY *key=table->key_info+i;
+ if (!key->rec_per_key)
+ continue;
+ if (key->algorithm != HA_KEY_ALG_BTREE)
+ {
+ if (key->flags & HA_NOSAME)
+ key->rec_per_key[key->key_parts-1]= 1;
+ else
+ {
+ unsigned vertices= graph->vertices_count();
+ unsigned edges= graph->edges_count();
+ uint no_records= vertices ? 2 * (edges + vertices) / vertices : 2;
+ if (no_records < 2)
+ no_records= 2;
+ key->rec_per_key[key->key_parts-1]= no_records;
+ }
+ }
+ }
+ records_changed= 0;
+ /* At the end of update_key_stats() we can proudly claim they are OK. */
+ key_stat_version= share->key_stat_version;
+}
+
+
+int ha_oqgraph::write_row(byte * buf)
+{
+ int res= oqgraph::MISC_FAIL;
+ Field ** const field= table->field;
+ STATISTIC_INCREMENT(ha_write_count);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ field[3]->MOVE(ptrdiff);
+ }
+
+ if (!field[1]->is_null() && !field[2]->is_null())
+ {
+ VertexID orig_id= (VertexID) field[1]->val_int();
+ VertexID dest_id= (VertexID) field[2]->val_int();
+ EdgeWeight weight= 1;
+
+ if (!field[3]->is_null())
+ weight= (EdgeWeight) field[3]->val_real();
+
+ if (!(res= graph->insert_edge(orig_id, dest_id, weight, replace_dups)))
+ {
+ ++records_changed;
+ share->records++;
+ }
+ if (res == oqgraph::DUPLICATE_EDGE && ignore_dups && !insert_dups)
+ res= oqgraph::OK;
+ }
+
+ if (ptrdiff)
+ {
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ field[3]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+
+ if (!res && records_changed*OQGRAPH_STATS_UPDATE_THRESHOLD > share->records)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+
+ return error_code(res);
+}
+
+int ha_oqgraph::update_row(const byte * old, byte * buf)
+{
+ int res= oqgraph::MISC_FAIL;
+ VertexID orig_id, dest_id;
+ EdgeWeight weight= 1;
+ Field **field= table->field;
+ STATISTIC_INCREMENT(ha_update_count);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ field[3]->MOVE(ptrdiff);
+ }
+
+ if (inited == INDEX || inited == RND)
+ {
+ VertexID *origp= 0, *destp= 0;
+ EdgeWeight *weightp= 0;
+ if (!field[1]->is_null())
+ *(origp= &orig_id)= (VertexID) field[1]->val_int();
+ if (!field[2]->is_null())
+ *(destp= &dest_id)= (VertexID) field[2]->val_int();
+ if (!field[3]->is_null())
+ *(weightp= &weight)= (EdgeWeight) field[3]->val_real();
+
+ my_ptrdiff_t ptrdiff2= old - buf;
+
+ field[0]->MOVE(ptrdiff2);
+ field[1]->MOVE(ptrdiff2);
+ field[2]->MOVE(ptrdiff2);
+ field[3]->MOVE(ptrdiff2);
+
+ if (field[0]->is_null())
+ {
+ if (!origp == field[1]->is_null() &&
+ *origp == (VertexID) field[1]->val_int())
+ origp= 0;
+ if (!destp == field[2]->is_null() &&
+ *destp == (VertexID) field[2]->val_int())
+ origp= 0;
+ if (!weightp == field[3]->is_null() &&
+ *weightp == (VertexID) field[3]->val_real())
+ weightp= 0;
+
+ if (!(res= graph->modify_edge(oqgraph::current_row(),
+ origp, destp, weightp, replace_dups)))
+ ++records_changed;
+ else if (ignore_dups && res == oqgraph::DUPLICATE_EDGE)
+ res= oqgraph::OK;
+ }
+
+ field[0]->MOVE(-ptrdiff2);
+ field[1]->MOVE(-ptrdiff2);
+ field[2]->MOVE(-ptrdiff2);
+ field[3]->MOVE(-ptrdiff2);
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ field[3]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+
+ if (!res && records_changed*OQGRAPH_STATS_UPDATE_THRESHOLD > share->records)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+ return error_code(res);
+}
+
+int ha_oqgraph::delete_row(const byte * buf)
+{
+ int res= oqgraph::EDGE_NOT_FOUND;
+ Field **field= table->field;
+ STATISTIC_INCREMENT(ha_delete_count);
+
+ if (inited == INDEX || inited == RND)
+ {
+ if ((res= graph->delete_edge(oqgraph::current_row())) == oqgraph::OK)
+ {
+ ++records_changed;
+ share->records--;
+ }
+ }
+ if (res != oqgraph::OK)
+ {
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ }
+
+ if (field[0]->is_null() && !field[1]->is_null() && !field[2]->is_null())
+ {
+ VertexID orig_id= (VertexID) field[1]->val_int();
+ VertexID dest_id= (VertexID) field[2]->val_int();
+
+ if ((res= graph->delete_edge(orig_id, dest_id)) == oqgraph::OK)
+ {
+ ++records_changed;
+ share->records--;
+ }
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+ }
+
+ if (!res && table->s->tmp_table == NO_TMP_TABLE &&
+ records_changed*OQGRAPH_STATS_UPDATE_THRESHOLD > share->records)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+ return error_code(res);
+}
+
+int ha_oqgraph::index_read(byte * buf, const byte * key, uint key_len,
+ enum ha_rkey_function find_flag)
+{
+ DBUG_ASSERT(inited==INDEX);
+ return index_read_idx(buf, active_index, key, key_len, find_flag);
+}
+
+int ha_oqgraph::index_next_same(byte *buf, const byte *key, uint key_len)
+{
+ int res;
+ open_query::row row;
+ DBUG_ASSERT(inited==INDEX);
+ STATISTIC_INCREMENT(ha_read_key_count);
+ if (!(res= graph->fetch_row(row)))
+ res= fill_record(buf, row);
+ table->status= res ? STATUS_NOT_FOUND : 0;
+ return error_code(res);
+}
+
+int ha_oqgraph::index_read_idx(byte * buf, uint index, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag)
+{
+ Field **field= table->field;
+ KEY *key_info= table->key_info + index;
+ int res;
+ VertexID orig_id, dest_id;
+ int latch;
+ VertexID *orig_idp=0, *dest_idp=0;
+ int *latchp=0;
+ open_query::row row;
+ STATISTIC_INCREMENT(ha_read_key_count);
+
+ bmove_align(buf, table->s->default_values, table->s->reclength);
+ key_restore(buf, (byte*) key, key_info, key_len);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+#endif
+ my_ptrdiff_t ptrdiff= buf - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ }
+
+ if (!field[0]->is_null())
+ {
+ latch= (int) field[0]->val_int();
+ latchp= &latch;
+ }
+
+ if (!field[1]->is_null())
+ {
+ orig_id= (VertexID) field[1]->val_int();
+ orig_idp= &orig_id;
+ }
+
+ if (!field[2]->is_null())
+ {
+ dest_id= (VertexID) field[2]->val_int();
+ dest_idp= &dest_id;
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+#endif
+
+ res= graph->search(latchp, orig_idp, dest_idp);
+
+ if (!res && !(res= graph->fetch_row(row)))
+ res= fill_record(buf, row);
+ table->status = res ? STATUS_NOT_FOUND : 0;
+ return error_code(res);
+}
+
+int ha_oqgraph::fill_record(byte *record, const open_query::row &row)
+{
+ Field **field= table->field;
+
+ bmove_align(record, table->s->default_values, table->s->reclength);
+
+#if MYSQL_VERSION_ID >= 50100
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
+#endif
+ my_ptrdiff_t ptrdiff= record - table->record[0];
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(ptrdiff);
+ field[1]->MOVE(ptrdiff);
+ field[2]->MOVE(ptrdiff);
+ field[3]->MOVE(ptrdiff);
+ field[4]->MOVE(ptrdiff);
+ field[5]->MOVE(ptrdiff);
+ }
+
+ // just each field specifically, no sense iterating
+ if (row.latch_indicator)
+ {
+ field[0]->set_notnull();
+ field[0]->store((longlong) row.latch);
+ }
+
+ if (row.orig_indicator)
+ {
+ field[1]->set_notnull();
+ field[1]->store((longlong) row.orig);
+ }
+
+ if (row.dest_indicator)
+ {
+ field[2]->set_notnull();
+ field[2]->store((longlong) row.dest);
+ }
+
+ if (row.weight_indicator)
+ {
+ field[3]->set_notnull();
+ field[3]->store((double) row.weight);
+ }
+
+ if (row.seq_indicator)
+ {
+ field[4]->set_notnull();
+ field[4]->store((longlong) row.seq);
+ }
+
+ if (row.link_indicator)
+ {
+ field[5]->set_notnull();
+ field[5]->store((longlong) row.link);
+ }
+
+ if (ptrdiff)
+ {
+ field[0]->MOVE(-ptrdiff);
+ field[1]->MOVE(-ptrdiff);
+ field[2]->MOVE(-ptrdiff);
+ field[3]->MOVE(-ptrdiff);
+ field[4]->MOVE(-ptrdiff);
+ field[5]->MOVE(-ptrdiff);
+ }
+#if MYSQL_VERSION_ID >= 50100
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+#endif
+
+ return 0;
+}
+
+int ha_oqgraph::rnd_init(bool scan)
+{
+ return error_code(graph->random(scan));
+}
+
+int ha_oqgraph::rnd_next(byte *buf)
+{
+ int res;
+ open_query::row row;
+ STATISTIC_INCREMENT(ha_read_rnd_next_count);
+ if (!(res= graph->fetch_row(row)))
+ res= fill_record(buf, row);
+ table->status= res ? STATUS_NOT_FOUND: 0;
+ return error_code(res);
+}
+
+int ha_oqgraph::rnd_pos(byte * buf, byte *pos)
+{
+ int res;
+ open_query::row row;
+ STATISTIC_INCREMENT(ha_read_rnd_count);
+ if (!(res= graph->fetch_row(row, pos)))
+ res= fill_record(buf, row);
+ table->status=res ? STATUS_NOT_FOUND: 0;
+ return error_code(res);
+}
+
+void ha_oqgraph::position(const byte *record)
+{
+ graph->row_ref((void*) ref); // Ref is aligned
+}
+
+int ha_oqgraph::cmp_ref(const byte *ref1, const byte *ref2)
+{
+ return memcmp(ref1, ref2, oqgraph::sizeof_ref);
+}
+
+int ha_oqgraph::info(uint flag)
+{
+ RECORDS= graph->vertices_count() + graph->edges_count();
+#if 0
+ records= hp_info.records;
+ deleted= hp_info.deleted;
+ errkey= hp_info.errkey;
+ mean_rec_length= hp_info.reclength;
+ data_file_length= hp_info.data_length;
+ index_file_length= hp_info.index_length;
+ max_data_file_length= hp_info.max_records* hp_info.reclength;
+ delete_length= hp_info.deleted * hp_info.reclength;
+#endif
+ /*
+ If info() is called for the first time after open(), we will still
+ have to update the key statistics. Hoping that a table lock is now
+ in place.
+ */
+ if (key_stat_version != share->key_stat_version)
+ update_key_stats();
+ return 0;
+}
+
+int ha_oqgraph::extra(enum ha_extra_function operation)
+{
+ switch (operation)
+ {
+ case HA_EXTRA_IGNORE_DUP_KEY:
+ ignore_dups= true;
+ break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ ignore_dups= false;
+ insert_dups= false;
+ break;
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ replace_dups= true;
+ break;
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ replace_dups= false;
+ break;
+ case HA_EXTRA_INSERT_WITH_UPDATE:
+ insert_dups= true;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int ha_oqgraph::delete_all_rows()
+{
+ int res;
+ if (!(res= graph->delete_all()))
+ {
+ share->records= 0;
+ }
+
+ if (!res && table->s->tmp_table == NO_TMP_TABLE)
+ {
+ /*
+ We can perform this safely since only one writer at the time is
+ allowed on the table.
+ */
+ share->key_stat_version++;
+ }
+ return error_code(res);
+}
+
+int ha_oqgraph::external_lock(THD *thd, int lock_type)
+{
+ return 0; // No external locking
+}
+
+
+THR_LOCK_DATA **ha_oqgraph::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ lock.type=lock_type;
+ *to++= &lock;
+ return to;
+}
+
+/*
+ We have to ignore ENOENT entries as the HEAP table is created on open and
+ not when doing a CREATE on the table.
+*/
+
+int ha_oqgraph::delete_table(const char *name)
+{
+ int res= 0;
+ OQGRAPH_INFO *share;
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if ((share= get_share(name)))
+ {
+ res= free_share(share, true);
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+ return error_code(res);
+}
+
+int ha_oqgraph::rename_table(const char * from, const char * to)
+{
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if (OQGRAPH_INFO *share= get_share(from))
+ {
+ strmov(share->name, to);
+ hash_update(&oqgraph_open_tables, (byte*) share,
+ (byte*) from, strlen(from));
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+ return 0;
+}
+
+
+ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
+ key_range *max_key)
+{
+ KEY *key=table->key_info+inx;
+ //if (key->algorithm == HA_KEY_ALG_BTREE)
+ // return btree_records_in_range(file, inx, min_key, max_key);
+
+ if (!min_key || !max_key ||
+ min_key->length != max_key->length ||
+ min_key->length < key->key_length - key->key_part[2].store_length ||
+ min_key->flag != HA_READ_KEY_EXACT ||
+ max_key->flag != HA_READ_AFTER_KEY)
+ {
+ if (min_key->length == key->key_part[0].store_length)
+ {
+ // If latch is not null and equals 0, return # nodes
+ DBUG_ASSERT(key->key_part[0].store_length == 3);
+ if (key->key_part[0].null_bit && !min_key->key[0] &&
+ !min_key->key[1] && !min_key->key[2])
+ return graph->vertices_count();
+ }
+ return HA_POS_ERROR; // Can only use exact keys
+ }
+
+ if (RECORDS <= 1)
+ return RECORDS;
+
+ /* Assert that info() did run. We need current statistics here. */
+ DBUG_ASSERT(key_stat_version == share->key_stat_version);
+ ha_rows result= key->rec_per_key[key->key_parts-1];
+
+ return result;
+}
+
+
+int ha_oqgraph::create(const char *name, TABLE *table_arg,
+ HA_CREATE_INFO *create_info)
+{
+ int res = -1;
+ OQGRAPH_INFO *share;
+
+ pthread_mutex_lock(&LOCK_oqgraph);
+ if ((share= get_share(name)))
+ {
+ free_share(share);
+ }
+ else
+ {
+ if (!oqgraph_check_table_structure(table_arg))
+ res= 0;;
+ }
+ pthread_mutex_unlock(&LOCK_oqgraph);
+
+ if (this->share)
+ info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ return error_code(res);
+}
+
+
+void ha_oqgraph::update_create_info(HA_CREATE_INFO *create_info)
+{
+ table->file->info(HA_STATUS_AUTO);
+ //if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
+ // create_info->auto_increment_value= auto_increment_value;
+}
+
+#if MYSQL_VERSION_ID >= 50100
+struct st_mysql_storage_engine oqgraph_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(oqgraph)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &oqgraph_storage_engine,
+ "OQGRAPH",
+ "Arjen Lentz & Antony T Curtis, Open Query",
+ oqgraph_description,
+ PLUGIN_LICENSE_GPL,
+ (int (*)(void*)) oqgraph_init, /* Plugin Init */
+ oqgraph_fini, /* Plugin Deinit */
+ 0x0200, /* Version: 2.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ NULL /* config options */
+}
+mysql_declare_plugin_end;
+#endif
+
+#endif
diff --git a/storage/oqgraph/ha_oqgraph.h b/storage/oqgraph/ha_oqgraph.h
new file mode 100644
index 00000000000..dcc14b074da
--- /dev/null
+++ b/storage/oqgraph/ha_oqgraph.h
@@ -0,0 +1,114 @@
+/* Copyright (C) 2007-2009 Arjen G Lentz & Antony T Curtis for Open Query
+ Portions of this file copyright (C) 2000-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* ======================================================================
+ Open Query Graph Computation Engine, based on a concept by Arjen Lentz
+ Mk.II implementation by Antony Curtis & Arjen Lentz
+ For more information, documentation, support, enhancement engineering,
+ and non-GPL licensing, see http://openquery.com/graph
+ or contact graph@openquery.com
+ For packaged binaries, see http://ourdelta.org
+ ======================================================================
+*/
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+
+typedef struct oqgraph_info_st OQGRAPH_INFO;
+
+#if MYSQL_VERSION_ID >= 50120
+typedef uchar byte;
+#endif
+
+namespace open_query
+{
+ struct row;
+ class oqgraph;
+}
+
+/* class for the the Open Query Graph handler */
+
+class ha_oqgraph: public handler
+{
+ OQGRAPH_INFO *share;
+ open_query::oqgraph *graph;
+ THR_LOCK_DATA lock;
+ /* number of records changed since last statistics update */
+ uint records_changed;
+ uint key_stat_version;
+ bool replace_dups, ignore_dups, insert_dups;
+
+ int fill_record(byte*, const open_query::row&);
+
+public:
+#if MYSQL_VERSION_ID >= 50100
+ ha_oqgraph(handlerton *hton, TABLE_SHARE *table);
+ ulonglong table_flags() const;
+#else
+ ha_oqgraph(TABLE *table);
+ ulong table_flags() const;
+#endif
+ ~ha_oqgraph() {}
+ const char *table_type() const
+ {
+ return "OQGRAPH";
+ }
+ const char *index_type(uint inx)
+ {
+ return "HASH";
+ }
+ /* Rows also use a fixed-size format */
+ enum row_type get_row_type() const { return ROW_TYPE_FIXED; }
+ const char **bas_ext() const;
+ ulong index_flags(uint inx, uint part, bool all_parts) const;
+ uint max_supported_keys() const { return MAX_KEY; }
+ uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
+ double scan_time() { return (double) 1000000000; }
+ double read_time(uint index, uint ranges, ha_rows rows)
+ { return 1; }
+
+ int open(const char *name, int mode, uint test_if_locked);
+ int close(void);
+ int write_row(byte * buf);
+ int update_row(const byte * old_data, byte * new_data);
+ int delete_row(const byte * buf);
+ int index_read(byte * buf, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_read_idx(byte * buf, uint idx, const byte * key,
+ uint key_len, enum ha_rkey_function find_flag);
+ int index_next_same(byte * buf, const byte * key, uint key_len);
+ int rnd_init(bool scan);
+ int rnd_next(byte *buf);
+ int rnd_pos(byte * buf, byte *pos);
+ void position(const byte *record);
+ int info(uint);
+ int extra(enum ha_extra_function operation);
+ int external_lock(THD *thd, int lock_type);
+ int delete_all_rows(void);
+ ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
+ int delete_table(const char *from);
+ int rename_table(const char * from, const char * to);
+ int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
+ void update_create_info(HA_CREATE_INFO *create_info);
+
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type);
+ int cmp_ref(const byte *ref1, const byte *ref2);
+private:
+ void update_key_stats();
+};
diff --git a/storage/oqgraph/oqgraph_config.h.in b/storage/oqgraph/oqgraph_config.h.in
new file mode 100644
index 00000000000..18dad70a75d
--- /dev/null
+++ b/storage/oqgraph/oqgraph_config.h.in
@@ -0,0 +1,73 @@
+/* src/oqgraph_config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Enables DTRACE Support */
+#undef HAVE_DTRACE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <syslimits.h> header file. */
+#undef HAVE_SYSLIMITS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Source directory for MySQL */
+#undef MYSQL_SRC
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/storage/oqgraph/oqgraph_probes.d b/storage/oqgraph/oqgraph_probes.d
new file mode 100644
index 00000000000..bfdee29ba6e
--- /dev/null
+++ b/storage/oqgraph/oqgraph_probes.d
@@ -0,0 +1,19 @@
+/* Copyright (C) 2004-2005 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 */
+
+provider oqgraph {
+ probe open();
+ probe close();
+};
diff --git a/storage/oqgraph/plug.in b/storage/oqgraph/plug.in
new file mode 100644
index 00000000000..6331dade3dd
--- /dev/null
+++ b/storage/oqgraph/plug.in
@@ -0,0 +1,40 @@
+MYSQL_STORAGE_ENGINE(oqgraph,,[Graph Storage Engine],
+ [Open Query Graph Computation Engine], [])
+MYSQL_PLUGIN_DYNAMIC(oqgraph, [oqgraph_engine.la])
+MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(oqgraph, [ha_oqgraph.cc])
+MYSQL_PLUGIN_ACTIONS(oqgraph,[
+ AC_LANG_PUSH([C++])
+ AC_MSG_CHECKING([whether compiler supports -fvisibility-inlines-hidden])
+ OLD_CXXFLAGS=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden"
+ AC_TRY_COMPILE([],[],[
+ AM_CONDITIONAL(HAVE_FVISIBILITY_INLINES_HIDDEN, true)
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+ CXXFLAGS=$OLD_CXXFLAGS
+ AC_LANG_POP()
+])
+
+AM_CONDITIONAL([BUILD_OQGRAPH_FOR_MYSQL], true)
+AM_CONDITIONAL([BUILD_OQGRAPH_STANDALONE], false)
+AM_CONDITIONAL([HAVE_DTRACE], false)
+AM_CONDITIONAL(HAVE_FVISIBILITY_INLINES_HIDDEN, false)
+
+AC_LANG_PUSH([C++])
+
+AC_MSG_CHECKING([for Boost usable by OQGraph engine])
+AC_PREPROC_IFELSE(
+ [
+#include <boost/version.hpp>
+#if BOOST_VERSION >= 104000
+#else
+#error oops
+#endif
+ ],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ with_plugin_oqgraph=no])
+
+AC_LANG_POP()
diff --git a/storage/pbxt/src/datadic_xt.cc b/storage/pbxt/src/datadic_xt.cc
index 1a1ffeeb096..075d28edabe 100644
--- a/storage/pbxt/src/datadic_xt.cc
+++ b/storage/pbxt/src/datadic_xt.cc
@@ -396,7 +396,7 @@ void XTToken::expectNumber(XTThreadPtr self)
struct charset_info_st;
class XTTokenizer {
- struct charset_info_st *tkn_charset;
+ const struct charset_info_st *tkn_charset;
char *tkn_cstring;
char *tkn_curr_pos;
XTToken *tkn_current;
@@ -1324,7 +1324,7 @@ void XTParseTable::parseDropIndex(XTThreadPtr self)
class XTCreateTable : public XTParseTable {
public:
bool ct_convert;
- struct charset_info_st *ct_charset;
+ const struct charset_info_st *ct_charset;
XTPathStrPtr ct_tab_path;
u_int ct_contraint_no;
XTDDTable *ct_curr_table;
diff --git a/storage/pbxt/src/discover_xt.cc b/storage/pbxt/src/discover_xt.cc
index 2a42c77ac69..09a2b09015e 100644
--- a/storage/pbxt/src/discover_xt.cc
+++ b/storage/pbxt/src/discover_xt.cc
@@ -1622,7 +1622,8 @@ int xt_create_table_frm(handlerton *hton, THD* thd, const char *db, const char *
COLUMN_FORMAT_TYPE_FIXED,
#endif
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
- NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/))
+ NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/,
+ NULL /*vcol_info*/, NULL /* create options */))
#endif
goto error;
diff --git a/storage/pbxt/src/ha_pbxt.cc b/storage/pbxt/src/ha_pbxt.cc
index 5bf2069f656..ba3aa756516 100644
--- a/storage/pbxt/src/ha_pbxt.cc
+++ b/storage/pbxt/src/ha_pbxt.cc
@@ -1248,10 +1248,6 @@ static int pbxt_init(void *p)
* Only real problem, 2 threads try to load the same
* plugin at the same time.
*/
-#if MYSQL_VERSION_ID <= 50146
- extern myxt_mutex_t LOCK_plugin;
- myxt_mutex_unlock(&LOCK_plugin);
-#endif
#endif
/* Can't do this here yet, because I need a THD! */
@@ -1285,9 +1281,6 @@ static int pbxt_init(void *p)
if (thd)
myxt_destroy_thread(thd, FALSE);
-#if MYSQL_VERSION_ID <= 50146 && !defined(DRIZZLED)
- myxt_mutex_lock(&LOCK_plugin);
-#endif
}
#endif
}
@@ -2006,7 +1999,7 @@ static int pbxt_statistics_fill_table(THD *thd, TABLE_LIST *tables, COND *cond)
xt_ha_open_database_of_table(self, (XTPathStrPtr) NULL);
}
- err = myxt_statistics_fill_table(self, thd, tables, cond, system_charset_info);
+ err = myxt_statistics_fill_table(self, thd, tables, cond, (void*) system_charset_info);
}
catch_(a) {
err = xt_ha_pbxt_thread_error_for_mysql(thd, self, FALSE);
@@ -6076,6 +6069,40 @@ mysql_declare_plugin(pbxt)
drizzle_declare_plugin_end;
#else
mysql_declare_plugin_end;
+#ifdef MARIADB_BASE_VERSION
+maria_declare_plugin(pbxt)
+{ /* PBXT */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &pbxt_storage_engine,
+ "PBXT",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "High performance, multi-versioning transactional engine",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init, /* Plugin Init */
+ pbxt_end, /* Plugin Deinit */
+ 0x0001 /* 0.1 */,
+ NULL, /* status variables */
+ pbxt_system_variables, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+},
+{ /* PBXT_STATISTICS */
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &pbxt_statitics,
+ "PBXT_STATISTICS",
+ "Paul McCullagh, PrimeBase Technologies GmbH",
+ "PBXT internal system statitics",
+ PLUGIN_LICENSE_GPL,
+ pbxt_init_statistics, /* plugin init */
+ pbxt_exit_statistics, /* plugin deinit */
+ 0x0005,
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0.09g RC3", /* string version */
+ MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */
+}
+maria_declare_plugin_end;
+#endif
#endif
#if defined(XT_WIN) && defined(XT_COREDUMP)
diff --git a/storage/pbxt/src/myxt_xt.h b/storage/pbxt/src/myxt_xt.h
index 546b57c6e84..62caf1c3b61 100644
--- a/storage/pbxt/src/myxt_xt.h
+++ b/storage/pbxt/src/myxt_xt.h
@@ -69,17 +69,17 @@ void myxt_free_dictionary(XTThreadPtr self, XTDictionary *dic);
void myxt_move_dictionary(XTDictionaryPtr dic, XTDictionaryPtr source_dic);
XTDDTable *myxt_create_table_from_table(XTThreadPtr self, STRUCT_TABLE *my_tab);
-void myxt_static_convert_identifier(XTThreadPtr self, struct charset_info_st *cs, char *from, char *to, size_t to_len);
-char *myxt_convert_identifier(XTThreadPtr self, struct charset_info_st *cs, char *from);
+void myxt_static_convert_identifier(XTThreadPtr self, const struct charset_info_st *cs, char *from, char *to, size_t to_len);
+char *myxt_convert_identifier(XTThreadPtr self, const struct charset_info_st *cs, char *from);
void myxt_static_convert_table_name(XTThreadPtr self, char *from, char *to, size_t to_len);
void myxt_static_convert_file_name(char *from, char *to, size_t to_len);
char *myxt_convert_table_name(XTThreadPtr self, char *from);
int myxt_strcasecmp(char * a, char *b);
-int myxt_isspace(struct charset_info_st *cs, char a);
-int myxt_ispunct(struct charset_info_st *cs, char a);
-int myxt_isdigit(struct charset_info_st *cs, char a);
+int myxt_isspace(const struct charset_info_st *cs, char a);
+int myxt_ispunct(const struct charset_info_st *cs, char a);
+int myxt_isdigit(const struct charset_info_st *cs, char a);
-struct charset_info_st *myxt_getcharset(bool convert);
+const struct charset_info_st *myxt_getcharset(bool convert);
void *myxt_create_thread();
void myxt_destroy_thread(void *thread, xtBool end_threads);
diff --git a/storage/pbxt/src/xt_defs.h b/storage/pbxt/src/xt_defs.h
index 4a03f941cf8..98ebe0957a5 100644
--- a/storage/pbxt/src/xt_defs.h
+++ b/storage/pbxt/src/xt_defs.h
@@ -782,7 +782,7 @@ extern xtBool pbxt_crash_debug;
#define MX_ULONG_T uint32_t
#define MX_ULONGLONG_T uint64_t
#define MX_LONGLONG_T uint64_t
-#define MX_CHARSET_INFO struct charset_info_st
+#define MX_CHARSET_INFO const struct charset_info_st
#define MX_CONST_CHARSET_INFO const struct charset_info_st
#define MX_CONST const
#define MX_BITMAP MyBitmap
@@ -873,7 +873,7 @@ extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
#define MX_ULONGLONG_T ulonglong
#define MX_LONGLONG_T longlong
#define MX_CHARSET_INFO CHARSET_INFO
-#define MX_CONST_CHARSET_INFO struct charset_info_st
+#define MX_CONST_CHARSET_INFO const struct charset_info_st
#define MX_CONST
#define MX_BITMAP MY_BITMAP
#define MX_BIT_SIZE() n_bits
diff --git a/storage/sphinx/CMakeLists.txt b/storage/sphinx/CMakeLists.txt
new file mode 100644
index 00000000000..2bc04eefc44
--- /dev/null
+++ b/storage/sphinx/CMakeLists.txt
@@ -0,0 +1,11 @@
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+ADD_DEFINITIONS(-DMYSQL_SERVER)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include
+ ${CMAKE_SOURCE_DIR}/regex)
+
+SET(SPHINX_SOURCES ha_sphinx.cc)
+ADD_LIBRARY(sphinx ha_sphinx.cc)
diff --git a/storage/sphinx/Makefile.am b/storage/sphinx/Makefile.am
new file mode 100644
index 00000000000..5f58d673547
--- /dev/null
+++ b/storage/sphinx/Makefile.am
@@ -0,0 +1,55 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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
+
+#called from the top level Makefile
+
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+pkgplugindir = $(pkglibdir)/plugin
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir)
+
+DEFS= @DEFS@ -D_REENTRANT -D_PTHREADS -DMYSQL_SERVER
+
+noinst_HEADERS = ha_sphinx.h
+
+EXTRA_LTLIBRARIES = ha_sphinx.la
+pkgplugin_LTLIBRARIES = @plugin_sphinx_shared_target@ sphinx.la
+
+ha_sphinx_la_LDFLAGS = -module -rpath $(MYSQLLIBdir) \
+ -L$(top_builddir)/libservices -lmysqlservices
+ha_sphinx_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_sphinx_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_sphinx_la_SOURCES = ha_sphinx.cc
+
+sphinx_la_LDFLAGS = -module
+sphinx_la_CXXFLAGS = $(AM_CFLAGS)
+sphinx_la_CFLAGS = $(AM_CFLAGS)
+sphinx_la_SOURCES = snippets_udf.cc
+
+EXTRA_LIBRARIES = libsphinx.a
+noinst_LIBRARIES = @plugin_sphinx_static_target@
+libsphinx_a_CXXFLAGS = $(AM_CFLAGS)
+libsphinx_a_CFLAGS = $(AM_CFLAGS)
+libsphinx_a_SOURCES= ha_sphinx.cc
+
+EXTRA_DIST = CMakeLists.txt
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/storage/sphinx/gen_data.php b/storage/sphinx/gen_data.php
new file mode 100644
index 00000000000..dac374f095d
--- /dev/null
+++ b/storage/sphinx/gen_data.php
@@ -0,0 +1,37 @@
+<?php
+
+$file_name= $argv[1];
+
+//echo $file_name;
+
+$cont= file_get_contents($file_name);
+
+$words= explode(" ", $cont);
+
+//echo "words: ".(count($words))."\n";
+
+$cw = count($words);
+
+echo "REPLACE INTO test.documents ( id, group_id, date_added, title, content ) VALUES\n";
+
+
+for ($i=1; $i<=100000; $i++)
+{
+ $count_words= mt_rand(10,30);
+ $pred = "";
+ for ($j=0; $j<$count_words; $j++)
+ {
+ $pred .= chop($words[mt_rand(1, $cw-1)])." ";
+ }
+ $count_words= mt_rand(3,5);
+ $tit = "";
+ for ($j=0; $j<$count_words; $j++)
+ {
+ $tit .= chop($words[mt_rand(1, $cw-1)])." ";
+ }
+ echo "($i,".mt_rand(1,20).",NOW(),'".addslashes($tit)."','".addslashes($pred)."'),\n";
+}
+ echo "(0,1,now(),'end','eND');\n";
+
+
+?>
diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc
new file mode 100644
index 00000000000..c66c1344138
--- /dev/null
+++ b/storage/sphinx/ha_sphinx.cc
@@ -0,0 +1,3115 @@
+//
+// $Id: ha_sphinx.cc 2058 2009-11-07 04:01:57Z shodan $
+//
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#if _MSC_VER>=1400
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+#include <mysql_version.h>
+
+#if MYSQL_VERSION_ID>50100
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+#else
+#include "../mysql_priv.h"
+#endif
+
+#include <mysys_err.h>
+#include <my_sys.h>
+
+#ifndef __WIN__
+ // UNIX-specific
+ #include <my_net.h>
+ #include <netdb.h>
+ #include <sys/un.h>
+
+ #define RECV_FLAGS MSG_WAITALL
+
+ #define sphSockClose(_sock) ::close(_sock)
+#else
+ // Windows-specific
+ #include <io.h>
+ #define strcasecmp stricmp
+ #define snprintf _snprintf
+
+ #define RECV_FLAGS 0
+
+ #define sphSockClose(_sock) ::closesocket(_sock)
+#endif
+
+#include <ctype.h>
+#include "ha_sphinx.h"
+
+#ifndef MSG_WAITALL
+#define MSG_WAITALL 0
+#endif
+
+#if _MSC_VER>=1400
+#pragma warning(push,4)
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+/// there might be issues with min() on different platforms (eg. Gentoo, they say)
+#define Min(a,b) ((a)<(b)?(a):(b))
+
+/// unaligned RAM accesses are forbidden on SPARC
+#if defined(sparc) || defined(__sparc__)
+#define UNALIGNED_RAM_ACCESS 0
+#else
+#define UNALIGNED_RAM_ACCESS 1
+#endif
+
+#if MYSQL_VERSION_ID<50100
+#define thd_ha_data(X,Y) (X)->ha_data[sphinx_hton.slot]
+#define ha_thd() current_thd
+#endif // <50100
+
+#if UNALIGNED_RAM_ACCESS
+
+/// pass-through wrapper
+template < typename T > inline T sphUnalignedRead ( const T & tRef )
+{
+ return tRef;
+}
+
+/// pass-through wrapper
+template < typename T > void sphUnalignedWrite ( void * pPtr, const T & tVal )
+{
+ *(T*)pPtr = tVal;
+}
+
+#else
+
+/// unaligned read wrapper for some architectures (eg. SPARC)
+template < typename T >
+inline T sphUnalignedRead ( const T & tRef )
+{
+ T uTmp;
+ byte * pSrc = (byte *) &tRef;
+ byte * pDst = (byte *) &uTmp;
+ for ( int i=0; i<(int)sizeof(T); i++ )
+ *pDst++ = *pSrc++;
+ return uTmp;
+}
+
+/// unaligned write wrapper for some architectures (eg. SPARC)
+template < typename T >
+void sphUnalignedWrite ( void * pPtr, const T & tVal )
+{
+ byte * pDst = (byte *) pPtr;
+ byte * pSrc = (byte *) &tVal;
+ for ( int i=0; i<(int)sizeof(T); i++ )
+ *pDst++ = *pSrc++;
+}
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+// FIXME! make this all dynamic
+#define SPHINXSE_MAX_FILTERS 32
+
+#define SPHINXSE_DEFAULT_HOST "127.0.0.1"
+#define SPHINXSE_DEFAULT_PORT 9312
+#define SPHINXSE_DEFAULT_INDEX "*"
+
+#define SPHINXSE_SYSTEM_COLUMNS 3
+
+#define SPHINXSE_MAX_ALLOC (16*1024*1024)
+#define SPHINXSE_MAX_KEYWORDSTATS 4096
+
+// FIXME! all the following is cut-n-paste from sphinx.h and searchd.cpp
+#define SPHINX_VERSION "0.9.9"
+
+enum
+{
+ SPHINX_SEARCHD_PROTO = 1,
+ SEARCHD_COMMAND_SEARCH = 0,
+ VER_COMMAND_SEARCH = 0x116,
+};
+
+/// search query sorting orders
+enum ESphSortOrder
+{
+ SPH_SORT_RELEVANCE = 0, ///< sort by document relevance desc, then by date
+ SPH_SORT_ATTR_DESC = 1, ///< sort by document date desc, then by relevance desc
+ SPH_SORT_ATTR_ASC = 2, ///< sort by document date asc, then by relevance desc
+ SPH_SORT_TIME_SEGMENTS = 3, ///< sort by time segments (hour/day/week/etc) desc, then by relevance desc
+ SPH_SORT_EXTENDED = 4, ///< sort by SQL-like expression (eg. "@relevance DESC, price ASC, @id DESC")
+ SPH_SORT_EXPR = 5, ///< sort by expression
+
+ SPH_SORT_TOTAL
+};
+
+/// search query matching mode
+enum ESphMatchMode
+{
+ SPH_MATCH_ALL = 0, ///< match all query words
+ SPH_MATCH_ANY, ///< match any query word
+ SPH_MATCH_PHRASE, ///< match this exact phrase
+ SPH_MATCH_BOOLEAN, ///< match this boolean query
+ SPH_MATCH_EXTENDED, ///< match this extended query
+ SPH_MATCH_FULLSCAN, ///< match all document IDs w/o fulltext query, apply filters
+ SPH_MATCH_EXTENDED2, ///< extended engine V2
+
+ SPH_MATCH_TOTAL
+};
+
+/// search query relevance ranking mode
+enum ESphRankMode
+{
+ SPH_RANK_PROXIMITY_BM25 = 0, ///< default mode, phrase proximity major factor and BM25 minor one
+ SPH_RANK_BM25 = 1, ///< statistical mode, BM25 ranking only (faster but worse quality)
+ SPH_RANK_NONE = 2, ///< no ranking, all matches get a weight of 1
+ SPH_RANK_WORDCOUNT = 3, ///< simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts
+ SPH_RANK_PROXIMITY = 4, ///< phrase proximity
+ SPH_RANK_MATCHANY = 5, ///< emulate old match-any weighting
+ SPH_RANK_FIELDMASK = 6, ///< sets bits where there were matches
+
+ SPH_RANK_TOTAL,
+ SPH_RANK_DEFAULT = SPH_RANK_PROXIMITY_BM25
+};
+
+/// search query grouping mode
+enum ESphGroupBy
+{
+ SPH_GROUPBY_DAY = 0, ///< group by day
+ SPH_GROUPBY_WEEK = 1, ///< group by week
+ SPH_GROUPBY_MONTH = 2, ///< group by month
+ SPH_GROUPBY_YEAR = 3, ///< group by year
+ SPH_GROUPBY_ATTR = 4 ///< group by attribute value
+};
+
+/// known attribute types
+enum
+{
+ SPH_ATTR_NONE = 0, ///< not an attribute at all
+ SPH_ATTR_INTEGER = 1, ///< this attr is just an integer
+ SPH_ATTR_TIMESTAMP = 2, ///< this attr is a timestamp
+ SPH_ATTR_ORDINAL = 3, ///< this attr is an ordinal string number (integer at search time, specially handled at indexing time)
+ SPH_ATTR_BOOL = 4, ///< this attr is a boolean bit field
+ SPH_ATTR_FLOAT = 5,
+ SPH_ATTR_BIGINT = 6,
+
+ SPH_ATTR_MULTI = 0x40000000UL ///< this attr has multiple values (0 or more)
+};
+
+/// known answers
+enum
+{
+ SEARCHD_OK = 0, ///< general success, command-specific reply follows
+ SEARCHD_ERROR = 1, ///< general failure, error message follows
+ SEARCHD_RETRY = 2, ///< temporary failure, error message follows, client should retry later
+ SEARCHD_WARNING = 3 ///< general success, warning message and command-specific reply follow
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define SPHINX_DEBUG_OUTPUT 0
+#define SPHINX_DEBUG_CALLS 0
+
+#include <stdarg.h>
+
+#if SPHINX_DEBUG_OUTPUT
+inline void SPH_DEBUG ( const char * format, ... )
+{
+ va_list ap;
+ va_start ( ap, format );
+ fprintf ( stderr, "SphinxSE: " );
+ vfprintf ( stderr, format, ap );
+ fprintf ( stderr, "\n" );
+ va_end ( ap );
+}
+#else
+inline void SPH_DEBUG ( const char *, ... ) {}
+#endif
+
+#if SPHINX_DEBUG_CALLS
+
+#define SPH_ENTER_FUNC() { SPH_DEBUG ( "enter %s", __FUNCTION__ ); }
+#define SPH_ENTER_METHOD() { SPH_DEBUG ( "enter %s(this=%08x)", __FUNCTION__, this ); }
+#define SPH_RET(_arg) { SPH_DEBUG ( "leave %s", __FUNCTION__ ); return _arg; }
+#define SPH_VOID_RET() { SPH_DEBUG ( "leave %s", __FUNCTION__ ); return; }
+
+#else
+
+#define SPH_ENTER_FUNC()
+#define SPH_ENTER_METHOD()
+#define SPH_RET(_arg) { return(_arg); }
+#define SPH_VOID_RET() { return; }
+
+#endif
+
+
+#define SafeDelete(_arg) { if ( _arg ) delete ( _arg ); (_arg) = NULL; }
+#define SafeDeleteArray(_arg) { if ( _arg ) delete [] ( _arg ); (_arg) = NULL; }
+
+//////////////////////////////////////////////////////////////////////////////
+
+/// a structure that will be shared among all open Sphinx SE handlers
+struct CSphSEShare
+{
+ pthread_mutex_t m_tMutex;
+ THR_LOCK m_tLock;
+
+ char * m_sTable;
+ char * m_sScheme;
+ char * m_sHost; ///< points into m_sScheme buffer, DO NOT FREE EXPLICITLY
+ char * m_sSocket; ///< points into m_sScheme buffer, DO NOT FREE EXPLICITLY
+ char * m_sIndex; ///< points into m_sScheme buffer, DO NOT FREE EXPLICITLY
+ ushort m_iPort;
+ uint m_iTableNameLen;
+ uint m_iUseCount;
+ CHARSET_INFO * m_pTableQueryCharset;
+
+ int m_iTableFields;
+ char ** m_sTableField;
+ enum_field_types * m_eTableFieldType;
+
+ CSphSEShare ()
+ : m_sTable ( NULL )
+ , m_sScheme ( NULL )
+ , m_sHost ( NULL )
+ , m_sSocket ( NULL )
+ , m_sIndex ( NULL )
+ , m_iPort ( 0 )
+ , m_iTableNameLen ( 0 )
+ , m_iUseCount ( 1 )
+ , m_pTableQueryCharset ( NULL )
+
+ , m_iTableFields ( 0 )
+ , m_sTableField ( NULL )
+ , m_eTableFieldType ( NULL )
+ {
+ thr_lock_init ( &m_tLock );
+ pthread_mutex_init ( &m_tMutex, MY_MUTEX_INIT_FAST );
+ }
+
+ ~CSphSEShare ()
+ {
+ pthread_mutex_destroy ( &m_tMutex );
+ thr_lock_delete ( &m_tLock );
+
+ SafeDeleteArray ( m_sTable );
+ SafeDeleteArray ( m_sScheme );
+ ResetTable ();
+ }
+
+ void ResetTable ()
+ {
+ for ( int i=0; i<m_iTableFields; i++ )
+ SafeDeleteArray ( m_sTableField[i] );
+ SafeDeleteArray ( m_sTableField );
+ SafeDeleteArray ( m_eTableFieldType );
+ }
+};
+
+/// schema attribute
+struct CSphSEAttr
+{
+ char * m_sName; ///< attribute name (received from Sphinx)
+ uint32 m_uType; ///< attribute type (received from Sphinx)
+ int m_iField; ///< field index in current table (-1 if none)
+
+ CSphSEAttr()
+ : m_sName ( NULL )
+ , m_uType ( SPH_ATTR_NONE )
+ , m_iField ( -1 )
+ {}
+
+ ~CSphSEAttr ()
+ {
+ SafeDeleteArray ( m_sName );
+ }
+};
+
+/// word stats
+struct CSphSEWordStats
+{
+ char * m_sWord;
+ int m_iDocs;
+ int m_iHits;
+
+ CSphSEWordStats ()
+ : m_sWord ( NULL )
+ , m_iDocs ( 0 )
+ , m_iHits ( 0 )
+ {}
+
+ ~CSphSEWordStats ()
+ {
+ SafeDeleteArray ( m_sWord );
+ }
+};
+
+/// request stats
+struct CSphSEStats
+{
+public:
+ int m_iMatchesTotal;
+ int m_iMatchesFound;
+ int m_iQueryMsec;
+ int m_iWords;
+ CSphSEWordStats * m_dWords;
+ bool m_bLastError;
+ char m_sLastMessage[1024];
+
+ CSphSEStats()
+ : m_dWords ( NULL )
+ {
+ Reset ();
+ }
+
+ void Reset ()
+ {
+ m_iMatchesTotal = 0;
+ m_iMatchesFound = 0;
+ m_iQueryMsec = 0;
+ m_iWords = 0;
+ SafeDeleteArray ( m_dWords );
+ m_bLastError = false;
+ m_sLastMessage[0] = '\0';
+ }
+
+ ~CSphSEStats()
+ {
+ Reset ();
+ }
+};
+
+/// thread local storage
+struct CSphSEThreadData
+{
+ static const int MAX_QUERY_LEN = 262144; // 256k should be enough, right?
+
+ bool m_bStats;
+ CSphSEStats m_tStats;
+
+ bool m_bQuery;
+ char m_sQuery[MAX_QUERY_LEN];
+
+ CHARSET_INFO * m_pQueryCharset;
+
+ CSphSEThreadData ()
+ : m_bStats ( false )
+ , m_bQuery ( false )
+ , m_pQueryCharset ( NULL )
+ {}
+};
+
+/// filter types
+enum ESphFilter
+{
+ SPH_FILTER_VALUES = 0, ///< filter by integer values set
+ SPH_FILTER_RANGE = 1, ///< filter by integer range
+ SPH_FILTER_FLOATRANGE = 2 ///< filter by float range
+};
+
+
+/// search query filter
+struct CSphSEFilter
+{
+public:
+ ESphFilter m_eType;
+ char * m_sAttrName;
+ longlong m_uMinValue;
+ longlong m_uMaxValue;
+ float m_fMinValue;
+ float m_fMaxValue;
+ int m_iValues;
+ longlong * m_pValues;
+ int m_bExclude;
+
+public:
+ CSphSEFilter ()
+ : m_eType ( SPH_FILTER_VALUES )
+ , m_sAttrName ( NULL )
+ , m_uMinValue ( 0 )
+ , m_uMaxValue ( UINT_MAX )
+ , m_fMinValue ( 0.0f )
+ , m_fMaxValue ( 0.0f )
+ , m_iValues ( 0 )
+ , m_pValues ( NULL )
+ , m_bExclude ( 0 )
+ {
+ }
+
+ ~CSphSEFilter ()
+ {
+ SafeDeleteArray ( m_pValues );
+ }
+};
+
+
+/// float vs dword conversion
+inline uint32 sphF2DW ( float f ) { union { float f; uint32 d; } u; u.f = f; return u.d; }
+
+/// dword vs float conversion
+inline float sphDW2F ( uint32 d ) { union { float f; uint32 d; } u; u.d = d; return u.f; }
+
+
+/// client-side search query
+struct CSphSEQuery
+{
+public:
+ const char * m_sHost;
+ int m_iPort;
+
+private:
+ char * m_sQueryBuffer;
+
+ const char * m_sIndex;
+ int m_iOffset;
+ int m_iLimit;
+
+ bool m_bQuery;
+ char * m_sQuery;
+ uint32 * m_pWeights;
+ int m_iWeights;
+ ESphMatchMode m_eMode;
+ ESphRankMode m_eRanker;
+ ESphSortOrder m_eSort;
+ char * m_sSortBy;
+ int m_iMaxMatches;
+ int m_iMaxQueryTime;
+ uint32 m_iMinID;
+ uint32 m_iMaxID;
+
+ int m_iFilters;
+ CSphSEFilter m_dFilters[SPHINXSE_MAX_FILTERS];
+
+ ESphGroupBy m_eGroupFunc;
+ char * m_sGroupBy;
+ char * m_sGroupSortBy;
+ int m_iCutoff;
+ int m_iRetryCount;
+ int m_iRetryDelay;
+ char * m_sGroupDistinct; ///< points to query buffer; do NOT delete
+ int m_iIndexWeights;
+ char * m_sIndexWeight[SPHINXSE_MAX_FILTERS]; ///< points to query buffer; do NOT delete
+ int m_iIndexWeight[SPHINXSE_MAX_FILTERS];
+ int m_iFieldWeights;
+ char * m_sFieldWeight[SPHINXSE_MAX_FILTERS]; ///< points to query buffer; do NOT delete
+ int m_iFieldWeight[SPHINXSE_MAX_FILTERS];
+
+ bool m_bGeoAnchor;
+ char * m_sGeoLatAttr;
+ char * m_sGeoLongAttr;
+ float m_fGeoLatitude;
+ float m_fGeoLongitude;
+
+ char * m_sComment;
+
+ struct Override_t
+ {
+ union Value_t
+ {
+ uint32 m_uValue;
+ longlong m_iValue64;
+ float m_fValue;
+ };
+ char * m_sName; ///< points to query buffer
+ int m_iType;
+ Dynamic_array<ulonglong> m_dIds;
+ Dynamic_array<Value_t> m_dValues;
+ };
+ Dynamic_array<Override_t *> m_dOverrides;
+
+public:
+ char m_sParseError[256];
+
+public:
+ CSphSEQuery ( const char * sQuery, int iLength, const char * sIndex );
+ ~CSphSEQuery ();
+
+ bool Parse ();
+ int BuildRequest ( char ** ppBuffer );
+
+protected:
+ char * m_pBuf;
+ char * m_pCur;
+ int m_iBufLeft;
+ bool m_bBufOverrun;
+
+ template < typename T > int ParseArray ( T ** ppValues, const char * sValue );
+ bool ParseField ( char * sField );
+
+ void SendBytes ( const void * pBytes, int iBytes );
+ void SendWord ( short int v ) { v = ntohs(v); SendBytes ( &v, sizeof(short int) ); }
+ void SendInt ( int v ) { v = ntohl(v); SendBytes ( &v, sizeof(int) ); }
+ void SendDword ( uint v ) { v = ntohl(v) ;SendBytes ( &v, sizeof(uint) ); }
+ void SendUint64 ( ulonglong v ) { SendDword ( uint(v>>32) ); SendDword ( uint(v&0xFFFFFFFFUL) ); }
+ void SendString ( const char * v ) { int iLen = strlen(v); SendDword(iLen); SendBytes ( v, iLen ); }
+ void SendFloat ( float v ) { SendDword ( sphF2DW(v) ); }
+};
+
+template int CSphSEQuery::ParseArray<uint32> ( uint32 **, const char * );
+template int CSphSEQuery::ParseArray<longlong> ( longlong **, const char * );
+
+//////////////////////////////////////////////////////////////////////////////
+
+#if MYSQL_VERSION_ID>50100
+
+#if MYSQL_VERSION_ID<50114
+#error Sphinx SE requires MySQL 5.1.14 or higher if compiling for 5.1.x series!
+#endif
+
+static handler * sphinx_create_handler ( handlerton * hton, TABLE_SHARE * table, MEM_ROOT * mem_root );
+static int sphinx_init_func ( void * p );
+static int sphinx_close_connection ( handlerton * hton, THD * thd );
+static int sphinx_panic ( handlerton * hton, enum ha_panic_function flag );
+static bool sphinx_show_status ( handlerton * hton, THD * thd, stat_print_fn * stat_print, enum ha_stat_type stat_type );
+
+#else
+
+static bool sphinx_init_func_for_handlerton ();
+static int sphinx_close_connection ( THD * thd );
+bool sphinx_show_status ( THD * thd );
+
+#endif // >50100
+
+//////////////////////////////////////////////////////////////////////////////
+
+static const char sphinx_hton_name[] = "SPHINX";
+static const char sphinx_hton_comment[] = "Sphinx storage engine " SPHINX_VERSION;
+
+#if MYSQL_VERSION_ID<50100
+handlerton sphinx_hton =
+{
+ #ifdef MYSQL_HANDLERTON_INTERFACE_VERSION
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
+ #endif
+ sphinx_hton_name,
+ SHOW_OPTION_YES,
+ sphinx_hton_comment,
+ DB_TYPE_SPHINX_DB,
+ sphinx_init_func_for_handlerton,
+ 0, // slot
+ 0, // savepoint size
+ sphinx_close_connection, // close_connection
+ NULL, // savepoint
+ NULL, // rollback to savepoint
+ NULL, // release savepoint
+ NULL, // commit
+ NULL, // rollback
+ NULL, // prepare
+ NULL, // recover
+ NULL, // commit_by_xid
+ NULL, // rollback_by_xid
+ NULL, // create_cursor_read_view
+ NULL, // set_cursor_read_view
+ NULL, // close_cursor_read_view
+ HTON_CAN_RECREATE
+};
+#else
+static handlerton * sphinx_hton_ptr = NULL;
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+
+// variables for Sphinx shared methods
+pthread_mutex_t sphinx_mutex; // mutex to init the hash
+static int sphinx_init = 0; // flag whether the hash was initialized
+static HASH sphinx_open_tables; // hash used to track open tables
+
+//////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION AND SHUTDOWN
+//////////////////////////////////////////////////////////////////////////////
+
+// hashing function
+#if MYSQL_VERSION_ID>=50120
+typedef size_t GetKeyLength_t;
+#else
+typedef uint GetKeyLength_t;
+#endif
+
+static byte * sphinx_get_key ( const byte * pSharePtr, GetKeyLength_t * pLength, my_bool )
+{
+ CSphSEShare * pShare = (CSphSEShare *) pSharePtr;
+ *pLength = (size_t) pShare->m_iTableNameLen;
+ return (byte*) pShare->m_sTable;
+}
+
+#if MYSQL_VERSION_ID<50100
+static int sphinx_init_func ( void * ) // to avoid unused arg warning
+#else
+static int sphinx_init_func ( void * p )
+#endif
+{
+ SPH_ENTER_FUNC();
+ if ( !sphinx_init )
+ {
+ sphinx_init = 1;
+ VOID ( pthread_mutex_init ( &sphinx_mutex, MY_MUTEX_INIT_FAST ) );
+ hash_init ( &sphinx_open_tables, system_charset_info, 32, 0, 0,
+ sphinx_get_key, 0, 0 );
+
+ #if MYSQL_VERSION_ID > 50100
+ handlerton * hton = (handlerton*) p;
+ hton->state = SHOW_OPTION_YES;
+ hton->db_type = DB_TYPE_AUTOASSIGN;
+ hton->create = sphinx_create_handler;
+ hton->close_connection = sphinx_close_connection;
+ hton->show_status = sphinx_show_status;
+ hton->panic = sphinx_panic;
+ hton->flags = HTON_CAN_RECREATE;
+ sphinx_hton_ptr = hton;
+ #endif
+ }
+ SPH_RET(0);
+}
+
+
+#if MYSQL_VERSION_ID<50100
+static bool sphinx_init_func_for_handlerton ()
+{
+ return sphinx_init_func ( &sphinx_hton );
+}
+#endif
+
+
+#if MYSQL_VERSION_ID>50100
+
+static int sphinx_close_connection ( handlerton * hton, THD * thd )
+{
+ // deallocate common handler data
+ SPH_ENTER_FUNC();
+ void ** tmp = thd_ha_data ( thd, hton );
+ CSphSEThreadData * pTls = (CSphSEThreadData*) (*tmp);
+ SafeDelete ( pTls );
+ *tmp = NULL;
+ SPH_RET(0);
+}
+
+
+static int sphinx_done_func ( void * )
+{
+ SPH_ENTER_FUNC();
+
+ int error = 0;
+ if ( sphinx_init )
+ {
+ sphinx_init = 0;
+ if ( sphinx_open_tables.records )
+ error = 1;
+ hash_free ( &sphinx_open_tables );
+ pthread_mutex_destroy ( &sphinx_mutex );
+ }
+
+ SPH_RET(0);
+}
+
+
+static int sphinx_panic ( handlerton * hton, enum ha_panic_function )
+{
+ return sphinx_done_func ( hton );
+}
+
+#else
+
+static int sphinx_close_connection ( THD * thd )
+{
+ // deallocate common handler data
+ SPH_ENTER_FUNC();
+ CSphSEThreadData * pTls = (CSphSEThreadData*) thd->ha_data[sphinx_hton.slot];
+ SafeDelete ( pTls );
+ thd->ha_data[sphinx_hton.slot] = NULL;
+ SPH_RET(0);
+}
+
+#endif // >50100
+
+//////////////////////////////////////////////////////////////////////////////
+// SHOW STATUS
+//////////////////////////////////////////////////////////////////////////////
+
+#if MYSQL_VERSION_ID>50100
+static bool sphinx_show_status ( handlerton * hton, THD * thd, stat_print_fn * stat_print,
+ enum ha_stat_type )
+#else
+bool sphinx_show_status ( THD * thd )
+#endif
+{
+ SPH_ENTER_FUNC();
+
+#if MYSQL_VERSION_ID<50100
+ Protocol * protocol = thd->protocol;
+ List<Item> field_list;
+#endif
+
+ char buf1[IO_SIZE];
+ uint buf1len;
+ char buf2[IO_SIZE];
+ uint buf2len= 0;
+ String words;
+
+ buf1[0] = '\0';
+ buf2[0] = '\0';
+
+#if MYSQL_VERSION_ID>50100
+ CSphSEThreadData * pTls = (CSphSEThreadData*) ( *thd_ha_data ( thd, hton ) );
+#else
+ if ( have_sphinx_db!=SHOW_OPTION_YES )
+ {
+ my_message ( ER_NOT_SUPPORTED_YET,
+ "failed to call SHOW SPHINX STATUS: --skip-sphinx was specified",
+ MYF(0) );
+ SPH_RET(TRUE);
+ }
+ CSphSEThreadData * pTls = (CSphSEThreadData*) thd->ha_data[sphinx_hton.slot];
+#endif
+
+ if ( pTls && pTls->m_bStats )
+ {
+ const CSphSEStats * pStats = &pTls->m_tStats;
+ buf1len = my_snprintf ( buf1, sizeof(buf1),
+ "total: %d, total found: %d, time: %d, words: %d",
+ pStats->m_iMatchesTotal, pStats->m_iMatchesFound, pStats->m_iQueryMsec, pStats->m_iWords );
+
+#if MYSQL_VERSION_ID>50100
+ stat_print ( thd, sphinx_hton_name, strlen(sphinx_hton_name),
+ STRING_WITH_LEN("stats"), buf1, buf1len );
+#else
+ field_list.push_back ( new Item_empty_string ( "Type",10 ) );
+ 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, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF ) )
+ SPH_RET(TRUE);
+
+ protocol->prepare_for_resend ();
+ protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
+ protocol->store ( STRING_WITH_LEN("stats"), system_charset_info );
+ protocol->store ( buf1, buf1len, system_charset_info );
+ if ( protocol->write() )
+ SPH_RET(TRUE);
+#endif
+
+ if ( pStats->m_iWords )
+ {
+ for ( int i=0; i<pStats->m_iWords; i++ )
+ {
+ CSphSEWordStats & tWord = pStats->m_dWords[i];
+ buf2len = my_snprintf ( buf2, sizeof(buf2), "%s%s:%d:%d ",
+ buf2, tWord.m_sWord, tWord.m_iDocs, tWord.m_iHits );
+ }
+
+ // convert it if we can
+ const char * sWord = buf2;
+ int iWord = buf2len;
+
+ String sBuf3;
+ if ( pTls->m_pQueryCharset )
+ {
+ uint iErrors;
+ sBuf3.copy ( buf2, buf2len, pTls->m_pQueryCharset, system_charset_info, &iErrors );
+ sWord = sBuf3.c_ptr();
+ iWord = sBuf3.length();
+ }
+
+#if MYSQL_VERSION_ID>50100
+ stat_print ( thd, sphinx_hton_name, strlen(sphinx_hton_name),
+ STRING_WITH_LEN("words"), sWord, iWord );
+#else
+ protocol->prepare_for_resend ();
+ protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
+ protocol->store ( STRING_WITH_LEN("words"), system_charset_info );
+ protocol->store ( sWord, iWord, system_charset_info );
+ if ( protocol->write() )
+ SPH_RET(TRUE);
+#endif
+ }
+
+ // send last error or warning
+ if ( pStats->m_sLastMessage && pStats->m_sLastMessage[0] )
+ {
+ const char * sMessageType = pStats->m_bLastError ? "error" : "warning";
+
+#if MYSQL_VERSION_ID>50100
+ stat_print ( thd, sphinx_hton_name, strlen(sphinx_hton_name),
+ sMessageType, strlen(sMessageType), pStats->m_sLastMessage, strlen(pStats->m_sLastMessage) );
+#else
+ protocol->prepare_for_resend ();
+ protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
+ protocol->store ( sMessageType, strlen(sMessageType), system_charset_info );
+ protocol->store ( pStats->m_sLastMessage, strlen(pStats->m_sLastMessage), system_charset_info );
+ if ( protocol->write() )
+ SPH_RET(TRUE);
+#endif
+ }
+
+ } else
+ {
+ #if MYSQL_VERSION_ID < 50100
+ field_list.push_back ( new Item_empty_string ( "Type", 10 ) );
+ 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, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF ) )
+ SPH_RET(TRUE);
+
+ protocol->prepare_for_resend ();
+ protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
+ protocol->store ( STRING_WITH_LEN("stats"), system_charset_info );
+ protocol->store ( STRING_WITH_LEN("no query has been executed yet"), system_charset_info );
+ if ( protocol->write() )
+ SPH_RET(TRUE);
+ #endif
+ }
+
+ #if MYSQL_VERSION_ID < 50100
+ send_eof(thd);
+ #endif
+
+ SPH_RET(FALSE);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// HELPERS
+//////////////////////////////////////////////////////////////////////////////
+
+static char * sphDup ( const char * sSrc, int iLen=-1 )
+{
+ if ( !sSrc )
+ return NULL;
+
+ if ( iLen<0 )
+ iLen = strlen(sSrc);
+
+ char * sRes = new char [ 1+iLen ];
+ memcpy ( sRes, sSrc, iLen );
+ sRes[iLen] = '\0';
+ return sRes;
+}
+
+
+static void sphLogError ( const char * sFmt, ... )
+{
+ // emit timestamp
+#ifdef __WIN__
+ SYSTEMTIME t;
+ GetLocalTime ( &t );
+
+ fprintf ( stderr, "%02d%02d%02d %2d:%02d:%02d SphinxSE: internal error: ",
+ (int)t.wYear % 100, (int)t.wMonth, (int)t.wDay,
+ (int)t.wHour, (int)t.wMinute, (int)t.wSecond );
+#else
+ // Unix version
+ time_t tStamp;
+ time ( &tStamp );
+
+ struct tm * pParsed;
+#ifdef HAVE_LOCALTIME_R
+ struct tm tParsed;
+ localtime_r ( &tStamp, &tParsed );
+ pParsed = &tParsed;
+#else
+ pParsed = localtime ( &tStamp );
+#endif // HAVE_LOCALTIME_R
+
+ fprintf ( stderr, "%02d%02d%02d %2d:%02d:%02d SphinxSE: internal error: ",
+ pParsed->tm_year % 100, pParsed->tm_mon + 1, pParsed->tm_mday,
+ pParsed->tm_hour, pParsed->tm_min, pParsed->tm_sec);
+#endif // __WIN__
+
+ // emit message
+ va_list ap;
+ va_start ( ap, sFmt );
+ vfprintf ( stderr, sFmt, ap );
+ va_end ( ap );
+
+ // emit newline
+ fprintf ( stderr, "\n" );
+}
+
+
+
+// the following scheme variants are recognized
+//
+// sphinx://host/index
+// sphinx://host:port/index
+// unix://unix/domain/socket:index
+// unix://unix/domain/socket
+static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
+{
+ SPH_ENTER_FUNC();
+
+ if ( share )
+ {
+ // check incoming stuff
+ if ( !table )
+ {
+ sphLogError ( "table==NULL in ParseUrl()" );
+ return false;
+ }
+ if ( !table->s )
+ {
+ sphLogError ( "(table->s)==NULL in ParseUrl()" );
+ return false;
+ }
+
+ // free old stuff
+ share->ResetTable ();
+
+ // fill new stuff
+ share->m_iTableFields = table->s->fields;
+ if ( share->m_iTableFields )
+ {
+ share->m_sTableField = new char * [ share->m_iTableFields ];
+ share->m_eTableFieldType = new enum_field_types [ share->m_iTableFields ];
+
+ for ( int i=0; i<share->m_iTableFields; i++ )
+ {
+ share->m_sTableField[i] = sphDup ( table->field[i]->field_name );
+ share->m_eTableFieldType[i] = table->field[i]->type();
+ }
+ }
+ }
+
+ char * sScheme = NULL;
+ char * sHost = (char*) SPHINXSE_DEFAULT_HOST;
+ char * sIndex = (char*) SPHINXSE_DEFAULT_INDEX;
+ int iPort = SPHINXSE_DEFAULT_PORT;
+
+ bool bOk = true;
+ while ( table->s->connect_string.length!=0 )
+ {
+ bOk = false;
+ sScheme = sphDup ( table->s->connect_string.str, table->s->connect_string.length );
+
+ sHost = strstr ( sScheme, "://" );
+ if ( !sHost )
+ break;
+ sHost[0] = '\0';
+ sHost += 2;
+
+ if ( !strcmp ( sScheme, "unix" ) )
+ {
+ // unix-domain socket
+ iPort = 0;
+ if (!( sIndex = strrchr ( sHost, ':' ) ))
+ sIndex = (char*) SPHINXSE_DEFAULT_INDEX;
+ else
+ {
+ *sIndex++ = '\0';
+ if ( !*sIndex )
+ sIndex = (char*) SPHINXSE_DEFAULT_INDEX;
+ }
+ bOk = true;
+ break;
+ }
+ if( strcmp ( sScheme, "sphinx" )!=0 && strcmp ( sScheme, "inet" )!=0 )
+ break;
+
+ // tcp
+ sHost++;
+ char * sPort = strchr ( sHost, ':' );
+ if ( sPort )
+ {
+ *sPort++ = '\0';
+ if ( *sPort )
+ {
+ sIndex = strchr ( sPort, '/' );
+ if ( sIndex )
+ *sIndex++ = '\0';
+ else
+ sIndex = (char*) SPHINXSE_DEFAULT_INDEX;
+
+ iPort = atoi(sPort);
+ if ( !iPort )
+ iPort = SPHINXSE_DEFAULT_PORT;
+ }
+ } else
+ {
+ sIndex = strchr ( sHost, '/' );
+ if ( sIndex )
+ *sIndex++ = '\0';
+ else
+ sIndex = (char*) SPHINXSE_DEFAULT_INDEX;
+ }
+
+ bOk = true;
+ break;
+ }
+
+ if ( !bOk )
+ {
+ my_error ( bCreate ? ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE : ER_FOREIGN_DATA_STRING_INVALID,
+ MYF(0), table->s->connect_string );
+ } else
+ {
+ if ( share )
+ {
+ SafeDeleteArray ( share->m_sScheme );
+ share->m_sScheme = sScheme;
+ share->m_sHost = sHost;
+ share->m_sIndex = sIndex;
+ share->m_iPort = (ushort)iPort;
+ }
+ }
+ if ( !bOk && !share )
+ SafeDeleteArray ( sScheme );
+
+ SPH_RET(bOk);
+}
+
+
+// Example of simple lock controls. The "share" it creates is structure we will
+// pass to each sphinx handler. Do you have to have one of these? Well, you have
+// pieces that are used for locking, and they are needed to function.
+static CSphSEShare * get_share ( const char * table_name, TABLE * table )
+{
+ SPH_ENTER_FUNC();
+ pthread_mutex_lock ( &sphinx_mutex );
+
+ CSphSEShare * pShare = NULL;
+ for ( ;; )
+ {
+ // check if we already have this share
+#if MYSQL_VERSION_ID>=50120
+ pShare = (CSphSEShare*) hash_search ( &sphinx_open_tables, (const uchar *) table_name, strlen(table_name) );
+#else
+#ifdef __WIN__
+ pShare = (CSphSEShare*) hash_search ( &sphinx_open_tables, (const byte *) table_name, strlen(table_name) );
+#else
+ pShare = (CSphSEShare*) hash_search ( &sphinx_open_tables, table_name, strlen(table_name) );
+#endif // win
+#endif // pre-5.1.20
+
+ if ( pShare )
+ {
+ pShare->m_iUseCount++;
+ break;
+ }
+
+ // try to allocate new share
+ pShare = new CSphSEShare ();
+ if ( !pShare )
+ break;
+
+ // try to setup it
+ pShare->m_pTableQueryCharset = table->field[2]->charset();
+ if ( !ParseUrl ( pShare, table, false ) )
+ {
+ SafeDelete ( pShare );
+ break;
+ }
+
+ // try to hash it
+ pShare->m_iTableNameLen = strlen(table_name);
+ pShare->m_sTable = sphDup ( table_name );
+ if ( my_hash_insert ( &sphinx_open_tables, (const byte *)pShare ) )
+ {
+ SafeDelete ( pShare );
+ break;
+ }
+
+ // all seems fine
+ break;
+ }
+
+ pthread_mutex_unlock ( &sphinx_mutex );
+ SPH_RET(pShare);
+}
+
+
+// Free lock controls. We call this whenever we close a table. If the table had
+// the last reference to the share then we free memory associated with it.
+static int free_share ( CSphSEShare * pShare )
+{
+ SPH_ENTER_FUNC();
+ pthread_mutex_lock ( &sphinx_mutex );
+
+ if ( !--pShare->m_iUseCount )
+ {
+ hash_delete ( &sphinx_open_tables, (byte *)pShare );
+ SafeDelete ( pShare );
+ }
+
+ pthread_mutex_unlock ( &sphinx_mutex );
+ SPH_RET(0);
+}
+
+
+#if MYSQL_VERSION_ID>50100
+static handler * sphinx_create_handler ( handlerton * hton, TABLE_SHARE * table, MEM_ROOT * mem_root )
+{
+ return new ( mem_root ) ha_sphinx ( hton, table );
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// CLIENT-SIDE REQUEST STUFF
+//////////////////////////////////////////////////////////////////////////////
+
+CSphSEQuery::CSphSEQuery ( const char * sQuery, int iLength, const char * sIndex )
+ : m_sHost ( "" )
+ , m_iPort ( 0 )
+ , m_sIndex ( sIndex ? sIndex : (char*) "*" )
+ , m_iOffset ( 0 )
+ , m_iLimit ( 20 )
+ , m_bQuery ( false )
+ , m_sQuery ( (char*) "" )
+ , m_pWeights ( NULL )
+ , m_iWeights ( 0 )
+ , m_eMode ( SPH_MATCH_ALL )
+ , m_eRanker ( SPH_RANK_PROXIMITY_BM25 )
+ , m_eSort ( SPH_SORT_RELEVANCE )
+ , m_sSortBy ( (char*) "" )
+ , m_iMaxMatches ( 1000 )
+ , m_iMaxQueryTime ( 0 )
+ , m_iMinID ( 0 )
+ , m_iMaxID ( 0 )
+ , m_iFilters ( 0 )
+ , m_eGroupFunc ( SPH_GROUPBY_DAY )
+ , m_sGroupBy ( (char*) "" )
+ , m_sGroupSortBy ( (char*) "@group desc" )
+ , m_iCutoff ( 0 )
+ , m_iRetryCount ( 0 )
+ , m_iRetryDelay ( 0 )
+ , m_sGroupDistinct ( (char*) "" )
+ , m_iIndexWeights ( 0 )
+ , m_iFieldWeights ( 0 )
+ , m_bGeoAnchor ( false )
+ , m_sGeoLatAttr ( (char*) "" )
+ , m_sGeoLongAttr ( (char*) "" )
+ , m_fGeoLatitude ( 0.0f )
+ , m_fGeoLongitude ( 0.0f )
+ , m_sComment ( (char*) "" )
+
+ , m_pBuf ( NULL )
+ , m_pCur ( NULL )
+ , m_iBufLeft ( 0 )
+ , m_bBufOverrun ( false )
+{
+ m_sQueryBuffer = new char [ iLength+2 ];
+ memcpy ( m_sQueryBuffer, sQuery, iLength );
+ m_sQueryBuffer[iLength]= ';';
+ m_sQueryBuffer[iLength+1]= '\0';
+}
+
+
+CSphSEQuery::~CSphSEQuery ()
+{
+ SPH_ENTER_METHOD();
+ SafeDeleteArray ( m_sQueryBuffer );
+ SafeDeleteArray ( m_pWeights );
+ SafeDeleteArray ( m_pBuf );
+ for ( int i=0; i<m_dOverrides.elements(); i++ )
+ SafeDelete ( m_dOverrides.at(i) );
+ SPH_VOID_RET();
+}
+
+
+template < typename T >
+int CSphSEQuery::ParseArray ( T ** ppValues, const char * sValue )
+{
+ SPH_ENTER_METHOD();
+
+ assert ( ppValues );
+ assert ( !(*ppValues) );
+
+ const char * pValue;
+ bool bPrevDigit = false;
+ int iValues = 0;
+
+ // count the values
+ for ( pValue=sValue; *pValue; pValue++ )
+ {
+ bool bDigit = (*pValue)>='0' && (*pValue)<='9';
+ if ( bDigit && !bPrevDigit )
+ iValues++;
+ bPrevDigit = bDigit;
+ }
+ if ( !iValues )
+ SPH_RET(0);
+
+ // extract the values
+ T * pValues = new T [ iValues ];
+ *ppValues = pValues;
+
+ int iIndex = 0, iSign = 1;
+ T uValue = 0;
+
+ bPrevDigit = false;
+ for ( pValue=sValue ;; pValue++ )
+ {
+ bool bDigit = (*pValue)>='0' && (*pValue)<='9';
+
+ if ( bDigit )
+ {
+ if ( !bPrevDigit )
+ uValue = 0;
+ uValue = uValue*10 + ( (*pValue)-'0' );
+ }
+ else if ( bPrevDigit )
+ {
+ assert ( iIndex<iValues );
+ pValues [ iIndex++ ] = uValue * iSign;
+ iSign = 1;
+ }
+ else if ( *pValue=='-' )
+ iSign = -1;
+ bPrevDigit = bDigit;
+
+ if ( !*pValue )
+ break;
+ }
+
+ SPH_RET(iValues);
+}
+
+
+static char * chop ( char * s )
+{
+ while ( *s && isspace(*s) )
+ s++;
+
+ char * p = s + strlen(s);
+ while ( p>s && isspace(p[-1]) )
+ p--;
+ *p = '\0';
+
+ return s;
+}
+
+
+static bool myisattr ( char c )
+{
+ return
+ ( c>='0' && c<='9' ) ||
+ ( c>='a' && c<='z' ) ||
+ ( c>='A' && c<='Z' ) ||
+ c=='_';
+}
+
+
+bool CSphSEQuery::ParseField ( char * sField )
+{
+ SPH_ENTER_METHOD();
+
+ // look for option name/value separator
+ char * sValue = strchr ( sField, '=' );
+ if ( !sValue || sValue==sField || sValue[-1]=='\\' )
+ {
+ // by default let's assume it's just query
+ if ( sField[0] )
+ {
+ if ( m_bQuery )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "search query already specified; '%s' is redundant", sField );
+ SPH_RET(false);
+ } else
+ {
+ m_sQuery = sField;
+ m_bQuery = true;
+
+ // unescape
+ char *s = sField, *d = sField;
+ while ( *s )
+ {
+ if ( *s!='\\' ) *d++ = *s;
+ s++;
+ }
+ *d = '\0';
+ }
+ }
+ SPH_RET(true);
+ }
+
+ // split
+ *sValue++ = '\0';
+ sValue = chop ( sValue );
+ int iValue = atoi ( sValue );
+
+ // handle options
+ char * sName = chop ( sField );
+
+ if ( !strcmp ( sName, "query" ) ) m_sQuery = sValue;
+ else if ( !strcmp ( sName, "host" ) ) m_sHost = sValue;
+ else if ( !strcmp ( sName, "port" ) ) m_iPort = iValue;
+ else if ( !strcmp ( sName, "index" ) ) m_sIndex = sValue;
+ else if ( !strcmp ( sName, "offset" ) ) m_iOffset = iValue;
+ else if ( !strcmp ( sName, "limit" ) ) m_iLimit = iValue;
+ else if ( !strcmp ( sName, "weights" ) ) m_iWeights = ParseArray<uint32> ( &m_pWeights, sValue );
+ else if ( !strcmp ( sName, "minid" ) ) m_iMinID = iValue;
+ else if ( !strcmp ( sName, "maxid" ) ) m_iMaxID = iValue;
+ else if ( !strcmp ( sName, "maxmatches" ) ) m_iMaxMatches = iValue;
+ else if ( !strcmp ( sName, "maxquerytime" ) ) m_iMaxQueryTime = iValue;
+ else if ( !strcmp ( sName, "groupsort" ) ) m_sGroupSortBy = sValue;
+ else if ( !strcmp ( sName, "distinct" ) ) m_sGroupDistinct = sValue;
+ else if ( !strcmp ( sName, "cutoff" ) ) m_iCutoff = iValue;
+ else if ( !strcmp ( sName, "comment" ) ) m_sComment = sValue;
+
+ else if ( !strcmp ( sName, "mode" ) )
+ {
+
+ m_eMode = SPH_MATCH_ALL;
+ if ( !strcmp ( sValue, "any") ) m_eMode = SPH_MATCH_ANY;
+ else if ( !strcmp ( sValue, "phrase" ) ) m_eMode = SPH_MATCH_PHRASE;
+ else if ( !strcmp ( sValue, "boolean") ) m_eMode = SPH_MATCH_BOOLEAN;
+ else if ( !strcmp ( sValue, "ext") ) m_eMode = SPH_MATCH_EXTENDED;
+ else if ( !strcmp ( sValue, "extended") ) m_eMode = SPH_MATCH_EXTENDED;
+ else if ( !strcmp ( sValue, "ext2") ) m_eMode = SPH_MATCH_EXTENDED2;
+ else if ( !strcmp ( sValue, "extended2") ) m_eMode = SPH_MATCH_EXTENDED2;
+ else if ( !strcmp ( sValue, "all") ) m_eMode = SPH_MATCH_ALL;
+ else if ( !strcmp ( sValue, "fullscan") ) m_eMode = SPH_MATCH_FULLSCAN;
+ else
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "unknown matching mode '%s'", sValue );
+ SPH_RET(false);
+ }
+ } else if ( !strcmp ( sName, "ranker" ) )
+ {
+
+ m_eRanker = SPH_RANK_PROXIMITY_BM25;
+ if ( !strcmp ( sValue, "proximity_bm25") ) m_eRanker = SPH_RANK_PROXIMITY_BM25;
+ else if ( !strcmp ( sValue, "bm25" ) ) m_eRanker = SPH_RANK_BM25;
+ else if ( !strcmp ( sValue, "none" ) ) m_eRanker = SPH_RANK_NONE;
+ else if ( !strcmp ( sValue, "wordcount" ) ) m_eRanker = SPH_RANK_WORDCOUNT;
+ else if ( !strcmp ( sValue, "proximity" ) ) m_eRanker = SPH_RANK_PROXIMITY;
+ else if ( !strcmp ( sValue, "matchany" ) ) m_eRanker = SPH_RANK_MATCHANY;
+ else if ( !strcmp ( sValue, "fieldmask" ) ) m_eRanker = SPH_RANK_FIELDMASK;
+ else
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "unknown ranking mode '%s'", sValue );
+ SPH_RET(false);
+ }
+ } else if ( !strcmp ( sName, "sort" ) )
+ {
+ static const struct
+ {
+ const char * m_sName;
+ ESphSortOrder m_eSort;
+ } dSortModes[] =
+ {
+ { "relevance", SPH_SORT_RELEVANCE },
+ { "attr_desc:", SPH_SORT_ATTR_DESC },
+ { "attr_asc:", SPH_SORT_ATTR_ASC },
+ { "time_segments:", SPH_SORT_TIME_SEGMENTS },
+ { "extended:", SPH_SORT_EXTENDED },
+ { "expr:", SPH_SORT_EXPR }
+ };
+
+ int i;
+ const int nModes = sizeof(dSortModes)/sizeof(dSortModes[0]);
+ for ( i=0; i<nModes; i++ )
+ if ( !strncmp ( sValue, dSortModes[i].m_sName, strlen(dSortModes[i].m_sName) ) )
+ {
+ m_eSort = dSortModes[i].m_eSort;
+ m_sSortBy = sValue + strlen(dSortModes[i].m_sName);
+ break;
+ }
+ if ( i==nModes )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "unknown sorting mode '%s'", sValue );
+ SPH_RET(false);
+ }
+
+ } else if ( !strcmp ( sName, "groupby" ) )
+ {
+ static const struct
+ {
+ const char * m_sName;
+ ESphGroupBy m_eFunc;
+ } dGroupModes[] =
+ {
+ { "day:", SPH_GROUPBY_DAY },
+ { "week:", SPH_GROUPBY_WEEK },
+ { "month:", SPH_GROUPBY_MONTH },
+ { "year:", SPH_GROUPBY_YEAR },
+ { "attr:", SPH_GROUPBY_ATTR },
+ };
+
+ int i;
+ const int nModes = sizeof(dGroupModes)/sizeof(dGroupModes[0]);
+ for ( i=0; i<nModes; i++ )
+ if ( !strncmp ( sValue, dGroupModes[i].m_sName, strlen(dGroupModes[i].m_sName) ) )
+ {
+ m_eGroupFunc = dGroupModes[i].m_eFunc;
+ m_sGroupBy = sValue + strlen(dGroupModes[i].m_sName);
+ break;
+ }
+ if ( i==nModes )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "unknown groupby mode '%s'", sValue );
+ SPH_RET(false);
+ }
+
+ } else if ( m_iFilters<SPHINXSE_MAX_FILTERS &&
+ ( !strcmp ( sName, "range" ) || !strcmp ( sName, "!range" ) || !strcmp ( sName, "floatrange" ) || !strcmp ( sName, "!floatrange" ) ) )
+ {
+ for ( ;; )
+ {
+ char * p = sName;
+ CSphSEFilter & tFilter = m_dFilters [ m_iFilters ];
+ tFilter.m_bExclude = ( *p=='!' ); if ( tFilter.m_bExclude ) p++;
+ tFilter.m_eType = ( *p=='f' ) ? SPH_FILTER_FLOATRANGE : SPH_FILTER_RANGE;
+
+ if (!( p = strchr ( sValue, ',' ) ))
+ break;
+ *p++ = '\0';
+
+ tFilter.m_sAttrName = chop ( sValue );
+ sValue = p;
+
+ if (!( p = strchr ( sValue, ',' ) ))
+ break;
+ *p++ = '\0';
+
+ if ( tFilter.m_eType==SPH_FILTER_RANGE )
+ {
+ tFilter.m_uMinValue = strtoll ( sValue, NULL, 0 );
+ tFilter.m_uMaxValue = strtoll ( p, NULL, 0 );
+ } else
+ {
+ tFilter.m_fMinValue = (float)atof(sValue);
+ tFilter.m_fMaxValue = (float)atof(p);
+ }
+
+ // all ok
+ m_iFilters++;
+ break;
+ }
+
+ } else if ( m_iFilters<SPHINXSE_MAX_FILTERS &&
+ ( !strcmp ( sName, "filter" ) || !strcmp ( sName, "!filter" ) ) )
+ {
+ for ( ;; )
+ {
+ CSphSEFilter & tFilter = m_dFilters [ m_iFilters ];
+ tFilter.m_eType = SPH_FILTER_VALUES;
+ tFilter.m_bExclude = ( strcmp ( sName, "!filter")==0 );
+
+ // get the attr name
+ while ( (*sValue) && !myisattr(*sValue) )
+ sValue++;
+ if ( !*sValue )
+ break;
+
+ tFilter.m_sAttrName = sValue;
+ while ( (*sValue) && myisattr(*sValue) )
+ sValue++;
+ if ( !*sValue )
+ break;
+ *sValue++ = '\0';
+
+ // get the values
+ tFilter.m_iValues = ParseArray<longlong> ( &tFilter.m_pValues, sValue );
+ if ( !tFilter.m_iValues )
+ {
+ assert ( !tFilter.m_pValues );
+ break;
+ }
+
+ // all ok
+ m_iFilters++;
+ break;
+ }
+
+ } else if ( !strcmp ( sName, "indexweights" ) || !strcmp ( sName, "fieldweights" ) )
+ {
+ bool bIndex = !strcmp ( sName, "indexweights" );
+ int * pCount = bIndex ? &m_iIndexWeights : &m_iFieldWeights;
+ char ** pNames = bIndex ? &m_sIndexWeight[0] : &m_sFieldWeight[0];
+ int * pWeights = bIndex ? &m_iIndexWeight[0] : &m_iFieldWeight[0];
+
+ *pCount = 0;
+
+ char * p = sValue;
+ while ( *p && *pCount<SPHINXSE_MAX_FILTERS )
+ {
+ // extract attr name
+ if ( !myisattr(*p) )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "%s: index name expected near '%s'", sName, p );
+ SPH_RET(false);
+ }
+
+ pNames[*pCount] = p;
+ while ( myisattr(*p) ) p++;
+
+ if ( *p!=',' )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "%s: comma expected near '%s'", sName, p );
+ SPH_RET(false);
+ }
+ *p++ = '\0';
+
+ // extract attr value
+ char * sVal = p;
+ while ( isdigit(*p) ) p++;
+ if ( p==sVal )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "%s: integer weight expected near '%s'", sName, sVal );
+ SPH_RET(false);
+ }
+ pWeights[*pCount] = atoi(sVal);
+ (*pCount)++;
+
+ if ( !*p ) break;
+ if ( *p!=',' )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "%s: comma expected near '%s'", sName, p );
+ SPH_RET(false);
+ }
+ p++;
+ }
+
+ } else if ( !strcmp ( sName, "geoanchor" ) )
+ {
+ m_bGeoAnchor = false;
+ for ( ;; )
+ {
+ char * sLat = sValue;
+ char * p = sValue;
+
+ if (!( p = strchr ( p, ',' ) )) break; *p++ = '\0';
+ char * sLong = p;
+
+ if (!( p = strchr ( p, ',' ) )) break; *p++ = '\0';
+ char * sLatVal = p;
+
+ if (!( p = strchr ( p, ',' ) )) break; *p++ = '\0';
+ char * sLongVal = p;
+
+ m_sGeoLatAttr = chop(sLat);
+ m_sGeoLongAttr = chop(sLong);
+ m_fGeoLatitude = (float)atof(sLatVal);
+ m_fGeoLongitude = (float)atof(sLongVal);
+ m_bGeoAnchor = true;
+ break;
+ }
+ if ( !m_bGeoAnchor )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "geoanchor: parse error, not enough comma-separated arguments" );
+ SPH_RET(false);
+ }
+ }
+ else if ( !strcmp ( sName, "override" ) ) // name,type,id:value,id:value,...
+ {
+ char * sName = NULL;
+ int iType = 0;
+ CSphSEQuery::Override_t * pOverride = NULL;
+
+ // get name and type
+ char * sRest = sValue;
+ for ( ;; )
+ {
+ sName = sRest;
+ if ( !*sName )
+ break;
+
+ if (!( sRest = strchr ( sRest, ',' ) )) break; *sRest++ = '\0';
+ char * sType = sRest;
+ if (!( sRest = strchr ( sRest, ',' ) )) break;
+
+ static const struct
+ {
+ const char * m_sName;
+ int m_iType;
+ }
+ dAttrTypes[] =
+ {
+ { "int", SPH_ATTR_INTEGER },
+ { "timestamp", SPH_ATTR_TIMESTAMP },
+ { "bool", SPH_ATTR_BOOL },
+ { "float", SPH_ATTR_FLOAT },
+ { "bigint", SPH_ATTR_BIGINT }
+ };
+ for ( uint i=0; i<sizeof(dAttrTypes)/sizeof(*dAttrTypes); i++ )
+ if ( !strncmp( sType, dAttrTypes[i].m_sName, sRest - sType ) )
+ {
+ iType = dAttrTypes[i].m_iType;
+ break;
+ }
+ break;
+ }
+
+ // fail
+ if ( !sName || !*sName || !iType )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "override: malformed query" );
+ SPH_RET(false);
+ }
+
+ // grab id:value pairs
+ sRest++;
+ while ( sRest )
+ {
+ char * sId = sRest;
+ if (!( sRest = strchr ( sRest, ':' ) )) break; *sRest++ = '\0';
+ if (!( sRest - sId )) break;
+
+ char * sValue = sRest;
+ if (( sRest = strchr ( sRest, ',' ) )) *sRest++ = '\0';
+ if ( !*sValue )
+ break;
+
+ if ( !pOverride )
+ {
+ pOverride = new CSphSEQuery::Override_t;
+ pOverride->m_sName = chop(sName);
+ pOverride->m_iType = iType;
+ m_dOverrides.append(pOverride);
+ }
+
+ ulonglong uId = strtoull ( sId, NULL, 10 );
+ CSphSEQuery::Override_t::Value_t tValue;
+ if ( iType == SPH_ATTR_FLOAT )
+ tValue.m_fValue = (float)atof(sValue);
+ else if ( iType == SPH_ATTR_BIGINT )
+ tValue.m_iValue64 = strtoll ( sValue, NULL, 10 );
+ else
+ tValue.m_uValue = (uint32)strtoul ( sValue, NULL, 10 );
+
+ pOverride->m_dIds.append ( uId );
+ pOverride->m_dValues.append ( tValue );
+ }
+
+ if ( !pOverride )
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "override: id:value mapping expected" );
+ SPH_RET(false);
+ }
+ SPH_RET(true);
+ }
+ else
+ {
+ snprintf ( m_sParseError, sizeof(m_sParseError), "unknown parameter '%s'", sName );
+ SPH_RET(false);
+ }
+
+ // !COMMIT handle syntax errors
+
+ SPH_RET(true);
+}
+
+
+bool CSphSEQuery::Parse ()
+{
+ SPH_ENTER_METHOD();
+ SPH_DEBUG ( "query [[ %s ]]", m_sQueryBuffer );
+
+ m_bQuery = false;
+ char * pCur = m_sQueryBuffer;
+ char * pNext = pCur;
+
+ while (( pNext = strchr ( pNext, ';' ) ))
+ {
+ // handle escaped semicolons
+ if ( pNext>m_sQueryBuffer && pNext[-1]=='\\' && pNext[1]!='\0' )
+ {
+ pNext++;
+ continue;
+ }
+
+ // handle semicolon-separated clauses
+ *pNext++ = '\0';
+ if ( !ParseField ( pCur ) )
+ SPH_RET(false);
+ pCur = pNext;
+ }
+
+ SPH_RET(true);
+}
+
+
+void CSphSEQuery::SendBytes ( const void * pBytes, int iBytes )
+{
+ SPH_ENTER_METHOD();
+ if ( m_iBufLeft<iBytes )
+ {
+ m_bBufOverrun = true;
+ SPH_VOID_RET();
+ }
+
+ memcpy ( m_pCur, pBytes, iBytes );
+
+ m_pCur += iBytes;
+ m_iBufLeft -= iBytes;
+ SPH_VOID_RET();
+}
+
+
+int CSphSEQuery::BuildRequest ( char ** ppBuffer )
+{
+ SPH_ENTER_METHOD();
+
+ // calc request length
+ int iReqSize = 124 + 4*m_iWeights
+ + strlen ( m_sSortBy )
+ + strlen ( m_sQuery )
+ + strlen ( m_sIndex )
+ + strlen ( m_sGroupBy )
+ + strlen ( m_sGroupSortBy )
+ + strlen ( m_sGroupDistinct )
+ + strlen ( m_sComment );
+ for ( int i=0; i<m_iFilters; i++ )
+ {
+ const CSphSEFilter & tFilter = m_dFilters[i];
+ iReqSize += 12 + strlen ( tFilter.m_sAttrName ); // string attr-name; int type; int exclude-flag
+ switch ( tFilter.m_eType )
+ {
+ case SPH_FILTER_VALUES: iReqSize += 4 + 8*tFilter.m_iValues; break;
+ case SPH_FILTER_RANGE: iReqSize += 16; break;
+ case SPH_FILTER_FLOATRANGE: iReqSize += 8; break;
+ }
+ }
+ if ( m_bGeoAnchor ) // 1.14+
+ iReqSize += 16 + strlen ( m_sGeoLatAttr ) + strlen ( m_sGeoLongAttr );
+ for ( int i=0; i<m_iIndexWeights; i++ ) // 1.15+
+ iReqSize += 8 + strlen(m_sIndexWeight[i] );
+ for ( int i=0; i<m_iFieldWeights; i++ ) // 1.18+
+ iReqSize += 8 + strlen(m_sFieldWeight[i] );
+ // overrides
+ iReqSize += 4;
+ for ( int i=0; i<m_dOverrides.elements(); i++ )
+ {
+ CSphSEQuery::Override_t * pOverride = m_dOverrides.at(i);
+ const uint32 uSize = pOverride->m_iType == SPH_ATTR_BIGINT ? 16 : 12; // id64 + value
+ iReqSize += strlen ( pOverride->m_sName ) + 12 + uSize*pOverride->m_dIds.elements();
+ }
+ // select
+ iReqSize += 4;
+
+ m_iBufLeft = 0;
+ SafeDeleteArray ( m_pBuf );
+
+ m_pBuf = new char [ iReqSize ];
+ if ( !m_pBuf )
+ SPH_RET(-1);
+
+ m_pCur = m_pBuf;
+ m_iBufLeft = iReqSize;
+ m_bBufOverrun = false;
+ (*ppBuffer) = m_pBuf;
+
+ // build request
+ SendWord ( SEARCHD_COMMAND_SEARCH ); // command id
+ SendWord ( VER_COMMAND_SEARCH ); // command version
+ SendInt ( iReqSize-8 ); // packet body length
+
+ SendInt ( 1 ); // number of queries
+ SendInt ( m_iOffset );
+ SendInt ( m_iLimit );
+ SendInt ( m_eMode );
+ SendInt ( m_eRanker ); // 1.16+
+ SendInt ( m_eSort );
+ SendString ( m_sSortBy ); // sort attr
+ SendString ( m_sQuery ); // query
+ SendInt ( m_iWeights );
+ for ( int j=0; j<m_iWeights; j++ )
+ SendInt ( m_pWeights[j] ); // weights
+ SendString ( m_sIndex ); // indexes
+ SendInt ( 1 ); // id64 range follows
+ SendUint64 ( m_iMinID ); // id/ts ranges
+ SendUint64 ( m_iMaxID );
+
+ SendInt ( m_iFilters );
+ for ( int j=0; j<m_iFilters; j++ )
+ {
+ const CSphSEFilter & tFilter = m_dFilters[j];
+ SendString ( tFilter.m_sAttrName );
+ SendInt ( tFilter.m_eType );
+
+ switch ( tFilter.m_eType )
+ {
+ case SPH_FILTER_VALUES:
+ SendInt ( tFilter.m_iValues );
+ for ( int k=0; k<tFilter.m_iValues; k++ )
+ SendUint64 ( tFilter.m_pValues[k] );
+ break;
+
+ case SPH_FILTER_RANGE:
+ SendUint64 ( tFilter.m_uMinValue );
+ SendUint64 ( tFilter.m_uMaxValue );
+ break;
+
+ case SPH_FILTER_FLOATRANGE:
+ SendFloat ( tFilter.m_fMinValue );
+ SendFloat ( tFilter.m_fMaxValue );
+ break;
+ }
+
+ SendInt ( tFilter.m_bExclude );
+ }
+
+ SendInt ( m_eGroupFunc );
+ SendString ( m_sGroupBy );
+ SendInt ( m_iMaxMatches );
+ SendString ( m_sGroupSortBy );
+ SendInt ( m_iCutoff ); // 1.9+
+ SendInt ( m_iRetryCount ); // 1.10+
+ SendInt ( m_iRetryDelay );
+ SendString ( m_sGroupDistinct ); // 1.11+
+ SendInt ( m_bGeoAnchor ); // 1.14+
+ if ( m_bGeoAnchor )
+ {
+ SendString ( m_sGeoLatAttr );
+ SendString ( m_sGeoLongAttr );
+ SendFloat ( m_fGeoLatitude );
+ SendFloat ( m_fGeoLongitude );
+ }
+ SendInt ( m_iIndexWeights ); // 1.15+
+ for ( int i=0; i<m_iIndexWeights; i++ )
+ {
+ SendString ( m_sIndexWeight[i] );
+ SendInt ( m_iIndexWeight[i] );
+ }
+ SendInt ( m_iMaxQueryTime ); // 1.17+
+ SendInt ( m_iFieldWeights ); // 1.18+
+ for ( int i=0; i<m_iFieldWeights; i++ )
+ {
+ SendString ( m_sFieldWeight[i] );
+ SendInt ( m_iFieldWeight[i] );
+ }
+ SendString ( m_sComment );
+
+ // overrides
+ SendInt ( m_dOverrides.elements() );
+ for ( int i=0; i<m_dOverrides.elements(); i++ )
+ {
+ CSphSEQuery::Override_t * pOverride = m_dOverrides.at(i);
+ SendString ( pOverride->m_sName );
+ SendDword ( pOverride->m_iType );
+ SendInt ( pOverride->m_dIds.elements() );
+ for ( int j=0; j<pOverride->m_dIds.elements(); j++ )
+ {
+ SendUint64 ( pOverride->m_dIds.at(j) );
+ if ( pOverride->m_iType == SPH_ATTR_FLOAT )
+ SendFloat ( pOverride->m_dValues.at(j).m_fValue );
+ else if ( pOverride->m_iType == SPH_ATTR_BIGINT )
+ SendUint64 ( pOverride->m_dValues.at(j).m_iValue64 );
+ else
+ SendDword ( pOverride->m_dValues.at(j).m_uValue );
+ }
+ }
+
+ // select
+ SendString ( "" );
+
+ // detect buffer overruns and underruns, and report internal error
+ if ( m_bBufOverrun || m_iBufLeft!=0 || m_pCur-m_pBuf!=iReqSize )
+ SPH_RET(-1);
+
+ // all fine
+ SPH_RET(iReqSize);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// SPHINX HANDLER
+//////////////////////////////////////////////////////////////////////////////
+
+static const char * ha_sphinx_exts[] = { NullS };
+
+
+#if MYSQL_VERSION_ID<50100
+ha_sphinx::ha_sphinx ( TABLE_ARG * table )
+ : handler ( &sphinx_hton, table )
+#else
+ha_sphinx::ha_sphinx ( handlerton * hton, TABLE_ARG * table )
+ : handler ( hton, table )
+#endif
+ , m_pShare ( NULL )
+ , m_iMatchesTotal ( 0 )
+ , m_iCurrentPos ( 0 )
+ , m_pCurrentKey ( NULL )
+ , m_iCurrentKeyLen ( 0 )
+ , m_pResponse ( NULL )
+ , m_pResponseEnd ( NULL )
+ , m_pCur ( NULL )
+ , m_bUnpackError ( false )
+ , m_iFields ( 0 )
+ , m_dFields ( NULL )
+ , m_iAttrs ( 0 )
+ , m_dAttrs ( NULL )
+ , m_bId64 ( 0 )
+ , m_dUnboundFields ( NULL )
+{
+ SPH_ENTER_METHOD();
+ SPH_VOID_RET();
+}
+
+
+// If frm_error() is called then we will use this to to find out what file extentions
+// exist for the storage engine. This is also used by the default rename_table and
+// delete_table method in handler.cc.
+const char ** ha_sphinx::bas_ext() const
+{
+ return ha_sphinx_exts;
+}
+
+
+// Used for opening tables. The name will be the name of the file.
+// A table is opened when it needs to be opened. For instance
+// when a request comes in for a select on the table (tables are not
+// open and closed for each request, they are cached).
+//
+// Called from handler.cc by handler::ha_open(). The server opens all tables by
+// calling ha_open() which then calls the handler specific open().
+int ha_sphinx::open ( const char * name, int, uint )
+{
+ SPH_ENTER_METHOD();
+ m_pShare = get_share ( name, table );
+ if ( !m_pShare )
+ SPH_RET(1);
+
+ thr_lock_data_init ( &m_pShare->m_tLock, &m_tLock, NULL );
+
+ *thd_ha_data ( table->in_use, ht ) = NULL;
+
+ SPH_RET(0);
+}
+
+
+int ha_sphinx::ConnectToSearchd ( const char * sQueryHost, int iQueryPort )
+{
+ SPH_ENTER_METHOD();
+
+ struct sockaddr_in sin;
+#ifndef __WIN__
+ struct sockaddr_un saun;
+#endif
+
+ int iDomain = 0;
+ int iSockaddrSize = 0;
+ struct sockaddr * pSockaddr = NULL;
+
+ in_addr_t ip_addr;
+ int version;
+ uint uClientVersion = htonl ( SPHINX_SEARCHD_PROTO );
+
+ const char * sHost = ( sQueryHost && *sQueryHost ) ? sQueryHost : m_pShare->m_sHost;
+ ushort iPort = iQueryPort ? (ushort)iQueryPort : m_pShare->m_iPort;
+
+ if ( iPort )
+ {
+ iDomain = AF_INET;
+ iSockaddrSize = sizeof(sin);
+ pSockaddr = (struct sockaddr *) &sin;
+
+ memset ( &sin, 0, sizeof(sin) );
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(iPort);
+
+ // prepare host address
+ if ( (int)( ip_addr=inet_addr(sHost) ) != (int)INADDR_NONE )
+ {
+ memcpy ( &sin.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 ( sHost, &tmp_hostent,
+ buff2, sizeof(buff2), &tmp_errno );
+ if ( !hp )
+ {
+ my_gethostbyname_r_free();
+
+ char sError[256];
+ my_snprintf ( sError, sizeof(sError), "failed to resolve searchd host (name=%s)", sHost );
+
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SPH_RET(-1);
+ }
+
+ memcpy ( &sin.sin_addr, hp->h_addr,
+ Min ( sizeof(sin.sin_addr), (size_t)hp->h_length ) );
+ my_gethostbyname_r_free();
+ }
+ } else
+ {
+#ifndef __WIN__
+ iDomain = AF_UNIX;
+ iSockaddrSize = sizeof(saun);
+ pSockaddr = (struct sockaddr *) &saun;
+
+ memset ( &saun, 0, sizeof(saun) );
+ saun.sun_family = AF_UNIX;
+ strncpy ( saun.sun_path, sHost, sizeof(saun.sun_path)-1 );
+#else
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "UNIX sockets are not supported on Windows" );
+ SPH_RET(-1);
+#endif
+ }
+
+ char sError[512];
+ int iSocket = socket ( iDomain, SOCK_STREAM, 0 );
+
+ if ( iSocket<0 )
+ {
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "failed to create client socket" );
+ SPH_RET(-1);
+ }
+
+ if ( connect ( iSocket, pSockaddr, iSockaddrSize )<0 )
+ {
+ sphSockClose ( iSocket );
+ my_snprintf ( sError, sizeof(sError), "failed to connect to searchd (host=%s, errno=%d, port=%d)",
+ sHost, errno, iPort );
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SPH_RET(-1);
+ }
+
+ if ( ::recv ( iSocket, (char *)&version, sizeof(version), 0 )!=sizeof(version) )
+ {
+ sphSockClose ( iSocket );
+ my_snprintf ( sError, sizeof(sError), "failed to receive searchd version (host=%s, port=%d)",
+ sHost, iPort );
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SPH_RET(-1);
+ }
+
+ if ( ::send ( iSocket, (char*)&uClientVersion, sizeof(uClientVersion), 0 )!=sizeof(uClientVersion) )
+ {
+ sphSockClose ( iSocket );
+ my_snprintf ( sError, sizeof(sError), "failed to send client version (host=%s, port=%d)",
+ sHost, iPort );
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SPH_RET(-1);
+ }
+
+ SPH_RET(iSocket);
+}
+
+
+// Closes a table. We call the free_share() function to free any resources
+// that we have allocated in the "shared" structure.
+//
+// Called from sql_base.cc, sql_select.cc, and table.cc.
+// In sql_select.cc it is only used to close up temporary tables or during
+// the process where a temporary table is converted over to being a
+// myisam table.
+// For sql_base.cc look at close_data_tables().
+int ha_sphinx::close()
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( free_share(m_pShare) );
+}
+
+
+int ha_sphinx::write_row ( uchar * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+int ha_sphinx::update_row ( const uchar *, uchar * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+int ha_sphinx::delete_row ( const uchar * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+// keynr is key (index) number
+// sorted is 1 if result MUST be sorted according to index
+int ha_sphinx::index_init ( uint keynr, bool )
+{
+ SPH_ENTER_METHOD();
+ active_index = keynr;
+ SPH_RET(0);
+}
+
+
+int ha_sphinx::index_end()
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(0);
+}
+
+
+uint32 ha_sphinx::UnpackDword ()
+{
+ if ( m_pCur+sizeof(uint32)>m_pResponseEnd )
+ {
+ m_pCur = m_pResponseEnd;
+ m_bUnpackError = true;
+ return 0;
+ }
+
+ uint32 uRes = ntohl ( sphUnalignedRead ( *(uint32*)m_pCur ) );
+ m_pCur += sizeof(uint32);
+ return uRes;
+}
+
+
+char * ha_sphinx::UnpackString ()
+{
+ uint32 iLen = UnpackDword ();
+ if ( !iLen )
+ return NULL;
+
+ if ( m_pCur+iLen>m_pResponseEnd )
+ {
+ m_pCur = m_pResponseEnd;
+ m_bUnpackError = true;
+ return NULL;
+ }
+
+ char * sRes = new char [ 1+iLen ];
+ memcpy ( sRes, m_pCur, iLen );
+ sRes[iLen] = '\0';
+ m_pCur += iLen;
+ return sRes;
+}
+
+
+static inline const char * FixNull ( const char * s )
+{
+ return s ? s : "(null)";
+}
+
+
+bool ha_sphinx::UnpackSchema ()
+{
+ SPH_ENTER_METHOD();
+
+ // cleanup
+ if ( m_dFields )
+ for ( int i=0; i<(int)m_iFields; i++ )
+ SafeDeleteArray ( m_dFields[i] );
+ SafeDeleteArray ( m_dFields );
+
+ // unpack network packet
+ uint32 uStatus = UnpackDword ();
+ char * sMessage = NULL;
+
+ if ( uStatus!=SEARCHD_OK )
+ {
+ sMessage = UnpackString ();
+ CSphSEThreadData * pTls = GetTls ();
+ if ( pTls )
+ {
+ strncpy ( pTls->m_tStats.m_sLastMessage, sMessage, sizeof(pTls->m_tStats.m_sLastMessage) );
+ pTls->m_tStats.m_bLastError = ( uStatus==SEARCHD_ERROR );
+ }
+
+ if ( uStatus==SEARCHD_ERROR )
+ {
+ char sError[1024];
+ my_snprintf ( sError, sizeof(sError), "searchd error: %s", sMessage );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SafeDeleteArray ( sMessage );
+ SPH_RET ( false );
+ }
+ }
+
+ m_iFields = UnpackDword ();
+ m_dFields = new char * [ m_iFields ];
+ if ( !m_dFields )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: UnpackSchema() failed (fields alloc error)" );
+ SPH_RET(false);
+ }
+
+ for ( uint32 i=0; i<m_iFields; i++ )
+ m_dFields[i] = UnpackString ();
+
+ SafeDeleteArray ( m_dAttrs );
+ m_iAttrs = UnpackDword ();
+ m_dAttrs = new CSphSEAttr [ m_iAttrs ];
+ if ( !m_dAttrs )
+ {
+ for ( int i=0; i<(int)m_iFields; i++ )
+ SafeDeleteArray ( m_dFields[i] );
+ SafeDeleteArray ( m_dFields );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: UnpackSchema() failed (attrs alloc error)" );
+ SPH_RET(false);
+ }
+
+ for ( uint32 i=0; i<m_iAttrs; i++ )
+ {
+ m_dAttrs[i].m_sName = UnpackString ();
+ m_dAttrs[i].m_uType = UnpackDword ();
+ if ( m_bUnpackError ) // m_sName may be null
+ break;
+
+ m_dAttrs[i].m_iField = -1;
+ for ( int j=SPHINXSE_SYSTEM_COLUMNS; j<m_pShare->m_iTableFields; j++ )
+ {
+ const char * sTableField = m_pShare->m_sTableField[j];
+ const char * sAttrField = m_dAttrs[i].m_sName;
+ if ( m_dAttrs[i].m_sName[0]=='@' )
+ {
+ const char * sAtPrefix = "_sph_";
+ if ( strncmp ( sTableField, sAtPrefix, strlen(sAtPrefix) ) )
+ continue;
+ sTableField += strlen(sAtPrefix);
+ sAttrField++;
+ }
+
+ if ( !strcasecmp ( sAttrField, sTableField ) )
+ {
+ // we're almost good, but
+ // let's enforce that timestamp columns can only receive timestamp attributes
+ if ( m_pShare->m_eTableFieldType[j]!=MYSQL_TYPE_TIMESTAMP || m_dAttrs[i].m_uType==SPH_ATTR_TIMESTAMP )
+ m_dAttrs[i].m_iField = j;
+ break;
+ }
+ }
+ }
+
+ m_iMatchesTotal = UnpackDword ();
+
+ m_bId64 = UnpackDword ();
+ if ( m_bId64 && m_pShare->m_eTableFieldType[0] != MYSQL_TYPE_LONGLONG )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: 1st column must be bigint to accept 64-bit DOCIDs" );
+ SPH_RET(false);
+ }
+
+ // network packet unpacked; build unbound fields map
+ SafeDeleteArray ( m_dUnboundFields );
+ m_dUnboundFields = new int [ m_pShare->m_iTableFields ];
+
+ for ( int i=0; i<m_pShare->m_iTableFields; i++ )
+ {
+ if ( i<SPHINXSE_SYSTEM_COLUMNS )
+ m_dUnboundFields[i] = SPH_ATTR_NONE;
+
+ else if ( m_pShare->m_eTableFieldType[i]==MYSQL_TYPE_TIMESTAMP )
+ m_dUnboundFields[i] = SPH_ATTR_TIMESTAMP;
+
+ else
+ m_dUnboundFields[i] = SPH_ATTR_INTEGER;
+ }
+
+ for ( uint32 i=0; i<m_iAttrs; i++ )
+ if ( m_dAttrs[i].m_iField>=0 )
+ m_dUnboundFields [ m_dAttrs[i].m_iField ] = SPH_ATTR_NONE;
+
+ if ( m_bUnpackError )
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: UnpackSchema() failed (unpack error)" );
+
+ SPH_RET(!m_bUnpackError);
+}
+
+
+bool ha_sphinx::UnpackStats ( CSphSEStats * pStats )
+{
+ assert ( pStats );
+
+ char * pCurSave = m_pCur;
+ for ( uint i=0; i<m_iMatchesTotal && m_pCur<m_pResponseEnd-sizeof(uint32); i++ )
+ {
+ m_pCur += m_bId64 ? 12 : 8; // skip id+weight
+ for ( uint32 i=0; i<m_iAttrs && m_pCur<m_pResponseEnd-sizeof(uint32); i++ )
+ {
+ if ( m_dAttrs[i].m_uType & SPH_ATTR_MULTI )
+ {
+ // skip MVA list
+ uint32 uCount = UnpackDword ();
+ m_pCur += uCount*4;
+ }
+ else // skip normal value
+ m_pCur += m_dAttrs[i].m_uType == SPH_ATTR_BIGINT ? 8 : 4;
+ }
+ }
+
+ pStats->m_iMatchesTotal = UnpackDword ();
+ pStats->m_iMatchesFound = UnpackDword ();
+ pStats->m_iQueryMsec = UnpackDword ();
+ pStats->m_iWords = UnpackDword ();
+
+ if ( m_bUnpackError )
+ return false;
+
+ SafeDeleteArray ( pStats->m_dWords );
+ if ( pStats->m_iWords<0 || pStats->m_iWords>=SPHINXSE_MAX_KEYWORDSTATS )
+ return false;
+ pStats->m_dWords = new CSphSEWordStats [ pStats->m_iWords ];
+ if ( !pStats->m_dWords )
+ return false;
+
+ for ( int i=0; i<pStats->m_iWords; i++ )
+ {
+ CSphSEWordStats & tWord = pStats->m_dWords[i];
+ tWord.m_sWord = UnpackString ();
+ tWord.m_iDocs = UnpackDword ();
+ tWord.m_iHits = UnpackDword ();
+ }
+
+ if ( m_bUnpackError )
+ return false;
+
+ m_pCur = pCurSave;
+ return true;
+}
+
+
+/// condition pushdown implementation, to properly intercept WHERE clauses on my columns
+const COND * ha_sphinx::cond_push ( const COND * cond )
+{
+ // catch the simplest case: query_column="some text"
+ for ( ;; )
+ {
+ if ( cond->type()!=COND::FUNC_ITEM )
+ break;
+
+ Item_func * condf = (Item_func *)cond;
+ if ( condf->functype()!=Item_func::EQ_FUNC || condf->argument_count()!=2 )
+ break;
+
+ Item ** args = condf->arguments();
+ if ( args[0]->type()!=COND::FIELD_ITEM || args[1]->type()!=COND::STRING_ITEM )
+ break;
+
+ Item_field * pField = (Item_field *) args[0];
+ if ( pField->field->field_index!=2 ) // FIXME! magic key index
+ break;
+
+ // get my tls
+ CSphSEThreadData * pTls = GetTls ();
+ if ( !pTls )
+ break;
+
+ // copy the query, and let know that we intercepted this condition
+ Item_string * pString = (Item_string *) args[1];
+ pTls->m_bQuery = true;
+ strncpy ( pTls->m_sQuery, pString->str_value.c_ptr(), sizeof(pTls->m_sQuery) );
+ pTls->m_sQuery[sizeof(pTls->m_sQuery)-1] = '\0';
+ pTls->m_pQueryCharset = pString->str_value.charset();
+ return NULL;
+ }
+
+ // don't change anything
+ return cond;
+}
+
+
+/// condition popup
+void ha_sphinx::cond_pop ()
+{
+ CSphSEThreadData * pTls = GetTls ();
+ if ( pTls && pTls->m_bQuery )
+ pTls->m_bQuery = false;
+ return;
+}
+
+
+/// get TLS (maybe allocate it, too)
+CSphSEThreadData * ha_sphinx::GetTls()
+{
+ // where do we store that pointer in today's version?
+ CSphSEThreadData ** ppTls;
+ ppTls = (CSphSEThreadData**) thd_ha_data ( ha_thd(), ht );
+
+ // allocate if needed
+ if ( !*ppTls )
+ *ppTls = new CSphSEThreadData ();
+
+ // errors will be handled by caller
+ return *ppTls;
+}
+
+
+// Positions an index cursor to the index specified in the handle. Fetches the
+// row if available. If the key value is null, begin at the first key of the
+// index.
+int ha_sphinx::index_read ( byte * buf, const byte * key, uint key_len, enum ha_rkey_function )
+{
+ SPH_ENTER_METHOD();
+ char sError[256];
+
+ // set new data for thd->ha_data, it is used in show_status
+ CSphSEThreadData * pTls = GetTls();
+ if ( !pTls )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: TLS malloc() failed" );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+ pTls->m_tStats.Reset ();
+
+ // parse query
+ if ( pTls->m_bQuery )
+ {
+ // we have a query from condition pushdown
+ m_pCurrentKey = (const byte *) pTls->m_sQuery;
+ m_iCurrentKeyLen = strlen(pTls->m_sQuery);
+ } else
+ {
+ // just use the key (might be truncated)
+ m_pCurrentKey = key+HA_KEY_BLOB_LENGTH;
+ m_iCurrentKeyLen = uint2korr(key); // or maybe key_len?
+ pTls->m_pQueryCharset = m_pShare ? m_pShare->m_pTableQueryCharset : NULL;
+ }
+
+ CSphSEQuery q ( (const char*)m_pCurrentKey, m_iCurrentKeyLen, m_pShare->m_sIndex );
+ if ( !q.Parse () )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), q.m_sParseError );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ // do connect
+ int iSocket = ConnectToSearchd ( q.m_sHost, q.m_iPort );
+ if ( iSocket<0 )
+ SPH_RET ( HA_ERR_END_OF_FILE );
+
+ // my buffer
+ char * pBuffer; // will be free by CSphSEQuery dtor; do NOT free manually
+ int iReqLen = q.BuildRequest ( &pBuffer );
+
+ if ( iReqLen<=0 )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: q.BuildRequest() failed" );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ // send request
+ ::send ( iSocket, pBuffer, iReqLen, 0 );
+
+ // receive reply
+ char sHeader[8];
+ int iGot = ::recv ( iSocket, sHeader, sizeof(sHeader), RECV_FLAGS );
+ if ( iGot!=sizeof(sHeader) )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "failed to receive response header (searchd went away?)" );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ short int uRespStatus = ntohs ( sphUnalignedRead ( *(short int*)( &sHeader[0] ) ) );
+ short int uRespVersion = ntohs ( sphUnalignedRead ( *(short int*)( &sHeader[2] ) ) );
+ uint uRespLength = ntohl ( sphUnalignedRead ( *(uint *)( &sHeader[4] ) ) );
+ SPH_DEBUG ( "got response header (status=%d version=%d length=%d)",
+ uRespStatus, uRespVersion, uRespLength );
+
+ SafeDeleteArray ( m_pResponse );
+ if ( uRespLength<=SPHINXSE_MAX_ALLOC )
+ m_pResponse = new char [ uRespLength+1 ];
+
+ if ( !m_pResponse )
+ {
+ my_snprintf ( sError, sizeof(sError), "bad searchd response length (length=%u)", uRespLength );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ int iRecvLength = 0;
+ while ( iRecvLength<(int)uRespLength )
+ {
+ int iRecv = ::recv ( iSocket, m_pResponse+iRecvLength, uRespLength-iRecvLength, RECV_FLAGS );
+ if ( iRecv<0 )
+ break;
+ iRecvLength += iRecv;
+ }
+
+ ::closesocket ( iSocket );
+ iSocket = -1;
+
+ if ( iRecvLength!=(int)uRespLength )
+ {
+ my_snprintf ( sError, sizeof(sError), "net read error (expected=%d, got=%d)", uRespLength, iRecvLength );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ // we'll have a message, at least
+ pTls->m_bStats = true;
+
+ // parse reply
+ m_iCurrentPos = 0;
+ m_pCur = m_pResponse;
+ m_pResponseEnd = m_pResponse + uRespLength;
+ m_bUnpackError = false;
+
+ if ( uRespStatus!=SEARCHD_OK )
+ {
+ char * sMessage = UnpackString ();
+ if ( !sMessage )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "no valid response from searchd (status=%d, resplen=%d)",
+ uRespStatus, uRespLength );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ strncpy ( pTls->m_tStats.m_sLastMessage, sMessage, sizeof(pTls->m_tStats.m_sLastMessage) );
+ SafeDeleteArray ( sMessage );
+
+ if ( uRespStatus!=SEARCHD_WARNING )
+ {
+ my_snprintf ( sError, sizeof(sError), "searchd error: %s", pTls->m_tStats.m_sLastMessage );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
+
+ pTls->m_tStats.m_bLastError = true;
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+ }
+
+ if ( !UnpackSchema () )
+ SPH_RET ( HA_ERR_END_OF_FILE );
+
+ if ( !UnpackStats ( &pTls->m_tStats ) )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: UnpackStats() failed" );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ SPH_RET ( get_rec ( buf, key, key_len ) );
+}
+
+
+// Positions an index cursor to the index specified in key. Fetches the
+// row if any. This is only used to read whole keys.
+int ha_sphinx::index_read_idx ( byte *, uint, const byte *, uint, enum ha_rkey_function )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+// Used to read forward through the index.
+int ha_sphinx::index_next ( byte * buf )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( get_rec ( buf, m_pCurrentKey, m_iCurrentKeyLen ) );
+}
+
+
+int ha_sphinx::index_next_same ( byte * buf, const byte * key, uint keylen )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( get_rec ( buf, key, keylen ) );
+}
+
+
+int ha_sphinx::get_rec ( byte * buf, const byte *, uint )
+{
+ SPH_ENTER_METHOD();
+
+ if ( m_iCurrentPos>=m_iMatchesTotal )
+ {
+ SafeDeleteArray ( m_pResponse );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ #if MYSQL_VERSION_ID>50100
+ my_bitmap_map * org_bitmap = dbug_tmp_use_all_columns ( table, table->write_set );
+ #endif
+ Field ** field = table->field;
+
+ // unpack and return the match
+ longlong uMatchID = UnpackDword ();
+ if ( m_bId64 )
+ uMatchID = ( uMatchID<<32 ) + UnpackDword();
+ uint32 uMatchWeight = UnpackDword ();
+
+ field[0]->store ( uMatchID, 1 );
+ field[1]->store ( uMatchWeight, 1 );
+ field[2]->store ( (const char*)m_pCurrentKey, m_iCurrentKeyLen, &my_charset_bin );
+
+ for ( uint32 i=0; i<m_iAttrs; i++ )
+ {
+ longlong iValue64;
+ uint32 uValue = UnpackDword ();
+ if ( m_dAttrs[i].m_uType == SPH_ATTR_BIGINT )
+ iValue64 = ( (longlong)uValue<<32 ) | UnpackDword();
+ if ( m_dAttrs[i].m_iField<0 )
+ {
+ // skip MVA
+ if ( m_dAttrs[i].m_uType & SPH_ATTR_MULTI )
+ for ( ; uValue>0 && !m_bUnpackError; uValue-- )
+ UnpackDword();
+ continue;
+ }
+
+ Field * af = field [ m_dAttrs[i].m_iField ];
+ switch ( m_dAttrs[i].m_uType )
+ {
+ case SPH_ATTR_INTEGER:
+ case SPH_ATTR_ORDINAL:
+ case SPH_ATTR_BOOL:
+ af->store ( uValue, 1 );
+ break;
+
+ case SPH_ATTR_FLOAT:
+ af->store ( sphDW2F(uValue) );
+ break;
+
+ case SPH_ATTR_TIMESTAMP:
+ if ( af->type()==MYSQL_TYPE_TIMESTAMP )
+ longstore ( af->ptr, uValue ); // because store() does not accept timestamps
+ else
+ af->store ( uValue, 1 );
+ break;
+
+ case SPH_ATTR_BIGINT:
+ af->store ( iValue64, 0 );
+ break;
+
+ case ( SPH_ATTR_MULTI | SPH_ATTR_INTEGER ):
+ if ( uValue<=0 )
+ {
+ // shortcut, empty MVA set
+ af->store ( "", 0, &my_charset_bin );
+
+ } else
+ {
+ // convert MVA set to comma-separated string
+ char sBuf[1024]; // FIXME! magic size
+ char * pCur = sBuf;
+
+ for ( ; uValue>0 && !m_bUnpackError; uValue-- )
+ {
+ uint32 uEntry = UnpackDword ();
+ if ( pCur < sBuf+sizeof(sBuf)-16 ) // 10 chars per 32bit value plus some safety bytes
+ {
+ sprintf ( pCur, "%u", uEntry );
+ while ( *pCur ) *pCur++;
+ if ( uValue>1 )
+ *pCur++ = ','; // non-trailing commas
+ }
+ }
+
+ af->store ( sBuf, pCur-sBuf, &my_charset_bin );
+ }
+ break;
+
+ default:
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: unhandled attr type" );
+ SafeDeleteArray ( m_pResponse );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+ }
+
+ if ( m_bUnpackError )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: response unpacker failed" );
+ SafeDeleteArray ( m_pResponse );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ // zero out unmapped fields
+ for ( int i=SPHINXSE_SYSTEM_COLUMNS; i<(int)table->s->fields; i++ )
+ if ( m_dUnboundFields[i]!=SPH_ATTR_NONE )
+ switch ( m_dUnboundFields[i] )
+ {
+ case SPH_ATTR_INTEGER: table->field[i]->store ( 0, 1 ); break;
+ case SPH_ATTR_TIMESTAMP: longstore ( table->field[i]->ptr, 0 ); break;
+ default:
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0),
+ "INTERNAL ERROR: unhandled unbound field type %d", m_dUnboundFields[i] );
+ SafeDeleteArray ( m_pResponse );
+ SPH_RET ( HA_ERR_END_OF_FILE );
+ }
+
+ memset ( buf, 0, table->s->null_bytes );
+ m_iCurrentPos++;
+
+ #if MYSQL_VERSION_ID > 50100
+ dbug_tmp_restore_column_map(table->write_set, org_bitmap);
+ #endif
+
+ SPH_RET(0);
+}
+
+
+// Used to read backwards through the index.
+int ha_sphinx::index_prev ( byte * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+// index_first() asks for the first key in the index.
+//
+// Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
+// and sql_select.cc.
+int ha_sphinx::index_first ( byte * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_END_OF_FILE );
+}
+
+// index_last() asks for the last key in the index.
+//
+// Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
+// and sql_select.cc.
+int ha_sphinx::index_last ( byte * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+int ha_sphinx::rnd_init ( bool )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(0);
+}
+
+
+int ha_sphinx::rnd_end()
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(0);
+}
+
+
+int ha_sphinx::rnd_next ( byte * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_END_OF_FILE );
+}
+
+
+void ha_sphinx::position ( const byte * )
+{
+ SPH_ENTER_METHOD();
+ SPH_VOID_RET();
+}
+
+
+// This is like rnd_next, but you are given a position to use
+// to determine the row. The position will be of the type that you stored in
+// ref. You can use ha_get_ptr(pos,ref_length) to retrieve whatever key
+// or position you saved when position() was called.
+// Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
+int ha_sphinx::rnd_pos ( byte *, byte * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+#if MYSQL_VERSION_ID>=50030
+int ha_sphinx::info ( uint )
+#else
+void ha_sphinx::info ( uint )
+#endif
+{
+ SPH_ENTER_METHOD();
+
+ if ( table->s->keys>0 )
+ table->key_info[0].rec_per_key[0] = 1;
+
+ #if MYSQL_VERSION_ID>50100
+ stats.records = 20;
+ #else
+ records = 20;
+ #endif
+
+#if MYSQL_VERSION_ID>=50030
+ SPH_RET(0);
+#else
+ SPH_VOID_RET();
+#endif
+}
+
+
+int ha_sphinx::reset ()
+{
+ SPH_ENTER_METHOD();
+ CSphSEThreadData * pTls = GetTls ();
+ if ( pTls )
+ pTls->m_bQuery = false;
+ SPH_RET(0);
+}
+
+
+int ha_sphinx::delete_all_rows()
+{
+ SPH_ENTER_METHOD();
+ SPH_RET ( HA_ERR_WRONG_COMMAND );
+}
+
+
+// First you should go read the section "locking functions for mysql" in
+// lock.cc to understand this.
+// This create a lock on the table. If you are implementing a storage engine
+// that can handle transacations look at ha_berkely.cc to see how you will
+// want to go about doing this. Otherwise you should consider calling flock()
+// here.
+//
+// Called from lock.cc by lock_external() and unlock_external(). Also called
+// from sql_table.cc by copy_data_between_tables().
+int ha_sphinx::external_lock ( THD *, int )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(0);
+}
+
+
+THR_LOCK_DATA ** ha_sphinx::store_lock ( THD *, THR_LOCK_DATA ** to,
+ enum thr_lock_type lock_type )
+{
+ SPH_ENTER_METHOD();
+
+ if ( lock_type!=TL_IGNORE && m_tLock.type==TL_UNLOCK )
+ m_tLock.type=lock_type;
+
+ *to++ = &m_tLock;
+ SPH_RET(to);
+}
+
+
+int ha_sphinx::delete_table ( const char * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(0);
+}
+
+
+// Renames a table from one name to another from alter table call.
+//
+// If you do not implement this, the default rename_table() is called from
+// handler.cc and it will delete all files with the file extentions returned
+// by bas_ext().
+//
+// Called from sql_table.cc by mysql_rename_table().
+int ha_sphinx::rename_table ( const char *, const char * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(0);
+}
+
+
+// Given a starting key, and an ending key estimate the number of rows that
+// will exist between the two. end_key may be empty which in case determine
+// if start_key matches any rows.
+//
+// Called from opt_range.cc by check_quick_keys().
+ha_rows ha_sphinx::records_in_range ( uint, key_range *, key_range * )
+{
+ SPH_ENTER_METHOD();
+ SPH_RET(3); // low number to force index usage
+}
+
+
+static inline bool IsIntegerFieldType ( enum_field_types eType )
+{
+ return eType==MYSQL_TYPE_LONG || eType==MYSQL_TYPE_LONGLONG;
+}
+
+
+// create() is called to create a database. The variable name will have the name
+// of the table. When create() is called you do not need to worry about opening
+// the table. Also, the FRM file will have already been created so adjusting
+// create_info will not do you any good. You can overwrite the frm file at this
+// point if you wish to change the table definition, but there are no methods
+// currently provided for doing that.
+//
+// Called from handle.cc by ha_create_table().
+int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
+{
+ SPH_ENTER_METHOD();
+ char sError[256];
+
+ if ( !ParseUrl ( NULL, table, true ) )
+ SPH_RET(-1);
+
+ for ( ;; )
+ {
+ // check system fields (count and types)
+ if ( table->s->fields<SPHINXSE_SYSTEM_COLUMNS )
+ {
+ my_snprintf ( sError, sizeof(sError), "%s: there MUST be at least %d columns",
+ name, SPHINXSE_SYSTEM_COLUMNS );
+ break;
+ }
+
+ if ( !IsIntegerFieldType ( table->field[0]->type() ) || !((Field_num *)table->field[0])->unsigned_flag )
+ {
+ my_snprintf ( sError, sizeof(sError), "%s: 1st column (docid) MUST be unsigned integer or bigint", name );
+ break;
+ }
+
+ if ( !IsIntegerFieldType ( table->field[1]->type() ) )
+ {
+ my_snprintf ( sError, sizeof(sError), "%s: 2nd column (weight) MUST be integer or bigint", name );
+ break;
+ }
+
+ enum_field_types f2 = table->field[2]->type();
+ if ( f2!=MYSQL_TYPE_VARCHAR
+ && f2!=MYSQL_TYPE_BLOB && f2!=MYSQL_TYPE_MEDIUM_BLOB && f2!=MYSQL_TYPE_LONG_BLOB && f2!=MYSQL_TYPE_TINY_BLOB )
+ {
+ my_snprintf ( sError, sizeof(sError), "%s: 3rd column (search query) MUST be varchar or text", name );
+ break;
+ }
+
+ // check attributes
+ int i;
+ for ( i=3; i<(int)table->s->fields; i++ )
+ {
+ enum_field_types eType = table->field[i]->type();
+ if ( eType!=MYSQL_TYPE_TIMESTAMP && !IsIntegerFieldType(eType) && eType!=MYSQL_TYPE_VARCHAR && eType!=MYSQL_TYPE_FLOAT )
+ {
+ my_snprintf ( sError, sizeof(sError), "%s: %dth column (attribute %s) MUST be integer, bigint, timestamp, varchar, or float",
+ name, i+1, table->field[i]->field_name );
+ break;
+ }
+ }
+
+ if ( i!=(int)table->s->fields )
+ break;
+
+ // check index
+ if (
+ table->s->keys!=1 ||
+ table->key_info[0].key_parts!=1 ||
+ strcasecmp ( table->key_info[0].key_part[0].field->field_name, table->field[2]->field_name ) )
+ {
+ my_snprintf ( sError, sizeof(sError), "%s: there must be an index on '%s' column",
+ name, table->field[2]->field_name );
+ break;
+ }
+
+ // all good
+ sError[0] = '\0';
+ break;
+ }
+ if ( sError[0] )
+ {
+ my_error ( ER_CANT_CREATE_TABLE, MYF(0), sError, -1 );
+ SPH_RET(-1);
+ }
+
+ SPH_RET(0);
+}
+
+//// show functions
+
+#if MYSQL_VERSION_ID<50100
+#define SHOW_VAR_FUNC_BUFF_SIZE 1024
+#endif
+
+static int sphinx_showfunc ( THD * thd, SHOW_VAR * out, char * sBuffer )
+{
+ CSphSEThreadData *pTls = (CSphSEThreadData *) *thd_ha_data ( thd, sphinx_hton_ptr );
+ CSphSEStats * pStats = ( pTls && pTls->m_bStats ) ? &pTls->m_tStats : 0;
+ SHOW_VAR *array = (SHOW_VAR*)thd_alloc(thd, sizeof(SHOW_VAR)*7);
+ out->type = SHOW_ARRAY;
+ out->value = (char*)array;
+ if (pStats)
+ {
+ array[0].name = "total";
+ array[0].type = SHOW_INT;
+ array[0].value = (char *) &pStats->m_iMatchesTotal;
+ array[1].name = "total_found";
+ array[1].type = SHOW_INT;
+ array[1].value = (char *) &pStats->m_iMatchesFound;
+ array[2].name = "time";
+ array[2].type = SHOW_INT;
+ array[2].value = (char *) &pStats->m_iQueryMsec;
+ array[3].name = "word_count";
+ array[3].type = SHOW_INT;
+ array[3].value = (char *) &pStats->m_iWords;
+ array[4].name = "error";
+ array[4].type = SHOW_CHAR;
+ array[4].value = (char *) &pStats->m_sLastMessage;
+ array[5].name = "words";
+ array[5].type = SHOW_CHAR;
+ array[5].value = sBuffer;
+ sBuffer[0] = 0;
+
+ if ( pStats->m_iWords )
+ {
+ uint uBuffLen = 0;
+
+ // the following is partially based on code in sphinx_show_status()
+ for ( int i=0; i<pStats->m_iWords; i++ )
+ {
+ CSphSEWordStats & tWord = pStats->m_dWords[i];
+ uBuffLen = my_snprintf ( sBuffer, SHOW_VAR_FUNC_BUFF_SIZE, "%s%s:%d:%d ", sBuffer,
+ tWord.m_sWord, tWord.m_iDocs, tWord.m_iHits );
+ }
+
+ if ( uBuffLen > 0 )
+ {
+ // trim last space
+ sBuffer [ --uBuffLen ] = 0;
+
+ if ( pTls->m_pQueryCharset )
+ {
+ // String::c_ptr() will nul-terminate the buffer.
+ //
+ // NOTE: It's not entirely clear whether this conversion is necessary at all.
+
+ String sConvert;
+ uint iErrors;
+ sConvert.copy ( sBuffer, uBuffLen, pTls->m_pQueryCharset, system_charset_info, &iErrors );
+ memcpy ( sBuffer, sConvert.c_ptr(), sConvert.length() + 1 );
+ }
+ }
+ }
+
+ array[6].name = 0; // terminate the array
+ }
+ else
+ array[0].name = 0;
+ return 0;
+}
+
+#if MYSQL_VERSION_ID>50100
+struct st_mysql_storage_engine sphinx_storage_engine =
+{
+ MYSQL_HANDLERTON_INTERFACE_VERSION
+};
+
+struct st_mysql_show_var sphinx_status_vars[] =
+{
+ {"sphinx", (char *)sphinx_showfunc, SHOW_FUNC},
+ {0, 0, (enum_mysql_show_type)0}
+};
+
+
+mysql_declare_plugin(sphinx)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &sphinx_storage_engine,
+ sphinx_hton_name,
+ "Sphinx developers",
+ sphinx_hton_comment,
+ PLUGIN_LICENSE_GPL,
+ sphinx_init_func, // Plugin Init
+ sphinx_done_func, // Plugin Deinit
+ 0x0001, // 0.1
+ sphinx_status_vars,
+ NULL,
+ NULL
+}
+mysql_declare_plugin_end;
+
+#ifdef maria_declare_plugin
+maria_declare_plugin(sphinx)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &sphinx_storage_engine,
+ sphinx_hton_name,
+ "Sphinx developers",
+ sphinx_hton_comment,
+ PLUGIN_LICENSE_GPL,
+ sphinx_init_func, // Plugin Init
+ sphinx_done_func, // Plugin Deinit
+ 0x0001, // 0.1
+ sphinx_status_vars,
+ NULL,
+ "0.1", // string version
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
+}
+maria_declare_plugin_end;
+#endif
+
+#endif // >50100
+
+//
+// $Id: ha_sphinx.cc 2058 2009-11-07 04:01:57Z shodan $
+//
diff --git a/storage/sphinx/ha_sphinx.h b/storage/sphinx/ha_sphinx.h
new file mode 100644
index 00000000000..2a7191fc34d
--- /dev/null
+++ b/storage/sphinx/ha_sphinx.h
@@ -0,0 +1,158 @@
+//
+// $Id: ha_sphinx.h 1428 2008-09-05 18:06:30Z xale $
+//
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface // gcc class implementation
+#endif
+
+
+#if MYSQL_VERSION_ID>50100
+#define TABLE_ARG st_table_share
+#else
+#define TABLE_ARG st_table
+#endif
+
+
+#if MYSQL_VERSION_ID>=50120
+typedef uchar byte;
+#endif
+
+
+/// forward decls
+class THD;
+struct CSphReqQuery;
+struct CSphSEShare;
+struct CSphSEAttr;
+struct CSphSEStats;
+struct CSphSEThreadData;
+
+/// Sphinx SE handler class
+class ha_sphinx : public handler
+{
+protected:
+ THR_LOCK_DATA m_tLock; ///< MySQL lock
+
+ CSphSEShare * m_pShare; ///< shared lock info
+
+ uint m_iMatchesTotal;
+ uint m_iCurrentPos;
+ const byte * m_pCurrentKey;
+ uint m_iCurrentKeyLen;
+
+ char * m_pResponse; ///< searchd response storage
+ char * m_pResponseEnd; ///< searchd response storage end (points to wilderness!)
+ char * m_pCur; ///< current position into response
+ bool m_bUnpackError; ///< any errors while unpacking response
+
+public:
+#if MYSQL_VERSION_ID<50100
+ ha_sphinx ( TABLE_ARG * table_arg );
+#else
+ ha_sphinx ( handlerton * hton, TABLE_ARG * table_arg );
+#endif
+ ~ha_sphinx () {}
+
+ const char * table_type () const { return "SPHINX"; } ///< SE name for display purposes
+ const char * index_type ( uint ) { return "HASH"; } ///< index type name for display purposes
+ const char ** bas_ext () const; ///< my file extensions
+
+ #if MYSQL_VERSION_ID>50100
+ ulonglong table_flags () const { return HA_CAN_INDEX_BLOBS; } ///< bitmap of implemented flags (see handler.h for more info)
+ #else
+ ulong table_flags () const { return HA_CAN_INDEX_BLOBS; } ///< bitmap of implemented flags (see handler.h for more info)
+ #endif
+
+ ulong index_flags ( uint, uint, bool ) const { return 0; } ///< bitmap of flags that says how SE implements indexes
+ uint max_supported_record_length () const { return HA_MAX_REC_LENGTH; }
+ uint max_supported_keys () const { return 1; }
+ uint max_supported_key_parts () const { return 1; }
+ uint max_supported_key_length () const { return MAX_KEY_LENGTH; }
+ uint max_supported_key_part_length () const { return MAX_KEY_LENGTH; }
+
+ #if MYSQL_VERSION_ID>50100
+ virtual double scan_time () { return (double)( stats.records+stats.deleted )/20.0 + 10; } ///< called in test_quick_select to determine if indexes should be used
+ #else
+ virtual double scan_time () { return (double)( records+deleted )/20.0 + 10; } ///< called in test_quick_select to determine if indexes should be used
+ #endif
+
+ virtual double read_time ( ha_rows rows ) { return (double)rows/20.0 + 1; } ///< index read time estimate
+
+public:
+ int open ( const char * name, int mode, uint test_if_locked );
+ int close ();
+
+ int write_row ( uchar * buf );
+ int update_row ( const uchar * old_data, uchar * new_data );
+ int delete_row ( const uchar * buf );
+
+ int index_init ( uint keynr, bool sorted ); // 5.1.x
+ int index_init ( uint keynr ) { return index_init ( keynr, false ); } // 5.0.x
+
+ int index_end ();
+ int index_read ( byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag );
+ int index_read_idx ( byte * buf, uint idx, const byte * key, uint key_len, enum ha_rkey_function find_flag );
+ int index_next ( byte * buf );
+ int index_next_same ( byte * buf, const byte * key, uint keylen );
+ int index_prev ( byte * buf );
+ int index_first ( byte * buf );
+ int index_last ( byte * buf );
+
+ int get_rec ( byte * buf, const byte * key, uint keylen );
+
+ int rnd_init ( bool scan );
+ int rnd_end ();
+ int rnd_next ( byte * buf );
+ int rnd_pos ( byte * buf, byte * pos );
+ void position ( const byte * record );
+
+#if MYSQL_VERSION_ID>=50030
+ int info ( uint );
+#else
+ void info ( uint );
+#endif
+
+ int reset();
+ int external_lock ( THD * thd, int lock_type );
+ int delete_all_rows ();
+ ha_rows records_in_range ( uint inx, key_range * min_key, key_range * max_key );
+
+ int delete_table ( const char * from );
+ int rename_table ( const char * from, const char * to );
+ int create ( const char * name, TABLE * form, HA_CREATE_INFO * create_info );
+
+ THR_LOCK_DATA **store_lock ( THD * thd, THR_LOCK_DATA ** to, enum thr_lock_type lock_type );
+
+public:
+ virtual const COND * cond_push ( const COND *cond );
+ virtual void cond_pop ();
+
+private:
+ uint32 m_iFields;
+ char ** m_dFields;
+
+ uint32 m_iAttrs;
+ CSphSEAttr * m_dAttrs;
+ int m_bId64;
+
+ int * m_dUnboundFields;
+
+private:
+ int ConnectToSearchd ( const char * sQueryHost, int iQueryPort );
+
+ uint32 UnpackDword ();
+ char * UnpackString ();
+ bool UnpackSchema ();
+ bool UnpackStats ( CSphSEStats * pStats );
+
+ CSphSEThreadData * GetTls ();
+};
+
+
+#if MYSQL_VERSION_ID < 50100
+bool sphinx_show_status ( THD * thd );
+#endif
+
+//
+// $Id: ha_sphinx.h 1428 2008-09-05 18:06:30Z xale $
+//
diff --git a/storage/sphinx/make-patch.sh b/storage/sphinx/make-patch.sh
new file mode 100644
index 00000000000..6fca5838ded
--- /dev/null
+++ b/storage/sphinx/make-patch.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+OUT=$1
+ORIG=$2
+NEW=$3
+
+if [ ! \( "$1" -a "$2" -a "$3" \) ]; then
+ echo "$0 <patch> <original> <new>"
+ exit 1
+fi
+
+FILES='
+/config/ac-macros/ha_sphinx.m4
+/configure.in
+/libmysqld/Makefile.am
+/sql/handler.cc
+/sql/handler.h
+/sql/Makefile.am
+/sql/mysqld.cc
+/sql/mysql_priv.h
+/sql/set_var.cc
+/sql/sql_lex.h
+/sql/sql_parse.cc
+/sql/sql_yacc.yy
+/sql/structs.h
+/sql/sql_show.cc
+'
+
+rm -f $OUT
+if [ -e $OUT ]; then
+ exit 1
+fi
+
+for name in $FILES; do
+ diff -BNru "$ORIG$name" "$NEW$name" >> $OUT
+done
diff --git a/storage/sphinx/plug.in b/storage/sphinx/plug.in
new file mode 100644
index 00000000000..6c96e41ae52
--- /dev/null
+++ b/storage/sphinx/plug.in
@@ -0,0 +1,6 @@
+MYSQL_STORAGE_ENGINE(sphinx,,[Sphinx Storage Engine],
+ [SE client for Sphinx search daemon], [])
+MYSQL_PLUGIN_DIRECTORY(sphinx, [storage/sphinx])
+MYSQL_PLUGIN_STATIC(sphinx, [libsphinx.a])
+MYSQL_PLUGIN_DYNAMIC(sphinx, [ha_sphinx.la])
+
diff --git a/storage/sphinx/snippets_udf.cc b/storage/sphinx/snippets_udf.cc
new file mode 100644
index 00000000000..a93aac0426e
--- /dev/null
+++ b/storage/sphinx/snippets_udf.cc
@@ -0,0 +1,766 @@
+//
+// $Id: snippets_udf.cc 2058 2009-11-07 04:01:57Z shodan $
+//
+
+//
+// Copyright (c) 2001-2008, Andrew Aksyonoff. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License. You should have
+// received a copy of the GPL license along with this program; if you
+// did not, you can find it at http://www.gnu.org/
+//
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/un.h>
+#include <netdb.h>
+
+#include <mysql_version.h>
+
+#if MYSQL_VERSION_ID>50100
+#include "mysql_priv.h"
+#include <mysql/plugin.h>
+#else
+#include "../mysql_priv.h"
+#endif
+
+#include <mysys_err.h>
+#include <my_sys.h>
+
+#if MYSQL_VERSION_ID>=50120
+typedef uchar byte;
+#endif
+
+/// partially copy-pasted stuff that should be moved elsewhere
+
+#if UNALIGNED_RAM_ACCESS
+
+/// pass-through wrapper
+template < typename T > inline T sphUnalignedRead ( const T & tRef )
+{
+ return tRef;
+}
+
+/// pass-through wrapper
+template < typename T > void sphUnalignedWrite ( void * pPtr, const T & tVal )
+{
+ *(T*)pPtr = tVal;
+}
+
+#else
+
+/// unaligned read wrapper for some architectures (eg. SPARC)
+template < typename T >
+inline T sphUnalignedRead ( const T & tRef )
+{
+ T uTmp;
+ byte * pSrc = (byte *) &tRef;
+ byte * pDst = (byte *) &uTmp;
+ for ( int i=0; i<(int)sizeof(T); i++ )
+ *pDst++ = *pSrc++;
+ return uTmp;
+}
+
+/// unaligned write wrapper for some architectures (eg. SPARC)
+template < typename T >
+void sphUnalignedWrite ( void * pPtr, const T & tVal )
+{
+ byte * pDst = (byte *) pPtr;
+ byte * pSrc = (byte *) &tVal;
+ for ( int i=0; i<(int)sizeof(T); i++ )
+ *pDst++ = *pSrc++;
+}
+
+#endif
+
+#define SPHINXSE_MAX_ALLOC (16*1024*1024)
+
+#define SafeDelete(_arg) { if ( _arg ) delete ( _arg ); (_arg) = NULL; }
+#define SafeDeleteArray(_arg) { if ( _arg ) delete [] ( _arg ); (_arg) = NULL; }
+
+#define Min(a,b) ((a)<(b)?(a):(b))
+
+typedef unsigned int DWORD;
+
+inline DWORD sphF2DW ( float f ) { union { float f; uint32 d; } u; u.f = f; return u.d; }
+
+static char * sphDup ( const char * sSrc, int iLen=-1 )
+{
+ if ( !sSrc )
+ return NULL;
+
+ if ( iLen<0 )
+ iLen = strlen(sSrc);
+
+ char * sRes = new char [ 1+iLen ];
+ memcpy ( sRes, sSrc, iLen );
+ sRes[iLen] = '\0';
+ return sRes;
+}
+
+static inline void sphShowErrno ( const char * sCall )
+{
+ char sError[256];
+ snprintf ( sError, sizeof(sError), "%s() failed: [%d] %s", sCall, errno, strerror(errno) );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
+}
+
+static const bool sphReportErrors = true;
+
+static bool sphSend ( int iFd, const char * pBuffer, int iSize, bool bReportErrors = false )
+{
+ assert ( pBuffer );
+ assert ( iSize > 0 );
+
+ const int iResult = send ( iFd, pBuffer, iSize, 0 );
+ if ( iResult != iSize )
+ {
+ if ( bReportErrors ) sphShowErrno("send");
+ return false;
+ }
+ return true;
+}
+
+static bool sphRecv ( int iFd, char * pBuffer, int iSize, bool bReportErrors = false )
+{
+ assert ( pBuffer );
+ assert ( iSize > 0 );
+
+ while ( iSize )
+ {
+ const int iResult = recv ( iFd, pBuffer, iSize, 0 );
+ if ( iResult > 0 )
+ {
+ iSize -= iResult;
+ pBuffer += iSize;
+ }
+ else if ( iResult == 0 )
+ {
+ if ( bReportErrors )
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "recv() failed: disconnected" );
+ return false;
+ }
+ else
+ {
+ if ( bReportErrors ) sphShowErrno("recv");
+ return false;
+ }
+ }
+ return true;
+}
+
+enum
+{
+ SPHINX_SEARCHD_PROTO = 1,
+
+ SEARCHD_COMMAND_SEARCH = 0,
+ SEARCHD_COMMAND_EXCERPT = 1,
+
+ VER_COMMAND_SEARCH = 0x116,
+ VER_COMMAND_EXCERPT = 0x100,
+};
+
+/// known answers
+enum
+{
+ SEARCHD_OK = 0, ///< general success, command-specific reply follows
+ SEARCHD_ERROR = 1, ///< general failure, error message follows
+ SEARCHD_RETRY = 2, ///< temporary failure, error message follows, client should retry later
+ SEARCHD_WARNING = 3 ///< general success, warning message and command-specific reply follow
+};
+
+#define SPHINXSE_DEFAULT_SCHEME "sphinx"
+#define SPHINXSE_DEFAULT_HOST "127.0.0.1"
+#define SPHINXSE_DEFAULT_PORT 9312
+#define SPHINXSE_DEFAULT_INDEX "*"
+
+class CSphBuffer
+{
+private:
+ bool m_bOverrun;
+ int m_iSize;
+ int m_iLeft;
+ char * m_pBuffer;
+ char * m_pCurrent;
+
+public:
+ CSphBuffer ( const int iSize )
+ : m_bOverrun ( false )
+ , m_iSize ( iSize )
+ , m_iLeft ( iSize )
+ {
+ assert ( iSize > 0 );
+ m_pBuffer = new char[iSize];
+ m_pCurrent = m_pBuffer;
+ }
+
+ ~CSphBuffer ()
+ {
+ SafeDelete ( m_pBuffer );
+ }
+
+ const char * Ptr() const { return m_pBuffer; }
+
+ bool Finalize()
+ {
+ return !( m_bOverrun || m_iLeft != 0 || m_pCurrent - m_pBuffer != m_iSize );
+ }
+
+ void SendBytes ( const void * pBytes, int iBytes );
+
+ void SendWord ( short int v ) { v = ntohs(v); SendBytes ( &v, sizeof(v) ); }
+ void SendInt ( int v ) { v = ntohl(v); SendBytes ( &v, sizeof(v) ); }
+ void SendDword ( DWORD v ) { v = ntohl(v) ;SendBytes ( &v, sizeof(v) ); }
+ void SendUint64 ( ulonglong v ) { SendDword ( uint(v>>32) ); SendDword ( uint(v&0xFFFFFFFFUL) ); }
+ void SendString ( const char * v ) { SendString ( v, strlen(v) ); }
+ void SendString ( const char * v, int iLen ) { SendDword(iLen); SendBytes ( v, iLen ); }
+ void SendFloat ( float v ) { SendDword ( sphF2DW(v) ); }
+};
+
+void CSphBuffer::SendBytes ( const void * pBytes, int iBytes )
+{
+ if ( m_iLeft < iBytes )
+ {
+ m_bOverrun = true;
+ return;
+ }
+
+ memcpy ( m_pCurrent, pBytes, iBytes );
+
+ m_pCurrent += iBytes;
+ m_iLeft -= iBytes;
+}
+
+struct CSphUrl
+{
+ char * m_sBuffer;
+ char * m_sFormatted;
+
+ char * m_sScheme;
+ char * m_sHost;
+ char * m_sIndex;
+
+ int m_iPort;
+
+ CSphUrl()
+ : m_sBuffer ( NULL )
+ , m_sFormatted ( NULL )
+ , m_sScheme ( SPHINXSE_DEFAULT_SCHEME )
+ , m_sHost ( SPHINXSE_DEFAULT_HOST )
+ , m_sIndex ( SPHINXSE_DEFAULT_INDEX )
+ , m_iPort ( SPHINXSE_DEFAULT_PORT )
+ {}
+
+ ~CSphUrl()
+ {
+ SafeDeleteArray ( m_sFormatted );
+ SafeDeleteArray ( m_sBuffer );
+ }
+
+ bool Parse ( const char * sUrl, int iLen );
+ int Connect();
+ const char * Format();
+};
+
+const char * CSphUrl::Format()
+{
+ if ( !m_sFormatted )
+ {
+ int iSize = 15 + strlen(m_sHost) + strlen(m_sIndex);
+ m_sFormatted = new char [ iSize ];
+ if ( m_iPort )
+ snprintf ( m_sFormatted, iSize, "inet://%s:%d/%s", m_sHost, m_iPort, m_sIndex );
+ else
+ snprintf ( m_sFormatted, iSize, "unix://%s/%s", m_sHost, m_sIndex );
+ }
+ return m_sFormatted;
+}
+
+// the following scheme variants are recognized
+//
+// inet://host/index
+// inet://host:port/index
+// unix://unix/domain/socket:index
+// unix://unix/domain/socket
+bool CSphUrl::Parse ( const char * sUrl, int iLen )
+{
+ bool bOk = true;
+ while ( iLen )
+ {
+ bOk = false;
+
+ m_sBuffer = sphDup ( sUrl, iLen );
+ m_sScheme = m_sBuffer;
+
+ m_sHost = strstr ( m_sBuffer, "://" );
+ if ( !m_sHost )
+ break;
+ m_sHost[0] = '\0';
+ m_sHost += 2;
+
+ if ( !strcmp ( m_sScheme, "unix" ) )
+ {
+ // unix-domain socket
+ m_iPort = 0;
+ if (!( m_sIndex = strrchr ( m_sHost, ':' ) ))
+ m_sIndex = SPHINXSE_DEFAULT_INDEX;
+ else
+ {
+ *m_sIndex++ = '\0';
+ if ( !*m_sIndex )
+ m_sIndex = SPHINXSE_DEFAULT_INDEX;
+ }
+ bOk = true;
+ break;
+ }
+ if( strcmp ( m_sScheme, "sphinx" ) != 0 && strcmp ( m_sScheme, "inet" ) != 0 )
+ break;
+
+ // inet
+ m_sHost++;
+ char * sPort = strchr ( m_sHost, ':' );
+ if ( sPort )
+ {
+ *sPort++ = '\0';
+ if ( *sPort )
+ {
+ m_sIndex = strchr ( sPort, '/' );
+ if ( m_sIndex )
+ *m_sIndex++ = '\0';
+ else
+ m_sIndex = SPHINXSE_DEFAULT_INDEX;
+
+ m_iPort = atoi(sPort);
+ if ( !m_iPort )
+ m_iPort = SPHINXSE_DEFAULT_PORT;
+ }
+ } else
+ {
+ m_sIndex = strchr ( m_sHost, '/' );
+ if ( m_sIndex )
+ *m_sIndex++ = '\0';
+ else
+ m_sIndex = SPHINXSE_DEFAULT_INDEX;
+ }
+
+ bOk = true;
+ break;
+ }
+
+ return bOk;
+}
+
+int CSphUrl::Connect()
+{
+ struct sockaddr_in sin;
+#ifndef __WIN__
+ struct sockaddr_un saun;
+#endif
+
+ int iDomain = 0;
+ int iSockaddrSize = 0;
+ struct sockaddr * pSockaddr = NULL;
+
+ in_addr_t ip_addr;
+
+ if ( m_iPort )
+ {
+ iDomain = AF_INET;
+ iSockaddrSize = sizeof(sin);
+ pSockaddr = (struct sockaddr *) &sin;
+
+ memset ( &sin, 0, sizeof(sin) );
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(m_iPort);
+
+ // resolve address
+ if ( (int)( ip_addr=inet_addr(m_sHost) ) != (int)INADDR_NONE )
+ memcpy ( &sin.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 ( m_sHost, &tmp_hostent,
+ buff2, sizeof(buff2), &tmp_errno );
+ if ( !hp )
+ {
+ my_gethostbyname_r_free();
+
+ char sError[256];
+ snprintf ( sError, sizeof(sError), "failed to resolve searchd host (name=%s)", m_sHost );
+
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+ return -1;
+ }
+
+ memcpy ( &sin.sin_addr, hp->h_addr, Min ( sizeof(sin.sin_addr), (size_t)hp->h_length ) );
+ my_gethostbyname_r_free();
+ }
+ }
+ else
+ {
+#ifndef __WIN__
+ iDomain = AF_UNIX;
+ iSockaddrSize = sizeof(saun);
+ pSockaddr = (struct sockaddr *) &saun;
+
+ memset ( &saun, 0, sizeof(saun) );
+ saun.sun_family = AF_UNIX;
+ strncpy ( saun.sun_path, m_sHost, sizeof(saun.sun_path)-1 );
+#else
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "Unix-domain sockets are not supported on Windows" );
+ return -1;
+#endif
+ }
+
+ // connect to searchd and exchange versions
+ uint uServerVersion;
+ uint uClientVersion = htonl ( SPHINX_SEARCHD_PROTO );
+ int iSocket = -1;
+ char * pError = NULL;
+ do
+ {
+ iSocket = socket ( iDomain, SOCK_STREAM, 0 );
+ if ( iSocket == -1 )
+ {
+ pError = "Failed to create client socket";
+ break;
+ }
+
+ if ( connect ( iSocket, pSockaddr, iSockaddrSize ) == -1)
+ {
+ pError = "Failed to connect to searchd";
+ break;
+ }
+
+ if ( !sphRecv ( iSocket, (char *)&uServerVersion, sizeof(uServerVersion) ) )
+ {
+ pError = "Failed to receive searchd version";
+ break;
+ }
+
+ if ( !sphSend ( iSocket, (char *)&uClientVersion, sizeof(uClientVersion) ) )
+ {
+ pError = "Failed to send client version";
+ break;
+ }
+ }
+ while(0);
+
+ // fixme: compare versions?
+
+ if ( pError )
+ {
+ char sError[1024];
+ snprintf ( sError, sizeof(sError), "%s [%d] %s", Format(), errno, strerror(errno) );
+ my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
+
+ if ( iSocket != -1 )
+ close ( iSocket );
+
+ return -1;
+ }
+
+ return iSocket;
+}
+
+struct CSphResponse
+{
+ char * m_pBuffer;
+ char * m_pBody;
+
+ CSphResponse ()
+ : m_pBuffer ( NULL )
+ , m_pBody ( NULL )
+ {}
+
+ CSphResponse ( DWORD uSize )
+ : m_pBody ( NULL )
+ {
+ m_pBuffer = new char[uSize];
+ }
+
+ ~CSphResponse ()
+ {
+ SafeDeleteArray ( m_pBuffer );
+ }
+
+ static CSphResponse * Read ( int iSocket, int iClientVersion );
+};
+
+CSphResponse *
+CSphResponse::Read ( int iSocket, int iClientVersion )
+{
+ char sHeader[8];
+ if ( !sphRecv ( iSocket, sHeader, sizeof(sHeader) ) )
+ return NULL;
+
+ int iStatus = ntohs ( sphUnalignedRead ( *(short int *) &sHeader[0] ) );
+ int iVersion = ntohs ( sphUnalignedRead ( *(short int *) &sHeader[2] ) );
+ DWORD uLength = ntohl ( sphUnalignedRead ( *(DWORD *) &sHeader[4] ) );
+
+ if ( iVersion < iClientVersion ) // fixme: warn
+ ;
+
+ if ( uLength <= SPHINXSE_MAX_ALLOC )
+ {
+ CSphResponse * pResponse = new CSphResponse ( uLength );
+ if ( !sphRecv ( iSocket, pResponse->m_pBuffer, uLength ) )
+ {
+ SafeDelete ( pResponse );
+ return NULL;
+ }
+
+ pResponse->m_pBody = pResponse->m_pBuffer;
+ if ( iStatus != SEARCHD_OK )
+ {
+ DWORD uSize = ntohl ( *(DWORD *)pResponse->m_pBuffer );
+ if ( iStatus == SEARCHD_WARNING )
+ pResponse->m_pBody += uSize; // fixme: report the warning somehow
+ else
+ {
+ char * sMessage = sphDup ( pResponse->m_pBuffer + sizeof(DWORD), uSize );
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sMessage );
+ SafeDelete ( sMessage );
+ SafeDelete ( pResponse );
+ return NULL;
+ }
+ }
+ return pResponse;
+ }
+ return NULL;
+}
+
+/// udf
+
+extern "C"
+{
+ my_bool sphinx_snippets_init ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sMessage );
+ void sphinx_snippets_deinit ( UDF_INIT * pUDF );
+ char * sphinx_snippets ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sResult, unsigned long * pLength, char * pIsNull, char * sError );
+};
+
+#define MAX_MESSAGE_LENGTH 255
+#define MAX_RESULT_LENGTH 255
+
+struct CSphSnippets
+{
+ CSphUrl m_tUrl;
+ CSphResponse * m_pResponse;
+
+ int m_iBeforeMatch;
+ int m_iAfterMatch;
+ int m_iChunkSeparator;
+ int m_iLimit;
+ int m_iAround;
+ int m_iFlags;
+
+ CSphSnippets()
+ : m_pResponse(NULL)
+ , m_iBeforeMatch(0)
+ , m_iAfterMatch(0)
+ , m_iChunkSeparator(0)
+ // defaults
+ , m_iLimit(256)
+ , m_iAround(5)
+ , m_iFlags(1)
+ {
+ }
+
+ ~CSphSnippets()
+ {
+ SafeDelete ( m_pResponse );
+ }
+};
+
+#define KEYWORD(NAME) else if ( strncmp ( NAME, pArgs->attributes[i], pArgs->attribute_lengths[i] ) == 0 )
+
+#define CHECK_TYPE(TYPE) \
+ if ( pArgs->arg_type[i] != TYPE ) \
+ { \
+ snprintf ( sMessage, MAX_MESSAGE_LENGTH, \
+ "%.*s argument must be a string", \
+ (int)pArgs->attribute_lengths[i], \
+ pArgs->attributes[i] ); \
+ bFail = true; \
+ break; \
+ } \
+ if ( TYPE == STRING_RESULT && !pArgs->args[i] ) \
+ { \
+ snprintf ( sMessage, MAX_MESSAGE_LENGTH, \
+ "%.*s argument must be constant (and not NULL)", \
+ (int)pArgs->attribute_lengths[i], \
+ pArgs->attributes[i] ); \
+ bFail = true; \
+ break; \
+ }
+
+#define STRING CHECK_TYPE(STRING_RESULT)
+#define INT CHECK_TYPE(INT_RESULT); int iValue = *(long long *)pArgs->args[i]
+
+my_bool sphinx_snippets_init ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sMessage )
+{
+ if ( pArgs->arg_count < 3 )
+ {
+ strncpy ( sMessage, "insufficient arguments", MAX_MESSAGE_LENGTH );
+ return 1;
+ }
+
+ bool bFail = false;
+ CSphSnippets * pOpts = new CSphSnippets;
+ for ( uint i = 0; i < pArgs->arg_count; i++ )
+ {
+ if ( i < 3 )
+ {
+ if ( pArgs->arg_type[i] != STRING_RESULT )
+ {
+ strncpy ( sMessage, "first three arguments must be of string type", MAX_MESSAGE_LENGTH );
+ bFail = true;
+ break;
+ }
+ }
+ KEYWORD("sphinx")
+ {
+ STRING;
+ if ( !pOpts->m_tUrl.Parse ( pArgs->args[i], pArgs->lengths[i] ) )
+ {
+ strncpy ( sMessage, "failed to parse connection string", MAX_MESSAGE_LENGTH );
+ bFail = true;
+ break;
+ }
+ }
+ KEYWORD("before_match") { STRING; pOpts->m_iBeforeMatch = i; }
+ KEYWORD("after_match") { STRING; pOpts->m_iAfterMatch = i; }
+ KEYWORD("chunk_separator") { STRING; pOpts->m_iChunkSeparator = i; }
+ KEYWORD("limit") { INT; pOpts->m_iLimit = iValue; }
+ KEYWORD("around") { INT; pOpts->m_iAround = iValue; }
+ KEYWORD("exact_phrase") { INT; if ( iValue ) pOpts->m_iFlags |= 2; }
+ KEYWORD("single_passage") { INT; if ( iValue ) pOpts->m_iFlags |= 4; }
+ KEYWORD("use_boundaries") { INT; if ( iValue ) pOpts->m_iFlags |= 8; }
+ KEYWORD("weight_order") { INT; if ( iValue ) pOpts->m_iFlags |= 16; }
+ else
+ {
+ snprintf ( sMessage, MAX_MESSAGE_LENGTH, "unrecognized argument: %.*s",
+ (int)pArgs->attribute_lengths[i], pArgs->attributes[i] );
+ bFail = true;
+ break;
+ }
+ }
+
+ if ( bFail )
+ {
+ SafeDelete ( pOpts );
+ return 1;
+ }
+ pUDF->ptr = (char *)pOpts;
+ return 0;
+}
+
+#undef STRING
+#undef INT
+#undef KEYWORD
+#undef CHECK_TYPE
+
+#define ARG(i) pArgs->args[i], pArgs->lengths[i]
+#define ARG_LEN(VAR, LEN) ( VAR ? pArgs->lengths[VAR] : LEN )
+
+#define SEND_STRING(INDEX, DEFAULT) \
+ if ( INDEX ) \
+ tBuffer.SendString ( ARG(INDEX) ); \
+ else \
+ tBuffer.SendString ( DEFAULT, sizeof(DEFAULT) - 1 );
+
+
+char * sphinx_snippets ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sResult, unsigned long * pLength, char * pIsNull, char * pError )
+{
+ CSphSnippets * pOpts = (CSphSnippets *)pUDF->ptr;
+ assert ( pOpts );
+
+ if ( !pArgs->args[0] || !pArgs->args[1] || !pArgs->args[2] )
+ {
+ *pIsNull = 1;
+ return sResult;
+ }
+
+ const int iSize =
+ 8 + // header
+ 8 +
+ 4 + pArgs->lengths[1] + // index
+ 4 + pArgs->lengths[2] + // words
+ 4 + ARG_LEN ( pOpts->m_iBeforeMatch, 3 ) +
+ 4 + ARG_LEN ( pOpts->m_iAfterMatch, 4 ) +
+ 4 + ARG_LEN ( pOpts->m_iChunkSeparator, 5 ) +
+ 12 +
+ 4 + pArgs->lengths[0]; // document
+
+ CSphBuffer tBuffer(iSize);
+
+ tBuffer.SendWord ( SEARCHD_COMMAND_EXCERPT );
+ tBuffer.SendWord ( VER_COMMAND_EXCERPT );
+ tBuffer.SendDword ( iSize - 8 );
+
+ tBuffer.SendDword ( 0 );
+ tBuffer.SendDword ( pOpts->m_iFlags );
+
+ tBuffer.SendString ( ARG(1) ); // index
+ tBuffer.SendString ( ARG(2) ); // words
+
+ SEND_STRING ( pOpts->m_iBeforeMatch, "<b>" );
+ SEND_STRING ( pOpts->m_iAfterMatch, "</b>" );
+ SEND_STRING ( pOpts->m_iChunkSeparator, " ... " );
+
+ tBuffer.SendInt ( pOpts->m_iLimit );
+ tBuffer.SendInt ( pOpts->m_iAround );
+
+ // single document
+ tBuffer.SendInt ( 1 );
+ tBuffer.SendString ( ARG(0) );
+
+ int iSocket = -1;
+ do
+ {
+ if ( !tBuffer.Finalize() )
+ {
+ my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: failed to build request" );
+ break;
+ }
+
+ iSocket = pOpts->m_tUrl.Connect();
+ if ( iSocket == -1 ) break;
+ if ( !sphSend ( iSocket, tBuffer.Ptr(), iSize, sphReportErrors ) ) break;
+
+ CSphResponse * pResponse = CSphResponse::Read ( iSocket, 0x100 );
+ if ( !pResponse ) break;
+
+ close ( iSocket );
+ pOpts->m_pResponse = pResponse;
+ *pLength = ntohl( *(DWORD *)pResponse->m_pBody );
+ return pResponse->m_pBody + sizeof(DWORD);
+ }
+ while(0);
+
+ if ( iSocket != -1 )
+ close ( iSocket );
+
+ *pError = 1;
+ return sResult;
+}
+
+#undef SEND_STRING
+#undef ARG_LEN
+#undef ARG
+
+void sphinx_snippets_deinit ( UDF_INIT * pUDF )
+{
+ CSphSnippets * pOpts = (CSphSnippets *)pUDF->ptr;
+ SafeDelete ( pOpts );
+}
+
+//
+// $Id: snippets_udf.cc 2058 2009-11-07 04:01:57Z shodan $
+//
diff --git a/storage/sphinx/sphinx.5.0.22.diff b/storage/sphinx/sphinx.5.0.22.diff
new file mode 100644
index 00000000000..7dd4ebf1410
--- /dev/null
+++ b/storage/sphinx/sphinx.5.0.22.diff
@@ -0,0 +1,284 @@
+diff -B -N -r -u mysql-5.0.22/config/ac-macros/ha_sphinx.m4 mysql-5.0.22.sx/config/ac-macros/ha_sphinx.m4
+--- mysql-5.0.22/config/ac-macros/ha_sphinx.m4 1970-01-01 01:00:00.000000000 +0100
++++ mysql-5.0.22.sx/config/ac-macros/ha_sphinx.m4 2006-06-06 19:49:38.000000000 +0200
+@@ -0,0 +1,30 @@
++dnl ---------------------------------------------------------------------------
++dnl Macro: MYSQL_CHECK_EXAMPLEDB
++dnl Sets HAVE_SPHINX_DB if --with-sphinx-storage-engine is used
++dnl ---------------------------------------------------------------------------
++AC_DEFUN([MYSQL_CHECK_SPHINXDB], [
++ AC_ARG_WITH([sphinx-storage-engine],
++ [
++ --with-sphinx-storage-engine
++ Enable the Sphinx Storage Engine],
++ [sphinxdb="$withval"],
++ [sphinxdb=no])
++ AC_MSG_CHECKING([for example storage engine])
++
++ case "$sphinxdb" in
++ yes )
++ AC_DEFINE([HAVE_SPHINX_DB], [1], [Builds Sphinx Engine])
++ AC_MSG_RESULT([yes])
++ [sphinxdb=yes]
++ ;;
++ * )
++ AC_MSG_RESULT([no])
++ [sphinxdb=no]
++ ;;
++ esac
++
++])
++dnl ---------------------------------------------------------------------------
++dnl END OF MYSQL_CHECK_EXAMPLE SECTION
++dnl ---------------------------------------------------------------------------
++
+diff -B -N -r -u mysql-5.0.22/configure.in mysql-5.0.22.sx/configure.in
+--- mysql-5.0.22/configure.in 2006-05-25 10:56:45.000000000 +0200
++++ mysql-5.0.22.sx/configure.in 2006-06-06 19:49:38.000000000 +0200
+@@ -41,6 +41,7 @@
+ sinclude(config/ac-macros/ha_berkeley.m4)
+ sinclude(config/ac-macros/ha_blackhole.m4)
+ sinclude(config/ac-macros/ha_example.m4)
++sinclude(config/ac-macros/ha_sphinx.m4)
+ sinclude(config/ac-macros/ha_federated.m4)
+ sinclude(config/ac-macros/ha_innodb.m4)
+ sinclude(config/ac-macros/ha_ndbcluster.m4)
+@@ -2450,6 +2451,7 @@
+ MYSQL_CHECK_BDB
+ MYSQL_CHECK_INNODB
+ MYSQL_CHECK_EXAMPLEDB
++MYSQL_CHECK_SPHINXDB
+ MYSQL_CHECK_ARCHIVEDB
+ MYSQL_CHECK_CSVDB
+ MYSQL_CHECK_BLACKHOLEDB
+diff -B -N -r -u mysql-5.0.22/libmysqld/Makefile.am mysql-5.0.22.sx/libmysqld/Makefile.am
+--- mysql-5.0.22/libmysqld/Makefile.am 2006-05-25 10:56:55.000000000 +0200
++++ mysql-5.0.22.sx/libmysqld/Makefile.am 2006-06-06 19:49:38.000000000 +0200
+@@ -27,7 +27,7 @@
+ -DSHAREDIR="\"$(MYSQLSHAREdir)\""
+ INCLUDES= @bdb_includes@ \
+ -I$(top_builddir)/include -I$(top_srcdir)/include \
+- -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \
++ -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/sql/sphinx \
+ -I$(top_srcdir)/regex \
+ $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@
+
+@@ -38,6 +38,7 @@
+ libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
+ my_time.c
+ sqlexamplessources = ha_example.cc ha_tina.cc
++sqlsphinxsources = ha_sphinx.cc
+
+ noinst_HEADERS = embedded_priv.h emb_qcache.h
+
+@@ -65,7 +66,7 @@
+ parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
+ ha_blackhole.cc ha_archive.cc my_user.c
+
+-libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
++libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) $(sqlsphinxsources)
+ libmysqld_a_SOURCES=
+
+ # automake misses these
+@@ -133,12 +134,16 @@
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/sql/examples/$$f $$f; \
+ done; \
++ for f in $(sqlsphinxsources); do \
++ rm -f $$f; \
++ @LN_CP_F@ $(top_srcdir)/sql/sphinx/$$f $$f; \
++ done; \
+ rm -f client_settings.h; \
+ @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
+
+
+ clean-local:
+- rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"` \
++ rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) $(sqlsphinxsources) | sed "s;\.lo;.c;g"` \
+ $(top_srcdir)/linked_libmysqld_sources; \
+ rm -f client_settings.h
+
+diff -B -N -r -u mysql-5.0.22/sql/handler.cc mysql-5.0.22.sx/sql/handler.cc
+--- mysql-5.0.22/sql/handler.cc 2006-05-25 10:56:42.000000000 +0200
++++ mysql-5.0.22.sx/sql/handler.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -78,6 +78,15 @@
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ HTON_NO_FLAGS };
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++extern handlerton sphinx_hton;
++#else
++handlerton sphinx_hton = { "SPHINX", SHOW_OPTION_NO, "SPHINX storage engine",
++ DB_TYPE_SPHINX_DB, NULL, 0, 0, NULL, NULL,
++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++ HTON_NO_FLAGS };
++#endif
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ extern handlerton innobase_hton;
+@@ -147,6 +156,7 @@
+ &example_hton,
+ &archive_hton,
+ &tina_hton,
++ &sphinx_hton,
+ &ndbcluster_hton,
+ &federated_hton,
+ &myisammrg_hton,
+@@ -345,6 +355,12 @@
+ return new (alloc) ha_tina(table);
+ return NULL;
+ #endif
++#ifdef HAVE_SPHINX_DB
++ case DB_TYPE_SPHINX_DB:
++ if (have_sphinx_db == SHOW_OPTION_YES)
++ return new (alloc) ha_sphinx(table);
++ return NULL;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+ case DB_TYPE_NDBCLUSTER:
+ if (have_ndbcluster == SHOW_OPTION_YES)
+diff -B -N -r -u mysql-5.0.22/sql/handler.h mysql-5.0.22.sx/sql/handler.h
+--- mysql-5.0.22/sql/handler.h 2006-05-25 10:56:55.000000000 +0200
++++ mysql-5.0.22.sx/sql/handler.h 2006-06-06 19:49:38.000000000 +0200
+@@ -183,8 +183,9 @@
+ DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
+ DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
+ DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
+- DB_TYPE_FEDERATED_DB,
++ DB_TYPE_FEDERATED_DB,
+ DB_TYPE_BLACKHOLE_DB,
++ DB_TYPE_SPHINX_DB,
+ DB_TYPE_DEFAULT // Must be last
+ };
+
+diff -B -N -r -u mysql-5.0.22/sql/Makefile.am mysql-5.0.22.sx/sql/Makefile.am
+--- mysql-5.0.22/sql/Makefile.am 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/Makefile.am 2006-06-06 19:49:38.000000000 +0200
+@@ -66,6 +66,7 @@
+ sql_array.h sql_cursor.h \
+ examples/ha_example.h ha_archive.h \
+ examples/ha_tina.h ha_blackhole.h \
++ sphinx/ha_sphinx.h \
+ ha_federated.h
+ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
+ item.cc item_sum.cc item_buff.cc item_func.cc \
+@@ -102,6 +103,7 @@
+ sp_cache.cc parse_file.cc sql_trigger.cc \
+ examples/ha_example.cc ha_archive.cc \
+ examples/ha_tina.cc ha_blackhole.cc \
++ sphinx/ha_sphinx.cc \
+ ha_federated.cc
+
+ gen_lex_hash_SOURCES = gen_lex_hash.cc
+diff -B -N -r -u mysql-5.0.22/sql/mysqld.cc mysql-5.0.22.sx/sql/mysqld.cc
+--- mysql-5.0.22/sql/mysqld.cc 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/mysqld.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -6420,6 +6420,11 @@
+ #else
+ have_csv_db= SHOW_OPTION_NO;
+ #endif
++#ifdef HAVE_SPHINX_DB
++ have_sphinx_db= SHOW_OPTION_YES;
++#else
++ have_sphinx_db= SHOW_OPTION_NO;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+ have_ndbcluster=SHOW_OPTION_DISABLED;
+ #else
+@@ -7457,6 +7462,7 @@
+ #undef have_example_db
+ #undef have_archive_db
+ #undef have_csv_db
++#undef have_sphinx_db
+ #undef have_federated_db
+ #undef have_partition_db
+ #undef have_blackhole_db
+@@ -7467,6 +7473,7 @@
+ SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_sphinx_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_blackhole_db= SHOW_OPTION_NO;
+diff -B -N -r -u mysql-5.0.22/sql/mysql_priv.h mysql-5.0.22.sx/sql/mysql_priv.h
+--- mysql-5.0.22/sql/mysql_priv.h 2006-05-25 10:56:43.000000000 +0200
++++ mysql-5.0.22.sx/sql/mysql_priv.h 2006-06-06 19:49:38.000000000 +0200
+@@ -1279,6 +1279,12 @@
+ #else
+ extern SHOW_COMP_OPTION have_csv_db;
+ #endif
++#ifdef HAVE_SPHINX_DB
++extern handlerton sphinx_hton;
++#define have_sphinx_db sphinx_hton.state
++#else
++extern SHOW_COMP_OPTION have_sphinx_db;
++#endif
+ #ifdef HAVE_FEDERATED_DB
+ extern handlerton federated_hton;
+ #define have_federated_db federated_hton.state
+diff -B -N -r -u mysql-5.0.22/sql/set_var.cc mysql-5.0.22.sx/sql/set_var.cc
+--- mysql-5.0.22/sql/set_var.cc 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/set_var.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -809,6 +809,7 @@
+ {"have_compress", (char*) &have_compress, SHOW_HAVE},
+ {"have_crypt", (char*) &have_crypt, SHOW_HAVE},
+ {"have_csv", (char*) &have_csv_db, SHOW_HAVE},
++ {"have_sphinx", (char*) &have_sphinx_db, SHOW_HAVE},
+ {"have_example_engine", (char*) &have_example_db, SHOW_HAVE},
+ {"have_federated_engine", (char*) &have_federated_db, SHOW_HAVE},
+ {"have_geometry", (char*) &have_geometry, SHOW_HAVE},
+diff -B -N -r -u mysql-5.0.22/sql/sql_lex.h mysql-5.0.22.sx/sql/sql_lex.h
+--- mysql-5.0.22/sql/sql_lex.h 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/sql_lex.h 2006-06-06 19:49:38.000000000 +0200
+@@ -58,6 +58,7 @@
+ SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
+ SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
+ SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_NDBCLUSTER_STATUS, SQLCOM_SHOW_MUTEX_STATUS,
++ SQLCOM_SHOW_SPHINX_STATUS,
+ SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
+ SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
+ SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
+diff -B -N -r -u mysql-5.0.22/sql/sql_parse.cc mysql-5.0.22.sx/sql/sql_parse.cc
+--- mysql-5.0.22/sql/sql_parse.cc 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/sql_parse.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -25,6 +25,9 @@
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++#endif
+
+ #ifdef HAVE_NDBCLUSTER_DB
+ #include "ha_ndbcluster.h"
+@@ -2722,6 +2725,15 @@
+ break;
+ }
+ #endif
++#ifdef HAVE_SPHINX_DB
++ case SQLCOM_SHOW_SPHINX_STATUS:
++ {
++ if (check_global_access(thd, SUPER_ACL))
++ goto error;
++ res = sphinx_show_status(thd);
++ break;
++ }
++#endif
+ #ifdef HAVE_REPLICATION
+ case SQLCOM_LOAD_MASTER_TABLE:
+ {
+diff -B -N -r -u mysql-5.0.22/sql/sql_yacc.yy mysql-5.0.22.sx/sql/sql_yacc.yy
+--- mysql-5.0.22/sql/sql_yacc.yy 2006-05-25 10:56:43.000000000 +0200
++++ mysql-5.0.22.sx/sql/sql_yacc.yy 2006-06-06 19:49:38.000000000 +0200
+@@ -6584,6 +6584,9 @@
+ case DB_TYPE_INNODB:
+ Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
+ break;
++ case DB_TYPE_SPHINX_DB:
++ Lex->sql_command = SQLCOM_SHOW_SPHINX_STATUS;
++ break;
+ default:
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
+ YYABORT;
diff --git a/storage/sphinx/sphinx.5.0.27.diff b/storage/sphinx/sphinx.5.0.27.diff
new file mode 100644
index 00000000000..9ff6cf4fe48
--- /dev/null
+++ b/storage/sphinx/sphinx.5.0.27.diff
@@ -0,0 +1,284 @@
+diff -B -N -r -u mysql-5.0.22/config/ac-macros/ha_sphinx.m4 mysql-5.0.22.sx/config/ac-macros/ha_sphinx.m4
+--- mysql-5.0.22/config/ac-macros/ha_sphinx.m4 1970-01-01 01:00:00.000000000 +0100
++++ mysql-5.0.22.sx/config/ac-macros/ha_sphinx.m4 2006-06-06 19:49:38.000000000 +0200
+@@ -0,0 +1,30 @@
++dnl ---------------------------------------------------------------------------
++dnl Macro: MYSQL_CHECK_EXAMPLEDB
++dnl Sets HAVE_SPHINX_DB if --with-sphinx-storage-engine is used
++dnl ---------------------------------------------------------------------------
++AC_DEFUN([MYSQL_CHECK_SPHINXDB], [
++ AC_ARG_WITH([sphinx-storage-engine],
++ [
++ --with-sphinx-storage-engine
++ Enable the Sphinx Storage Engine],
++ [sphinxdb="$withval"],
++ [sphinxdb=no])
++ AC_MSG_CHECKING([for example storage engine])
++
++ case "$sphinxdb" in
++ yes )
++ AC_DEFINE([HAVE_SPHINX_DB], [1], [Builds Sphinx Engine])
++ AC_MSG_RESULT([yes])
++ [sphinxdb=yes]
++ ;;
++ * )
++ AC_MSG_RESULT([no])
++ [sphinxdb=no]
++ ;;
++ esac
++
++])
++dnl ---------------------------------------------------------------------------
++dnl END OF MYSQL_CHECK_EXAMPLE SECTION
++dnl ---------------------------------------------------------------------------
++
+diff -B -N -r -u mysql-5.0.22/configure.in mysql-5.0.22.sx/configure.in
+--- mysql-5.0.22/configure.in 2006-05-25 10:56:45.000000000 +0200
++++ mysql-5.0.22.sx/configure.in 2006-06-06 19:49:38.000000000 +0200
+@@ -41,6 +41,7 @@
+ sinclude(config/ac-macros/ha_berkeley.m4)
+ sinclude(config/ac-macros/ha_blackhole.m4)
+ sinclude(config/ac-macros/ha_example.m4)
++sinclude(config/ac-macros/ha_sphinx.m4)
+ sinclude(config/ac-macros/ha_federated.m4)
+ sinclude(config/ac-macros/ha_innodb.m4)
+ sinclude(config/ac-macros/ha_ndbcluster.m4)
+@@ -2450,6 +2451,7 @@
+ MYSQL_CHECK_BDB
+ MYSQL_CHECK_INNODB
+ MYSQL_CHECK_EXAMPLEDB
++MYSQL_CHECK_SPHINXDB
+ MYSQL_CHECK_ARCHIVEDB
+ MYSQL_CHECK_CSVDB
+ MYSQL_CHECK_BLACKHOLEDB
+diff -B -N -r -u mysql-5.0.22/libmysqld/Makefile.am mysql-5.0.22.sx/libmysqld/Makefile.am
+--- mysql-5.0.22/libmysqld/Makefile.am 2006-05-25 10:56:55.000000000 +0200
++++ mysql-5.0.22.sx/libmysqld/Makefile.am 2006-06-06 19:49:38.000000000 +0200
+@@ -27,7 +27,7 @@
+ -DSHAREDIR="\"$(MYSQLSHAREdir)\""
+ INCLUDES= @bdb_includes@ \
+ -I$(top_builddir)/include -I$(top_srcdir)/include \
+- -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \
++ -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/sql/sphinx \
+ -I$(top_srcdir)/regex \
+ $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@
+
+@@ -38,6 +38,7 @@
+ libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
+ my_time.c
+ sqlexamplessources = ha_example.cc ha_tina.cc
++sqlsphinxsources = ha_sphinx.cc
+
+ noinst_HEADERS = embedded_priv.h emb_qcache.h
+
+@@ -65,7 +66,7 @@
+ parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
+ ha_blackhole.cc ha_archive.cc my_user.c
+
+-libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
++libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) $(sqlsphinxsources)
+ libmysqld_a_SOURCES=
+
+ # automake misses these
+@@ -133,12 +134,16 @@
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/sql/examples/$$f $$f; \
+ done; \
++ for f in $(sqlsphinxsources); do \
++ rm -f $$f; \
++ @LN_CP_F@ $(top_srcdir)/sql/sphinx/$$f $$f; \
++ done; \
+ rm -f client_settings.h; \
+ @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
+
+
+ clean-local:
+- rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"` \
++ rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) $(sqlsphinxsources) | sed "s;\.lo;.c;g"` \
+ $(top_srcdir)/linked_libmysqld_sources; \
+ rm -f client_settings.h
+
+diff -B -N -r -u mysql-5.0.22/sql/handler.cc mysql-5.0.22.sx/sql/handler.cc
+--- mysql-5.0.22/sql/handler.cc 2006-05-25 10:56:42.000000000 +0200
++++ mysql-5.0.22.sx/sql/handler.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -78,6 +78,15 @@
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ HTON_NO_FLAGS };
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++extern handlerton sphinx_hton;
++#else
++handlerton sphinx_hton = { "SPHINX", SHOW_OPTION_NO, "SPHINX storage engine",
++ DB_TYPE_SPHINX_DB, NULL, 0, 0, NULL, NULL,
++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++ HTON_NO_FLAGS };
++#endif
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ extern handlerton innobase_hton;
+@@ -147,6 +156,7 @@
+ &example_hton,
+ &archive_hton,
+ &tina_hton,
++ &sphinx_hton,
+ &ndbcluster_hton,
+ &federated_hton,
+ &myisammrg_hton,
+@@ -345,6 +355,12 @@
+ return new (alloc) ha_tina(table);
+ return NULL;
+ #endif
++#ifdef HAVE_SPHINX_DB
++ case DB_TYPE_SPHINX_DB:
++ if (have_sphinx_db == SHOW_OPTION_YES)
++ return new (alloc) ha_sphinx(table);
++ return NULL;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+ case DB_TYPE_NDBCLUSTER:
+ if (have_ndbcluster == SHOW_OPTION_YES)
+diff -B -N -r -u mysql-5.0.22/sql/handler.h mysql-5.0.22.sx/sql/handler.h
+--- mysql-5.0.22/sql/handler.h 2006-05-25 10:56:55.000000000 +0200
++++ mysql-5.0.22.sx/sql/handler.h 2006-06-06 19:49:38.000000000 +0200
+@@ -183,8 +183,9 @@
+ DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
+ DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
+ DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
+- DB_TYPE_FEDERATED_DB,
++ DB_TYPE_FEDERATED_DB,
+ DB_TYPE_BLACKHOLE_DB,
++ DB_TYPE_SPHINX_DB,
+ DB_TYPE_DEFAULT // Must be last
+ };
+
+diff -B -N -r -u mysql-5.0.22/sql/Makefile.am mysql-5.0.22.sx/sql/Makefile.am
+--- mysql-5.0.22/sql/Makefile.am 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/Makefile.am 2006-06-06 19:49:38.000000000 +0200
+@@ -66,6 +66,7 @@
+ sql_array.h sql_cursor.h \
+ examples/ha_example.h ha_archive.h \
+ examples/ha_tina.h ha_blackhole.h \
++ sphinx/ha_sphinx.h \
+ ha_federated.h
+ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
+ item.cc item_sum.cc item_buff.cc item_func.cc \
+@@ -102,6 +103,7 @@
+ sp_cache.cc parse_file.cc sql_trigger.cc \
+ examples/ha_example.cc ha_archive.cc \
+ examples/ha_tina.cc ha_blackhole.cc \
++ sphinx/ha_sphinx.cc \
+ ha_federated.cc
+
+ gen_lex_hash_SOURCES = gen_lex_hash.cc
+diff -B -N -r -u mysql-5.0.22/sql/mysqld.cc mysql-5.0.22.sx/sql/mysqld.cc
+--- mysql-5.0.22/sql/mysqld.cc 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/mysqld.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -6420,6 +6420,11 @@
+ #else
+ have_csv_db= SHOW_OPTION_NO;
+ #endif
++#ifdef HAVE_SPHINX_DB
++ have_sphinx_db= SHOW_OPTION_YES;
++#else
++ have_sphinx_db= SHOW_OPTION_NO;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+ have_ndbcluster=SHOW_OPTION_DISABLED;
+ #else
+@@ -7457,6 +7462,7 @@
+ #undef have_example_db
+ #undef have_archive_db
+ #undef have_csv_db
++#undef have_sphinx_db
+ #undef have_federated_db
+ #undef have_partition_db
+ #undef have_blackhole_db
+@@ -7467,6 +7473,7 @@
+ SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_sphinx_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_blackhole_db= SHOW_OPTION_NO;
+diff -B -N -r -u mysql-5.0.22/sql/mysql_priv.h mysql-5.0.22.sx/sql/mysql_priv.h
+--- mysql-5.0.22/sql/mysql_priv.h 2006-05-25 10:56:43.000000000 +0200
++++ mysql-5.0.22.sx/sql/mysql_priv.h 2006-06-06 19:49:38.000000000 +0200
+@@ -1279,6 +1279,12 @@
+ #else
+ extern SHOW_COMP_OPTION have_csv_db;
+ #endif
++#ifdef HAVE_SPHINX_DB
++extern handlerton sphinx_hton;
++#define have_sphinx_db sphinx_hton.state
++#else
++extern SHOW_COMP_OPTION have_sphinx_db;
++#endif
+ #ifdef HAVE_FEDERATED_DB
+ extern handlerton federated_hton;
+ #define have_federated_db federated_hton.state
+diff -B -N -r -u mysql-5.0.22/sql/set_var.cc mysql-5.0.22.sx/sql/set_var.cc
+--- mysql-5.0.22/sql/set_var.cc 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/set_var.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -864,6 +864,7 @@
+ {"have_compress", (char*) &have_compress, SHOW_HAVE},
+ {"have_crypt", (char*) &have_crypt, SHOW_HAVE},
+ {"have_csv", (char*) &have_csv_db, SHOW_HAVE},
++ {"have_sphinx", (char*) &have_sphinx_db, SHOW_HAVE},
+ {"have_dynamic_loading", (char*) &have_dlopen, SHOW_HAVE},
+ {"have_example_engine", (char*) &have_example_db, SHOW_HAVE},
+ {"have_federated_engine", (char*) &have_federated_db, SHOW_HAVE},
+diff -B -N -r -u mysql-5.0.22/sql/sql_lex.h mysql-5.0.22.sx/sql/sql_lex.h
+--- mysql-5.0.22/sql/sql_lex.h 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/sql_lex.h 2006-06-06 19:49:38.000000000 +0200
+@@ -58,6 +58,7 @@
+ SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
+ SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
+ SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_NDBCLUSTER_STATUS, SQLCOM_SHOW_MUTEX_STATUS,
++ SQLCOM_SHOW_SPHINX_STATUS,
+ SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
+ SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
+ SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
+diff -B -N -r -u mysql-5.0.22/sql/sql_parse.cc mysql-5.0.22.sx/sql/sql_parse.cc
+--- mysql-5.0.22/sql/sql_parse.cc 2006-05-25 10:56:41.000000000 +0200
++++ mysql-5.0.22.sx/sql/sql_parse.cc 2006-06-06 19:49:38.000000000 +0200
+@@ -25,6 +25,9 @@
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++#endif
+
+ #ifdef HAVE_NDBCLUSTER_DB
+ #include "ha_ndbcluster.h"
+@@ -2722,6 +2725,15 @@
+ break;
+ }
+ #endif
++#ifdef HAVE_SPHINX_DB
++ case SQLCOM_SHOW_SPHINX_STATUS:
++ {
++ if (check_global_access(thd, SUPER_ACL))
++ goto error;
++ res = sphinx_show_status(thd);
++ break;
++ }
++#endif
+ #ifdef HAVE_REPLICATION
+ case SQLCOM_LOAD_MASTER_TABLE:
+ {
+diff -B -N -r -u mysql-5.0.22/sql/sql_yacc.yy mysql-5.0.22.sx/sql/sql_yacc.yy
+--- mysql-5.0.22/sql/sql_yacc.yy 2006-05-25 10:56:43.000000000 +0200
++++ mysql-5.0.22.sx/sql/sql_yacc.yy 2006-06-06 19:49:38.000000000 +0200
+@@ -6584,6 +6584,9 @@
+ case DB_TYPE_INNODB:
+ Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
+ break;
++ case DB_TYPE_SPHINX_DB:
++ Lex->sql_command = SQLCOM_SHOW_SPHINX_STATUS;
++ break;
+ default:
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
+ YYABORT;
diff --git a/storage/sphinx/sphinx.5.0.37.diff b/storage/sphinx/sphinx.5.0.37.diff
new file mode 100644
index 00000000000..3f86e545b4d
--- /dev/null
+++ b/storage/sphinx/sphinx.5.0.37.diff
@@ -0,0 +1,338 @@
+--- mysql-5.0.67/config/ac-macros/ha_sphinx.m4 1970-01-01 10:00:00.000000000 +1000
++++ mysql-5.0.67-sphinx/config/ac-macros/ha_sphinx.m4 2009-02-14 09:15:48.000000000 +1000
+@@ -0,0 +1,30 @@
++dnl ---------------------------------------------------------------------------
++dnl Macro: MYSQL_CHECK_EXAMPLEDB
++dnl Sets HAVE_SPHINX_DB if --with-sphinx-storage-engine is used
++dnl ---------------------------------------------------------------------------
++AC_DEFUN([MYSQL_CHECK_SPHINXDB], [
++ AC_ARG_WITH([sphinx-storage-engine],
++ [
++ --with-sphinx-storage-engine
++ Enable the Sphinx Storage Engine],
++ [sphinxdb="$withval"],
++ [sphinxdb=no])
++ AC_MSG_CHECKING([for example storage engine])
++
++ case "$sphinxdb" in
++ yes )
++ AC_DEFINE([HAVE_SPHINX_DB], [1], [Builds Sphinx Engine])
++ AC_MSG_RESULT([yes])
++ [sphinxdb=yes]
++ ;;
++ * )
++ AC_MSG_RESULT([no])
++ [sphinxdb=no]
++ ;;
++ esac
++
++])
++dnl ---------------------------------------------------------------------------
++dnl END OF MYSQL_CHECK_EXAMPLE SECTION
++dnl ---------------------------------------------------------------------------
++
+--- mysql-5.0.67/configure.in 2008-08-04 23:19:07.000000000 +1100
++++ mysql-5.0.67-sphinx/configure.in 2009-02-14 09:15:48.000000000 +1000
+@@ -58,6 +58,7 @@
+ sinclude(config/ac-macros/ha_berkeley.m4)
+ sinclude(config/ac-macros/ha_blackhole.m4)
+ sinclude(config/ac-macros/ha_example.m4)
++sinclude(config/ac-macros/ha_sphinx.m4)
+ sinclude(config/ac-macros/ha_federated.m4)
+ sinclude(config/ac-macros/ha_innodb.m4)
+ sinclude(config/ac-macros/ha_ndbcluster.m4)
+@@ -2625,6 +2626,7 @@
+ MYSQL_CHECK_BDB
+ MYSQL_CHECK_INNODB
+ MYSQL_CHECK_EXAMPLEDB
++MYSQL_CHECK_SPHINXDB
+ MYSQL_CHECK_ARCHIVEDB
+ MYSQL_CHECK_CSVDB
+ MYSQL_CHECK_BLACKHOLEDB
+--- mysql-5.0.67/libmysqld/Makefile.am 2008-08-04 23:19:18.000000000 +1100
++++ mysql-5.0.67-sphinx/libmysqld/Makefile.am 2009-02-14 09:15:48.000000000 +1000
+@@ -29,6 +29,7 @@
+ -I$(top_builddir)/include -I$(top_srcdir)/include \
+ -I$(top_builddir)/sql -I$(top_srcdir)/sql \
+ -I$(top_srcdir)/sql/examples \
++ -I$(top_srcdir)/sql/sphinx \
+ -I$(top_srcdir)/regex \
+ $(openssl_includes) @ZLIB_INCLUDES@
+
+@@ -39,6 +40,7 @@
+ libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
+ my_time.c
+ sqlexamplessources = ha_example.cc ha_tina.cc
++sqlsphinxsources = ha_sphinx.cc
+
+ noinst_HEADERS = embedded_priv.h emb_qcache.h
+
+@@ -67,7 +69,7 @@
+ parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
+ ha_blackhole.cc ha_archive.cc my_user.c
+
+-libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
++libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) $(sqlsphinxsources)
+ libmysqld_a_SOURCES=
+
+ # automake misses these
+@@ -147,12 +149,16 @@
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/sql/examples/$$f $$f; \
+ done; \
++ for f in $(sqlsphinxsources); do \
++ rm -f $$f; \
++ @LN_CP_F@ $(top_srcdir)/sql/sphinx/$$f $$f; \
++ done; \
+ rm -f client_settings.h; \
+ @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
+
+
+ clean-local:
+- rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"` \
++ rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) $(sqlsphinxsources) | sed "s;\.lo;.c;g"` \
+ $(top_srcdir)/linked_libmysqld_sources; \
+ rm -f client_settings.h
+
+--- mysql-5.0.67/sql/handler.cc 2008-08-04 23:20:04.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/handler.cc 2009-02-14 09:15:48.000000000 +1000
+@@ -77,6 +77,15 @@
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ HTON_NO_FLAGS };
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++extern handlerton sphinx_hton;
++#else
++handlerton sphinx_hton = { "SPHINX", SHOW_OPTION_NO, "SPHINX storage engine",
++ DB_TYPE_SPHINX_DB, NULL, 0, 0, NULL, NULL,
++ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++ HTON_NO_FLAGS };
++#endif
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ extern handlerton innobase_hton;
+@@ -141,6 +150,7 @@
+ &example_hton,
+ &archive_hton,
+ &tina_hton,
++ &sphinx_hton,
+ &ndbcluster_hton,
+ &federated_hton,
+ &myisammrg_hton,
+@@ -341,6 +351,12 @@
+ return new (alloc) ha_tina(table);
+ return NULL;
+ #endif
++#ifdef HAVE_SPHINX_DB
++ case DB_TYPE_SPHINX_DB:
++ if (have_sphinx_db == SHOW_OPTION_YES)
++ return new (alloc) ha_sphinx(table);
++ return NULL;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+ case DB_TYPE_NDBCLUSTER:
+ if (have_ndbcluster == SHOW_OPTION_YES)
+--- mysql-5.0.67/sql/handler.h 2008-08-04 23:20:04.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/handler.h 2009-02-14 09:15:48.000000000 +1000
+@@ -186,8 +186,9 @@
+ DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
+ DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
+ DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
+- DB_TYPE_FEDERATED_DB,
++ DB_TYPE_FEDERATED_DB,
+ DB_TYPE_BLACKHOLE_DB,
++ DB_TYPE_SPHINX_DB,
+ DB_TYPE_DEFAULT // Must be last
+ };
+
+--- mysql-5.0.67/sql/Makefile.am 2008-08-04 23:20:02.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/Makefile.am 2009-02-14 09:23:28.000000000 +1000
+@@ -68,6 +68,7 @@
+ sql_array.h sql_cursor.h \
+ examples/ha_example.h ha_archive.h \
+ examples/ha_tina.h ha_blackhole.h \
++ sphinx/ha_sphinx.h \
+ ha_federated.h
+ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
+ item.cc item_sum.cc item_buff.cc item_func.cc \
+@@ -105,6 +106,7 @@
+ sp_cache.cc parse_file.cc sql_trigger.cc \
+ examples/ha_example.cc ha_archive.cc \
+ examples/ha_tina.cc ha_blackhole.cc \
++ sphinx/ha_sphinx.cc \
+ ha_federated.cc
+
+ gen_lex_hash_SOURCES = gen_lex_hash.cc
+@@ -174,6 +176,10 @@
+ udf_example_la_SOURCES= udf_example.c
+ udf_example_la_LDFLAGS= -module -rpath $(pkglibdir)
+
++pkglib_LTLIBRARIES = sphinx/sphinx.la
++sphinx_sphinx_la_SOURCES = sphinx/snippets_udf.cc
++sphinx_sphinx_la_LDFLAGS = -module
++
+
+ # Don't update the files from bitkeeper
+ %::SCCS/s.%
+--- mysql-5.0.67/sql/mysqld.cc 2008-08-04 23:20:07.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/mysqld.cc 2009-02-14 09:15:48.000000000 +1000
+@@ -36,6 +36,10 @@
+ #include <sys/prctl.h>
+ #endif
+
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++#endif
++
+ #ifdef HAVE_INNOBASE_DB
+ #define OPT_INNODB_DEFAULT 1
+ #else
+@@ -6633,6 +6637,13 @@
+ {"Threads_running", (char*) &thread_running, SHOW_INT_CONST},
+ {"Uptime", (char*) 0, SHOW_STARTTIME},
+ {"Uptime_since_flush_status",(char*) 0, SHOW_FLUSHTIME},
++#ifdef HAVE_SPHINX_DB
++ {"sphinx_total", (char *)sphinx_showfunc_total, SHOW_SPHINX_FUNC},
++ {"sphinx_total_found", (char *)sphinx_showfunc_total_found, SHOW_SPHINX_FUNC},
++ {"sphinx_time", (char *)sphinx_showfunc_time, SHOW_SPHINX_FUNC},
++ {"sphinx_word_count", (char *)sphinx_showfunc_word_count, SHOW_SPHINX_FUNC},
++ {"sphinx_words", (char *)sphinx_showfunc_words, SHOW_SPHINX_FUNC},
++#endif
+ {NullS, NullS, SHOW_LONG}
+ };
+
+@@ -6875,6 +6886,11 @@
+ #else
+ have_csv_db= SHOW_OPTION_NO;
+ #endif
++#ifdef HAVE_SPHINX_DB
++ have_sphinx_db= SHOW_OPTION_YES;
++#else
++ have_sphinx_db= SHOW_OPTION_NO;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+ have_ndbcluster=SHOW_OPTION_DISABLED;
+ #else
+@@ -7983,6 +7999,7 @@
+ #undef have_example_db
+ #undef have_archive_db
+ #undef have_csv_db
++#undef have_sphinx_db
+ #undef have_federated_db
+ #undef have_partition_db
+ #undef have_blackhole_db
+@@ -7993,6 +8010,7 @@
+ SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_sphinx_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_blackhole_db= SHOW_OPTION_NO;
+--- mysql-5.0.67/sql/mysql_priv.h 2008-08-04 23:20:07.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/mysql_priv.h 2009-02-14 09:15:48.000000000 +1000
+@@ -1439,6 +1439,12 @@
+ #else
+ extern SHOW_COMP_OPTION have_csv_db;
+ #endif
++#ifdef HAVE_SPHINX_DB
++extern handlerton sphinx_hton;
++#define have_sphinx_db sphinx_hton.state
++#else
++extern SHOW_COMP_OPTION have_sphinx_db;
++#endif
+ #ifdef HAVE_FEDERATED_DB
+ extern handlerton federated_hton;
+ #define have_federated_db federated_hton.state
+--- mysql-5.0.67/sql/set_var.cc 2008-08-04 23:20:08.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/set_var.cc 2009-02-14 09:15:48.000000000 +1000
+@@ -888,6 +888,7 @@
+ {"have_compress", (char*) &have_compress, SHOW_HAVE},
+ {"have_crypt", (char*) &have_crypt, SHOW_HAVE},
+ {"have_csv", (char*) &have_csv_db, SHOW_HAVE},
++ {"have_sphinx", (char*) &have_sphinx_db, SHOW_HAVE},
+ {"have_dynamic_loading", (char*) &have_dlopen, SHOW_HAVE},
+ {"have_example_engine", (char*) &have_example_db, SHOW_HAVE},
+ {"have_federated_engine", (char*) &have_federated_db, SHOW_HAVE},
+--- mysql-5.0.67/sql/sql_lex.h 2008-08-04 23:20:10.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/sql_lex.h 2009-02-14 09:15:48.000000000 +1000
+@@ -57,6 +57,7 @@
+ SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
+ SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
+ SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_NDBCLUSTER_STATUS, SQLCOM_SHOW_MUTEX_STATUS,
++ SQLCOM_SHOW_SPHINX_STATUS,
+ SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
+ SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
+ SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
+--- mysql-5.0.67/sql/sql_parse.cc 2008-08-04 23:20:10.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/sql_parse.cc 2009-02-14 09:15:48.000000000 +1000
+@@ -24,6 +24,9 @@
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++#endif
+
+ #ifdef HAVE_NDBCLUSTER_DB
+ #include "ha_ndbcluster.h"
+@@ -3006,6 +3009,15 @@
+ break;
+ }
+ #endif
++#ifdef HAVE_SPHINX_DB
++ case SQLCOM_SHOW_SPHINX_STATUS:
++ {
++ if (check_global_access(thd, SUPER_ACL))
++ goto error;
++ res = sphinx_show_status(thd);
++ break;
++ }
++#endif
+ #ifdef HAVE_REPLICATION
+ case SQLCOM_LOAD_MASTER_TABLE:
+ {
+--- mysql-5.0.67/sql/sql_yacc.yy 2008-08-04 23:20:12.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/sql_yacc.yy 2009-02-14 09:15:48.000000000 +1000
+@@ -7393,6 +7393,9 @@
+ case DB_TYPE_INNODB:
+ Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
+ break;
++ case DB_TYPE_SPHINX_DB:
++ Lex->sql_command = SQLCOM_SHOW_SPHINX_STATUS;
++ break;
+ default:
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
+ MYSQL_YYABORT;
+--- mysql-5.0.67/sql/structs.h 2008-08-04 23:20:12.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/structs.h 2009-02-14 09:15:48.000000000 +1000
+@@ -188,6 +188,9 @@
+ SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL,
+ SHOW_SSL_GET_CIPHER_LIST,
+ #endif /* HAVE_OPENSSL */
++#ifdef HAVE_SPHINX_DB
++ SHOW_SPHINX_FUNC,
++#endif
+ SHOW_NET_COMPRESSION,
+ SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_SLAVE_RETRIED_TRANS,
+ SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG,
+--- mysql-5.0.67/sql/sql_show.cc 2008-08-04 23:20:11.000000000 +1100
++++ mysql-5.0.67-sphinx/sql/sql_show.cc 2009-02-14 09:15:48.000000000 +1000
+@@ -1473,6 +1473,16 @@
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
+ &null_lex_str);
+ }
++ #ifdef HAVE_SPHINX_DB
++ else if (show_type == SHOW_SPHINX_FUNC)
++ {
++ SHOW_VAR var;
++ ((int (*)(THD *, SHOW_VAR *, char *))value)(thd, &var, buff);
++
++ value = var.value;
++ show_type = var.type;
++ }
++ #endif /* HAVE_SPHINX_DB */
+
+ pos= end= buff;
+ switch (show_type) {
diff --git a/storage/xtradb/Makefile.am b/storage/xtradb/Makefile.am
index b0b4721a9c5..172b9099568 100644
--- a/storage/xtradb/Makefile.am
+++ b/storage/xtradb/Makefile.am
@@ -332,7 +332,7 @@ libxtradb_a_CFLAGS= $(AM_CFLAGS)
EXTRA_LTLIBRARIES= ha_xtradb.la
pkgplugin_LTLIBRARIES= @plugin_xtradb_shared_target@
-ha_xtradb_la_LDFLAGS= -module -rpath $(pkgplugindir)
+ha_xtradb_la_LDFLAGS= -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
ha_xtradb_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_xtradb_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_xtradb_la_SOURCES= $(libxtradb_a_SOURCES)
diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index bb1eed2a1e3..08789691159 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -3206,7 +3206,7 @@ skip_info:
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
for (i = 0; (ulint) i < n_index; i++) {
- if ((ulint) (offset / UNIV_PAGE_SIZE) == root_page[i]) {
+ if ((ulint) (offset / UNIV_PAGE_SIZE) == root_page[i]) {
/* this is index root page */
mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ FSEG_HDR_SPACE, id);
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 1eb0eb51f0a..ad4a1f8d3bd 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -3694,12 +3694,12 @@ ha_innobase::open(
}
/* Create buffers for packing the fields of a record. Why
- table->reclength did not work here? Obviously, because char
+ table->stored_rec_length did not work here? Obviously, because char
fields when packed actually became 1 byte longer, when we also
stored the string length as the first byte. */
upd_and_key_val_buff_len =
- table->s->reclength + table->s->max_key_length
+ table->s->stored_rec_length + table->s->max_key_length
+ MAX_REF_PARTS * 3;
if (!(uchar*) my_multi_malloc(MYF(MY_WME),
&upd_buff, upd_and_key_val_buff_len,
@@ -3787,7 +3787,7 @@ retry:
prebuilt = row_create_prebuilt(ib_table);
- prebuilt->mysql_row_len = table->s->reclength;
+ prebuilt->mysql_row_len = table->s->stored_rec_length;;
prebuilt->default_rec = table->s->default_values;
ut_ad(prebuilt->default_rec);
@@ -4564,11 +4564,11 @@ build_template(
dict_index_t* clust_index;
mysql_row_templ_t* templ;
Field* field;
- ulint n_fields;
+ ulint n_fields, n_stored_fields;
ulint n_requested_fields = 0;
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
- ulint i;
+ ulint i, sql_idx, innodb_idx=0;
/* byte offset of the end of last requested column */
ulint mysql_prefix_len = 0;
@@ -4629,10 +4629,11 @@ build_template(
}
n_fields = (ulint)table->s->fields; /* number of columns */
+ n_stored_fields= (ulint)table->s->stored_fields; /* number of stored columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
- mem_alloc(n_fields * sizeof(mysql_row_templ_t));
+ mem_alloc(n_stored_fields * sizeof(mysql_row_templ_t));
}
prebuilt->template_type = templ_type;
@@ -4642,15 +4643,17 @@ build_template(
/* Note that in InnoDB, i is the column number. MySQL calls columns
'fields'. */
- for (i = 0; i < n_fields; i++) {
+ for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
templ = prebuilt->mysql_template + n_requested_fields;
- field = table->field[i];
+ field = table->field[sql_idx];
+ if (!field->stored_in_db)
+ goto skip_field;
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
/* Decide which columns we should fetch
and which we can skip. */
register const ibool index_contains_field =
- dict_index_contains_col_or_prefix(index, i);
+ dict_index_contains_col_or_prefix(index, innodb_idx);
if (!index_contains_field && prebuilt->read_just_key) {
/* If this is a 'key read', we do not need
@@ -4665,8 +4668,8 @@ build_template(
goto include_field;
}
- if (bitmap_is_set(table->read_set, i) ||
- bitmap_is_set(table->write_set, i)) {
+ if (bitmap_is_set(table->read_set, sql_idx) ||
+ bitmap_is_set(table->write_set, sql_idx)) {
/* This field is needed in the query */
goto include_field;
@@ -4674,7 +4677,7 @@ build_template(
if (fetch_primary_key_cols
&& dict_table_col_in_clustered_key(
- index->table, i)) {
+ index->table, innodb_idx)) {
/* This field is needed in the query */
goto include_field;
@@ -4687,14 +4690,14 @@ build_template(
include_field:
n_requested_fields++;
- templ->col_no = i;
+ templ->col_no = innodb_idx;
if (index == clust_index) {
templ->rec_field_no = dict_col_get_clust_pos(
- &index->table->cols[i], index);
+ &index->table->cols[innodb_idx], index);
} else {
templ->rec_field_no = dict_index_get_nth_col_pos(
- index, i);
+ index, innodb_idx);
}
if (templ->rec_field_no == ULINT_UNDEFINED) {
@@ -4720,7 +4723,7 @@ include_field:
mysql_prefix_len = templ->mysql_col_offset
+ templ->mysql_col_len;
}
- templ->type = index->table->cols[i].mtype;
+ templ->type = index->table->cols[innodb_idx].mtype;
templ->mysql_type = (ulint)field->type();
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
@@ -4729,16 +4732,18 @@ include_field:
}
templ->charset = dtype_get_charset_coll(
- index->table->cols[i].prtype);
- templ->mbminlen = index->table->cols[i].mbminlen;
- templ->mbmaxlen = index->table->cols[i].mbmaxlen;
- templ->is_unsigned = index->table->cols[i].prtype
+ index->table->cols[innodb_idx].prtype);
+ templ->mbminlen = index->table->cols[innodb_idx].mbminlen;
+ templ->mbmaxlen = index->table->cols[innodb_idx].mbmaxlen;
+ templ->is_unsigned = index->table->cols[innodb_idx].prtype
& DATA_UNSIGNED;
if (templ->type == DATA_BLOB) {
prebuilt->templ_contains_blob = TRUE;
}
skip_field:
- ;
+ if (field->stored_in_db) {
+ innodb_idx++;
+ }
}
prebuilt->n_template = n_requested_fields;
@@ -5161,7 +5166,7 @@ calc_row_difference(
ulint n_changed = 0;
dfield_t dfield;
dict_index_t* clust_index;
- uint i;
+ uint sql_idx, innodb_idx= 0;
n_fields = table->s->fields;
clust_index = dict_table_get_first_index(prebuilt->table);
@@ -5169,8 +5174,10 @@ calc_row_difference(
/* We use upd_buff to convert changed fields */
buf = (byte*) upd_buff;
- for (i = 0; i < n_fields; i++) {
- field = table->field[i];
+ for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
+ field = table->field[sql_idx];
+ if (!field->stored_in_db)
+ continue;
o_ptr = (const byte*) old_row + get_field_offset(table, field);
n_ptr = (const byte*) new_row + get_field_offset(table, field);
@@ -5188,7 +5195,7 @@ calc_row_difference(
field_mysql_type = field->type();
- col_type = prebuilt->table->cols[i].mtype;
+ col_type = prebuilt->table->cols[innodb_idx].mtype;
switch (col_type) {
@@ -5243,7 +5250,7 @@ calc_row_difference(
/* Let us use a dummy dfield to make the conversion
from the MySQL column format to the InnoDB format */
- dict_col_copy_type(prebuilt->table->cols + i,
+ dict_col_copy_type(prebuilt->table->cols + innodb_idx,
dfield_get_type(&dfield));
if (n_len != UNIV_SQL_NULL) {
@@ -5262,9 +5269,11 @@ calc_row_difference(
ufield->exp = NULL;
ufield->orig_len = 0;
ufield->field_no = dict_col_get_clust_pos(
- &prebuilt->table->cols[i], clust_index);
+ &prebuilt->table->cols[innodb_idx], clust_index);
n_changed++;
}
+ if (field->stored_in_db)
+ innodb_idx++;
}
uvect->n_fields = n_changed;
@@ -6330,7 +6339,7 @@ create_table_def(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
- table = dict_mem_table_create(table_name, 0, n_cols, flags);
+ table = dict_mem_table_create(table_name, 0, form->s->stored_fields, flags);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@@ -6339,6 +6348,8 @@ create_table_def(
for (i = 0; i < n_cols; i++) {
field = form->field[i];
+ if (!field->stored_in_db)
+ continue;
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
field);
@@ -6844,7 +6855,7 @@ ha_innobase::create(
}
#endif
- if (form->s->fields > 1000) {
+ if (form->s->stored_fields > 1000) {
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
but we play safe here */
@@ -7551,10 +7562,10 @@ ha_innobase::records_in_range(
KEY* key;
dict_index_t* index;
uchar* key_val_buff2 = (uchar*) my_malloc(
- table->s->reclength
+ table->s->stored_rec_length
+ table->s->max_key_length + 100,
MYF(MY_FAE));
- ulint buff2_len = table->s->reclength
+ ulint buff2_len = table->s->stored_rec_length
+ table->s->max_key_length + 100;
dtuple_t* range_start;
dtuple_t* range_end;
@@ -11530,6 +11541,41 @@ i_s_innodb_sys_tables,
i_s_innodb_sys_indexes,
i_s_innodb_patches
mysql_declare_plugin_end;
+maria_declare_plugin(xtradb)
+{ /* InnoDB */
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase Oy",
+ "Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ INNODB_VERSION_SHORT,
+ innodb_status_variables_export,/* status variables */
+ innobase_system_variables, /* system variables */
+ INNODB_VERSION_STR, /* string version */
+ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
+},
+i_s_innodb_rseg_maria,
+i_s_innodb_buffer_pool_pages_maria,
+i_s_innodb_buffer_pool_pages_index_maria,
+i_s_innodb_buffer_pool_pages_blob_maria,
+i_s_innodb_trx_maria,
+i_s_innodb_locks_maria,
+i_s_innodb_lock_waits_maria,
+i_s_innodb_cmp_maria,
+i_s_innodb_cmp_reset_maria,
+i_s_innodb_cmpmem_maria,
+i_s_innodb_cmpmem_reset_maria,
+i_s_innodb_table_stats_maria,
+i_s_innodb_index_stats_maria,
+i_s_innodb_admin_command_maria,
+i_s_innodb_sys_tables_maria,
+i_s_innodb_sys_indexes_maria,
+i_s_innodb_patches_maria
+maria_declare_plugin_end;
+
/** @brief Initialize the default value of innodb_commit_concurrency.
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 729abcbcd0a..5f5f6de98ba 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -221,6 +221,7 @@ class ha_innobase: public handler
/** @} */
bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes);
+ bool check_if_supported_virtual_columns(void) { return TRUE; }
};
/* Some accessor functions which the InnoDB plugin needs, but which
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index c48676c2892..cc30bdee1dd 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -394,6 +394,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_patches =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_patches_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "XTRADB_ENHANCEMENTS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Percona"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Enhancements applied to InnoDB plugin"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_patches_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
{
@@ -1041,6 +1094,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1090,6 +1196,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -1139,6 +1298,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
@@ -1374,6 +1586,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx =
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_trx_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_TRX"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB transactions"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_trx_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
static ST_FIELD_INFO innodb_locks_fields_info[] =
{
@@ -1649,6 +1915,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_locks_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCKS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB conflicting locks"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_locks_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
{
@@ -1832,6 +2151,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, "Innobase Oy"),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_lock_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -2164,6 +2536,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2214,6 +2639,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMP_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmp_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
{
@@ -2432,6 +2910,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
@@ -2482,6 +3013,60 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
+ " reset cumulated counts"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_cmpmem_reset_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
@@ -2661,6 +3246,59 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_rseg =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_rseg_maria =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_RSEG"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB rollback segment information"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, i_s_innodb_rseg_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* string version */
+ /* const char * */
+ STRUCT_FLD(version_info, "1.0"),
+
+ /* Maturity */
+ /* int */
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
@@ -2989,6 +3627,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_table_stats =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_table_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
@@ -3005,6 +3660,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_index_stats_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
/***********************************************************************
*/
static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
@@ -3171,6 +3843,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_admin_command_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
+};
+
static ST_FIELD_INFO i_s_innodb_sys_tables_info[] =
{
{STRUCT_FLD(field_name, "SCHEMA"),
@@ -3713,6 +4402,23 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables =
STRUCT_FLD(__reserved1, NULL)
};
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_SYS_TABLES"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB SYS_TABLES table"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_sys_tables_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA)
+};
+
UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
@@ -3728,3 +4434,21 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL)
};
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes_maria =
+{
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+ STRUCT_FLD(info, &i_s_info),
+ STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
+ STRUCT_FLD(author, plugin_author),
+ STRUCT_FLD(descr, "InnoDB SYS_INDEXES table"),
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+ STRUCT_FLD(init, i_s_innodb_sys_indexes_init),
+ STRUCT_FLD(deinit, i_s_common_deinit),
+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
+ STRUCT_FLD(status_vars, NULL),
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(version_info, "1.0"),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA)
+};
+
diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h
index 41c63a98d76..8252c6d1fa2 100644
--- a/storage/xtradb/handler/i_s.h
+++ b/storage/xtradb/handler/i_s.h
@@ -44,4 +44,22 @@ extern struct st_mysql_plugin i_s_innodb_admin_command;
extern struct st_mysql_plugin i_s_innodb_sys_tables;
extern struct st_mysql_plugin i_s_innodb_sys_indexes;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index_maria;
+extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob_maria;
+extern struct st_maria_plugin i_s_innodb_trx_maria;
+extern struct st_maria_plugin i_s_innodb_locks_maria;
+extern struct st_maria_plugin i_s_innodb_lock_waits_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_maria;
+extern struct st_maria_plugin i_s_innodb_cmp_reset_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_maria;
+extern struct st_maria_plugin i_s_innodb_cmpmem_reset_maria;
+extern struct st_maria_plugin i_s_innodb_patches_maria;
+extern struct st_maria_plugin i_s_innodb_rseg_maria;
+extern struct st_maria_plugin i_s_innodb_table_stats_maria;
+extern struct st_maria_plugin i_s_innodb_index_stats_maria;
+extern struct st_maria_plugin i_s_innodb_admin_command_maria;
+extern struct st_maria_plugin i_s_innodb_sys_tables_maria;
+extern struct st_maria_plugin i_s_innodb_sys_indexes_maria;
+
#endif /* i_s_h */
diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c
index aa40a269848..0f1644b27e8 100644
--- a/strings/conf_to_src.c
+++ b/strings/conf_to_src.c
@@ -23,15 +23,15 @@
#define ROW16_LEN 8
#define MAX_BUF 64*1024
-static CHARSET_INFO all_charsets[256];
+static struct charset_info_st all_charsets[256];
void
-print_array(FILE *f, const char *set, const char *name, uchar *a, int n)
+print_array(FILE *f, const char *set, const char *name, const uchar *a, int n)
{
int i;
- fprintf(f,"uchar %s_%s[] = {\n", name, set);
+ fprintf(f,"static const uchar %s_%s[] = {\n", name, set);
for (i=0 ;i<n ; i++)
{
@@ -44,11 +44,11 @@ print_array(FILE *f, const char *set, const char *name, uchar *a, int n)
void
-print_array16(FILE *f, const char *set, const char *name, uint16 *a, int n)
+print_array16(FILE *f, const char *set, const char *name, const uint16 *a, int n)
{
int i;
- fprintf(f,"uint16 %s_%s[] = {\n", name, set);
+ fprintf(f,"static const uint16 %s_%s[] = {\n", name, set);
for (i=0 ;i<n ; i++)
{
@@ -80,7 +80,7 @@ char *mdup(const char *src, uint len)
return dst;
}
-static void simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
+static void simple_cs_copy_data(struct charset_info_st *to, CHARSET_INFO *from)
{
to->number= from->number ? from->number : to->number;
to->state|= from->state;
@@ -122,7 +122,7 @@ static my_bool simple_cs_is_full(CHARSET_INFO *cs)
(cs->sort_order || (cs->state & MY_CS_BINSORT))));
}
-static int add_collation(CHARSET_INFO *cs)
+static int add_collation(struct charset_info_st *cs)
{
if (cs->name && (cs->number || (cs->number=get_charset_number(cs->name))))
{
@@ -329,7 +329,7 @@ main(int argc, char **argv __attribute__((unused)))
}
}
- fprintf(f,"CHARSET_INFO compiled_charsets[] = {\n");
+ fprintf(f,"struct charset_info_st compiled_charsets[] = {\n");
for (cs=all_charsets; cs < all_charsets+256; cs++)
{
if (simple_cs_is_full(cs))
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 3da307b82fc..4c29886d307 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -47,7 +47,7 @@
#define big5head(e) ((uchar)(e>>8))
#define big5tail(e) ((uchar)(e&0xff))
-static uchar NEAR ctype_big5[257] =
+static const uchar NEAR ctype_big5[257] =
{
0, /* For standard library */
32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
@@ -68,7 +68,7 @@ static uchar NEAR ctype_big5[257] =
3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,
};
-static uchar NEAR to_lower_big5[]=
+static const uchar NEAR to_lower_big5[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -104,7 +104,7 @@ static uchar NEAR to_lower_big5[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR to_upper_big5[]=
+static const uchar NEAR to_upper_big5[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -140,7 +140,7 @@ static uchar NEAR to_upper_big5[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR sort_order_big5[]=
+static const uchar NEAR sort_order_big5[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -471,7 +471,7 @@ static uint mbcharlen_big5(CHARSET_INFO *cs __attribute__((unused)), uint c)
/* page 0 0xA140-0xC7FC */
-static uint16 tab_big5_uni0[]={
+static const uint16 tab_big5_uni0[]={
0x3000,0xFF0C,0x3001,0x3002,0xFF0E,0x2022,0xFF1B,0xFF1A,
0xFF1F,0xFF01,0xFE30,0x2026,0x2025,0xFE50,0xFF64,0xFE52,
0x00B7,0xFE54,0xFE55,0xFE56,0xFE57,0xFF5C,0x2013,0xFE31,
@@ -1714,7 +1714,7 @@ static uint16 tab_big5_uni0[]={
0x2479,0x247A,0x247B,0x247C,0x247D};
/* page 1 0xC940-0xF9DC */
-static uint16 tab_big5_uni1[]={
+static const uint16 tab_big5_uni1[]={
0x4E42,0x4E5C,0x51F5,0x531A,0x5382,0x4E07,0x4E0C,0x4E47,
0x4E8D,0x56D7,0xFA0C,0x5C6E,0x5F73,0x4E0F,0x5187,0x4E0E,
0x4E2E,0x4E93,0x4EC2,0x4EC9,0x4EC8,0x5198,0x52FC,0x536C,
@@ -3282,7 +3282,7 @@ static int func_big5_uni_onechar(int code){
/* page 0 0x00A2-0x00F7 */
-static uint16 tab_uni_big50[]={
+static const uint16 tab_uni_big50[]={
0xA246,0xA247, 0,0xA244, 0,0xA1B1, 0, 0,
0, 0, 0, 0, 0, 0,0xA258,0xA1D3,
0, 0, 0, 0, 0,0xA150, 0, 0,
@@ -3296,7 +3296,7 @@ static uint16 tab_uni_big50[]={
0, 0, 0, 0, 0,0xA1D2};
/* page 1 0x02C7-0x0451 */
-static uint16 tab_uni_big51[]={
+static const uint16 tab_uni_big51[]={
0xA3BE, 0,0xA3BC,0xA3BD,0xA3BF, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0,0xA3BB, 0, 0, 0, 0, 0,
@@ -3349,7 +3349,7 @@ static uint16 tab_uni_big51[]={
0xC7E8, 0,0xC7CE};
/* page 2 0x2013-0x22BF */
-static uint16 tab_uni_big52[]={
+static const uint16 tab_uni_big52[]={
0xA156,0xA158, 0, 0, 0,0xA1A5,0xA1A6, 0,
0,0xA1A7,0xA1A8, 0, 0, 0, 0,0xA145,
0, 0,0xA14C,0xA14B, 0, 0, 0, 0,
@@ -3438,7 +3438,7 @@ static uint16 tab_uni_big52[]={
0, 0, 0, 0,0xA1E9};
/* page 3 0x2460-0x2642 */
-static uint16 tab_uni_big53[]={
+static const uint16 tab_uni_big53[]={
0xC7E9,0xC7EA,0xC7EB,0xC7EC,0xC7ED,0xC7EE,0xC7EF,0xC7F0,
0xC7F1,0xC7F2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0xC7F3,0xC7F4,0xC7F5,0xC7F6,
@@ -3502,7 +3502,7 @@ static uint16 tab_uni_big53[]={
0xA1F0,0xA1F2,0xA1F1};
/* page 4 0x3000-0x3129 */
-static uint16 tab_uni_big54[]={
+static const uint16 tab_uni_big54[]={
0xA140,0xA142,0xA143,0xA1B2, 0,0xC6A4, 0, 0,
0xA171,0xA172,0xA16D,0xA16E,0xA175,0xA176,0xA179,0xA17A,
0xA169,0xA16A,0xA245, 0,0xA165,0xA166, 0, 0,
@@ -3543,11 +3543,11 @@ static uint16 tab_uni_big54[]={
0xA3B9,0xA3BA};
/* page 5 0x32A3-0x32A3 */
-static uint16 tab_uni_big55[]={
+static const uint16 tab_uni_big55[]={
0xA1C0};
/* page 6 0x338E-0x33D5 */
-static uint16 tab_uni_big56[]={
+static const uint16 tab_uni_big56[]={
0xA255,0xA256, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0xA250,0xA251,
0xA252, 0, 0,0xA254, 0, 0, 0, 0,
@@ -3560,7 +3560,7 @@ static uint16 tab_uni_big56[]={
};
/* page 7 0x4E00-0x9483 */
-static uint16 tab_uni_big57[]={
+static const uint16 tab_uni_big57[]={
0xA440,0xA442, 0,0xA443, 0, 0, 0,0xC945,
0xA456,0xA454,0xA457,0xA455,0xC946,0xA4A3,0xC94F,0xC94D,
0xA4A2,0xA4A1, 0, 0,0xA542,0xA541,0xA540, 0,
@@ -5820,7 +5820,7 @@ static uint16 tab_uni_big57[]={
0xF9C0,0xF9C1,0xF9BF,0xF9C9};
/* page 8 0x9577-0x9FA4 */
-static uint16 tab_uni_big58[]={
+static const uint16 tab_uni_big58[]={
0xAAF8, 0, 0,0xD844,0xDC78,0xE8A5,0xF376, 0,
0,0xAAF9, 0,0xADAC,0xB07B, 0, 0,0xD845,
0,0xD846,0xB3AC, 0,0xB67D,0xDC7A,0xDC79,0xB6A3,
@@ -6149,11 +6149,11 @@ static uint16 tab_uni_big58[]={
0,0xEFB6, 0,0xF7CF, 0,0xF9A1};
/* page 9 0xFA0C-0xFA0D */
-static uint16 tab_uni_big59[]={
+static const uint16 tab_uni_big59[]={
0xC94A,0xDDFC};
/* page 10 0xFE30-0xFFFD */
-static uint16 tab_uni_big510[]={
+static const uint16 tab_uni_big510[]={
0xA14A,0xA157, 0,0xA159,0xA15B,0xA15F,0xA160,0xA163,
0xA164,0xA167,0xA168,0xA16B,0xA16C,0xA16F,0xA170,0xA173,
0xA174,0xA177,0xA178,0xA17B,0xA17C, 0, 0, 0,
@@ -6377,7 +6377,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler=
my_scan_8bit
};
-CHARSET_INFO my_charset_big5_chinese_ci=
+struct charset_info_st my_charset_big5_chinese_ci=
{
1,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
@@ -6410,7 +6410,7 @@ CHARSET_INFO my_charset_big5_chinese_ci=
};
-CHARSET_INFO my_charset_big5_bin=
+struct charset_info_st my_charset_big5_bin=
{
84,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 95d97af2bfb..95544cdf42b 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -22,7 +22,7 @@
#include "m_string.h"
#include "m_ctype.h"
-static uchar ctype_bin[]=
+static const uchar ctype_bin[]=
{
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
@@ -46,7 +46,7 @@ static uchar ctype_bin[]=
/* Dummy array for toupper / tolower / sortorder */
-static uchar bin_char_array[] =
+static const uchar bin_char_array[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -68,7 +68,7 @@ static uchar bin_char_array[] =
static my_bool
-my_coll_init_8bit_bin(CHARSET_INFO *cs,
+my_coll_init_8bit_bin(struct charset_info_st *cs,
void *(*alloc)(size_t) __attribute__((unused)))
{
cs->max_sort_char=255;
@@ -549,7 +549,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_bin =
+struct charset_info_st my_charset_bin =
{
63,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_PRIMARY,/* state */
diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c
index 07191c436b7..2caffe7aea2 100644
--- a/strings/ctype-cp932.c
+++ b/strings/ctype-cp932.c
@@ -31,7 +31,7 @@
* .configure. mbmaxlen_cp932=2
*/
-static uchar NEAR ctype_cp932[257] =
+static const uchar NEAR ctype_cp932[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -68,7 +68,7 @@ static uchar NEAR ctype_cp932[257] =
0020, 0020, 0020, 0020, 0020, 0000, 0000, 0000
};
-static uchar NEAR to_lower_cp932[]=
+static const uchar NEAR to_lower_cp932[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -104,7 +104,7 @@ static uchar NEAR to_lower_cp932[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR to_upper_cp932[]=
+static const uchar NEAR to_upper_cp932[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -140,7 +140,7 @@ static uchar NEAR to_upper_cp932[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR sort_order_cp932[]=
+static const uchar NEAR sort_order_cp932[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -377,7 +377,7 @@ static my_bool my_like_range_cp932(CHARSET_INFO *cs __attribute__((unused)),
}
/* page 0 0x00A1-0x00DF */
-static uint16 tab_cp932_uni0[]={
+static const uint16 tab_cp932_uni0[]={
0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,0xFF68,
0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F,0xFF70,
0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,0xFF78,
@@ -388,7 +388,7 @@ static uint16 tab_cp932_uni0[]={
0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F};
/* page 1 0x8140-0x84BE */
-static uint16 tab_cp932_uni1[]={
+static const uint16 tab_cp932_uni1[]={
0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
@@ -503,7 +503,7 @@ static uint16 tab_cp932_uni1[]={
0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542};
/* page 2 0x8740-0x879C - NEC Row 13 */
-static uint16 tab_cp932_uni2[]={
+static const uint16 tab_cp932_uni2[]={
0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
0x2470,0x2471,0x2472,0x2473,0x2160,0x2161,0x2162,0x2163,
@@ -518,7 +518,7 @@ static uint16 tab_cp932_uni2[]={
0x221F,0x22BF,0x2235,0x2229,0x222A};
/* page 3 0x889F-0x9FFC */
-static uint16 tab_cp932_uni3[]={
+static const uint16 tab_cp932_uni3[]={
0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
@@ -1269,7 +1269,7 @@ static uint16 tab_cp932_uni3[]={
0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
/* page 4 0xE040-0xEAA4 */
-static uint16 tab_cp932_uni4[]={
+static const uint16 tab_cp932_uni4[]={
0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
@@ -1606,7 +1606,7 @@ static uint16 tab_cp932_uni4[]={
/* page 5 0xED40-0xEEFC -
IBM Selected Kanji and Non-Kanji(NEC implementation) */
-static uint16 tab_cp932_uni5[]={
+static const uint16 tab_cp932_uni5[]={
0x7E8A,0x891C,0x9348,0x9288,0x84DC,0x4FC9,0x70BB,0x6631,
0x68C8,0x92F9,0x66FB,0x5F45,0x4E28,0x4EE1,0x4EFC,0x4F00,
0x4F03,0x4F39,0x4F56,0x4F92,0x4F8A,0x4F9A,0x4F94,0x4FCD,
@@ -1665,7 +1665,7 @@ static uint16 tab_cp932_uni5[]={
0x2179,0xFFE2,0xFFE4,0xFF07,0xFF02};
/* page 6 0xF040-0xF9FC - User defined characters */
-static uint16 tab_cp932_uni6[]={
+static const uint16 tab_cp932_uni6[]={
0xE000,0xE001,0xE002,0xE003,0xE004,0xE005,0xE006,0xE007,
0xE008,0xE009,0xE00A,0xE00B,0xE00C,0xE00D,0xE00E,0xE00F,
0xE010,0xE011,0xE012,0xE013,0xE014,0xE015,0xE016,0xE017,
@@ -1981,7 +1981,7 @@ static uint16 tab_cp932_uni6[]={
/* page 7 0xFA40-0xFC4B -
IBM Selected Kanji and Non-Kanji */
-static uint16 tab_cp932_uni7[]={
+static const uint16 tab_cp932_uni7[]={
0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,
0x2178,0x2179,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,
0x2166,0x2167,0x2168,0x2169,0xFFE2,0xFFE4,0xFF07,0xFF02,
@@ -2070,7 +2070,7 @@ static int func_cp932_uni_onechar(int code){
}
/* page 0 0x005C-0x00F7 */
-static uint16 tab_uni_cp9320[]={
+static const uint16 tab_uni_cp9320[]={
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -2093,7 +2093,7 @@ static uint16 tab_uni_cp9320[]={
0, 0, 0,0x8180};
/* page 1 0x0391-0x0451 */
-static uint16 tab_uni_cp9321[]={
+static const uint16 tab_uni_cp9321[]={
0x839F,0x83A0,0x83A1,0x83A2,0x83A3,0x83A4,0x83A5,0x83A6,
0x83A7,0x83A8,0x83A9,0x83AA,0x83AB,0x83AC,0x83AD,0x83AE,
0x83AF, 0,0x83B0,0x83B1,0x83B2,0x83B3,0x83B4,0x83B5,
@@ -2121,7 +2121,7 @@ static uint16 tab_uni_cp9321[]={
0x8476};
/* page 2 0x2010-0x2473 */
-static uint16 tab_uni_cp9322[]={
+static const uint16 tab_uni_cp9322[]={
0x815D, 0, 0, 0, 0,0x815C, 0, 0,
0x8165,0x8166, 0, 0,0x8167,0x8168, 0, 0,
0x81F5,0x81F6, 0, 0, 0,0x8164,0x8163, 0,
@@ -2265,7 +2265,7 @@ static uint16 tab_uni_cp9322[]={
0x8750,0x8751,0x8752,0x8753};
/* page 3 0x2500-0x266F */
-static uint16 tab_uni_cp9323[]={
+static const uint16 tab_uni_cp9323[]={
0x849F,0x84AA,0x84A0,0x84AB, 0, 0, 0, 0,
0, 0, 0, 0,0x84A1, 0, 0,0x84AC,
0x84A2, 0, 0,0x84AD,0x84A4, 0, 0,0x84AF,
@@ -2315,7 +2315,7 @@ static uint16 tab_uni_cp9323[]={
};
/* page 4 0x3000-0x30FE */
-static uint16 tab_uni_cp9324[]={
+static const uint16 tab_uni_cp9324[]={
0x8140,0x8141,0x8142,0x8156, 0,0x8158,0x8159,0x815A,
0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177,0x8178,
0x8179,0x817A,0x81A7,0x81AC,0x816B,0x816C, 0, 0,
@@ -2350,7 +2350,7 @@ static uint16 tab_uni_cp9324[]={
0, 0, 0,0x8145,0x815B,0x8152,0x8153};
/* page 5 0x3230-0x33CD */
-static uint16 tab_uni_cp9325[]={
+static const uint16 tab_uni_cp9325[]={
0,0x878A,0x878B, 0, 0, 0, 0, 0,
0,0x878C, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -2405,7 +2405,7 @@ static uint16 tab_uni_cp9325[]={
0, 0, 0, 0, 0,0x8783};
/* page 6 0x4E00-0x9481 */
-static uint16 tab_uni_cp9326[]={
+static const uint16 tab_uni_cp9326[]={
0x88EA,0x929A, 0,0x8EB5, 0, 0, 0,0x969C,
0x8FE4,0x8E4F,0x8FE3,0x89BA, 0,0x9573,0x975E, 0,
0x98A0,0x894E, 0, 0,0x8A8E,0x98A1,0x90A2,0x99C0,
@@ -4665,7 +4665,7 @@ static uint16 tab_uni_cp9326[]={
0,0xE876};
/* page 7 0x9577-0x9FA0 */
-static uint16 tab_uni_cp9327[]={
+static const uint16 tab_uni_cp9327[]={
0x92B7, 0, 0, 0, 0, 0, 0, 0,
0,0x96E5, 0,0xE878,0x914D, 0, 0, 0,
0xE879, 0,0x95C2,0xE87A,0x8A4A, 0, 0, 0,
@@ -4994,7 +4994,7 @@ static uint16 tab_uni_cp9327[]={
0,0xEA9E};
/* page 8 0xE000-0xE757 - User defined characters */
-static uint16 tab_uni_cp9328[]={
+static const uint16 tab_uni_cp9328[]={
0xF040,0xF041,0xF042,0xF043,0xF044,0xF045,0xF046,0xF047,
0xF048,0xF049,0xF04A,0xF04B,0xF04C,0xF04D,0xF04E,0xF04F,
0xF050,0xF051,0xF052,0xF053,0xF054,0xF055,0xF056,0xF057,
@@ -5232,7 +5232,7 @@ static uint16 tab_uni_cp9328[]={
0xF9F5,0xF9F6,0xF9F7,0xF9F8,0xF9F9,0xF9FA,0xF9FB,0xF9FC};
/* page 9 0xF920-0xFA2D */
-static uint16 tab_uni_cp9329[]={
+static const uint16 tab_uni_cp9329[]={
0, 0, 0, 0, 0, 0, 0, 0,
0,0xFAE0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -5269,7 +5269,7 @@ static uint16 tab_uni_cp9329[]={
0xFBDA,0xFBEA,0xFBF6,0xFBF7,0xFBF9,0xFC49};
/* page 10 0xFF01-0xFFE5 */
-static uint16 tab_uni_cp93210[]={
+static const uint16 tab_uni_cp93210[]={
0x8149,0xFA57,0x8194,0x8190,0x8193,0x8195,0xFA56,0x8169,
0x816A,0x8196,0x817B,0x8143,0x817C,0x8144,0x815E,0x824F,
0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257,
@@ -5508,7 +5508,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_cp932_japanese_ci=
+struct charset_info_st my_charset_cp932_japanese_ci=
{
95,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
@@ -5540,7 +5540,7 @@ CHARSET_INFO my_charset_cp932_japanese_ci=
&my_collation_ci_handler
};
-CHARSET_INFO my_charset_cp932_bin=
+struct charset_info_st my_charset_cp932_bin=
{
96,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index a5df86cc6b3..2f32d3eae88 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -83,7 +83,7 @@
below for what are the "special values"
*/
-static uchar *CZ_SORT_TABLE[] = {
+static const uchar *const CZ_SORT_TABLE[] = {
(uchar*) "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\043\044\045\046\047\050\051\052\053\054\000\000\000\000\000\000\000\003\004\377\007\010\011\012\013\015\016\017\020\022\023\024\025\026\027\031\033\034\035\036\037\040\041\000\000\000\000\000\000\003\004\377\007\010\011\012\013\015\016\017\020\022\023\024\025\026\027\031\033\034\035\036\037\040\041\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\021\000\020\032\000\000\032\032\033\042\000\042\042\000\003\000\021\000\020\032\000\000\032\032\033\042\000\042\042\027\003\003\003\003\020\006\006\006\010\010\010\010\015\015\007\007\023\023\024\024\024\024\000\030\034\034\034\034\040\033\000\027\003\003\003\003\020\006\006\006\010\010\010\010\015\015\007\007\023\023\024\024\024\024\000\030\034\034\034\034\040\033\000",
(uchar*) "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\106\107\110\111\112\113\114\115\116\117\000\000\000\000\000\000\000\003\011\377\016\021\026\027\030\032\035\036\037\043\044\047\054\055\056\061\065\070\075\076\077\100\102\000\000\000\000\000\000\003\011\377\016\021\026\027\030\032\035\036\037\043\044\047\054\055\056\061\065\070\075\076\077\100\102\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\042\000\041\063\000\000\062\064\066\104\000\103\105\000\010\000\042\000\041\063\000\000\062\064\066\104\000\103\105\057\004\005\007\006\040\014\015\013\022\025\024\023\033\034\017\020\046\045\050\051\053\052\000\060\072\071\074\073\101\067\000\057\004\005\007\006\040\014\015\013\022\025\024\023\033\034\017\020\046\045\050\051\053\052\000\060\072\071\074\073\101\067\000",
(uchar*) "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\212\213\214\215\216\217\220\221\222\223\000\000\000\000\000\000\000\004\020\377\032\040\052\054\056\063\071\073\075\105\107\115\127\131\133\141\151\157\171\173\175\177\203\000\000\000\000\000\000\003\017\377\031\037\051\053\055\062\070\072\074\104\106\114\126\130\132\140\150\156\170\172\174\176\202\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\103\000\101\145\000\000\143\147\153\207\000\205\211\000\015\000\102\000\100\144\000\000\142\146\152\206\000\204\210\135\006\010\014\012\077\026\030\024\042\050\046\044\065\067\034\036\113\111\117\121\125\123\000\137\163\161\167\165\201\155\000\134\005\007\013\011\076\025\027\023\041\047\045\043\064\066\033\035\112\110\116\120\124\122\000\136\162\160\166\164\200\154\000",
@@ -99,14 +99,14 @@ static uchar *CZ_SORT_TABLE[] = {
struct wordvalue
{
const char * word;
- uchar *outvalue;
+ const uchar *outvalue;
};
-static struct wordvalue doubles[] = {
- { "ch", (uchar*) "\014\031\057\057" },
- { "Ch", (uchar*) "\014\031\060\060" },
- { "CH", (uchar*) "\014\031\061\061" },
- { "c", (uchar*) "\005\012\021\021" },
- { "C", (uchar*) "\005\012\022\022" },
+static const struct wordvalue doubles[] = {
+ { "ch", (const uchar*) "\014\031\057\057" },
+ { "Ch", (const uchar*) "\014\031\060\060" },
+ { "CH", (const uchar*) "\014\031\061\061" },
+ { "c", (const uchar*) "\005\012\021\021" },
+ { "C", (const uchar*) "\005\012\022\022" },
};
/*
@@ -430,7 +430,7 @@ static my_bool my_like_range_czech(CHARSET_INFO *cs __attribute__((unused)),
#include <my_global.h>
#include "m_string.h"
-static uchar NEAR ctype_czech[257] = {
+static const uchar NEAR ctype_czech[257] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@@ -450,7 +450,7 @@ static uchar NEAR ctype_czech[257] = {
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 16,
};
-static uchar NEAR to_lower_czech[] = {
+static const uchar NEAR to_lower_czech[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -469,7 +469,7 @@ static uchar NEAR to_lower_czech[] = {
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
};
-static uchar NEAR to_upper_czech[] = {
+static const uchar NEAR to_upper_czech[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -488,7 +488,7 @@ static uchar NEAR to_upper_czech[] = {
240,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255,
};
-static uchar NEAR sort_order_czech[] = {
+static const uchar NEAR sort_order_czech[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -507,7 +507,7 @@ static uchar NEAR sort_order_czech[] = {
255, 98, 99,101,102,103,104,255,109,119,118,120,121,126,116,255,
};
-static uint16 tab_8859_2_uni[256]={
+static const uint16 tab_8859_2_uni[256]={
0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -544,7 +544,7 @@ static uint16 tab_8859_2_uni[256]={
/* 0000-00FD , 254 chars */
-static uchar tab_uni_8859_2_plane00[]={
+static const uchar tab_uni_8859_2_plane00[]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -563,7 +563,7 @@ static uchar tab_uni_8859_2_plane00[]={
0x00,0x00,0x00,0xF3,0xF4,0x00,0xF6,0xF7,0x00,0x00,0xFA,0x00,0xFC,0xFD};
/* 0102-017E , 125 chars */
-static uchar tab_uni_8859_2_plane01[]={
+static const uchar tab_uni_8859_2_plane01[]={
0xC3,0xE3,0xA1,0xB1,0xC6,0xE6,0x00,0x00,0x00,0x00,0xC8,0xE8,0xCF,0xEF,0xD0,0xF0,
0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -574,7 +574,7 @@ static uchar tab_uni_8859_2_plane01[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0xBC,0xAF,0xBF,0xAE,0xBE};
/* 02C7-02DD , 23 chars */
-static uchar tab_uni_8859_2_plane02[]={
+static const uchar tab_uni_8859_2_plane02[]={
0xB7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xA2,0xFF,0x00,0xB2,0x00,0xBD};
@@ -601,7 +601,7 @@ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
my_propagate_simple
};
-CHARSET_INFO my_charset_latin2_czech_ci =
+struct charset_info_st my_charset_latin2_czech_ci =
{
2,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_CSSORT, /* state */
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index fc0af7e35d5..a5d5c1ee6ea 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -32,7 +32,7 @@
#ifdef HAVE_CHARSET_euckr
-static uchar NEAR ctype_euc_kr[257] =
+static const uchar NEAR ctype_euc_kr[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -69,7 +69,7 @@ static uchar NEAR ctype_euc_kr[257] =
0020, 0020, 0020, 0020, 0020, 0020, 0020, 0000,
};
-static uchar NEAR to_lower_euc_kr[]=
+static const uchar NEAR to_lower_euc_kr[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -105,7 +105,7 @@ static uchar NEAR to_lower_euc_kr[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR to_upper_euc_kr[]=
+static const uchar NEAR to_upper_euc_kr[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -141,7 +141,7 @@ static uchar NEAR to_upper_euc_kr[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR sort_order_euc_kr[]=
+static const uchar NEAR sort_order_euc_kr[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -217,7 +217,7 @@ static uint mbcharlen_euc_kr(CHARSET_INFO *cs __attribute__((unused)),uint c)
/* page 0 0x8141-0xC8FE */
-static uint16 tab_ksc5601_uni0[]={
+static const uint16 tab_ksc5601_uni0[]={
0xAC02,0xAC03,0xAC05,0xAC06,0xAC0B,0xAC0C,0xAC0D,0xAC0E,
0xAC0F,0xAC18,0xAC1E,0xAC1F,0xAC21,0xAC22,0xAC23,0xAC25,
0xAC26,0xAC27,0xAC28,0xAC29,0xAC2A,0xAC2B,0xAC2E,0xAC32,
@@ -2516,7 +2516,7 @@ static uint16 tab_ksc5601_uni0[]={
0xD78C,0xD790,0xD798,0xD799,0xD79B,0xD79D};
/* page 1 0xCAA1-0xFDFE */
-static uint16 tab_ksc5601_uni1[]={
+static const uint16 tab_ksc5601_uni1[]={
0x4F3D,0x4F73,0x5047,0x50F9,0x52A0,0x53EF,0x5475,0x54E5,
0x5609,0x5AC1,0x5BB6,0x6687,0x67B6,0x67B7,0x67EF,0x6B4C,
0x73C2,0x75C2,0x7A3C,0x82DB,0x8304,0x8857,0x8888,0x8A36,
@@ -4170,7 +4170,7 @@ static int func_ksc5601_uni_onechar(int code){
return(0);
}
/* page 0 0x00A1-0x0167 */
-static uint16 tab_uni_ksc56010[]={
+static const uint16 tab_uni_ksc56010[]={
0xA2AE, 0, 0,0xA2B4, 0, 0,0xA1D7,0xA1A7,
0,0xA8A3, 0, 0,0xA1A9,0xA2E7, 0,0xA1C6,
0xA1BE,0xA9F7,0xA9F8,0xA2A5, 0,0xA2D2,0xA1A4,0xA2AC,
@@ -4198,7 +4198,7 @@ static uint16 tab_uni_ksc56010[]={
0, 0, 0, 0, 0,0xA8AE,0xA9AE};
/* page 1 0x02C7-0x0451 */
-static uint16 tab_uni_ksc56011[]={
+static const uint16 tab_uni_ksc56011[]={
0xA2A7, 0, 0, 0, 0, 0, 0, 0,
0,0xA2B0, 0, 0, 0, 0, 0, 0,
0,0xA2A8,0xA2AB,0xA2AA,0xA2AD, 0,0xA2A9, 0,
@@ -4251,7 +4251,7 @@ static uint16 tab_uni_ksc56011[]={
0xACF1, 0,0xACD7};
/* page 2 0x2015-0x2312 */
-static uint16 tab_uni_ksc56012[]={
+static const uint16 tab_uni_ksc56012[]={
0xA1AA, 0, 0,0xA1AE,0xA1AF, 0, 0,0xA1B0,
0xA1B1, 0, 0,0xA2D3,0xA2D4, 0, 0, 0,
0xA1A5,0xA1A6, 0, 0, 0, 0, 0, 0,
@@ -4350,7 +4350,7 @@ static uint16 tab_uni_ksc56012[]={
0, 0, 0, 0, 0,0xA1D2};
/* page 3 0x2460-0x266D */
-static uint16 tab_uni_ksc56013[]={
+static const uint16 tab_uni_ksc56013[]={
0xA8E7,0xA8E8,0xA8E9,0xA8EA,0xA8EB,0xA8EC,0xA8ED,0xA8EE,
0xA8EF,0xA8F0,0xA8F1,0xA8F2,0xA8F3,0xA8F4,0xA8F5, 0,
0, 0, 0, 0,0xA9E7,0xA9E8,0xA9E9,0xA9EA,
@@ -4419,7 +4419,7 @@ static uint16 tab_uni_ksc56013[]={
0xA2CD,0xA2DB,0xA2DC, 0,0xA2DD,0xA2DA};
/* page 4 0x3000-0x327F */
-static uint16 tab_uni_ksc56014[]={
+static const uint16 tab_uni_ksc56014[]={
0xA1A1,0xA1A2,0xA1A3,0xA1A8, 0, 0, 0, 0,
0xA1B4,0xA1B5,0xA1B6,0xA1B7,0xA1B8,0xA1B9,0xA1BA,0xA1BB,
0xA1BC,0xA1BD, 0,0xA1EB,0xA1B2,0xA1B3, 0, 0,
@@ -4503,7 +4503,7 @@ static uint16 tab_uni_ksc56014[]={
};
/* page 5 0x3380-0x33DD */
-static uint16 tab_uni_ksc56015[]={
+static const uint16 tab_uni_ksc56015[]={
0xA7C9,0xA7CA,0xA7CB,0xA7CC,0xA7CD, 0, 0, 0,
0xA7BA,0xA7BB,0xA7DC,0xA7DD,0xA7DE,0xA7B6,0xA7B7,0xA7B8,
0xA7D4,0xA7D5,0xA7D6,0xA7D7,0xA7D8,0xA7A1,0xA7A2,0xA7A3,
@@ -4518,7 +4518,7 @@ static uint16 tab_uni_ksc56015[]={
0xA2E4, 0, 0,0xA7E4,0xA7EE,0xA7E9};
/* page 6 0x4E00-0x947F */
-static uint16 tab_uni_ksc56016[]={
+static const uint16 tab_uni_ksc56016[]={
0xECE9,0xEFCB, 0,0xF6D2, 0, 0, 0,0xD8B2,
0xEDDB,0xDFB2,0xDFBE,0xF9BB, 0,0xDCF4, 0, 0,
0,0xF5E4, 0, 0,0xF3A6,0xDDE0,0xE1A6, 0,
@@ -6778,7 +6778,7 @@ static uint16 tab_uni_ksc56016[]={
};
/* page 7 0x9577-0x9F9C */
-static uint16 tab_uni_ksc56017[]={
+static const uint16 tab_uni_ksc56017[]={
0xEDFE, 0, 0, 0, 0, 0, 0, 0,
0,0xDAA6, 0, 0,0xE0EC, 0, 0, 0,
0, 0,0xF8CD, 0,0xCBD2, 0, 0, 0,
@@ -7106,7 +7106,7 @@ static uint16 tab_uni_ksc56017[]={
0, 0, 0, 0, 0,0xCFCF};
/* page 8 0xAC00-0xD7A3 */
-static uint16 tab_uni_ksc56018[]={
+static const uint16 tab_uni_ksc56018[]={
0xB0A1,0xB0A2,0x8141,0x8142,0xB0A3,0x8143,0x8144,0xB0A4,
0xB0A5,0xB0A6,0xB0A7,0x8145,0x8146,0x8147,0x8148,0x8149,
0xB0A8,0xB0A9,0xB0AA,0xB0AB,0xB0AC,0xB0AD,0xB0AE,0xB0AF,
@@ -8506,7 +8506,7 @@ static uint16 tab_uni_ksc56018[]={
0xC64F,0xC650,0xC651,0xC652};
/* page 9 0xF900-0xFA0B */
-static uint16 tab_uni_ksc56019[]={
+static const uint16 tab_uni_ksc56019[]={
0xCBD0,0xCBD6,0xCBE7,0xCDCF,0xCDE8,0xCEAD,0xCFFB,0xD0A2,
0xD0B8,0xD0D0,0xD0DD,0xD1D4,0xD1D5,0xD1D8,0xD1DB,0xD1DC,
0xD1DD,0xD1DE,0xD1DF,0xD1E0,0xD1E2,0xD1E3,0xD1E4,0xD1E5,
@@ -8543,7 +8543,7 @@ static uint16 tab_uni_ksc56019[]={
0xFAA1,0xFAA2,0xFAE6,0xFCA9};
/* page 10 0xFF01-0xFFE6 */
-static uint16 tab_uni_ksc560110[]={
+static const uint16 tab_uni_ksc560110[]={
0xA3A1,0xA3A2,0xA3A3,0xA3A4,0xA3A5,0xA3A6,0xA3A7,0xA3A8,
0xA3A9,0xA3AA,0xA3AB,0xA3AC,0xA3AD,0xA3AE,0xA3AF,0xA3B0,
0xA3B1,0xA3B2,0xA3B3,0xA3B4,0xA3B5,0xA3B6,0xA3B7,0xA3B8,
@@ -8737,7 +8737,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_euckr_korean_ci=
+struct charset_info_st my_charset_euckr_korean_ci=
{
19,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
@@ -8770,7 +8770,7 @@ CHARSET_INFO my_charset_euckr_korean_ci=
};
-CHARSET_INFO my_charset_euckr_bin=
+struct charset_info_st my_charset_euckr_bin=
{
85,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c
index b8b04dfca6b..119135c7515 100644
--- a/strings/ctype-eucjpms.c
+++ b/strings/ctype-eucjpms.c
@@ -33,7 +33,7 @@ ctype-ujis.c file.
#ifdef HAVE_CHARSET_eucjpms
-static uchar NEAR ctype_eucjpms[257] =
+static const uchar NEAR ctype_eucjpms[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -70,7 +70,7 @@ static uchar NEAR ctype_eucjpms[257] =
0020, 0020, 0020, 0020, 0020, 0020, 0020, 0000,
};
-static uchar NEAR to_lower_eucjpms[]=
+static const uchar NEAR to_lower_eucjpms[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -106,7 +106,7 @@ static uchar NEAR to_lower_eucjpms[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR to_upper_eucjpms[]=
+static const uchar NEAR to_upper_eucjpms[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -142,7 +142,7 @@ static uchar NEAR to_upper_eucjpms[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR sort_order_eucjpms[]=
+static const uchar NEAR sort_order_eucjpms[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -201,7 +201,7 @@ static uint mbcharlen_eucjpms(CHARSET_INFO *cs __attribute__((unused)),uint c)
}
-static uint16 tab_jisx0201_uni[256]={
+static const uint16 tab_jisx0201_uni[256]={
0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -270,7 +270,7 @@ my_wc_mb_jisx0201(CHARSET_INFO *cs __attribute__((unused)),
/* page 0 0x2121-0x217E */
-static uint16 tab_jisx0208_uni0[]={
+static const uint16 tab_jisx0208_uni0[]={
0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
@@ -285,7 +285,7 @@ static uint16 tab_jisx0208_uni0[]={
0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7};
/* page 1 0x2221-0x227E */
-static uint16 tab_jisx0208_uni1[]={
+static const uint16 tab_jisx0208_uni1[]={
0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x203B,
0x3012,0x2192,0x2190,0x2191,0x2193,0x3013, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -300,7 +300,7 @@ static uint16 tab_jisx0208_uni1[]={
0x00B6, 0, 0, 0, 0,0x25EF};
/* page 2 0x2330-0x237A */
-static uint16 tab_jisx0208_uni2[]={
+static const uint16 tab_jisx0208_uni2[]={
0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,
0xFF18,0xFF19, 0, 0, 0, 0, 0, 0,
0,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,
@@ -313,7 +313,7 @@ static uint16 tab_jisx0208_uni2[]={
0xFF58,0xFF59,0xFF5A};
/* page 3 0x2421-0x2473 */
-static uint16 tab_jisx0208_uni3[]={
+static const uint16 tab_jisx0208_uni3[]={
0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
@@ -327,7 +327,7 @@ static uint16 tab_jisx0208_uni3[]={
0x3091,0x3092,0x3093};
/* page 4 0x2521-0x2576 */
-static uint16 tab_jisx0208_uni4[]={
+static const uint16 tab_jisx0208_uni4[]={
0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
@@ -341,7 +341,7 @@ static uint16 tab_jisx0208_uni4[]={
0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6};
/* page 5 0x2621-0x2658 */
-static uint16 tab_jisx0208_uni5[]={
+static const uint16 tab_jisx0208_uni5[]={
0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
@@ -352,7 +352,7 @@ static uint16 tab_jisx0208_uni5[]={
};
/* page 6 0x2721-0x2771 */
-static uint16 tab_jisx0208_uni6[]={
+static const uint16 tab_jisx0208_uni6[]={
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,
0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,
@@ -366,7 +366,7 @@ static uint16 tab_jisx0208_uni6[]={
0x044F};
/* page 7 0x2821-0x2840 */
-static uint16 tab_jisx0208_uni7[]={
+static const uint16 tab_jisx0208_uni7[]={
0x2500,0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,
0x2524,0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,
0x2517,0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,
@@ -374,7 +374,7 @@ static uint16 tab_jisx0208_uni7[]={
};
/* page 8 0x3021-0x307E */
-static uint16 tab_jisx0208_uni8[]={
+static const uint16 tab_jisx0208_uni8[]={
0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
@@ -389,7 +389,7 @@ static uint16 tab_jisx0208_uni8[]={
0x59FB,0x5F15,0x98F2,0x6DEB,0x80E4,0x852D};
/* page 9 0x3121-0x317E */
-static uint16 tab_jisx0208_uni9[]={
+static const uint16 tab_jisx0208_uni9[]={
0x9662,0x9670,0x96A0,0x97FB,0x540B,0x53F3,0x5B87,0x70CF,
0x7FBD,0x8FC2,0x96E8,0x536F,0x9D5C,0x7ABA,0x4E11,0x7893,
0x81FC,0x6E26,0x5618,0x5504,0x6B1D,0x851A,0x9C3B,0x59E5,
@@ -404,7 +404,7 @@ static uint16 tab_jisx0208_uni9[]={
0x7525,0x51F9,0x592E,0x5965,0x5F80,0x5FDC};
/* page 10 0x3221-0x327E */
-static uint16 tab_jisx0208_uni10[]={
+static const uint16 tab_jisx0208_uni10[]={
0x62BC,0x65FA,0x6A2A,0x6B27,0x6BB4,0x738B,0x7FC1,0x8956,
0x9D2C,0x9D0E,0x9EC4,0x5CA1,0x6C96,0x837B,0x5104,0x5C4B,
0x61B6,0x81C6,0x6876,0x7261,0x4E59,0x4FFA,0x5378,0x6069,
@@ -419,7 +419,7 @@ static uint16 tab_jisx0208_uni10[]={
0x6094,0x6062,0x61D0,0x6212,0x62D0,0x6539};
/* page 11 0x3321-0x337E */
-static uint16 tab_jisx0208_uni11[]={
+static const uint16 tab_jisx0208_uni11[]={
0x9B41,0x6666,0x68B0,0x6D77,0x7070,0x754C,0x7686,0x7D75,
0x82A5,0x87F9,0x958B,0x968E,0x8C9D,0x51F1,0x52BE,0x5916,
0x54B3,0x5BB3,0x5D16,0x6168,0x6982,0x6DAF,0x788D,0x84CB,
@@ -434,7 +434,7 @@ static uint16 tab_jisx0208_uni11[]={
0x938C,0x565B,0x9D28,0x6822,0x8305,0x8431};
/* page 12 0x3421-0x347E */
-static uint16 tab_jisx0208_uni12[]={
+static const uint16 tab_jisx0208_uni12[]={
0x7CA5,0x5208,0x82C5,0x74E6,0x4E7E,0x4F83,0x51A0,0x5BD2,
0x520A,0x52D8,0x52E7,0x5DFB,0x559A,0x582A,0x59E6,0x5B8C,
0x5B98,0x5BDB,0x5E72,0x5E79,0x60A3,0x611F,0x6163,0x61BE,
@@ -449,7 +449,7 @@ static uint16 tab_jisx0208_uni12[]={
0x673A,0x65D7,0x65E2,0x671F,0x68CB,0x68C4};
/* page 13 0x3521-0x357E */
-static uint16 tab_jisx0208_uni13[]={
+static const uint16 tab_jisx0208_uni13[]={
0x6A5F,0x5E30,0x6BC5,0x6C17,0x6C7D,0x757F,0x7948,0x5B63,
0x7A00,0x7D00,0x5FBD,0x898F,0x8A18,0x8CB4,0x8D77,0x8ECC,
0x8F1D,0x98E2,0x9A0E,0x9B3C,0x4E80,0x507D,0x5100,0x5993,
@@ -464,7 +464,7 @@ static uint16 tab_jisx0208_uni13[]={
0x6F01,0x79A6,0x9B5A,0x4EA8,0x4EAB,0x4EAC};
/* page 14 0x3621-0x367E */
-static uint16 tab_jisx0208_uni14[]={
+static const uint16 tab_jisx0208_uni14[]={
0x4F9B,0x4FA0,0x50D1,0x5147,0x7AF6,0x5171,0x51F6,0x5354,
0x5321,0x537F,0x53EB,0x55AC,0x5883,0x5CE1,0x5F37,0x5F4A,
0x602F,0x6050,0x606D,0x631F,0x6559,0x6A4B,0x6CC1,0x72C2,
@@ -479,7 +479,7 @@ static uint16 tab_jisx0208_uni14[]={
0x9685,0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48};
/* page 15 0x3721-0x377E */
-static uint16 tab_jisx0208_uni15[]={
+static const uint16 tab_jisx0208_uni15[]={
0x6398,0x7A9F,0x6C93,0x9774,0x8F61,0x7AAA,0x718A,0x9688,
0x7C82,0x6817,0x7E70,0x6851,0x936C,0x52F2,0x541B,0x85AB,
0x8A13,0x7FA4,0x8ECD,0x90E1,0x5366,0x8888,0x7941,0x4FC2,
@@ -494,7 +494,7 @@ static uint16 tab_jisx0208_uni15[]={
0x5ACC,0x5EFA,0x61B2,0x61F8,0x62F3,0x6372};
/* page 16 0x3821-0x387E */
-static uint16 tab_jisx0208_uni16[]={
+static const uint16 tab_jisx0208_uni16[]={
0x691C,0x6A29,0x727D,0x72AC,0x732E,0x7814,0x786F,0x7D79,
0x770C,0x80A9,0x898B,0x8B19,0x8CE2,0x8ED2,0x9063,0x9375,
0x967A,0x9855,0x9A13,0x9E78,0x5143,0x539F,0x53B3,0x5E7B,
@@ -509,7 +509,7 @@ static uint16 tab_jisx0208_uni16[]={
0x529F,0x52B9,0x52FE,0x539A,0x53E3,0x5411};
/* page 17 0x3921-0x397E */
-static uint16 tab_jisx0208_uni17[]={
+static const uint16 tab_jisx0208_uni17[]={
0x540E,0x5589,0x5751,0x57A2,0x597D,0x5B54,0x5B5D,0x5B8F,
0x5DE5,0x5DE7,0x5DF7,0x5E78,0x5E83,0x5E9A,0x5EB7,0x5F18,
0x6052,0x614C,0x6297,0x62D8,0x63A7,0x653B,0x6602,0x6643,
@@ -524,7 +524,7 @@ static uint16 tab_jisx0208_uni17[]={
0x7511,0x5FFD,0x60DA,0x9AA8,0x72DB,0x8FBC};
/* page 18 0x3A21-0x3A7E */
-static uint16 tab_jisx0208_uni18[]={
+static const uint16 tab_jisx0208_uni18[]={
0x6B64,0x9803,0x4ECA,0x56F0,0x5764,0x58BE,0x5A5A,0x6068,
0x61C7,0x660F,0x6606,0x6839,0x68B1,0x6DF7,0x75D5,0x7D3A,
0x826E,0x9B42,0x4E9B,0x4F50,0x53C9,0x5506,0x5D6F,0x5DE6,
@@ -539,7 +539,7 @@ static uint16 tab_jisx0208_uni18[]={
0x685C,0x9BAD,0x7B39,0x5319,0x518A,0x5237};
/* page 19 0x3B21-0x3B7E */
-static uint16 tab_jisx0208_uni19[]={
+static const uint16 tab_jisx0208_uni19[]={
0x5BDF,0x62F6,0x64AE,0x64E6,0x672D,0x6BBA,0x85A9,0x96D1,
0x7690,0x9BD6,0x634C,0x9306,0x9BAB,0x76BF,0x6652,0x4E09,
0x5098,0x53C2,0x5C71,0x60E8,0x6492,0x6563,0x685F,0x71E6,
@@ -554,7 +554,7 @@ static uint16 tab_jisx0208_uni19[]={
0x5150,0x5B57,0x5BFA,0x6148,0x6301,0x6642};
/* page 20 0x3C21-0x3C7E */
-static uint16 tab_jisx0208_uni20[]={
+static const uint16 tab_jisx0208_uni20[]={
0x6B21,0x6ECB,0x6CBB,0x723E,0x74BD,0x75D4,0x78C1,0x793A,
0x800C,0x8033,0x81EA,0x8494,0x8F9E,0x6C50,0x9E7F,0x5F0F,
0x8B58,0x9D2B,0x7AFA,0x8EF8,0x5B8D,0x96EB,0x4E03,0x53F1,
@@ -569,7 +569,7 @@ static uint16 tab_jisx0208_uni20[]={
0x6A39,0x7DAC,0x9700,0x56DA,0x53CE,0x5468};
/* page 21 0x3D21-0x3D7E */
-static uint16 tab_jisx0208_uni21[]={
+static const uint16 tab_jisx0208_uni21[]={
0x5B97,0x5C31,0x5DDE,0x4FEE,0x6101,0x62FE,0x6D32,0x79C0,
0x79CB,0x7D42,0x7E4D,0x7FD2,0x81ED,0x821F,0x8490,0x8846,
0x8972,0x8B90,0x8E74,0x8F2F,0x9031,0x914B,0x916C,0x96C6,
@@ -584,7 +584,7 @@ static uint16 tab_jisx0208_uni21[]={
0x5F90,0x6055,0x92E4,0x9664,0x50B7,0x511F};
/* page 22 0x3E21-0x3E7E */
-static uint16 tab_jisx0208_uni22[]={
+static const uint16 tab_jisx0208_uni22[]={
0x52DD,0x5320,0x5347,0x53EC,0x54E8,0x5546,0x5531,0x5617,
0x5968,0x59BE,0x5A3C,0x5BB5,0x5C06,0x5C0F,0x5C11,0x5C1A,
0x5E84,0x5E8A,0x5EE0,0x5F70,0x627F,0x6284,0x62DB,0x638C,
@@ -599,7 +599,7 @@ static uint16 tab_jisx0208_uni22[]={
0x8B72,0x91B8,0x9320,0x5631,0x57F4,0x98FE};
/* page 23 0x3F21-0x3F7E */
-static uint16 tab_jisx0208_uni23[]={
+static const uint16 tab_jisx0208_uni23[]={
0x62ED,0x690D,0x6B96,0x71ED,0x7E54,0x8077,0x8272,0x89E6,
0x98DF,0x8755,0x8FB1,0x5C3B,0x4F38,0x4FE1,0x4FB5,0x5507,
0x5A20,0x5BDD,0x5BE9,0x5FC3,0x614E,0x632F,0x65B0,0x664B,
@@ -614,7 +614,7 @@ static uint16 tab_jisx0208_uni23[]={
0x6749,0x6919,0x83C5,0x9817,0x96C0,0x88FE};
/* page 24 0x4021-0x407E */
-static uint16 tab_jisx0208_uni24[]={
+static const uint16 tab_jisx0208_uni24[]={
0x6F84,0x647A,0x5BF8,0x4E16,0x702C,0x755D,0x662F,0x51C4,
0x5236,0x52E2,0x59D3,0x5F81,0x6027,0x6210,0x653F,0x6574,
0x661F,0x6674,0x68F2,0x6816,0x6B63,0x6E05,0x7272,0x751F,
@@ -629,7 +629,7 @@ static uint16 tab_jisx0208_uni24[]={
0x714E,0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA};
/* page 25 0x4121-0x417E */
-static uint16 tab_jisx0208_uni25[]={
+static const uint16 tab_jisx0208_uni25[]={
0x7E4A,0x7FA8,0x817A,0x821B,0x8239,0x85A6,0x8A6E,0x8CCE,
0x8DF5,0x9078,0x9077,0x92AD,0x9291,0x9583,0x9BAE,0x524D,
0x5584,0x6F38,0x7136,0x5168,0x7985,0x7E55,0x81B3,0x7CCE,
@@ -644,7 +644,7 @@ static uint16 tab_jisx0208_uni25[]={
0x9397,0x971C,0x9A12,0x50CF,0x5897,0x618E};
/* page 26 0x4221-0x427E */
-static uint16 tab_jisx0208_uni26[]={
+static const uint16 tab_jisx0208_uni26[]={
0x81D3,0x8535,0x8D08,0x9020,0x4FC3,0x5074,0x5247,0x5373,
0x606F,0x6349,0x675F,0x6E2C,0x8DB3,0x901F,0x4FD7,0x5C5E,
0x8CCA,0x65CF,0x7D9A,0x5352,0x8896,0x5176,0x63C3,0x5B58,
@@ -659,7 +659,7 @@ static uint16 tab_jisx0208_uni26[]={
0x6FC1,0x8AFE,0x8338,0x51E7,0x86F8,0x53EA};
/* page 27 0x4321-0x437E */
-static uint16 tab_jisx0208_uni27[]={
+static const uint16 tab_jisx0208_uni27[]={
0x53E9,0x4F46,0x9054,0x8FB0,0x596A,0x8131,0x5DFD,0x7AEA,
0x8FBF,0x68DA,0x8C37,0x72F8,0x9C48,0x6A3D,0x8AB0,0x4E39,
0x5358,0x5606,0x5766,0x62C5,0x63A2,0x65E6,0x6B4E,0x6DE1,
@@ -674,7 +674,7 @@ static uint16 tab_jisx0208_uni27[]={
0x8CAF,0x4E01,0x5146,0x51CB,0x558B,0x5BF5};
/* page 28 0x4421-0x447E */
-static uint16 tab_jisx0208_uni28[]={
+static const uint16 tab_jisx0208_uni28[]={
0x5E16,0x5E33,0x5E81,0x5F14,0x5F35,0x5F6B,0x5FB4,0x61F2,
0x6311,0x66A2,0x671D,0x6F6E,0x7252,0x753A,0x773A,0x8074,
0x8139,0x8178,0x8776,0x8ABF,0x8ADC,0x8D85,0x8DF3,0x929A,
@@ -689,7 +689,7 @@ static uint16 tab_jisx0208_uni28[]={
0x7DE0,0x8247,0x8A02,0x8AE6,0x8E44,0x9013};
/* page 29 0x4521-0x457E */
-static uint16 tab_jisx0208_uni29[]={
+static const uint16 tab_jisx0208_uni29[]={
0x90B8,0x912D,0x91D8,0x9F0E,0x6CE5,0x6458,0x64E2,0x6575,
0x6EF4,0x7684,0x7B1B,0x9069,0x93D1,0x6EBA,0x54F2,0x5FB9,
0x64A4,0x8F4D,0x8FED,0x9244,0x5178,0x586B,0x5929,0x5C55,
@@ -704,7 +704,7 @@ static uint16 tab_jisx0208_uni29[]={
0x7B49,0x7B54,0x7B52,0x7CD6,0x7D71,0x5230};
/* page 30 0x4621-0x467E */
-static uint16 tab_jisx0208_uni30[]={
+static const uint16 tab_jisx0208_uni30[]={
0x8463,0x8569,0x85E4,0x8A0E,0x8B04,0x8C46,0x8E0F,0x9003,
0x900F,0x9419,0x9676,0x982D,0x9A30,0x95D8,0x50CD,0x52D5,
0x540C,0x5802,0x5C0E,0x61A7,0x649E,0x6D1E,0x77B3,0x7AE5,
@@ -719,7 +719,7 @@ static uint16 tab_jisx0208_uni30[]={
0x8089,0x8679,0x5EFF,0x65E5,0x4E73,0x5165};
/* page 31 0x4721-0x477E */
-static uint16 tab_jisx0208_uni31[]={
+static const uint16 tab_jisx0208_uni31[]={
0x5982,0x5C3F,0x97EE,0x4EFB,0x598A,0x5FCD,0x8A8D,0x6FE1,
0x79B0,0x7962,0x5BE7,0x8471,0x732B,0x71B1,0x5E74,0x5FF5,
0x637B,0x649A,0x71C3,0x7C98,0x4E43,0x5EFC,0x4E4B,0x57DC,
@@ -734,7 +734,7 @@ static uint16 tab_jisx0208_uni31[]={
0x6F20,0x7206,0x7E1B,0x83AB,0x99C1,0x9EA6};
/* page 32 0x4821-0x487E */
-static uint16 tab_jisx0208_uni32[]={
+static const uint16 tab_jisx0208_uni32[]={
0x51FD,0x7BB1,0x7872,0x7BB8,0x8087,0x7B48,0x6AE8,0x5E61,
0x808C,0x7551,0x7560,0x516B,0x9262,0x6E8C,0x767A,0x9197,
0x9AEA,0x4F10,0x7F70,0x629C,0x7B4F,0x95A5,0x9CE9,0x567A,
@@ -749,7 +749,7 @@ static uint16 tab_jisx0208_uni32[]={
0x5FAE,0x6787,0x6BD8,0x7435,0x7709,0x7F8E};
/* page 33 0x4921-0x497E */
-static uint16 tab_jisx0208_uni33[]={
+static const uint16 tab_jisx0208_uni33[]={
0x9F3B,0x67CA,0x7A17,0x5339,0x758B,0x9AED,0x5F66,0x819D,
0x83F1,0x8098,0x5F3C,0x5FC5,0x7562,0x7B46,0x903C,0x6867,
0x59EB,0x5A9B,0x7D10,0x767E,0x8B2C,0x4FF5,0x5F6A,0x6A19,
@@ -764,7 +764,7 @@ static uint16 tab_jisx0208_uni33[]={
0x8557,0x4F0F,0x526F,0x5FA9,0x5E45,0x670D};
/* page 34 0x4A21-0x4A7E */
-static uint16 tab_jisx0208_uni34[]={
+static const uint16 tab_jisx0208_uni34[]={
0x798F,0x8179,0x8907,0x8986,0x6DF5,0x5F17,0x6255,0x6CB8,
0x4ECF,0x7269,0x9B92,0x5206,0x543B,0x5674,0x58B3,0x61A4,
0x626E,0x711A,0x596E,0x7C89,0x7CDE,0x7D1B,0x96F0,0x6587,
@@ -779,7 +779,7 @@ static uint16 tab_jisx0208_uni34[]={
0x5E96,0x62B1,0x6367,0x653E,0x65B9,0x670B};
/* page 35 0x4B21-0x4B7E */
-static uint16 tab_jisx0208_uni35[]={
+static const uint16 tab_jisx0208_uni35[]={
0x6CD5,0x6CE1,0x70F9,0x7832,0x7E2B,0x80DE,0x82B3,0x840C,
0x84EC,0x8702,0x8912,0x8A2A,0x8C4A,0x90A6,0x92D2,0x98FD,
0x9CF3,0x9D6C,0x4E4F,0x4EA1,0x508D,0x5256,0x574A,0x59A8,
@@ -794,7 +794,7 @@ static uint16 tab_jisx0208_uni35[]={
0x4FAD,0x7E6D,0x9EBF,0x4E07,0x6162,0x6E80};
/* page 36 0x4C21-0x4C7E */
-static uint16 tab_jisx0208_uni36[]={
+static const uint16 tab_jisx0208_uni36[]={
0x6F2B,0x8513,0x5473,0x672A,0x9B45,0x5DF3,0x7B95,0x5CAC,
0x5BC6,0x871C,0x6E4A,0x84D1,0x7A14,0x8108,0x5999,0x7C8D,
0x6C11,0x7720,0x52D9,0x5922,0x7121,0x725F,0x77DB,0x9727,
@@ -809,7 +809,7 @@ static uint16 tab_jisx0208_uni36[]={
0x85AE,0x9453,0x6109,0x6108,0x6CB9,0x7652};
/* page 37 0x4D21-0x4D7E */
-static uint16 tab_jisx0208_uni37[]={
+static const uint16 tab_jisx0208_uni37[]={
0x8AED,0x8F38,0x552F,0x4F51,0x512A,0x52C7,0x53CB,0x5BA5,
0x5E7D,0x60A0,0x6182,0x63D6,0x6709,0x67DA,0x6E67,0x6D8C,
0x7336,0x7337,0x7531,0x7950,0x88D5,0x8A98,0x904A,0x9091,
@@ -824,7 +824,7 @@ static uint16 tab_jisx0208_uni37[]={
0x540F,0x5C65,0x674E,0x68A8,0x7406,0x7483};
/* page 38 0x4E21-0x4E7E */
-static uint16 tab_jisx0208_uni38[]={
+static const uint16 tab_jisx0208_uni38[]={
0x75E2,0x88CF,0x88E1,0x91CC,0x96E2,0x9678,0x5F8B,0x7387,
0x7ACB,0x844E,0x63A0,0x7565,0x5289,0x6D41,0x6E9C,0x7409,
0x7559,0x786B,0x7C92,0x9686,0x7ADC,0x9F8D,0x4FB6,0x616E,
@@ -839,7 +839,7 @@ static uint16 tab_jisx0208_uni38[]={
0x6190,0x6F23,0x7149,0x7C3E,0x7DF4,0x806F};
/* page 39 0x4F21-0x4F53 */
-static uint16 tab_jisx0208_uni39[]={
+static const uint16 tab_jisx0208_uni39[]={
0x84EE,0x9023,0x932C,0x5442,0x9B6F,0x6AD3,0x7089,0x8CC2,
0x8DEF,0x9732,0x52B4,0x5A41,0x5ECA,0x5F04,0x6717,0x697C,
0x6994,0x6D6A,0x6F0F,0x7262,0x72FC,0x7BED,0x8001,0x807E,
@@ -849,7 +849,7 @@ static uint16 tab_jisx0208_uni39[]={
0x6E7E,0x7897,0x8155};
/* page 40 0x5021-0x507E */
-static uint16 tab_jisx0208_uni40[]={
+static const uint16 tab_jisx0208_uni40[]={
0x5F0C,0x4E10,0x4E15,0x4E2A,0x4E31,0x4E36,0x4E3C,0x4E3F,
0x4E42,0x4E56,0x4E58,0x4E82,0x4E85,0x8C6B,0x4E8A,0x8212,
0x5F0D,0x4E8E,0x4E9E,0x4E9F,0x4EA0,0x4EA2,0x4EB0,0x4EB3,
@@ -864,7 +864,7 @@ static uint16 tab_jisx0208_uni40[]={
0x5078,0x5080,0x509A,0x5085,0x50B4,0x50B2};
/* page 41 0x5121-0x517E */
-static uint16 tab_jisx0208_uni41[]={
+static const uint16 tab_jisx0208_uni41[]={
0x50C9,0x50CA,0x50B3,0x50C2,0x50D6,0x50DE,0x50E5,0x50ED,
0x50E3,0x50EE,0x50F9,0x50F5,0x5109,0x5101,0x5102,0x5116,
0x5115,0x5114,0x511A,0x5121,0x513A,0x5137,0x513C,0x513B,
@@ -879,7 +879,7 @@ static uint16 tab_jisx0208_uni41[]={
0x5294,0x5292,0x5271,0x5288,0x5291,0x8FA8};
/* page 42 0x5221-0x527E */
-static uint16 tab_jisx0208_uni42[]={
+static const uint16 tab_jisx0208_uni42[]={
0x8FA7,0x52AC,0x52AD,0x52BC,0x52B5,0x52C1,0x52CD,0x52D7,
0x52DE,0x52E3,0x52E6,0x98ED,0x52E0,0x52F3,0x52F5,0x52F8,
0x52F9,0x5306,0x5308,0x7538,0x530D,0x5310,0x530F,0x5315,
@@ -894,7 +894,7 @@ static uint16 tab_jisx0208_uni42[]={
0x54B8,0x54A5,0x54AC,0x54C4,0x54C8,0x54A8};
/* page 43 0x5321-0x537E */
-static uint16 tab_jisx0208_uni43[]={
+static const uint16 tab_jisx0208_uni43[]={
0x54AB,0x54C2,0x54A4,0x54BE,0x54BC,0x54D8,0x54E5,0x54E6,
0x550F,0x5514,0x54FD,0x54EE,0x54ED,0x54FA,0x54E2,0x5539,
0x5540,0x5563,0x554C,0x552E,0x555C,0x5545,0x5556,0x5557,
@@ -909,7 +909,7 @@ static uint16 tab_jisx0208_uni43[]={
0x56EE,0x56F9,0x5700,0x56FF,0x5704,0x5709};
/* page 44 0x5421-0x547E */
-static uint16 tab_jisx0208_uni44[]={
+static const uint16 tab_jisx0208_uni44[]={
0x5708,0x570B,0x570D,0x5713,0x5718,0x5716,0x55C7,0x571C,
0x5726,0x5737,0x5738,0x574E,0x573B,0x5740,0x574F,0x5769,
0x57C0,0x5788,0x5761,0x577F,0x5789,0x5793,0x57A0,0x57B3,
@@ -924,7 +924,7 @@ static uint16 tab_jisx0208_uni44[]={
0x5958,0x5962,0x5960,0x5967,0x596C,0x5969};
/* page 45 0x5521-0x557E */
-static uint16 tab_jisx0208_uni45[]={
+static const uint16 tab_jisx0208_uni45[]={
0x5978,0x5981,0x599D,0x4F5E,0x4FAB,0x59A3,0x59B2,0x59C6,
0x59E8,0x59DC,0x598D,0x59D9,0x59DA,0x5A25,0x5A1F,0x5A11,
0x5A1C,0x5A09,0x5A1A,0x5A40,0x5A6C,0x5A49,0x5A35,0x5A36,
@@ -939,7 +939,7 @@ static uint16 tab_jisx0208_uni45[]={
0x5C38,0x5C39,0x5C41,0x5C46,0x5C4E,0x5C53};
/* page 46 0x5621-0x567E */
-static uint16 tab_jisx0208_uni46[]={
+static const uint16 tab_jisx0208_uni46[]={
0x5C50,0x5C4F,0x5B71,0x5C6C,0x5C6E,0x4E62,0x5C76,0x5C79,
0x5C8C,0x5C91,0x5C94,0x599B,0x5CAB,0x5CBB,0x5CB6,0x5CBC,
0x5CB7,0x5CC5,0x5CBE,0x5CC7,0x5CD9,0x5CE9,0x5CFD,0x5CFA,
@@ -954,7 +954,7 @@ static uint16 tab_jisx0208_uni46[]={
0x5EA0,0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF};
/* page 47 0x5721-0x577E */
-static uint16 tab_jisx0208_uni47[]={
+static const uint16 tab_jisx0208_uni47[]={
0x5ED6,0x5EE3,0x5EDD,0x5EDA,0x5EDB,0x5EE2,0x5EE1,0x5EE8,
0x5EE9,0x5EEC,0x5EF1,0x5EF3,0x5EF0,0x5EF4,0x5EF8,0x5EFE,
0x5F03,0x5F09,0x5F5D,0x5F5C,0x5F0B,0x5F11,0x5F16,0x5F29,
@@ -969,7 +969,7 @@ static uint16 tab_jisx0208_uni47[]={
0x6059,0x6081,0x608D,0x60E7,0x6083,0x609A};
/* page 48 0x5821-0x587E */
-static uint16 tab_jisx0208_uni48[]={
+static const uint16 tab_jisx0208_uni48[]={
0x6084,0x609B,0x6096,0x6097,0x6092,0x60A7,0x608B,0x60E1,
0x60B8,0x60E0,0x60D3,0x60B4,0x5FF0,0x60BD,0x60C6,0x60B5,
0x60D8,0x614D,0x6115,0x6106,0x60F6,0x60F7,0x6100,0x60F4,
@@ -984,7 +984,7 @@ static uint16 tab_jisx0208_uni48[]={
0x6208,0x6209,0x620D,0x620C,0x6214,0x621B};
/* page 49 0x5921-0x597E */
-static uint16 tab_jisx0208_uni49[]={
+static const uint16 tab_jisx0208_uni49[]={
0x621E,0x6221,0x622A,0x622E,0x6230,0x6232,0x6233,0x6241,
0x624E,0x625E,0x6263,0x625B,0x6260,0x6268,0x627C,0x6282,
0x6289,0x627E,0x6292,0x6293,0x6296,0x62D4,0x6283,0x6294,
@@ -999,7 +999,7 @@ static uint16 tab_jisx0208_uni49[]={
0x6495,0x6493,0x64A5,0x64A9,0x6488,0x64BC};
/* page 50 0x5A21-0x5A7E */
-static uint16 tab_jisx0208_uni50[]={
+static const uint16 tab_jisx0208_uni50[]={
0x64DA,0x64D2,0x64C5,0x64C7,0x64BB,0x64D8,0x64C2,0x64F1,
0x64E7,0x8209,0x64E0,0x64E1,0x62AC,0x64E3,0x64EF,0x652C,
0x64F6,0x64F4,0x64F2,0x64FA,0x6500,0x64FD,0x6518,0x651C,
@@ -1014,7 +1014,7 @@ static uint16 tab_jisx0208_uni50[]={
0x669D,0x66C1,0x66B9,0x66C9,0x66BE,0x66BC};
/* page 51 0x5B21-0x5B7E */
-static uint16 tab_jisx0208_uni51[]={
+static const uint16 tab_jisx0208_uni51[]={
0x66C4,0x66B8,0x66D6,0x66DA,0x66E0,0x663F,0x66E6,0x66E9,
0x66F0,0x66F5,0x66F7,0x670F,0x6716,0x671E,0x6726,0x6727,
0x9738,0x672E,0x673F,0x6736,0x6741,0x6738,0x6737,0x6746,
@@ -1029,7 +1029,7 @@ static uint16 tab_jisx0208_uni51[]={
0x68D8,0x6922,0x6926,0x68E1,0x690C,0x68CD};
/* page 52 0x5C21-0x5C7E */
-static uint16 tab_jisx0208_uni52[]={
+static const uint16 tab_jisx0208_uni52[]={
0x68D4,0x68E7,0x68D5,0x6936,0x6912,0x6904,0x68D7,0x68E3,
0x6925,0x68F9,0x68E0,0x68EF,0x6928,0x692A,0x691A,0x6923,
0x6921,0x68C6,0x6979,0x6977,0x695C,0x6978,0x696B,0x6954,
@@ -1044,7 +1044,7 @@ static uint16 tab_jisx0208_uni52[]={
0x6A90,0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3};
/* page 53 0x5D21-0x5D7E */
-static uint16 tab_jisx0208_uni53[]={
+static const uint16 tab_jisx0208_uni53[]={
0x6A97,0x8617,0x6ABB,0x6AC3,0x6AC2,0x6AB8,0x6AB3,0x6AAC,
0x6ADE,0x6AD1,0x6ADF,0x6AAA,0x6ADA,0x6AEA,0x6AFB,0x6B05,
0x8616,0x6AFA,0x6B12,0x6B16,0x9B31,0x6B1F,0x6B38,0x6B37,
@@ -1059,7 +1059,7 @@ static uint16 tab_jisx0208_uni53[]={
0x6CD7,0x6CC5,0x6CDD,0x6CAE,0x6CB1,0x6CBE};
/* page 54 0x5E21-0x5E7E */
-static uint16 tab_jisx0208_uni54[]={
+static const uint16 tab_jisx0208_uni54[]={
0x6CBA,0x6CDB,0x6CEF,0x6CD9,0x6CEA,0x6D1F,0x884D,0x6D36,
0x6D2B,0x6D3D,0x6D38,0x6D19,0x6D35,0x6D33,0x6D12,0x6D0C,
0x6D63,0x6D93,0x6D64,0x6D5A,0x6D79,0x6D59,0x6D8E,0x6D95,
@@ -1074,7 +1074,7 @@ static uint16 tab_jisx0208_uni54[]={
0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
/* page 55 0x5F21-0x5F7E */
-static uint16 tab_jisx0208_uni55[]={
+static const uint16 tab_jisx0208_uni55[]={
0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
@@ -1089,7 +1089,7 @@ static uint16 tab_jisx0208_uni55[]={
0x71CE,0x71E0,0x71EC,0x71E7,0x71F5,0x71FC};
/* page 56 0x6021-0x607E */
-static uint16 tab_jisx0208_uni56[]={
+static const uint16 tab_jisx0208_uni56[]={
0x71F9,0x71FF,0x720D,0x7210,0x721B,0x7228,0x722D,0x722C,
0x7230,0x7232,0x723B,0x723C,0x723F,0x7240,0x7246,0x724B,
0x7258,0x7274,0x727E,0x7282,0x7281,0x7287,0x7292,0x7296,
@@ -1104,7 +1104,7 @@ static uint16 tab_jisx0208_uni56[]={
0x749E,0x74A7,0x74CA,0x74CF,0x74D4,0x73F1};
/* page 57 0x6121-0x617E */
-static uint16 tab_jisx0208_uni57[]={
+static const uint16 tab_jisx0208_uni57[]={
0x74E0,0x74E3,0x74E7,0x74E9,0x74EE,0x74F2,0x74F0,0x74F1,
0x74F8,0x74F7,0x7504,0x7503,0x7505,0x750C,0x750E,0x750D,
0x7515,0x7513,0x751E,0x7526,0x752C,0x753C,0x7544,0x754D,
@@ -1119,7 +1119,7 @@ static uint16 tab_jisx0208_uni57[]={
0x7668,0x7669,0x766A,0x7667,0x766C,0x7670};
/* page 58 0x6221-0x627E */
-static uint16 tab_jisx0208_uni58[]={
+static const uint16 tab_jisx0208_uni58[]={
0x7672,0x7676,0x7678,0x767C,0x7680,0x7683,0x7688,0x768B,
0x768E,0x7696,0x7693,0x7699,0x769A,0x76B0,0x76B4,0x76B8,
0x76B9,0x76BA,0x76C2,0x76CD,0x76D6,0x76D2,0x76DE,0x76E1,
@@ -1134,7 +1134,7 @@ static uint16 tab_jisx0208_uni58[]={
0x78D4,0x78BE,0x78BC,0x78C5,0x78CA,0x78EC};
/* page 59 0x6321-0x637E */
-static uint16 tab_jisx0208_uni59[]={
+static const uint16 tab_jisx0208_uni59[]={
0x78E7,0x78DA,0x78FD,0x78F4,0x7907,0x7912,0x7911,0x7919,
0x792C,0x792B,0x7940,0x7960,0x7957,0x795F,0x795A,0x7955,
0x7953,0x797A,0x797F,0x798A,0x799D,0x79A7,0x9F4B,0x79AA,
@@ -1149,7 +1149,7 @@ static uint16 tab_jisx0208_uni59[]={
0x7B19,0x7B1E,0x7B35,0x7B28,0x7B36,0x7B50};
/* page 60 0x6421-0x647E */
-static uint16 tab_jisx0208_uni60[]={
+static const uint16 tab_jisx0208_uni60[]={
0x7B7A,0x7B04,0x7B4D,0x7B0B,0x7B4C,0x7B45,0x7B75,0x7B65,
0x7B74,0x7B67,0x7B70,0x7B71,0x7B6C,0x7B6E,0x7B9D,0x7B98,
0x7B9F,0x7B8D,0x7B9C,0x7B9A,0x7B8B,0x7B92,0x7B8F,0x7B5D,
@@ -1164,7 +1164,7 @@ static uint16 tab_jisx0208_uni60[]={
0x7CEF,0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06};
/* page 61 0x6521-0x657E */
-static uint16 tab_jisx0208_uni61[]={
+static const uint16 tab_jisx0208_uni61[]={
0x7D02,0x7D1C,0x7D15,0x7D0A,0x7D45,0x7D4B,0x7D2E,0x7D32,
0x7D3F,0x7D35,0x7D46,0x7D73,0x7D56,0x7D4E,0x7D72,0x7D68,
0x7D6E,0x7D4F,0x7D63,0x7D93,0x7D89,0x7D5B,0x7D8F,0x7D7D,
@@ -1179,7 +1179,7 @@ static uint16 tab_jisx0208_uni61[]={
0x7E96,0x7E8E,0x7E9B,0x7E9C,0x7F38,0x7F3A};
/* page 62 0x6621-0x667E */
-static uint16 tab_jisx0208_uni62[]={
+static const uint16 tab_jisx0208_uni62[]={
0x7F45,0x7F4C,0x7F4D,0x7F4E,0x7F50,0x7F51,0x7F55,0x7F54,
0x7F58,0x7F5F,0x7F60,0x7F68,0x7F69,0x7F67,0x7F78,0x7F82,
0x7F86,0x7F83,0x7F88,0x7F87,0x7F8C,0x7F94,0x7F9E,0x7F9D,
@@ -1194,7 +1194,7 @@ static uint16 tab_jisx0208_uni62[]={
0x80F1,0x811B,0x8129,0x8123,0x812F,0x814B};
/* page 63 0x6721-0x677E */
-static uint16 tab_jisx0208_uni63[]={
+static const uint16 tab_jisx0208_uni63[]={
0x968B,0x8146,0x813E,0x8153,0x8151,0x80FC,0x8171,0x816E,
0x8165,0x8166,0x8174,0x8183,0x8188,0x818A,0x8180,0x8182,
0x81A0,0x8195,0x81A4,0x81A3,0x815F,0x8193,0x81A9,0x81B0,
@@ -1209,7 +1209,7 @@ static uint16 tab_jisx0208_uni63[]={
0x82F9,0x82DE,0x8306,0x82DC,0x8309,0x82D9};
/* page 64 0x6821-0x687E */
-static uint16 tab_jisx0208_uni64[]={
+static const uint16 tab_jisx0208_uni64[]={
0x8335,0x8334,0x8316,0x8332,0x8331,0x8340,0x8339,0x8350,
0x8345,0x832F,0x832B,0x8317,0x8318,0x8385,0x839A,0x83AA,
0x839F,0x83A2,0x8396,0x8323,0x838E,0x8387,0x838A,0x837C,
@@ -1224,7 +1224,7 @@ static uint16 tab_jisx0208_uni64[]={
0x8514,0x84FC,0x8540,0x8563,0x8558,0x8548};
/* page 65 0x6921-0x697E */
-static uint16 tab_jisx0208_uni65[]={
+static const uint16 tab_jisx0208_uni65[]={
0x8541,0x8602,0x854B,0x8555,0x8580,0x85A4,0x8588,0x8591,
0x858A,0x85A8,0x856D,0x8594,0x859B,0x85EA,0x8587,0x859C,
0x8577,0x857E,0x8590,0x85C9,0x85BA,0x85CF,0x85B9,0x85D0,
@@ -1239,7 +1239,7 @@ static uint16 tab_jisx0208_uni65[]={
0x874E,0x8774,0x8757,0x8768,0x876E,0x8759};
/* page 66 0x6A21-0x6A7E */
-static uint16 tab_jisx0208_uni66[]={
+static const uint16 tab_jisx0208_uni66[]={
0x8753,0x8763,0x876A,0x8805,0x87A2,0x879F,0x8782,0x87AF,
0x87CB,0x87BD,0x87C0,0x87D0,0x96D6,0x87AB,0x87C4,0x87B3,
0x87C7,0x87C6,0x87BB,0x87EF,0x87F2,0x87E0,0x880F,0x880D,
@@ -1254,7 +1254,7 @@ static uint16 tab_jisx0208_uni66[]={
0x8936,0x8938,0x894C,0x891D,0x8960,0x895E};
/* page 67 0x6B21-0x6B7E */
-static uint16 tab_jisx0208_uni67[]={
+static const uint16 tab_jisx0208_uni67[]={
0x8966,0x8964,0x896D,0x896A,0x896F,0x8974,0x8977,0x897E,
0x8983,0x8988,0x898A,0x8993,0x8998,0x89A1,0x89A9,0x89A6,
0x89AC,0x89AF,0x89B2,0x89BA,0x89BD,0x89BF,0x89C0,0x89DA,
@@ -1269,7 +1269,7 @@ static uint16 tab_jisx0208_uni67[]={
0x8B4E,0x8B49,0x8B56,0x8B5B,0x8B5A,0x8B6B};
/* page 68 0x6C21-0x6C7E */
-static uint16 tab_jisx0208_uni68[]={
+static const uint16 tab_jisx0208_uni68[]={
0x8B5F,0x8B6C,0x8B6F,0x8B74,0x8B7D,0x8B80,0x8B8C,0x8B8E,
0x8B92,0x8B93,0x8B96,0x8B99,0x8B9A,0x8C3A,0x8C41,0x8C3F,
0x8C48,0x8C4C,0x8C4E,0x8C50,0x8C55,0x8C62,0x8C6C,0x8C78,
@@ -1284,7 +1284,7 @@ static uint16 tab_jisx0208_uni68[]={
0x8E1F,0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A};
/* page 69 0x6D21-0x6D7E */
-static uint16 tab_jisx0208_uni69[]={
+static const uint16 tab_jisx0208_uni69[]={
0x8E47,0x8E49,0x8E4C,0x8E50,0x8E48,0x8E59,0x8E64,0x8E60,
0x8E2A,0x8E63,0x8E55,0x8E76,0x8E72,0x8E7C,0x8E81,0x8E87,
0x8E85,0x8E84,0x8E8B,0x8E8A,0x8E93,0x8E91,0x8E94,0x8E99,
@@ -1299,7 +1299,7 @@ static uint16 tab_jisx0208_uni69[]={
0x900B,0x9027,0x9036,0x9035,0x9039,0x8FF8};
/* page 70 0x6E21-0x6E7E */
-static uint16 tab_jisx0208_uni70[]={
+static const uint16 tab_jisx0208_uni70[]={
0x904F,0x9050,0x9051,0x9052,0x900E,0x9049,0x903E,0x9056,
0x9058,0x905E,0x9068,0x906F,0x9076,0x96A8,0x9072,0x9082,
0x907D,0x9081,0x9080,0x908A,0x9089,0x908F,0x90A8,0x90AF,
@@ -1314,7 +1314,7 @@ static uint16 tab_jisx0208_uni70[]={
0x92B7,0x92E9,0x930F,0x92FA,0x9344,0x932E};
/* page 71 0x6F21-0x6F7E */
-static uint16 tab_jisx0208_uni71[]={
+static const uint16 tab_jisx0208_uni71[]={
0x9319,0x9322,0x931A,0x9323,0x933A,0x9335,0x933B,0x935C,
0x9360,0x937C,0x936E,0x9356,0x93B0,0x93AC,0x93AD,0x9394,
0x93B9,0x93D6,0x93D7,0x93E8,0x93E5,0x93D8,0x93C3,0x93DD,
@@ -1329,7 +1329,7 @@ static uint16 tab_jisx0208_uni71[]={
0x964C,0x964F,0x964B,0x9677,0x965C,0x965E};
/* page 72 0x7021-0x707E */
-static uint16 tab_jisx0208_uni72[]={
+static const uint16 tab_jisx0208_uni72[]={
0x965D,0x965F,0x9666,0x9672,0x966C,0x968D,0x9698,0x9695,
0x9697,0x96AA,0x96A7,0x96B1,0x96B2,0x96B0,0x96B4,0x96B6,
0x96B8,0x96B9,0x96CE,0x96CB,0x96C9,0x96CD,0x894D,0x96DC,
@@ -1344,7 +1344,7 @@ static uint16 tab_jisx0208_uni72[]={
0x9846,0x984F,0x984B,0x986B,0x986F,0x9870};
/* page 73 0x7121-0x717E */
-static uint16 tab_jisx0208_uni73[]={
+static const uint16 tab_jisx0208_uni73[]={
0x9871,0x9874,0x9873,0x98AA,0x98AF,0x98B1,0x98B6,0x98C4,
0x98C3,0x98C6,0x98E9,0x98EB,0x9903,0x9909,0x9912,0x9914,
0x9918,0x9921,0x991D,0x991E,0x9924,0x9920,0x992C,0x992E,
@@ -1359,7 +1359,7 @@ static uint16 tab_jisx0208_uni73[]={
0x9AEF,0x9AEB,0x9AEE,0x9AF4,0x9AF1,0x9AF7};
/* page 74 0x7221-0x727E */
-static uint16 tab_jisx0208_uni74[]={
+static const uint16 tab_jisx0208_uni74[]={
0x9AFB,0x9B06,0x9B18,0x9B1A,0x9B1F,0x9B22,0x9B23,0x9B25,
0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2E,0x9B2F,0x9B32,0x9B44,
0x9B43,0x9B4F,0x9B4D,0x9B4E,0x9B51,0x9B58,0x9B74,0x9B93,
@@ -1374,7 +1374,7 @@ static uint16 tab_jisx0208_uni74[]={
0x9D12,0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48};
/* page 75 0x7321-0x737E */
-static uint16 tab_jisx0208_uni75[]={
+static const uint16 tab_jisx0208_uni75[]={
0x9D5D,0x9D5E,0x9D64,0x9D51,0x9D50,0x9D59,0x9D72,0x9D89,
0x9D87,0x9DAB,0x9D6F,0x9D7A,0x9D9A,0x9DA4,0x9DA9,0x9DB2,
0x9DC4,0x9DC1,0x9DBB,0x9DB8,0x9DBA,0x9DC6,0x9DCF,0x9DC2,
@@ -1389,11 +1389,11 @@ static uint16 tab_jisx0208_uni75[]={
0x9F77,0x9F72,0x9F76,0x9F95,0x9F9C,0x9FA0};
/* page 76 0x7421-0x7426 */
-static uint16 tab_jisx0208_uni76[]={
+static const uint16 tab_jisx0208_uni76[]={
0x582F,0x69C7,0x9059,0x7464,0x51DC,0x7199};
/* page 77 0x2D21 - 0x2D7C */
-static uint16 tab_nec13_uni0[]={
+static const uint16 tab_nec13_uni0[]={
0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
0x2470,0x2471,0x2472,0x2473,0x2160,0x2161,0x2162,0x2163,
@@ -1569,25 +1569,25 @@ my_jisx0208_uni_onechar(int code){
}
/* page 0 0x005C-0x005C */
-static uint16 tab_uni_jisx02080[]={
+static const uint16 tab_uni_jisx02080[]={
0x5C};
/* page 1 0x00A2-0x00B6 */
-static uint16 tab_uni_jisx02081[]={
+static const uint16 tab_uni_jisx02081[]={
0, 0, 0, 0, 0,0x2178,0x212F, 0,
0, 0, 0, 0, 0, 0,0x216B,0x215E,
0, 0,0x212D, 0,0x2279};
/* page 2 0x00D7-0x00D7 */
-static uint16 tab_uni_jisx02082[]={
+static const uint16 tab_uni_jisx02082[]={
0x215F};
/* page 3 0x00F7-0x00F7 */
-static uint16 tab_uni_jisx02083[]={
+static const uint16 tab_uni_jisx02083[]={
0x2160};
/* page 4 0x0391-0x03C9 */
-static uint16 tab_uni_jisx02084[]={
+static const uint16 tab_uni_jisx02084[]={
0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,0x2628,
0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F,0x2630,
0x2631, 0,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637,
@@ -1598,7 +1598,7 @@ static uint16 tab_uni_jisx02084[]={
0x2658};
/* page 5 0x0401-0x0451 */
-static uint16 tab_uni_jisx02085[]={
+static const uint16 tab_uni_jisx02085[]={
0x2727, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x2721,
0x2722,0x2723,0x2724,0x2725,0x2726,0x2728,0x2729,0x272A,
@@ -1612,7 +1612,7 @@ static uint16 tab_uni_jisx02085[]={
0x2757};
/* page 6 0x2010-0x203B */
-static uint16 tab_uni_jisx02086[]={
+static const uint16 tab_uni_jisx02086[]={
0x213E, 0, 0, 0, 0,0x213D, 0, 0,
0x2146,0x2147, 0, 0,0x2148,0x2149, 0, 0,
0x2277,0x2278, 0, 0, 0,0x2145,0x2144, 0,
@@ -1621,31 +1621,31 @@ static uint16 tab_uni_jisx02086[]={
0, 0, 0,0x2228};
/* page 7 0x2100-0x2116 */
-static uint16 tab_uni_jisx02087[]={
+static const uint16 tab_uni_jisx02087[]={
0, 0, 0,0x216E, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x2D62};
/* page 8 0x2120-0x212B */
-static uint16 tab_uni_jisx02088[]={
+static const uint16 tab_uni_jisx02088[]={
0,0x2D64, 0, 0, 0, 0, 0, 0,
0, 0, 0,0x2272};
/* page 9 0x2160-0x2169 */
-static uint16 tab_uni_jisx02089[]={
+static const uint16 tab_uni_jisx02089[]={
0x2D35,0x2D36,0x2D37,0x2D38,0x2D39,0x2D3A,0x2D3B,0x2D3C,
0x2D3D,0x2D3E};
/* page 10 0x2190-0x2193 */
-static uint16 tab_uni_jisx020810[]={
+static const uint16 tab_uni_jisx020810[]={
0x222B,0x222C,0x222A,0x222D};
/* page 11 0x21D2-0x21D4 */
-static uint16 tab_uni_jisx020811[]={
+static const uint16 tab_uni_jisx020811[]={
0x224D, 0,0x224E};
/* page 12 0x2200-0x223D */
-static uint16 tab_uni_jisx020812[]={
+static const uint16 tab_uni_jisx020812[]={
0x224F, 0,0x225F,0x2250, 0, 0, 0,0x2260,
0x223A, 0, 0,0x223B, 0, 0, 0, 0,
0,0x2D74, 0, 0, 0, 0, 0, 0,
@@ -1656,35 +1656,35 @@ static uint16 tab_uni_jisx020812[]={
0, 0, 0, 0, 0,0x2266};
/* page 13 0x2252-0x226B */
-static uint16 tab_uni_jisx020813[]={
+static const uint16 tab_uni_jisx020813[]={
0x2262, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x2162,0x2261,
0, 0, 0, 0,0x2165,0x2166, 0, 0,
0x2263,0x2264};
/* page 14 0x2282-0x2287 */
-static uint16 tab_uni_jisx020814[]={
+static const uint16 tab_uni_jisx020814[]={
0x223E,0x223F, 0, 0,0x223C,0x223D};
/* page 15 0x22A0-0x22BF */
-static uint16 tab_uni_jisx020815[]={
+static const uint16 tab_uni_jisx020815[]={
0, 0, 0, 0, 0,0x225D, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x2D79};
/* page 16 0x2312-0x2312 */
-static uint16 tab_uni_jisx020816[]={
+static const uint16 tab_uni_jisx020816[]={
0x225E};
/* page 17 0x2460-0x2473 */
-static uint16 tab_uni_jisx020817[]={
+static const uint16 tab_uni_jisx020817[]={
0x2D21,0x2D22,0x2D23,0x2D24,0x2D25,0x2D26,0x2D27,0x2D28,
0x2D29,0x2D2A,0x2D2B,0x2D2C,0x2D2D,0x2D2E,0x2D2F,0x2D30,
0x2D31,0x2D32,0x2D33,0x2D34};
/* page 18 0x2500-0x254B */
-static uint16 tab_uni_jisx020818[]={
+static const uint16 tab_uni_jisx020818[]={
0x2821,0x282C,0x2822,0x282D, 0, 0, 0, 0,
0, 0, 0, 0,0x2823, 0, 0,0x282E,
0x2824, 0, 0,0x282F,0x2826, 0, 0,0x2831,
@@ -1697,7 +1697,7 @@ static uint16 tab_uni_jisx020818[]={
0, 0, 0,0x2836};
/* page 19 0x25A0-0x25CF */
-static uint16 tab_uni_jisx020819[]={
+static const uint16 tab_uni_jisx020819[]={
0x2223,0x2222, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0,0x2225,0x2224, 0, 0, 0, 0,
@@ -1707,30 +1707,30 @@ static uint16 tab_uni_jisx020819[]={
};
/* page 20 0x25EF-0x25EF */
-static uint16 tab_uni_jisx020820[]={
+static const uint16 tab_uni_jisx020820[]={
0x227E};
/* page 21 0x2605-0x2606 */
-static uint16 tab_uni_jisx020821[]={
+static const uint16 tab_uni_jisx020821[]={
0x217A,0x2179};
/* page 22 0x2640-0x2642 */
-static uint16 tab_uni_jisx020822[]={
+static const uint16 tab_uni_jisx020822[]={
0x216A, 0,0x2169};
/* page 23 0x266A-0x266F */
-static uint16 tab_uni_jisx020823[]={
+static const uint16 tab_uni_jisx020823[]={
0x2276, 0, 0,0x2275, 0,0x2274};
/* page 24 0x3000-0x301F */
-static uint16 tab_uni_jisx020824[]={
+static const uint16 tab_uni_jisx020824[]={
0x2121,0x2122,0x2123,0x2137, 0,0x2139,0x213A,0x213B,
0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,
0x215A,0x215B,0x2229,0x222E,0x214C,0x214D, 0, 0,
0, 0, 0, 0, 0,0x2D60, 0,0x2D61};
/* page 25 0x3041-0x30FE */
-static uint16 tab_uni_jisx020825[]={
+static const uint16 tab_uni_jisx020825[]={
0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,0x2428,
0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,0x2430,
0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,0x2438,
@@ -1757,17 +1757,17 @@ static uint16 tab_uni_jisx020825[]={
0, 0,0x2126,0x213C,0x2133,0x2134};
/* page 26 0x3230-0x3239 */
-static uint16 tab_uni_jisx020826[]={
+static const uint16 tab_uni_jisx020826[]={
0,0x2D6A,0x2D6B, 0, 0, 0, 0, 0,
0,0x2D6C};
/* page 27 0x32A0-0x32A8 */
-static uint16 tab_uni_jisx020827[]={
+static const uint16 tab_uni_jisx020827[]={
0, 0, 0, 0,0x2D65,0x2D66,0x2D67,0x2D68,
0x2D69};
/* page 28 0x3300-0x33CD */
-static uint16 tab_uni_jisx020828[]={
+static const uint16 tab_uni_jisx020828[]={
0, 0, 0,0x2D46, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x2D4A, 0, 0,
0, 0, 0, 0,0x2D41, 0, 0, 0,
@@ -1796,7 +1796,7 @@ static uint16 tab_uni_jisx020828[]={
0, 0, 0, 0, 0,0x2D63};
/* page 29 0x4E00-0x5516 */
-static uint16 tab_uni_jisx020829[]={
+static const uint16 tab_uni_jisx020829[]={
0x306C,0x437A, 0,0x3C37, 0, 0, 0,0x4B7C,
0x3E66,0x3B30,0x3E65,0x323C, 0,0x4954,0x4D3F, 0,
0x5022,0x312F, 0, 0,0x336E,0x5023,0x4024,0x5242,
@@ -2026,7 +2026,7 @@ static uint16 tab_uni_jisx020829[]={
0x4562, 0, 0, 0,0x532A, 0,0x3022};
/* page 30 0x552E-0x5563 */
-static uint16 tab_uni_jisx020830[]={
+static const uint16 tab_uni_jisx020830[]={
0x5334,0x4D23, 0,0x3E27, 0,0x533A, 0, 0,
0, 0,0x5339,0x5330, 0, 0, 0, 0,
0x4243, 0,0x5331, 0, 0, 0,0x426F,0x5336,
@@ -2036,7 +2036,7 @@ static uint16 tab_uni_jisx020830[]={
0, 0, 0, 0, 0,0x5332};
/* page 31 0x557B-0x576A */
-static uint16 tab_uni_jisx020831[]={
+static const uint16 tab_uni_jisx020831[]={
0x5341,0x5346, 0,0x5342, 0,0x533D, 0, 0,
0x5347,0x4131, 0, 0,0x5349, 0,0x3922,0x533F,
0x437D, 0, 0, 0, 0, 0, 0, 0,
@@ -2102,7 +2102,7 @@ static uint16 tab_uni_jisx020831[]={
};
/* page 32 0x577F-0x5A9B */
-static uint16 tab_uni_jisx020832[]={
+static const uint16 tab_uni_jisx020832[]={
0x5434, 0, 0,0x3F62, 0, 0, 0, 0,
0,0x5432,0x5435, 0,0x373F, 0, 0, 0,
0, 0, 0, 0,0x5436, 0, 0, 0,
@@ -2205,7 +2205,7 @@ static uint16 tab_uni_jisx020832[]={
0, 0, 0,0x553B,0x4932};
/* page 33 0x5ABC-0x5D29 */
-static uint16 tab_uni_jisx020833[]={
+static const uint16 tab_uni_jisx020833[]={
0x553C,0x5540,0x553D, 0, 0,0x3247,0x553F, 0,
0, 0, 0, 0, 0,0x3C3B, 0,0x553E,
0x3779, 0, 0, 0,0x554C, 0, 0, 0,
@@ -2286,7 +2286,7 @@ static uint16 tab_uni_jisx020833[]={
0, 0, 0, 0, 0,0x4A78};
/* page 34 0x5D4B-0x6BF3 */
-static uint16 tab_uni_jisx020834[]={
+static const uint16 tab_uni_jisx020834[]={
0x564B,0x5648, 0,0x564A, 0,0x4D72, 0,0x5649,
0, 0, 0, 0, 0, 0, 0, 0,
0,0x563F, 0, 0, 0, 0, 0, 0,
@@ -2759,7 +2759,7 @@ static uint16 tab_uni_jisx020834[]={
0x5D5E};
/* page 35 0x6C08-0x6CF3 */
-static uint16 tab_uni_jisx020835[]={
+static const uint16 tab_uni_jisx020835[]={
0x5D61, 0, 0, 0, 0, 0, 0,0x3B61,
0,0x4C31, 0,0x5D62,0x5D63, 0, 0,0x3524,
0, 0, 0,0x5D64, 0, 0, 0, 0,
@@ -2792,7 +2792,7 @@ static uint16 tab_uni_jisx020835[]={
0x4259,0x5D76, 0,0x314B};
/* page 36 0x6D0B-0x7409 */
-static uint16 tab_uni_jisx020836[]={
+static const uint16 tab_uni_jisx020836[]={
0x4D4E,0x5E30, 0, 0, 0, 0, 0,0x5E2F,
0, 0, 0, 0,0x4076, 0,0x5E2C, 0,
0x4D6C, 0, 0,0x4636,0x5E26, 0, 0, 0,
@@ -3019,7 +3019,7 @@ static uint16 tab_uni_jisx020836[]={
0x3565, 0,0x6066,0x4D7D, 0, 0,0x4E30};
/* page 37 0x7422-0x7845 */
-static uint16 tab_uni_jisx020837[]={
+static const uint16 tab_uni_jisx020837[]={
0x4276, 0, 0,0x6068, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0x606A,0x4E56,0x3657,0x487C,0x474A, 0, 0, 0,
@@ -3155,7 +3155,7 @@ static uint16 tab_uni_jisx020837[]={
0, 0, 0,0x626B};
/* page 38 0x785D-0x7E9C */
-static uint16 tab_uni_jisx020838[]={
+static const uint16 tab_uni_jisx020838[]={
0x3E4B, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x4E32,0x3945,
0, 0,0x3827, 0, 0,0x4823, 0,0x626D,
@@ -3359,7 +3359,7 @@ static uint16 tab_uni_jisx020838[]={
};
/* page 39 0x7F36-0x8358 */
-static uint16 tab_uni_jisx020839[]={
+static const uint16 tab_uni_jisx020839[]={
0x344C, 0,0x657D, 0,0x657E, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x6621,
0, 0, 0, 0, 0, 0,0x6622,0x6623,
@@ -3495,7 +3495,7 @@ static uint16 tab_uni_jisx020839[]={
0, 0,0x4171};
/* page 40 0x8373-0x8B9A */
-static uint16 tab_uni_jisx020840[]={
+static const uint16 tab_uni_jisx020840[]={
0x683A, 0,0x683B, 0,0x3259, 0, 0, 0,
0x322E,0x6838, 0, 0, 0, 0, 0, 0,
0, 0,0x682E, 0,0x6836, 0,0x683D,0x6837,
@@ -3760,7 +3760,7 @@ static uint16 tab_uni_jisx020840[]={
};
/* page 41 0x8C37-0x8D16 */
-static uint16 tab_uni_jisx020841[]={
+static const uint16 tab_uni_jisx020841[]={
0x432B, 0, 0,0x6C2E, 0, 0, 0, 0,
0x6C30, 0,0x6C2F, 0, 0, 0, 0,0x4626,
0,0x6C31, 0,0x4B2D, 0,0x6C32, 0,0x6C33,
@@ -3792,7 +3792,7 @@ static uint16 tab_uni_jisx020841[]={
};
/* page 42 0x8D64-0x8F64 */
-static uint16 tab_uni_jisx020842[]={
+static const uint16 tab_uni_jisx020842[]={
0x4056, 0,0x3C4F,0x6C5F, 0, 0, 0,0x3352,
0,0x6C60, 0, 0,0x4176,0x6C61, 0,0x6C62,
0x496B, 0, 0,0x352F, 0, 0, 0, 0,
@@ -3860,7 +3860,7 @@ static uint16 tab_uni_jisx020842[]={
0x6D62};
/* page 43 0x8F9B-0x9132 */
-static uint16 tab_uni_jisx020843[]={
+static const uint16 tab_uni_jisx020843[]={
0x3F49,0x6D63, 0,0x3C2D,0x6D64, 0, 0, 0,
0x6D65, 0, 0, 0,0x5221,0x517E, 0, 0,
0, 0,0x6D66,0x6570,0x6D67,0x4324,0x3F2B,0x4740,
@@ -3915,7 +3915,7 @@ static uint16 tab_uni_jisx020843[]={
};
/* page 44 0x9149-0x92B9 */
-static uint16 tab_uni_jisx020844[]={
+static const uint16 tab_uni_jisx020844[]={
0x4653,0x6E44,0x3D36,0x3C60,0x475B,0x4371, 0, 0,
0,0x3C72, 0,0x3F6C, 0,0x6E45, 0,0x6E46,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -3965,7 +3965,7 @@ static uint16 tab_uni_jisx020844[]={
0x6E78};
/* page 45 0x92CF-0x93E8 */
-static uint16 tab_uni_jisx020845[]={
+static const uint16 tab_uni_jisx020845[]={
0x6E77, 0, 0,0x4B2F, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x3D7B, 0, 0,
@@ -4004,7 +4004,7 @@ static uint16 tab_uni_jisx020845[]={
0,0x6F34};
/* page 46 0x9403-0x9481 */
-static uint16 tab_uni_jisx020846[]={
+static const uint16 tab_uni_jisx020846[]={
0x6F3F, 0, 0, 0,0x6F40, 0, 0, 0,
0, 0, 0, 0, 0,0x6F41, 0, 0,
0x6F3E,0x6F3D, 0, 0, 0,0x3E62,0x462A,0x6F3C,
@@ -4023,7 +4023,7 @@ static uint16 tab_uni_jisx020846[]={
0,0x6F55,0x6F53,0x6F56,0x6F58, 0,0x6F57};
/* page 47 0x9577-0x95E5 */
-static uint16 tab_uni_jisx020847[]={
+static const uint16 tab_uni_jisx020847[]={
0x4439, 0, 0, 0, 0, 0, 0, 0,
0,0x4C67, 0,0x6F59,0x412E, 0, 0, 0,
0x6F5A, 0,0x4A44,0x6F5B,0x332B, 0, 0, 0,
@@ -4040,7 +4040,7 @@ static uint16 tab_uni_jisx020847[]={
0, 0,0x6F71,0x6F73, 0, 0,0x6F72};
/* page 48 0x961C-0x9874 */
-static uint16 tab_uni_jisx020848[]={
+static const uint16 tab_uni_jisx020848[]={
0x496C, 0, 0, 0, 0,0x6F74, 0, 0,
0, 0, 0, 0,0x6F75, 0,0x3A65, 0,
0, 0,0x6F76,0x6F77, 0, 0,0x4B49, 0,
@@ -4119,14 +4119,14 @@ static uint16 tab_uni_jisx020848[]={
0x7122};
/* page 49 0x98A8-0x98C6 */
-static uint16 tab_uni_jisx020849[]={
+static const uint16 tab_uni_jisx020849[]={
0x4977, 0,0x7124, 0, 0, 0, 0,0x7125,
0,0x7126, 0, 0, 0, 0,0x7127, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,0x7129,0x7128, 0,0x712A};
/* page 50 0x98DB-0x9957 */
-static uint16 tab_uni_jisx020850[]={
+static const uint16 tab_uni_jisx020850[]={
0x4874,0x664C, 0, 0,0x3F29, 0, 0,0x3532,
0, 0, 0, 0, 0, 0,0x712B, 0,
0x712C, 0,0x522C,0x5D3B,0x4853, 0, 0,0x307B,
@@ -4145,7 +4145,7 @@ static uint16 tab_uni_jisx020850[]={
0, 0,0x7143, 0,0x3642};
/* page 51 0x9996-0x9A6B */
-static uint16 tab_uni_jisx020851[]={
+static const uint16 tab_uni_jisx020851[]={
0x3C73,0x7144,0x7145,0x3961, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x7146,
0, 0,0x333E, 0, 0, 0,0x474F,0x7147,
@@ -4175,7 +4175,7 @@ static uint16 tab_uni_jisx020851[]={
0, 0, 0,0x7169,0x716B,0x716A};
/* page 52 0x9AA8-0x9B5A */
-static uint16 tab_uni_jisx020852[]={
+static const uint16 tab_uni_jisx020852[]={
0x397C, 0, 0, 0, 0,0x716C, 0, 0,
0x716D, 0, 0, 0, 0, 0, 0, 0,
0x333C, 0, 0, 0,0x716E, 0, 0, 0,
@@ -4201,7 +4201,7 @@ static uint16 tab_uni_jisx020852[]={
0x7236, 0,0x357B};
/* page 53 0x9B6F-0x9C78 */
-static uint16 tab_uni_jisx020853[]={
+static const uint16 tab_uni_jisx020853[]={
0x4F25, 0, 0, 0, 0,0x7237, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x7239, 0, 0, 0,
@@ -4238,7 +4238,7 @@ static uint16 tab_uni_jisx020853[]={
0,0x7269};
/* page 54 0x9CE5-0x9DFD */
-static uint16 tab_uni_jisx020854[]={
+static const uint16 tab_uni_jisx020854[]={
0x443B, 0,0x726A, 0,0x4837, 0,0x726F,0x726B,
0, 0, 0,0x726C, 0, 0,0x4B31,0x4C44,
0,0x4650, 0, 0, 0, 0, 0, 0,
@@ -4277,11 +4277,11 @@ static uint16 tab_uni_jisx020854[]={
0x733F};
/* page 55 0x9E1A-0x9E1E */
-static uint16 tab_uni_jisx020855[]={
+static const uint16 tab_uni_jisx020855[]={
0x7340,0x7341, 0, 0,0x7342};
/* page 56 0x9E75-0x9F77 */
-static uint16 tab_uni_jisx020856[]={
+static const uint16 tab_uni_jisx020856[]={
0x7343, 0, 0,0x3834,0x7344, 0, 0, 0,
0x7345, 0,0x3C2F, 0,0x7346, 0, 0, 0,
0, 0, 0,0x7347, 0, 0,0x7348,0x7349,
@@ -4317,13 +4317,13 @@ static uint16 tab_uni_jisx020856[]={
0,0x737B,0x7379};
/* page 57 0x9F8D-0x9FA0 */
-static uint16 tab_uni_jisx020857[]={
+static const uint16 tab_uni_jisx020857[]={
0x4E36, 0, 0, 0, 0, 0, 0, 0,
0x737C, 0, 0, 0, 0, 0, 0,0x737D,
0x6354, 0, 0,0x737E};
/* page 58 0xFF01-0xFF5E */
-static uint16 tab_uni_jisx020858[]={
+static const uint16 tab_uni_jisx020858[]={
0x212A, 0,0x2174,0x2170,0x2173,0x2175, 0,0x214A,
0x214B,0x2176,0x215C,0x2124,0x215D,0x2125,0x213F,0x2330,
0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,
@@ -4338,7 +4338,7 @@ static uint16 tab_uni_jisx020858[]={
0x2379,0x237A,0x2150,0x2143,0x2151,0x2141};
/* page 59 0xFFE0-0xFFE5 */
-static uint16 tab_uni_jisx020859[]={
+static const uint16 tab_uni_jisx020859[]={
0x2171,0x2172,0x224C,0x2131, 0,0x216F};
static int
@@ -4468,11 +4468,11 @@ my_uni_jisx0208_onechar(int code){
/* page 0 0x007E-0x007E */
-static uint16 tab_uni_jisx02120[]={
+static const uint16 tab_uni_jisx02120[]={
0};
/* page 1 0x00A1-0x017E */
-static uint16 tab_uni_jisx02121[]={
+static const uint16 tab_uni_jisx02121[]={
0x2242, 0, 0,0x2270, 0, 0, 0, 0,
0x226D,0x226C, 0, 0, 0,0x226E,0x2234, 0,
0, 0, 0, 0, 0, 0, 0,0x2231,
@@ -4503,28 +4503,28 @@ static uint16 tab_uni_jisx02121[]={
0x2A75,0x2B75,0x2A77,0x2B77,0x2A76,0x2B76};
/* page 2 0x01CD-0x01DC */
-static uint16 tab_uni_jisx02122[]={
+static const uint16 tab_uni_jisx02122[]={
0x2A26,0x2B26,0x2A43,0x2B43,0x2A55,0x2B55,0x2A67,0x2B67,
0x2A70,0x2B70,0x2A6D,0x2B6D,0x2A6F,0x2B6F,0x2A6E,0x2B6E
};
/* page 3 0x01F5-0x01F5 */
-static uint16 tab_uni_jisx02123[]={
+static const uint16 tab_uni_jisx02123[]={
0x2B39};
/* page 4 0x02C7-0x02DD */
-static uint16 tab_uni_jisx02124[]={
+static const uint16 tab_uni_jisx02124[]={
0x2230, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,0x222F,0x2232,0x2236,0x2235, 0,0x2233};
/* page 5 0x0384-0x0390 */
-static uint16 tab_uni_jisx02125[]={
+static const uint16 tab_uni_jisx02125[]={
0x2238,0x2239,0x2661, 0,0x2662,0x2663,0x2664, 0,
0x2667, 0,0x2669,0x266C,0x2676};
/* page 6 0x03AA-0x03CE */
-static uint16 tab_uni_jisx02126[]={
+static const uint16 tab_uni_jisx02126[]={
0x2665,0x266A,0x2671,0x2672,0x2673,0x2674,0x267B, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -4532,26 +4532,26 @@ static uint16 tab_uni_jisx02126[]={
0x2675,0x267A,0x2677,0x2679,0x267C};
/* page 7 0x0402-0x040F */
-static uint16 tab_uni_jisx02127[]={
+static const uint16 tab_uni_jisx02127[]={
0x2742,0x2743,0x2744,0x2745,0x2746,0x2747,0x2748,0x2749,
0x274A,0x274B,0x274C, 0,0x274D,0x274E};
/* page 8 0x0452-0x045F */
-static uint16 tab_uni_jisx02128[]={
+static const uint16 tab_uni_jisx02128[]={
0x2772,0x2773,0x2774,0x2775,0x2776,0x2777,0x2778,0x2779,
0x277A,0x277B,0x277C, 0,0x277D,0x277E};
/* page 9 0x2122-0x2122 */
-static uint16 tab_uni_jisx02129[]={
+static const uint16 tab_uni_jisx02129[]={
0x226F};
/* page 10 0x2170-0x2179 */
-static uint16 tab_uni_jisx021210[]={
+static const uint16 tab_uni_jisx021210[]={
0x7373,0x7374,0x7375,0x7376,0x7377,0x7378,0x7379,0x737A,
0x737B,0x737C};
/* page 11 0x4E02-0x4F19 */
-static uint16 tab_uni_jisx021211[]={
+static const uint16 tab_uni_jisx021211[]={
0x3021, 0,0x3022,0x3023, 0, 0, 0, 0,
0, 0,0x3024, 0, 0, 0, 0, 0,
0x3025, 0, 0, 0, 0, 0, 0, 0,
@@ -4590,7 +4590,7 @@ static uint16 tab_uni_jisx021211[]={
};
/* page 12 0x4F2E-0x5166 */
-static uint16 tab_uni_jisx021212[]={
+static const uint16 tab_uni_jisx021212[]={
0x305D, 0, 0,0x305E, 0,0x3060, 0,0x3061,
0,0x3062, 0,0x3063, 0,0x3064, 0, 0,
0x3065, 0,0x3066, 0,0x3067, 0, 0, 0,
@@ -4665,7 +4665,7 @@ static uint16 tab_uni_jisx021212[]={
0x326E};
/* page 13 0x517E-0x5515 */
-static uint16 tab_uni_jisx021213[]={
+static const uint16 tab_uni_jisx021213[]={
0x326F, 0, 0, 0, 0,0x3270,0x3271, 0,
0, 0, 0, 0, 0,0x3272, 0, 0,
0x3273, 0, 0, 0, 0, 0, 0, 0,
@@ -4784,7 +4784,7 @@ static uint16 tab_uni_jisx021213[]={
};
/* page 14 0x552A-0x5566 */
-static uint16 tab_uni_jisx021214[]={
+static const uint16 tab_uni_jisx021214[]={
0x354E,0x354F, 0, 0, 0, 0, 0, 0,
0x3550, 0, 0,0x3551,0x3552, 0, 0, 0,
0,0x3553,0x3554,0x3555, 0, 0, 0,0x3556,
@@ -4795,7 +4795,7 @@ static uint16 tab_uni_jisx021214[]={
0, 0,0x3563, 0,0x3564};
/* page 15 0x557F-0x5C36 */
-static uint16 tab_uni_jisx021215[]={
+static const uint16 tab_uni_jisx021215[]={
0x3565, 0,0x3566,0x3567, 0, 0, 0,0x3568,
0,0x3569, 0, 0, 0, 0, 0,0x356A,
0x356B, 0,0x356C,0x356D,0x356E,0x356F, 0, 0,
@@ -5014,7 +5014,7 @@ static uint16 tab_uni_jisx021215[]={
};
/* page 16 0x5C59-0x5EEB */
-static uint16 tab_uni_jisx021216[]={
+static const uint16 tab_uni_jisx021216[]={
0x3A77,0x3A78, 0,0x3A79, 0, 0, 0, 0,
0,0x3A7A,0x3A7B, 0, 0, 0,0x3A7C,0x3A7D,
0x3A7E, 0, 0, 0,0x3B21, 0, 0,0x3B22,
@@ -5100,7 +5100,7 @@ static uint16 tab_uni_jisx021216[]={
0, 0,0x3C5B};
/* page 17 0x5F02-0x6149 */
-static uint16 tab_uni_jisx021217[]={
+static const uint16 tab_uni_jisx021217[]={
0x3C5C, 0, 0, 0,0x3C5D,0x3C5E,0x3C5F, 0,
0, 0, 0, 0,0x3C60, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x3C61,
@@ -5177,7 +5177,7 @@ static uint16 tab_uni_jisx021217[]={
};
/* page 18 0x615E-0x6290 */
-static uint16 tab_uni_jisx021218[]={
+static const uint16 tab_uni_jisx021218[]={
0x3E53, 0,0x3E54, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x3E55, 0,
0, 0, 0, 0,0x3E56, 0, 0, 0,
@@ -5219,7 +5219,7 @@ static uint16 tab_uni_jisx021218[]={
0x3F46,0x3F47,0x3F48};
/* page 19 0x62A6-0x679B */
-static uint16 tab_uni_jisx021219[]={
+static const uint16 tab_uni_jisx021219[]={
0x3F49, 0,0x3F4A, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x3F4B, 0, 0,
0x3F4C,0x3F4D, 0, 0,0x3F4E, 0, 0, 0,
@@ -5381,7 +5381,7 @@ static uint16 tab_uni_jisx021219[]={
0x432D, 0,0x432E,0x432F, 0,0x4330};
/* page 20 0x67B0-0x6801 */
-static uint16 tab_uni_jisx021220[]={
+static const uint16 tab_uni_jisx021220[]={
0x4331,0x4332,0x4333, 0, 0,0x4334, 0, 0,
0, 0, 0,0x4335,0x4336,0x4337, 0, 0,
0x4339, 0,0x433A,0x433B, 0,0x433C, 0, 0,
@@ -5395,7 +5395,7 @@ static uint16 tab_uni_jisx021220[]={
0,0x7446};
/* page 21 0x6814-0x6917 */
-static uint16 tab_uni_jisx021221[]={
+static const uint16 tab_uni_jisx021221[]={
0x434A, 0, 0, 0, 0,0x434B, 0, 0,
0,0x434C, 0,0x434D, 0, 0, 0, 0,
0, 0, 0,0x434F,0x434E, 0, 0, 0,
@@ -5431,7 +5431,7 @@ static uint16 tab_uni_jisx021221[]={
0, 0,0x443B,0x443C};
/* page 22 0x6931-0x6D3F */
-static uint16 tab_uni_jisx021222[]={
+static const uint16 tab_uni_jisx021222[]={
0x443D, 0,0x443E, 0,0x443F, 0, 0,0x4440,
0, 0,0x4441, 0, 0, 0, 0, 0,
0,0x4442, 0, 0,0x4443, 0, 0, 0,
@@ -5564,7 +5564,7 @@ static uint16 tab_uni_jisx021222[]={
0x473A, 0, 0,0x473B, 0, 0,0x473C};
/* page 23 0x6D57-0x6E04 */
-static uint16 tab_uni_jisx021223[]={
+static const uint16 tab_uni_jisx021223[]={
0x473D, 0, 0, 0, 0, 0, 0,0x473E,
0x473F, 0,0x4740, 0, 0, 0,0x4741, 0,
0x4742, 0, 0, 0, 0, 0, 0, 0,
@@ -5589,7 +5589,7 @@ static uint16 tab_uni_jisx021223[]={
0,0x4767, 0, 0, 0,0x4768};
/* page 24 0x6E1E-0x6ECF */
-static uint16 tab_uni_jisx021224[]={
+static const uint16 tab_uni_jisx021224[]={
0x4769, 0, 0, 0,0x476A, 0, 0, 0,
0,0x476B, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x476C, 0, 0, 0,
@@ -5615,7 +5615,7 @@ static uint16 tab_uni_jisx021224[]={
0x4839,0x483A};
/* page 25 0x6EEB-0x70E4 */
-static uint16 tab_uni_jisx021225[]={
+static const uint16 tab_uni_jisx021225[]={
0x483B, 0,0x483C,0x483D, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x483E, 0,
0x483F, 0,0x4840, 0, 0, 0, 0, 0,
@@ -5682,7 +5682,7 @@ static uint16 tab_uni_jisx021225[]={
0,0x4960};
/* page 26 0x70FA-0x71DC */
-static uint16 tab_uni_jisx021226[]={
+static const uint16 tab_uni_jisx021226[]={
0x4961, 0, 0, 0, 0, 0, 0, 0,
0,0x4962,0x4963,0x4964,0x4965,0x4966, 0, 0,
0,0x4967,0x4968, 0, 0,0x4969, 0, 0,
@@ -5714,7 +5714,7 @@ static uint16 tab_uni_jisx021226[]={
0x4A3A, 0,0x4A3B};
/* page 27 0x71F8-0x7E9E */
-static uint16 tab_uni_jisx021227[]={
+static const uint16 tab_uni_jisx021227[]={
0x4A3C, 0, 0, 0, 0, 0,0x4A3D, 0,
0x4A3E, 0, 0, 0, 0, 0, 0,0x4A3F,
0x4A40,0x4A41, 0, 0, 0, 0, 0, 0,
@@ -6122,7 +6122,7 @@ static uint16 tab_uni_jisx021227[]={
0x5467, 0,0x5468, 0, 0,0x5469,0x546A};
/* page 28 0x7F3B-0x8044 */
-static uint16 tab_uni_jisx021228[]={
+static const uint16 tab_uni_jisx021228[]={
0x546C,0x546B,0x546D,0x546E,0x546F, 0, 0, 0,
0x5470,0x5471, 0, 0,0x5472, 0, 0, 0,
0, 0, 0, 0,0x5473, 0, 0,0x5474,
@@ -6159,7 +6159,7 @@ static uint16 tab_uni_jisx021228[]={
0,0x5563};
/* page 29 0x8060-0x8362 */
-static uint16 tab_uni_jisx021229[]={
+static const uint16 tab_uni_jisx021229[]={
0x5564, 0, 0, 0,0x5565, 0,0x5566, 0,
0, 0, 0, 0, 0,0x5567, 0, 0,
0,0x5568, 0, 0, 0,0x5569, 0, 0,
@@ -6259,7 +6259,7 @@ static uint16 tab_uni_jisx021229[]={
0, 0,0x745F};
/* page 30 0x8370-0x8419 */
-static uint16 tab_uni_jisx021230[]={
+static const uint16 tab_uni_jisx021230[]={
0x577D, 0, 0, 0, 0, 0, 0, 0,
0x577E, 0, 0, 0, 0,0x5821, 0,0x5822,
0x5823, 0,0x5824, 0,0x5825, 0,0x5826, 0,
@@ -6284,7 +6284,7 @@ static uint16 tab_uni_jisx021230[]={
0,0x584B};
/* page 31 0x842F-0x8880 */
-static uint16 tab_uni_jisx021231[]={
+static const uint16 tab_uni_jisx021231[]={
0x584D, 0, 0, 0, 0, 0, 0, 0,
0, 0,0x584E, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x584F, 0,
@@ -6426,7 +6426,7 @@ static uint16 tab_uni_jisx021231[]={
0,0x5C38};
/* page 32 0x8898-0x89BC */
-static uint16 tab_uni_jisx021232[]={
+static const uint16 tab_uni_jisx021232[]={
0x5C39, 0,0x5C3A,0x5C3B,0x5C3C, 0, 0,0x5C3D,
0x5C3E, 0, 0, 0, 0, 0, 0, 0,
0x5C3F, 0,0x5C40, 0, 0, 0, 0, 0,
@@ -6466,7 +6466,7 @@ static uint16 tab_uni_jisx021232[]={
0, 0, 0, 0,0x5D33};
/* page 33 0x89D4-0x8B9F */
-static uint16 tab_uni_jisx021233[]={
+static const uint16 tab_uni_jisx021233[]={
0x5D34,0x5D35,0x5D36,0x5D37,0x5D38, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,0x5D39, 0, 0, 0,0x5D3A, 0,0x5D3B,
@@ -6527,7 +6527,7 @@ static uint16 tab_uni_jisx021233[]={
0x5E5F, 0,0x5E60,0x5E61};
/* page 34 0x8C38-0x8CA4 */
-static uint16 tab_uni_jisx021234[]={
+static const uint16 tab_uni_jisx021234[]={
0x5E62,0x5E63, 0, 0, 0,0x5E64,0x5E65, 0,
0, 0, 0, 0, 0,0x5E66, 0,0x5E67,
0,0x5E68, 0,0x5E69, 0, 0, 0,0x5E6A,
@@ -6544,7 +6544,7 @@ static uint16 tab_uni_jisx021234[]={
0, 0, 0, 0,0x5F29};
/* page 35 0x8CB9-0x8D1B */
-static uint16 tab_uni_jisx021235[]={
+static const uint16 tab_uni_jisx021235[]={
0x5F2A,0x5F2B, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x5F2C,0x5F2D, 0, 0,
0x5F2E, 0,0x5F2F, 0, 0, 0,0x5F30, 0,
@@ -6560,7 +6560,7 @@ static uint16 tab_uni_jisx021235[]={
0, 0,0x5F45};
/* page 36 0x8D65-0x8F65 */
-static uint16 tab_uni_jisx021236[]={
+static const uint16 tab_uni_jisx021236[]={
0x5F46, 0, 0, 0,0x5F47, 0, 0,0x5F48,
0,0x5F49, 0, 0, 0, 0, 0, 0,
0,0x7468, 0, 0, 0, 0, 0, 0,
@@ -6628,7 +6628,7 @@ static uint16 tab_uni_jisx021236[]={
0x612C};
/* page 37 0x8F9D-0x9484 */
-static uint16 tab_uni_jisx021237[]={
+static const uint16 tab_uni_jisx021237[]={
0x612D, 0, 0,0x612E,0x612F, 0, 0,0x6130,
0x6131,0x6132, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -6789,7 +6789,7 @@ static uint16 tab_uni_jisx021237[]={
};
/* page 38 0x9578-0x95E6 */
-static uint16 tab_uni_jisx021238[]={
+static const uint16 tab_uni_jisx021238[]={
0x657D,0x657E, 0, 0, 0, 0,0x6621, 0,
0, 0, 0, 0,0x6622, 0, 0, 0,
0x6623, 0, 0, 0,0x6624,0x6625,0x6626, 0,
@@ -6806,7 +6806,7 @@ static uint16 tab_uni_jisx021238[]={
0x6641, 0, 0, 0,0x6642, 0,0x6643};
/* page 39 0x961D-0x986C */
-static uint16 tab_uni_jisx021239[]={
+static const uint16 tab_uni_jisx021239[]={
0x6644,0x6645, 0, 0, 0,0x6646, 0,0x6647,
0x6648,0x6649, 0, 0, 0, 0, 0,0x664A,
0, 0, 0, 0,0x664B, 0,0x664C, 0,
@@ -6884,7 +6884,7 @@ static uint16 tab_uni_jisx021239[]={
};
/* page 40 0x98AB-0x98CC */
-static uint16 tab_uni_jisx021240[]={
+static const uint16 tab_uni_jisx021240[]={
0x683A, 0,0x683B,0x683C, 0,0x683D, 0, 0,
0,0x683E, 0, 0,0x683F,0x6840, 0,0x6841,
0x6842, 0, 0, 0,0x6843, 0, 0,0x6844,
@@ -6892,7 +6892,7 @@ static uint16 tab_uni_jisx021240[]={
0,0x6847};
/* page 41 0x98E1-0x9960 */
-static uint16 tab_uni_jisx021241[]={
+static const uint16 tab_uni_jisx021241[]={
0x6848, 0,0x6849, 0,0x684A,0x684B,0x684C, 0,
0,0x684D, 0, 0, 0, 0, 0, 0,
0, 0,0x684E, 0, 0,0x684F, 0, 0,
@@ -6912,7 +6912,7 @@ static uint16 tab_uni_jisx021241[]={
};
/* page 42 0x999B-0x9A5D */
-static uint16 tab_uni_jisx021242[]={
+static const uint16 tab_uni_jisx021242[]={
0x6877, 0,0x6878,0x747A,0x6879, 0, 0, 0,
0, 0, 0,0x687A, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x687B,0x687C,0x687D,
@@ -6940,7 +6940,7 @@ static uint16 tab_uni_jisx021242[]={
0, 0,0x6955};
/* page 43 0x9AAA-0x9C7B */
-static uint16 tab_uni_jisx021243[]={
+static const uint16 tab_uni_jisx021243[]={
0x6956, 0,0x6957, 0,0x6958,0x6959, 0, 0,
0x695A, 0,0x695B,0x695C,0x695D, 0, 0,0x695E,
0,0x695F, 0, 0,0x6960,0x6961, 0,0x6962,
@@ -7002,7 +7002,7 @@ static uint16 tab_uni_jisx021243[]={
0,0x6B58};
/* page 44 0x9CE6-0x9E1D */
-static uint16 tab_uni_jisx021244[]={
+static const uint16 tab_uni_jisx021244[]={
0x6B59, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x6B5A, 0, 0, 0,
0,0x6B5B, 0,0x6B5C, 0, 0, 0, 0,
@@ -7045,7 +7045,7 @@ static uint16 tab_uni_jisx021244[]={
};
/* page 45 0x9E7A-0x9FA5 */
-static uint16 tab_uni_jisx021245[]={
+static const uint16 tab_uni_jisx021245[]={
0x6C59,0x6C5A,0x6C5B, 0, 0, 0,0x6C5C, 0,
0x6C5D,0x6C5E,0x6C5F,0x6C60, 0,0x6C61, 0, 0,
0, 0, 0, 0,0x6C62,0x6C63, 0, 0,
@@ -7086,15 +7086,15 @@ static uint16 tab_uni_jisx021245[]={
0x6D61,0x6D62, 0,0x6D63};
/* page 46 0xF929-0xF929 */
-static uint16 tab_uni_jisx021246[]={
+static const uint16 tab_uni_jisx021246[]={
0x7445};
/* page 47 0xF9DC-0xF9DC */
-static uint16 tab_uni_jisx021247[]={
+static const uint16 tab_uni_jisx021247[]={
0x7472};
/* page 48 0xFA00-0xFA2D */
-static uint16 tab_uni_jisx021248[]={
+static const uint16 tab_uni_jisx021248[]={
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x7434,0x7437,
0x7438,0x743D,0x7444,0x7447,0x7448,0x744E,0x744F,0x7453,
@@ -7103,11 +7103,11 @@ static uint16 tab_uni_jisx021248[]={
0x7470,0x7473,0x7477,0x7478,0x7479,0x747D};
/* page 49 0xFF00-0XFF07 */
-static uint16 tab_uni_jisx021249[]={
+static const uint16 tab_uni_jisx021249[]={
0, 0,0x742A, 0, 0, 0, 0,0x7429};
/* page 50 0xFFE4-0xFFE4 */
-static uint16 tab_uni_jisx021250[]={
+static const uint16 tab_uni_jisx021250[]={
0x2243};
static int
@@ -7218,34 +7218,34 @@ my_uni_jisx0212_onechar(int code){
}
/* page 0 0x222F-0x2244 */
-static uint16 tab_jisx0212_uni0[]={
+static const uint16 tab_jisx0212_uni0[]={
0x02D8,0x02C7,0x00B8,0x02D9,0x02DD,0x00AF,0x02DB,0x02DA,
0xFF5E,0x0384,0x0385, 0, 0, 0, 0, 0,
0, 0, 0,0x00A1,0xFFE4,0x00BF};
/* page 1 0x226B-0x2271 */
-static uint16 tab_jisx0212_uni1[]={
+static const uint16 tab_jisx0212_uni1[]={
0x00BA,0x00AA,0x00A9,0x00AE,0x2122,0x00A4,0x2116};
/* page 2 0x2661-0x267C */
-static uint16 tab_jisx0212_uni2[]={
+static const uint16 tab_jisx0212_uni2[]={
0x0386,0x0388,0x0389,0x038A,0x03AA, 0,0x038C, 0,
0x038E,0x03AB, 0,0x038F, 0, 0, 0, 0,
0x03AC,0x03AD,0x03AE,0x03AF,0x03CA,0x0390,0x03CC,0x03C2,
0x03CD,0x03CB,0x03B0,0x03CE};
/* page 3 0x2742-0x274E */
-static uint16 tab_jisx0212_uni3[]={
+static const uint16 tab_jisx0212_uni3[]={
0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,0x0409,
0x040A,0x040B,0x040C,0x040E,0x040F};
/* page 4 0x2772-0x277E */
-static uint16 tab_jisx0212_uni4[]={
+static const uint16 tab_jisx0212_uni4[]={
0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,
0x045A,0x045B,0x045C,0x045E,0x045F};
/* page 5 0x2921-0x2950 */
-static uint16 tab_jisx0212_uni5[]={
+static const uint16 tab_jisx0212_uni5[]={
0x00C6,0x0110, 0,0x0126, 0,0x0132, 0,0x0141,
0x013F, 0,0x014A,0x00D8,0x0152, 0,0x0166,0x00DE,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -7255,7 +7255,7 @@ static uint16 tab_jisx0212_uni5[]={
};
/* page 6 0x2A21-0x2A77 */
-static uint16 tab_jisx0212_uni6[]={
+static const uint16 tab_jisx0212_uni6[]={
0x00C1,0x00C0,0x00C4,0x00C2,0x0102,0x01CD,0x0100,0x0104,
0x00C5,0x00C3,0x0106,0x0108,0x010C,0x00C7,0x010A,0x010E,
0x00C9,0x00C8,0x00CB,0x00CA,0x011A,0x0116,0x0112,0x0118,
@@ -7269,7 +7269,7 @@ static uint16 tab_jisx0212_uni6[]={
0x0174,0x00DD,0x0178,0x0176,0x0179,0x017D,0x017B};
/* page 7 0x2B21-0x2B77 */
-static uint16 tab_jisx0212_uni7[]={
+static const uint16 tab_jisx0212_uni7[]={
0x00E1,0x00E0,0x00E4,0x00E2,0x0103,0x01CE,0x0101,0x0105,
0x00E5,0x00E3,0x0107,0x0109,0x010D,0x00E7,0x010B,0x010F,
0x00E9,0x00E8,0x00EB,0x00EA,0x011B,0x0117,0x0113,0x0119,
@@ -7283,7 +7283,7 @@ static uint16 tab_jisx0212_uni7[]={
0x0175,0x00FD,0x00FF,0x0177,0x017A,0x017E,0x017C};
/* page 8 0x3021-0x307E */
-static uint16 tab_jisx0212_uni8[]={
+static const uint16 tab_jisx0212_uni8[]={
0x4E02,0x4E04,0x4E05,0x4E0C,0x4E12,0x4E1F,0x4E23,0x4E24,
0x4E28,0x4E2B,0x4E2E,0x4E2F,0x4E30,0x4E35,0x4E40,0x4E41,
0x4E44,0x4E47,0x4E51,0x4E5A,0x4E5C,0x4E63,0x4E68,0x4E69,
@@ -7298,7 +7298,7 @@ static uint16 tab_jisx0212_uni8[]={
0x4F7A,0x4F7D,0x4F7E,0x4F81,0x4F82,0x4F84};
/* page 9 0x3121-0x317E */
-static uint16 tab_jisx0212_uni9[]={
+static const uint16 tab_jisx0212_uni9[]={
0x4F85,0x4F89,0x4F8A,0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,
0x4F94,0x4F97,0x4F99,0x4F9A,0x4F9E,0x4F9F,0x4FB2,0x4FB7,
0x4FB9,0x4FBB,0x4FBC,0x4FBD,0x4FBE,0x4FC0,0x4FC1,0x4FC5,
@@ -7313,7 +7313,7 @@ static uint16 tab_jisx0212_uni9[]={
0x5084,0x5086,0x508A,0x508E,0x508F,0x5090};
/* page 10 0x3221-0x327E */
-static uint16 tab_jisx0212_uni10[]={
+static const uint16 tab_jisx0212_uni10[]={
0x5092,0x5093,0x5094,0x5096,0x509B,0x509C,0x509E,0x509F,
0x50A0,0x50A1,0x50A2,0x50AA,0x50AF,0x50B0,0x50B9,0x50BA,
0x50BD,0x50C0,0x50C3,0x50C4,0x50C7,0x50CC,0x50CE,0x50D0,
@@ -7328,7 +7328,7 @@ static uint16 tab_jisx0212_uni10[]={
0x51B8,0x51BA,0x51BC,0x51BE,0x51BF,0x51C2};
/* page 11 0x3321-0x337E */
-static uint16 tab_jisx0212_uni11[]={
+static const uint16 tab_jisx0212_uni11[]={
0x51C8,0x51CF,0x51D1,0x51D2,0x51D3,0x51D5,0x51D8,0x51DE,
0x51E2,0x51E5,0x51EE,0x51F2,0x51F3,0x51F4,0x51F7,0x5201,
0x5202,0x5205,0x5212,0x5213,0x5215,0x5216,0x5218,0x5222,
@@ -7343,7 +7343,7 @@ static uint16 tab_jisx0212_uni11[]={
0x52F6,0x52F7,0x5300,0x5303,0x530A,0x530B};
/* page 12 0x3421-0x347E */
-static uint16 tab_jisx0212_uni12[]={
+static const uint16 tab_jisx0212_uni12[]={
0x530C,0x5311,0x5313,0x5318,0x531B,0x531C,0x531E,0x531F,
0x5325,0x5327,0x5328,0x5329,0x532B,0x532C,0x532D,0x5330,
0x5332,0x5335,0x533C,0x533D,0x533E,0x5342,0x534C,0x534B,
@@ -7358,7 +7358,7 @@ static uint16 tab_jisx0212_uni12[]={
0x5469,0x546B,0x546D,0x546E,0x5474,0x547F};
/* page 13 0x3521-0x357E */
-static uint16 tab_jisx0212_uni13[]={
+static const uint16 tab_jisx0212_uni13[]={
0x5481,0x5483,0x5485,0x5488,0x5489,0x548D,0x5491,0x5495,
0x5496,0x549C,0x549F,0x54A1,0x54A6,0x54A7,0x54A9,0x54AA,
0x54AD,0x54AE,0x54B1,0x54B7,0x54B9,0x54BA,0x54BB,0x54BF,
@@ -7373,7 +7373,7 @@ static uint16 tab_jisx0212_uni13[]={
0x55C9,0x55CB,0x55CC,0x55CE,0x55D1,0x55D2};
/* page 14 0x3621-0x367E */
-static uint16 tab_jisx0212_uni14[]={
+static const uint16 tab_jisx0212_uni14[]={
0x55D3,0x55D7,0x55D8,0x55DB,0x55DE,0x55E2,0x55E9,0x55F6,
0x55FF,0x5605,0x5608,0x560A,0x560D,0x560E,0x560F,0x5610,
0x5611,0x5612,0x5619,0x562C,0x5630,0x5633,0x5635,0x5637,
@@ -7388,7 +7388,7 @@ static uint16 tab_jisx0212_uni14[]={
0x56E6,0x56E7,0x56E8,0x56F1,0x56EB,0x56ED};
/* page 15 0x3721-0x377E */
-static uint16 tab_jisx0212_uni15[]={
+static const uint16 tab_jisx0212_uni15[]={
0x56F6,0x56F7,0x5701,0x5702,0x5707,0x570A,0x570C,0x5711,
0x5715,0x571A,0x571B,0x571D,0x5720,0x5722,0x5723,0x5724,
0x5725,0x5729,0x572A,0x572C,0x572E,0x572F,0x5733,0x5734,
@@ -7403,7 +7403,7 @@ static uint16 tab_jisx0212_uni15[]={
0x57FF,0x5803,0x5804,0x5808,0x5809,0x57E1};
/* page 16 0x3821-0x387E */
-static uint16 tab_jisx0212_uni16[]={
+static const uint16 tab_jisx0212_uni16[]={
0x580C,0x580D,0x581B,0x581E,0x581F,0x5820,0x5826,0x5827,
0x582D,0x5832,0x5839,0x583F,0x5849,0x584C,0x584D,0x584F,
0x5850,0x5855,0x585F,0x5861,0x5864,0x5867,0x5868,0x5878,
@@ -7418,7 +7418,7 @@ static uint16 tab_jisx0212_uni16[]={
0x595E,0x595F,0x5961,0x5963,0x596B,0x596D};
/* page 17 0x3921-0x397E */
-static uint16 tab_jisx0212_uni17[]={
+static const uint16 tab_jisx0212_uni17[]={
0x596F,0x5972,0x5975,0x5976,0x5979,0x597B,0x597C,0x598B,
0x598C,0x598E,0x5992,0x5995,0x5997,0x599F,0x59A4,0x59A7,
0x59AD,0x59AE,0x59AF,0x59B0,0x59B3,0x59B7,0x59BA,0x59BC,
@@ -7433,7 +7433,7 @@ static uint16 tab_jisx0212_uni17[]={
0x5AB3,0x5AB5,0x5AB8,0x5ABA,0x5ABB,0x5ABF};
/* page 18 0x3A21-0x3A7E */
-static uint16 tab_jisx0212_uni18[]={
+static const uint16 tab_jisx0212_uni18[]={
0x5AC4,0x5AC6,0x5AC8,0x5ACF,0x5ADA,0x5ADC,0x5AE0,0x5AE5,
0x5AEA,0x5AEE,0x5AF5,0x5AF6,0x5AFD,0x5B00,0x5B01,0x5B08,
0x5B17,0x5B34,0x5B19,0x5B1B,0x5B1D,0x5B21,0x5B25,0x5B2D,
@@ -7448,7 +7448,7 @@ static uint16 tab_jisx0212_uni18[]={
0x5C5C,0x5C62,0x5C63,0x5C67,0x5C68,0x5C69};
/* page 19 0x3B21-0x3B7E */
-static uint16 tab_jisx0212_uni19[]={
+static const uint16 tab_jisx0212_uni19[]={
0x5C6D,0x5C70,0x5C74,0x5C75,0x5C7A,0x5C7B,0x5C7C,0x5C7D,
0x5C87,0x5C88,0x5C8A,0x5C8F,0x5C92,0x5C9D,0x5C9F,0x5CA0,
0x5CA2,0x5CA3,0x5CA6,0x5CAA,0x5CB2,0x5CB4,0x5CB5,0x5CBA,
@@ -7463,7 +7463,7 @@ static uint16 tab_jisx0212_uni19[]={
0x5DD0,0x5DCE,0x5DD8,0x5DD9,0x5DE0,0x5DE4};
/* page 20 0x3C21-0x3C7E */
-static uint16 tab_jisx0212_uni20[]={
+static const uint16 tab_jisx0212_uni20[]={
0x5DE9,0x5DF8,0x5DF9,0x5E00,0x5E07,0x5E0D,0x5E12,0x5E14,
0x5E15,0x5E18,0x5E1F,0x5E20,0x5E2E,0x5E28,0x5E32,0x5E35,
0x5E3E,0x5E4B,0x5E50,0x5E49,0x5E51,0x5E56,0x5E58,0x5E5B,
@@ -7478,7 +7478,7 @@ static uint16 tab_jisx0212_uni20[]={
0x5F58,0x5F5B,0x5F60,0x5F63,0x5F64,0x5F67};
/* page 21 0x3D21-0x3D7E */
-static uint16 tab_jisx0212_uni21[]={
+static const uint16 tab_jisx0212_uni21[]={
0x5F6F,0x5F72,0x5F74,0x5F75,0x5F78,0x5F7A,0x5F7D,0x5F7E,
0x5F89,0x5F8D,0x5F8F,0x5F96,0x5F9C,0x5F9D,0x5FA2,0x5FA7,
0x5FAB,0x5FA4,0x5FAC,0x5FAF,0x5FB0,0x5FB1,0x5FB8,0x5FC4,
@@ -7493,7 +7493,7 @@ static uint16 tab_jisx0212_uni21[]={
0x60A4,0x60A5,0x60A8,0x60B0,0x60B1,0x60B7};
/* page 22 0x3E21-0x3E7E */
-static uint16 tab_jisx0212_uni22[]={
+static const uint16 tab_jisx0212_uni22[]={
0x60BB,0x60BE,0x60C2,0x60C4,0x60C8,0x60C9,0x60CA,0x60CB,
0x60CE,0x60CF,0x60D4,0x60D5,0x60D9,0x60DB,0x60DD,0x60DE,
0x60E2,0x60E5,0x60F2,0x60F5,0x60F8,0x60FC,0x60FD,0x6102,
@@ -7508,7 +7508,7 @@ static uint16 tab_jisx0212_uni22[]={
0x61DF,0x61E1,0x61E2,0x61E7,0x61E9,0x61E5};
/* page 23 0x3F21-0x3F7E */
-static uint16 tab_jisx0212_uni23[]={
+static const uint16 tab_jisx0212_uni23[]={
0x61EC,0x61ED,0x61EF,0x6201,0x6203,0x6204,0x6207,0x6213,
0x6215,0x621C,0x6220,0x6222,0x6223,0x6227,0x6229,0x622B,
0x6239,0x623D,0x6242,0x6243,0x6244,0x6246,0x624C,0x6250,
@@ -7523,7 +7523,7 @@ static uint16 tab_jisx0212_uni23[]={
0x6366,0x636C,0x636D,0x6371,0x6374,0x6375};
/* page 24 0x4021-0x407E */
-static uint16 tab_jisx0212_uni24[]={
+static const uint16 tab_jisx0212_uni24[]={
0x6378,0x637C,0x637D,0x637F,0x6382,0x6384,0x6387,0x638A,
0x6390,0x6394,0x6395,0x6399,0x639A,0x639E,0x63A4,0x63A6,
0x63AD,0x63AE,0x63AF,0x63BD,0x63C1,0x63C5,0x63C8,0x63CE,
@@ -7538,7 +7538,7 @@ static uint16 tab_jisx0212_uni24[]={
0x64A8,0x64AC,0x64B3,0x64BD,0x64BE,0x64BF};
/* page 25 0x4121-0x417E */
-static uint16 tab_jisx0212_uni25[]={
+static const uint16 tab_jisx0212_uni25[]={
0x64C4,0x64C9,0x64CA,0x64CB,0x64CC,0x64CE,0x64D0,0x64D1,
0x64D5,0x64D7,0x64E4,0x64E5,0x64E9,0x64EA,0x64ED,0x64F0,
0x64F5,0x64F7,0x64FB,0x64FF,0x6501,0x6504,0x6508,0x6509,
@@ -7553,7 +7553,7 @@ static uint16 tab_jisx0212_uni25[]={
0x660D,0x6611,0x6612,0x6615,0x6616,0x661D};
/* page 26 0x4221-0x427E */
-static uint16 tab_jisx0212_uni26[]={
+static const uint16 tab_jisx0212_uni26[]={
0x661E,0x6621,0x6622,0x6623,0x6624,0x6626,0x6629,0x662A,
0x662B,0x662C,0x662E,0x6630,0x6631,0x6633,0x6639,0x6637,
0x6640,0x6645,0x6646,0x664A,0x664C,0x6651,0x664E,0x6657,
@@ -7568,7 +7568,7 @@ static uint16 tab_jisx0212_uni26[]={
0x6747,0x6748,0x674C,0x6754,0x6755,0x675D};
/* page 27 0x4321-0x437E */
-static uint16 tab_jisx0212_uni27[]={
+static const uint16 tab_jisx0212_uni27[]={
0x6766,0x676C,0x676E,0x6774,0x6776,0x677B,0x6781,0x6784,
0x678E,0x678F,0x6791,0x6793,0x6796,0x6798,0x6799,0x679B,
0x67B0,0x67B1,0x67B2,0x67B5,0x67BB,0x67BC,0x67BD,0x67F9,
@@ -7583,7 +7583,7 @@ static uint16 tab_jisx0212_uni27[]={
0x68B2,0x68BB,0x68C5,0x68C8,0x68CC,0x68CF};
/* page 28 0x4421-0x447E */
-static uint16 tab_jisx0212_uni28[]={
+static const uint16 tab_jisx0212_uni28[]={
0x68D0,0x68D1,0x68D3,0x68D6,0x68D9,0x68DC,0x68DD,0x68E5,
0x68E8,0x68EA,0x68EB,0x68EC,0x68ED,0x68F0,0x68F1,0x68F5,
0x68F6,0x68FB,0x68FC,0x68FD,0x6906,0x6909,0x690A,0x6910,
@@ -7598,7 +7598,7 @@ static uint16 tab_jisx0212_uni28[]={
0x6A1D,0x6A20,0x6A24,0x6A28,0x6A30,0x6A32};
/* page 29 0x4521-0x457E */
-static uint16 tab_jisx0212_uni29[]={
+static const uint16 tab_jisx0212_uni29[]={
0x6A34,0x6A37,0x6A3B,0x6A3E,0x6A3F,0x6A45,0x6A46,0x6A49,
0x6A4A,0x6A4E,0x6A50,0x6A51,0x6A52,0x6A55,0x6A56,0x6A5B,
0x6A64,0x6A67,0x6A6A,0x6A71,0x6A73,0x6A7E,0x6A81,0x6A83,
@@ -7613,7 +7613,7 @@ static uint16 tab_jisx0212_uni29[]={
0x6B67,0x6B6B,0x6B6E,0x6B70,0x6B75,0x6B7D};
/* page 30 0x4621-0x467E */
-static uint16 tab_jisx0212_uni30[]={
+static const uint16 tab_jisx0212_uni30[]={
0x6B7E,0x6B82,0x6B85,0x6B97,0x6B9B,0x6B9F,0x6BA0,0x6BA2,
0x6BA3,0x6BA8,0x6BA9,0x6BAC,0x6BAD,0x6BAE,0x6BB0,0x6BB8,
0x6BB9,0x6BBD,0x6BBE,0x6BC3,0x6BC4,0x6BC9,0x6BCC,0x6BD6,
@@ -7628,7 +7628,7 @@ static uint16 tab_jisx0212_uni30[]={
0x6CCF,0x6CD0,0x6CD1,0x6CD2,0x6CD4,0x6CD6};
/* page 31 0x4721-0x477E */
-static uint16 tab_jisx0212_uni31[]={
+static const uint16 tab_jisx0212_uni31[]={
0x6CDA,0x6CDC,0x6CE0,0x6CE7,0x6CE9,0x6CEB,0x6CEC,0x6CEE,
0x6CF2,0x6CF4,0x6D04,0x6D07,0x6D0A,0x6D0E,0x6D0F,0x6D11,
0x6D13,0x6D1A,0x6D26,0x6D27,0x6D28,0x6C67,0x6D2E,0x6D2F,
@@ -7643,7 +7643,7 @@ static uint16 tab_jisx0212_uni31[]={
0x6E53,0x6E54,0x6E57,0x6E5C,0x6E5D,0x6E5E};
/* page 32 0x4821-0x487E */
-static uint16 tab_jisx0212_uni32[]={
+static const uint16 tab_jisx0212_uni32[]={
0x6E62,0x6E63,0x6E68,0x6E73,0x6E7B,0x6E7D,0x6E8D,0x6E93,
0x6E99,0x6EA0,0x6EA7,0x6EAD,0x6EAE,0x6EB1,0x6EB3,0x6EBB,
0x6EBF,0x6EC0,0x6EC1,0x6EC3,0x6EC7,0x6EC8,0x6ECA,0x6ECD,
@@ -7658,7 +7658,7 @@ static uint16 tab_jisx0212_uni32[]={
0x6FB6,0x6FBC,0x6FC5,0x6FC7,0x6FC8,0x6FCA};
/* page 33 0x4921-0x497E */
-static uint16 tab_jisx0212_uni33[]={
+static const uint16 tab_jisx0212_uni33[]={
0x6FDA,0x6FDE,0x6FE8,0x6FE9,0x6FF0,0x6FF5,0x6FF9,0x6FFC,
0x6FFD,0x7000,0x7005,0x7006,0x7007,0x700D,0x7017,0x7020,
0x7023,0x702F,0x7034,0x7037,0x7039,0x703C,0x7043,0x7044,
@@ -7673,7 +7673,7 @@ static uint16 tab_jisx0212_uni33[]={
0x7152,0x7157,0x715A,0x715C,0x715E,0x7160};
/* page 34 0x4A21-0x4A7E */
-static uint16 tab_jisx0212_uni34[]={
+static const uint16 tab_jisx0212_uni34[]={
0x7168,0x7179,0x7180,0x7185,0x7187,0x718C,0x7192,0x719A,
0x719B,0x71A0,0x71A2,0x71AF,0x71B0,0x71B2,0x71B3,0x71BA,
0x71BF,0x71C0,0x71C1,0x71C4,0x71CB,0x71CC,0x71D3,0x71D6,
@@ -7688,7 +7688,7 @@ static uint16 tab_jisx0212_uni34[]={
0x72DF,0x72E5,0x72F3,0x72F4,0x72FA,0x72FB};
/* page 35 0x4B21-0x4B7E */
-static uint16 tab_jisx0212_uni35[]={
+static const uint16 tab_jisx0212_uni35[]={
0x72FE,0x7302,0x7304,0x7305,0x7307,0x730B,0x730D,0x7312,
0x7313,0x7318,0x7319,0x731E,0x7322,0x7324,0x7327,0x7328,
0x732C,0x7331,0x7332,0x7335,0x733A,0x733B,0x733D,0x7343,
@@ -7703,7 +7703,7 @@ static uint16 tab_jisx0212_uni35[]={
0x73F5,0x73F7,0x73F9,0x73FA,0x73FB,0x73FD};
/* page 36 0x4C21-0x4C7E */
-static uint16 tab_jisx0212_uni36[]={
+static const uint16 tab_jisx0212_uni36[]={
0x73FF,0x7400,0x7401,0x7404,0x7407,0x740A,0x7411,0x741A,
0x741B,0x7424,0x7426,0x7428,0x7429,0x742A,0x742B,0x742C,
0x742D,0x742E,0x742F,0x7430,0x7431,0x7439,0x7440,0x7443,
@@ -7718,7 +7718,7 @@ static uint16 tab_jisx0212_uni36[]={
0x74F4,0x74FA,0x74FB,0x74FC,0x74FF,0x7506};
/* page 37 0x4D21-0x4D7E */
-static uint16 tab_jisx0212_uni37[]={
+static const uint16 tab_jisx0212_uni37[]={
0x7512,0x7516,0x7517,0x7520,0x7521,0x7524,0x7527,0x7529,
0x752A,0x752F,0x7536,0x7539,0x753D,0x753E,0x753F,0x7540,
0x7543,0x7547,0x7548,0x754E,0x7550,0x7552,0x7557,0x755E,
@@ -7733,7 +7733,7 @@ static uint16 tab_jisx0212_uni37[]={
0x762D,0x7632,0x7633,0x7635,0x7638,0x7639};
/* page 38 0x4E21-0x4E7E */
-static uint16 tab_jisx0212_uni38[]={
+static const uint16 tab_jisx0212_uni38[]={
0x763A,0x763C,0x764A,0x7640,0x7641,0x7643,0x7644,0x7645,
0x7649,0x764B,0x7655,0x7659,0x765F,0x7664,0x7665,0x766D,
0x766E,0x766F,0x7671,0x7674,0x7681,0x7685,0x768C,0x768D,
@@ -7748,7 +7748,7 @@ static uint16 tab_jisx0212_uni38[]={
0x7757,0x775C,0x775E,0x775F,0x7760,0x7762};
/* page 39 0x4F21-0x4F7E */
-static uint16 tab_jisx0212_uni39[]={
+static const uint16 tab_jisx0212_uni39[]={
0x7764,0x7767,0x776A,0x776C,0x7770,0x7772,0x7773,0x7774,
0x777A,0x777D,0x7780,0x7784,0x778C,0x778D,0x7794,0x7795,
0x7796,0x779A,0x779F,0x77A2,0x77A7,0x77AA,0x77AE,0x77AF,
@@ -7763,7 +7763,7 @@ static uint16 tab_jisx0212_uni39[]={
0x78AC,0x78AD,0x78B0,0x78B1,0x78B2,0x78B3};
/* page 40 0x5021-0x507E */
-static uint16 tab_jisx0212_uni40[]={
+static const uint16 tab_jisx0212_uni40[]={
0x78BB,0x78BD,0x78BF,0x78C7,0x78C8,0x78C9,0x78CC,0x78CE,
0x78D2,0x78D3,0x78D5,0x78D6,0x78E4,0x78DB,0x78DF,0x78E0,
0x78E1,0x78E6,0x78EA,0x78F2,0x78F3,0x7900,0x78F6,0x78F7,
@@ -7778,7 +7778,7 @@ static uint16 tab_jisx0212_uni40[]={
0x79CF,0x79D4,0x79D6,0x79DA,0x79DD,0x79DE};
/* page 41 0x5121-0x517E */
-static uint16 tab_jisx0212_uni41[]={
+static const uint16 tab_jisx0212_uni41[]={
0x79E0,0x79E2,0x79E5,0x79EA,0x79EB,0x79ED,0x79F1,0x79F8,
0x79FC,0x7A02,0x7A03,0x7A07,0x7A09,0x7A0A,0x7A0C,0x7A11,
0x7A15,0x7A1B,0x7A1E,0x7A21,0x7A27,0x7A2B,0x7A2D,0x7A2F,
@@ -7793,7 +7793,7 @@ static uint16 tab_jisx0212_uni41[]={
0x7B2A,0x7B2B,0x7B2D,0x7B2E,0x7B2F,0x7B30};
/* page 42 0x5221-0x527E */
-static uint16 tab_jisx0212_uni42[]={
+static const uint16 tab_jisx0212_uni42[]={
0x7B31,0x7B34,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B47,0x7B4E,
0x7B55,0x7B60,0x7B64,0x7B66,0x7B69,0x7B6A,0x7B6D,0x7B6F,
0x7B72,0x7B73,0x7B77,0x7B84,0x7B89,0x7B8E,0x7B90,0x7B91,
@@ -7808,7 +7808,7 @@ static uint16 tab_jisx0212_uni42[]={
0x7C59,0x7C5A,0x7C5B,0x7C5C,0x7C5D,0x7C5E};
/* page 43 0x5321-0x537E */
-static uint16 tab_jisx0212_uni43[]={
+static const uint16 tab_jisx0212_uni43[]={
0x7C61,0x7C63,0x7C67,0x7C69,0x7C6D,0x7C6E,0x7C70,0x7C72,
0x7C79,0x7C7C,0x7C7D,0x7C86,0x7C87,0x7C8F,0x7C94,0x7C9E,
0x7CA0,0x7CA6,0x7CB0,0x7CB6,0x7CB7,0x7CBA,0x7CBB,0x7CBC,
@@ -7823,7 +7823,7 @@ static uint16 tab_jisx0212_uni43[]={
0x7D8C,0x7D8D,0x7D91,0x7D96,0x7D97,0x7D9D};
/* page 44 0x5421-0x547E */
-static uint16 tab_jisx0212_uni44[]={
+static const uint16 tab_jisx0212_uni44[]={
0x7D9E,0x7DA6,0x7DA7,0x7DAA,0x7DB3,0x7DB6,0x7DB7,0x7DB9,
0x7DC2,0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DCC,0x7DCD,0x7DCE,
0x7DD7,0x7DD9,0x7E00,0x7DE2,0x7DE5,0x7DE6,0x7DEA,0x7DEB,
@@ -7838,7 +7838,7 @@ static uint16 tab_jisx0212_uni44[]={
0x7F61,0x7F63,0x7F64,0x7F65,0x7F66,0x7F6D};
/* page 45 0x5521-0x557E */
-static uint16 tab_jisx0212_uni45[]={
+static const uint16 tab_jisx0212_uni45[]={
0x7F71,0x7F7D,0x7F7E,0x7F7F,0x7F80,0x7F8B,0x7F8D,0x7F8F,
0x7F90,0x7F91,0x7F96,0x7F97,0x7F9C,0x7FA1,0x7FA2,0x7FA6,
0x7FAA,0x7FAD,0x7FB4,0x7FBC,0x7FBF,0x7FC0,0x7FC3,0x7FC8,
@@ -7853,7 +7853,7 @@ static uint16 tab_jisx0212_uni45[]={
0x80D5,0x80D7,0x80D8,0x80E0,0x80ED,0x80EE};
/* page 46 0x5621-0x567E */
-static uint16 tab_jisx0212_uni46[]={
+static const uint16 tab_jisx0212_uni46[]={
0x80F0,0x80F2,0x80F3,0x80F6,0x80F9,0x80FA,0x80FE,0x8103,
0x810B,0x8116,0x8117,0x8118,0x811C,0x811E,0x8120,0x8124,
0x8127,0x812C,0x8130,0x8135,0x813A,0x813C,0x8145,0x8147,
@@ -7868,7 +7868,7 @@ static uint16 tab_jisx0212_uni46[]={
0x8234,0x823A,0x8243,0x8244,0x8245,0x8246};
/* page 47 0x5721-0x577E */
-static uint16 tab_jisx0212_uni47[]={
+static const uint16 tab_jisx0212_uni47[]={
0x824B,0x824E,0x824F,0x8251,0x8256,0x825C,0x8260,0x8263,
0x8267,0x826D,0x8274,0x827B,0x827D,0x827F,0x8280,0x8281,
0x8283,0x8284,0x8287,0x8289,0x828A,0x828E,0x8291,0x8294,
@@ -7883,7 +7883,7 @@ static uint16 tab_jisx0212_uni47[]={
0x8351,0x8355,0x8356,0x8357,0x8370,0x8378};
/* page 48 0x5821-0x587E */
-static uint16 tab_jisx0212_uni48[]={
+static const uint16 tab_jisx0212_uni48[]={
0x837D,0x837F,0x8380,0x8382,0x8384,0x8386,0x838D,0x8392,
0x8394,0x8395,0x8398,0x8399,0x839B,0x839C,0x839D,0x83A6,
0x83A7,0x83A9,0x83AC,0x83BE,0x83BF,0x83C0,0x83C7,0x83C9,
@@ -7898,7 +7898,7 @@ static uint16 tab_jisx0212_uni48[]={
0x84C2,0x84C7,0x84C8,0x84CC,0x84CF,0x84D3};
/* page 49 0x5921-0x597E */
-static uint16 tab_jisx0212_uni49[]={
+static const uint16 tab_jisx0212_uni49[]={
0x84DC,0x84E7,0x84EA,0x84EF,0x84F0,0x84F1,0x84F2,0x84F7,
0x8532,0x84FA,0x84FB,0x84FD,0x8502,0x8503,0x8507,0x850C,
0x850E,0x8510,0x851C,0x851E,0x8522,0x8523,0x8524,0x8525,
@@ -7913,7 +7913,7 @@ static uint16 tab_jisx0212_uni49[]={
0x85E6,0x85E8,0x85ED,0x85F3,0x85F6,0x85FC};
/* page 50 0x5A21-0x5A7E */
-static uint16 tab_jisx0212_uni50[]={
+static const uint16 tab_jisx0212_uni50[]={
0x85FF,0x8600,0x8604,0x8605,0x860D,0x860E,0x8610,0x8611,
0x8612,0x8618,0x8619,0x861B,0x861E,0x8621,0x8627,0x8629,
0x8636,0x8638,0x863A,0x863C,0x863D,0x8640,0x8642,0x8646,
@@ -7928,7 +7928,7 @@ static uint16 tab_jisx0212_uni50[]={
0x8714,0x8719,0x871E,0x871F,0x8721,0x8723};
/* page 51 0x5B21-0x5B7E */
-static uint16 tab_jisx0212_uni51[]={
+static const uint16 tab_jisx0212_uni51[]={
0x8728,0x872E,0x872F,0x8731,0x8732,0x8739,0x873A,0x873C,
0x873D,0x873E,0x8740,0x8743,0x8745,0x874D,0x8758,0x875D,
0x8761,0x8764,0x8765,0x876F,0x8771,0x8772,0x877B,0x8783,
@@ -7943,7 +7943,7 @@ static uint16 tab_jisx0212_uni51[]={
0x8828,0x882D,0x882E,0x8830,0x8832,0x8835};
/* page 52 0x5C21-0x5C7E */
-static uint16 tab_jisx0212_uni52[]={
+static const uint16 tab_jisx0212_uni52[]={
0x883A,0x883C,0x8841,0x8843,0x8845,0x8848,0x8849,0x884A,
0x884B,0x884E,0x8851,0x8855,0x8856,0x8858,0x885A,0x885C,
0x885F,0x8860,0x8864,0x8869,0x8871,0x8879,0x887B,0x8880,
@@ -7958,7 +7958,7 @@ static uint16 tab_jisx0212_uni52[]={
0x896B,0x896E,0x8970,0x8973,0x8975,0x897A};
/* page 53 0x5D21-0x5D7E */
-static uint16 tab_jisx0212_uni53[]={
+static const uint16 tab_jisx0212_uni53[]={
0x897B,0x897C,0x897D,0x8989,0x898D,0x8990,0x8994,0x8995,
0x899B,0x899C,0x899F,0x89A0,0x89A5,0x89B0,0x89B4,0x89B5,
0x89B6,0x89B7,0x89BC,0x89D4,0x89D5,0x89D6,0x89D7,0x89D8,
@@ -7973,7 +7973,7 @@ static uint16 tab_jisx0212_uni53[]={
0x8A9F,0x8AA7,0x8AA9,0x8AAE,0x8AAF,0x8AB3};
/* page 54 0x5E21-0x5E7E */
-static uint16 tab_jisx0212_uni54[]={
+static const uint16 tab_jisx0212_uni54[]={
0x8AB6,0x8AB7,0x8ABB,0x8ABE,0x8AC3,0x8AC6,0x8AC8,0x8AC9,
0x8ACA,0x8AD1,0x8AD3,0x8AD4,0x8AD5,0x8AD7,0x8ADD,0x8ADF,
0x8AEC,0x8AF0,0x8AF4,0x8AF5,0x8AF6,0x8AFC,0x8AFF,0x8B05,
@@ -7988,7 +7988,7 @@ static uint16 tab_jisx0212_uni54[]={
0x8C73,0x8C75,0x8C76,0x8C7B,0x8C7E,0x8C86};
/* page 55 0x5F21-0x5F7E */
-static uint16 tab_jisx0212_uni55[]={
+static const uint16 tab_jisx0212_uni55[]={
0x8C87,0x8C8B,0x8C90,0x8C92,0x8C93,0x8C99,0x8C9B,0x8C9C,
0x8CA4,0x8CB9,0x8CBA,0x8CC5,0x8CC6,0x8CC9,0x8CCB,0x8CCF,
0x8CD6,0x8CD5,0x8CD9,0x8CDD,0x8CE1,0x8CE8,0x8CEC,0x8CEF,
@@ -8003,7 +8003,7 @@ static uint16 tab_jisx0212_uni55[]={
0x8E11,0x8E14,0x8E16,0x8E20,0x8E21,0x8E22};
/* page 56 0x6021-0x607E */
-static uint16 tab_jisx0212_uni56[]={
+static const uint16 tab_jisx0212_uni56[]={
0x8E23,0x8E26,0x8E27,0x8E31,0x8E33,0x8E36,0x8E37,0x8E38,
0x8E39,0x8E3D,0x8E40,0x8E41,0x8E4B,0x8E4D,0x8E4E,0x8E4F,
0x8E54,0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E61,0x8E62,0x8E69,
@@ -8018,7 +8018,7 @@ static uint16 tab_jisx0212_uni56[]={
0x8F35,0x8F36,0x8F37,0x8F3A,0x8F40,0x8F41};
/* page 57 0x6121-0x617E */
-static uint16 tab_jisx0212_uni57[]={
+static const uint16 tab_jisx0212_uni57[]={
0x8F43,0x8F47,0x8F4F,0x8F51,0x8F52,0x8F53,0x8F54,0x8F55,
0x8F58,0x8F5D,0x8F5E,0x8F65,0x8F9D,0x8FA0,0x8FA1,0x8FA4,
0x8FA5,0x8FA6,0x8FB5,0x8FB6,0x8FB8,0x8FBE,0x8FC0,0x8FC1,
@@ -8033,7 +8033,7 @@ static uint16 tab_jisx0212_uni57[]={
0x90B4,0x90B6,0x90BD,0x90CC,0x90BE,0x90C3};
/* page 58 0x6221-0x627E */
-static uint16 tab_jisx0212_uni58[]={
+static const uint16 tab_jisx0212_uni58[]={
0x90C4,0x90C5,0x90C7,0x90C8,0x90D5,0x90D7,0x90D8,0x90D9,
0x90DC,0x90DD,0x90DF,0x90E5,0x90D2,0x90F6,0x90EB,0x90EF,
0x90F0,0x90F4,0x90FE,0x90FF,0x9100,0x9104,0x9105,0x9106,
@@ -8048,7 +8048,7 @@ static uint16 tab_jisx0212_uni58[]={
0x91B3,0x91B6,0x91BB,0x91BC,0x91BD,0x91BF};
/* page 59 0x6321-0x637E */
-static uint16 tab_jisx0212_uni59[]={
+static const uint16 tab_jisx0212_uni59[]={
0x91C2,0x91C3,0x91C5,0x91D3,0x91D4,0x91D7,0x91D9,0x91DA,
0x91DE,0x91E4,0x91E5,0x91E9,0x91EA,0x91EC,0x91ED,0x91EE,
0x91EF,0x91F0,0x91F1,0x91F7,0x91F9,0x91FB,0x91FD,0x9200,
@@ -8063,7 +8063,7 @@ static uint16 tab_jisx0212_uni59[]={
0x9289,0x928A,0x928D,0x928E,0x9292,0x9297};
/* page 60 0x6421-0x647E */
-static uint16 tab_jisx0212_uni60[]={
+static const uint16 tab_jisx0212_uni60[]={
0x9299,0x929F,0x92A0,0x92A4,0x92A5,0x92A7,0x92A8,0x92AB,
0x92AF,0x92B2,0x92B6,0x92B8,0x92BA,0x92BB,0x92BC,0x92BD,
0x92BF,0x92C0,0x92C1,0x92C2,0x92C3,0x92C5,0x92C6,0x92C7,
@@ -8078,7 +8078,7 @@ static uint16 tab_jisx0212_uni60[]={
0x936F,0x9370,0x9371,0x9373,0x9374,0x9376};
/* page 61 0x6521-0x657E */
-static uint16 tab_jisx0212_uni61[]={
+static const uint16 tab_jisx0212_uni61[]={
0x937A,0x937D,0x937F,0x9380,0x9381,0x9382,0x9388,0x938A,
0x938B,0x938D,0x938F,0x9392,0x9395,0x9398,0x939B,0x939E,
0x93A1,0x93A3,0x93A4,0x93A6,0x93A8,0x93AB,0x93B4,0x93B5,
@@ -8093,7 +8093,7 @@ static uint16 tab_jisx0212_uni61[]={
0x9471,0x9472,0x9484,0x9483,0x9578,0x9579};
/* page 62 0x6621-0x667E */
-static uint16 tab_jisx0212_uni62[]={
+static const uint16 tab_jisx0212_uni62[]={
0x957E,0x9584,0x9588,0x958C,0x958D,0x958E,0x959D,0x959E,
0x959F,0x95A1,0x95A6,0x95A9,0x95AB,0x95AC,0x95B4,0x95B6,
0x95BA,0x95BD,0x95BF,0x95C6,0x95C8,0x95C9,0x95CB,0x95D0,
@@ -8108,7 +8108,7 @@ static uint16 tab_jisx0212_uni62[]={
0x96DF,0x96E9,0x96EF,0x96F1,0x96FA,0x9702};
/* page 63 0x6721-0x677E */
-static uint16 tab_jisx0212_uni63[]={
+static const uint16 tab_jisx0212_uni63[]={
0x9703,0x9705,0x9709,0x971A,0x971B,0x971D,0x9721,0x9722,
0x9723,0x9728,0x9731,0x9733,0x9741,0x9743,0x974A,0x974E,
0x974F,0x9755,0x9757,0x9758,0x975A,0x975B,0x9763,0x9767,
@@ -8123,7 +8123,7 @@ static uint16 tab_jisx0212_uni63[]={
0x9816,0x981C,0x981E,0x9820,0x9823,0x9826};
/* page 64 0x6821-0x687E */
-static uint16 tab_jisx0212_uni64[]={
+static const uint16 tab_jisx0212_uni64[]={
0x982B,0x982E,0x982F,0x9830,0x9832,0x9833,0x9835,0x9825,
0x983E,0x9844,0x9847,0x984A,0x9851,0x9852,0x9853,0x9856,
0x9857,0x9859,0x985A,0x9862,0x9863,0x9865,0x9866,0x986A,
@@ -8138,7 +8138,7 @@ static uint16 tab_jisx0212_uni64[]={
0x999F,0x99A6,0x99B0,0x99B1,0x99B2,0x99B5};
/* page 65 0x6921-0x697E */
-static uint16 tab_jisx0212_uni65[]={
+static const uint16 tab_jisx0212_uni65[]={
0x99B9,0x99BA,0x99BD,0x99BF,0x99C3,0x99C9,0x99D3,0x99D4,
0x99D9,0x99DA,0x99DC,0x99DE,0x99E7,0x99EA,0x99EB,0x99EC,
0x99F0,0x99F4,0x99F5,0x99F9,0x99FD,0x99FE,0x9A02,0x9A03,
@@ -8153,7 +8153,7 @@ static uint16 tab_jisx0212_uni65[]={
0x9AFD,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B03};
/* page 66 0x6A21-0x6A7E */
-static uint16 tab_jisx0212_uni66[]={
+static const uint16 tab_jisx0212_uni66[]={
0x9B04,0x9B05,0x9B08,0x9B09,0x9B0B,0x9B0C,0x9B0D,0x9B0E,
0x9B10,0x9B12,0x9B16,0x9B19,0x9B1B,0x9B1C,0x9B20,0x9B26,
0x9B2B,0x9B2D,0x9B33,0x9B34,0x9B35,0x9B37,0x9B39,0x9B3A,
@@ -8168,7 +8168,7 @@ static uint16 tab_jisx0212_uni66[]={
0x9BEA,0x9BEB,0x9BEF,0x9BF3,0x9BF7,0x9BF8};
/* page 67 0x6B21-0x6B7E */
-static uint16 tab_jisx0212_uni67[]={
+static const uint16 tab_jisx0212_uni67[]={
0x9BF9,0x9BFA,0x9BFD,0x9BFF,0x9C00,0x9C02,0x9C0B,0x9C0F,
0x9C11,0x9C16,0x9C18,0x9C19,0x9C1A,0x9C1C,0x9C1E,0x9C22,
0x9C23,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,0x9C31,0x9C35,
@@ -8183,7 +8183,7 @@ static uint16 tab_jisx0212_uni67[]={
0x9D6A,0x9D6B,0x9D70,0x9D76,0x9D77,0x9D7B};
/* page 68 0x6C21-0x6C7E */
-static uint16 tab_jisx0212_uni68[]={
+static const uint16 tab_jisx0212_uni68[]={
0x9D7C,0x9D7E,0x9D83,0x9D84,0x9D86,0x9D8A,0x9D8D,0x9D8E,
0x9D92,0x9D93,0x9D95,0x9D96,0x9D97,0x9D98,0x9DA1,0x9DAA,
0x9DAC,0x9DAE,0x9DB1,0x9DB5,0x9DB9,0x9DBC,0x9DBF,0x9DC3,
@@ -8198,7 +8198,7 @@ static uint16 tab_jisx0212_uni68[]={
0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2,0x9EF5};
/* page 69 0x6D21-0x6D63 */
-static uint16 tab_jisx0212_uni69[]={
+static const uint16 tab_jisx0212_uni69[]={
0x9EF8,0x9EFF,0x9F02,0x9F03,0x9F09,0x9F0F,0x9F10,0x9F11,
0x9F12,0x9F14,0x9F16,0x9F17,0x9F19,0x9F1A,0x9F1B,0x9F1F,
0x9F22,0x9F26,0x9F2A,0x9F2B,0x9F2F,0x9F31,0x9F32,0x9F34,
@@ -8210,12 +8210,12 @@ static uint16 tab_jisx0212_uni69[]={
0x9FA2,0x9FA3,0x9FA5};
/* page 70 0x7371-0x737E IBM Kanji and Nonkanji */
-static uint16 tab_jisx0212_uni70[]={
+static const uint16 tab_jisx0212_uni70[]={
0, 0,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,
0x2176,0x2177,0x2178,0x2179,0x2160,0x2161};
/* page 71 0x7421-0x747E IBM Kanji and Nonkanji*/
-static uint16 tab_jisx0212_uni71[]={
+static const uint16 tab_jisx0212_uni71[]={
0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,
0xFF07,0xFF02,0x3231,0x2116,0x2121,0x70BB,0x4EFC,0x50F4,
0x51EC,0x5307,0x5324,0xFA0E,0x548A,0x5759,0xFA0F,0xFA10,
@@ -8685,7 +8685,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
-CHARSET_INFO my_charset_eucjpms_japanese_ci=
+struct charset_info_st my_charset_eucjpms_japanese_ci=
{
97,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
@@ -8718,7 +8718,7 @@ CHARSET_INFO my_charset_eucjpms_japanese_ci=
};
-CHARSET_INFO my_charset_eucjpms_bin=
+struct charset_info_st my_charset_eucjpms_bin=
{
98,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
index 64cf30e3673..3e30931f579 100644
--- a/strings/ctype-extra.c
+++ b/strings/ctype-extra.c
@@ -6,7 +6,7 @@
./conf_to_src ../sql/share/charsets/ > FILE
*/
-/* Copyright (C) 2000-2007 MySQL AB
+/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
#include <m_ctype.h>
#ifdef HAVE_CHARSET_dec8
-uchar ctype_dec8_swedish_ci[] = {
+static const uchar ctype_dec8_swedish_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -45,7 +45,7 @@ uchar ctype_dec8_swedish_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_dec8_swedish_ci[] = {
+static const uchar to_lower_dec8_swedish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -64,7 +64,7 @@ uchar to_lower_dec8_swedish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_dec8_swedish_ci[] = {
+static const uchar to_upper_dec8_swedish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -83,7 +83,7 @@ uchar to_upper_dec8_swedish_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_dec8_swedish_ci[] = {
+static const uchar sort_order_dec8_swedish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -102,7 +102,7 @@ uchar sort_order_dec8_swedish_ci[] = {
0x44,0x4E,0x4F,0x4F,0x4F,0x4F,0x5D,0xF7,0xD8,0x55,0x55,0x55,0x59,0x59,0xDE,0xFF
};
-uint16 to_uni_dec8_swedish_ci[] = {
+static const uint16 to_uni_dec8_swedish_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -140,7 +140,7 @@ uint16 to_uni_dec8_swedish_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp850
-uchar ctype_cp850_general_ci[] = {
+static const uchar ctype_cp850_general_ci[] = {
0x00,
0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x20,0x30,0x30,0x30,0x30,0x30,
@@ -160,7 +160,7 @@ uchar ctype_cp850_general_ci[] = {
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x20
};
-uchar to_lower_cp850_general_ci[] = {
+static const uchar to_lower_cp850_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -179,7 +179,7 @@ uchar to_lower_cp850_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp850_general_ci[] = {
+static const uchar to_upper_cp850_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -198,7 +198,7 @@ uchar to_upper_cp850_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_cp850_general_ci[] = {
+static const uchar sort_order_cp850_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -217,7 +217,7 @@ uchar sort_order_cp850_general_ci[] = {
0xED,0xF1,0xC1,0xFE,0xF6,0xE7,0xBF,0xBC,0xF0,0xE8,0xF7,0xF9,0xF3,0xF2,0xDF,0xE0
};
-uint16 to_uni_cp850_general_ci[] = {
+static const uint16 to_uni_cp850_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -255,7 +255,7 @@ uint16 to_uni_cp850_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin1
-uchar ctype_latin1_german1_ci[] = {
+static const uchar ctype_latin1_german1_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -275,7 +275,7 @@ uchar ctype_latin1_german1_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin1_german1_ci[] = {
+static const uchar to_lower_latin1_german1_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -294,7 +294,7 @@ uchar to_lower_latin1_german1_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin1_german1_ci[] = {
+static const uchar to_upper_latin1_german1_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -313,7 +313,7 @@ uchar to_upper_latin1_german1_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin1_german1_ci[] = {
+static const uchar sort_order_latin1_german1_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -332,7 +332,7 @@ uchar sort_order_latin1_german1_ci[] = {
0xD0,0x4E,0x4F,0x4F,0x4F,0x4F,0x4F,0xF7,0x4F,0x55,0x55,0x55,0x55,0x59,0xDE,0xFF
};
-uint16 to_uni_latin1_german1_ci[] = {
+static const uint16 to_uni_latin1_german1_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -370,7 +370,7 @@ uint16 to_uni_latin1_german1_ci[] = {
#endif
#ifdef HAVE_CHARSET_hp8
-uchar ctype_hp8_english_ci[] = {
+static const uchar ctype_hp8_english_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -390,7 +390,7 @@ uchar ctype_hp8_english_ci[] = {
0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x20
};
-uchar to_lower_hp8_english_ci[] = {
+static const uchar to_lower_hp8_english_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -409,7 +409,7 @@ uchar to_lower_hp8_english_ci[] = {
0xF1,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_hp8_english_ci[] = {
+static const uchar to_upper_hp8_english_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -428,7 +428,7 @@ uchar to_upper_hp8_english_ci[] = {
0xF0,0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_hp8_english_ci[] = {
+static const uchar sort_order_hp8_english_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -447,7 +447,7 @@ uchar sort_order_hp8_english_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_hp8_english_ci[] = {
+static const uint16 to_uni_hp8_english_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -485,7 +485,7 @@ uint16 to_uni_hp8_english_ci[] = {
#endif
#ifdef HAVE_CHARSET_koi8r
-uchar ctype_koi8r_general_ci[] = {
+static const uchar ctype_koi8r_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -505,7 +505,7 @@ uchar ctype_koi8r_general_ci[] = {
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
};
-uchar to_lower_koi8r_general_ci[] = {
+static const uchar to_lower_koi8r_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -524,7 +524,7 @@ uchar to_lower_koi8r_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar to_upper_koi8r_general_ci[] = {
+static const uchar to_upper_koi8r_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -543,7 +543,7 @@ uchar to_upper_koi8r_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_koi8r_general_ci[] = {
+static const uchar sort_order_koi8r_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -562,7 +562,7 @@ uchar sort_order_koi8r_general_ci[] = {
0xEF,0xFF,0xF0,0xF1,0xF2,0xF3,0xE6,0xE1,0xFC,0xFB,0xE7,0xF8,0xFD,0xF9,0xF7,0xFA
};
-uint16 to_uni_koi8r_general_ci[] = {
+static const uint16 to_uni_koi8r_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -600,7 +600,7 @@ uint16 to_uni_koi8r_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin2
-uchar ctype_latin2_general_ci[] = {
+static const uchar ctype_latin2_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -620,7 +620,7 @@ uchar ctype_latin2_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin2_general_ci[] = {
+static const uchar to_lower_latin2_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -639,7 +639,7 @@ uchar to_lower_latin2_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin2_general_ci[] = {
+static const uchar to_upper_latin2_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -658,7 +658,7 @@ uchar to_upper_latin2_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin2_general_ci[] = {
+static const uchar sort_order_latin2_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -677,7 +677,7 @@ uchar sort_order_latin2_general_ci[] = {
0xFF,0x55,0x54,0x57,0x56,0x56,0x56,0xFF,0x5A,0x5F,0x5F,0x5F,0x5F,0x63,0x5E,0xFF
};
-uint16 to_uni_latin2_general_ci[] = {
+static const uint16 to_uni_latin2_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -715,7 +715,7 @@ uint16 to_uni_latin2_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_swe7
-uchar ctype_swe7_swedish_ci[] = {
+static const uchar ctype_swe7_swedish_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -735,7 +735,7 @@ uchar ctype_swe7_swedish_ci[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_swe7_swedish_ci[] = {
+static const uchar to_lower_swe7_swedish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -754,7 +754,7 @@ uchar to_lower_swe7_swedish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_swe7_swedish_ci[] = {
+static const uchar to_upper_swe7_swedish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -773,7 +773,7 @@ uchar to_upper_swe7_swedish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_swe7_swedish_ci[] = {
+static const uchar sort_order_swe7_swedish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -792,7 +792,7 @@ uchar sort_order_swe7_swedish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_swe7_swedish_ci[] = {
+static const uint16 to_uni_swe7_swedish_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -830,7 +830,7 @@ uint16 to_uni_swe7_swedish_ci[] = {
#endif
#ifdef HAVE_CHARSET_ascii
-uchar ctype_ascii_general_ci[] = {
+static const uchar ctype_ascii_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -850,7 +850,7 @@ uchar ctype_ascii_general_ci[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_ascii_general_ci[] = {
+static const uchar to_lower_ascii_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -869,7 +869,7 @@ uchar to_lower_ascii_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_ascii_general_ci[] = {
+static const uchar to_upper_ascii_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -888,7 +888,7 @@ uchar to_upper_ascii_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_ascii_general_ci[] = {
+static const uchar sort_order_ascii_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -907,7 +907,7 @@ uchar sort_order_ascii_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_ascii_general_ci[] = {
+static const uint16 to_uni_ascii_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -945,7 +945,7 @@ uint16 to_uni_ascii_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1251
-uchar ctype_cp1251_bulgarian_ci[] = {
+static const uchar ctype_cp1251_bulgarian_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -965,7 +965,7 @@ uchar ctype_cp1251_bulgarian_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_cp1251_bulgarian_ci[] = {
+static const uchar to_lower_cp1251_bulgarian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -984,7 +984,7 @@ uchar to_lower_cp1251_bulgarian_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1251_bulgarian_ci[] = {
+static const uchar to_upper_cp1251_bulgarian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1003,7 +1003,7 @@ uchar to_upper_cp1251_bulgarian_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar sort_order_cp1251_bulgarian_ci[] = {
+static const uchar sort_order_cp1251_bulgarian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1022,7 +1022,7 @@ uchar sort_order_cp1251_bulgarian_ci[] = {
0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B
};
-uint16 to_uni_cp1251_bulgarian_ci[] = {
+static const uint16 to_uni_cp1251_bulgarian_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1060,7 +1060,7 @@ uint16 to_uni_cp1251_bulgarian_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin1
-uchar ctype_latin1_danish_ci[] = {
+static const uchar ctype_latin1_danish_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1080,7 +1080,7 @@ uchar ctype_latin1_danish_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin1_danish_ci[] = {
+static const uchar to_lower_latin1_danish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1099,7 +1099,7 @@ uchar to_lower_latin1_danish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin1_danish_ci[] = {
+static const uchar to_upper_latin1_danish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1118,7 +1118,7 @@ uchar to_upper_latin1_danish_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin1_danish_ci[] = {
+static const uchar sort_order_latin1_danish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1137,7 +1137,7 @@ uchar sort_order_latin1_danish_ci[] = {
0x44,0x4E,0x4F,0x4F,0x4F,0x4F,0x5C,0xF7,0x5C,0x55,0x55,0x55,0x59,0x59,0xDE,0xFF
};
-uint16 to_uni_latin1_danish_ci[] = {
+static const uint16 to_uni_latin1_danish_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1175,7 +1175,7 @@ uint16 to_uni_latin1_danish_ci[] = {
#endif
#ifdef HAVE_CHARSET_hebrew
-uchar ctype_hebrew_general_ci[] = {
+static const uchar ctype_hebrew_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1195,7 +1195,7 @@ uchar ctype_hebrew_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x20,0x20,0x00
};
-uchar to_lower_hebrew_general_ci[] = {
+static const uchar to_lower_hebrew_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1214,7 +1214,7 @@ uchar to_lower_hebrew_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_hebrew_general_ci[] = {
+static const uchar to_upper_hebrew_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1233,7 +1233,7 @@ uchar to_upper_hebrew_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_hebrew_general_ci[] = {
+static const uchar sort_order_hebrew_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1252,7 +1252,7 @@ uchar sort_order_hebrew_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_hebrew_general_ci[] = {
+static const uint16 to_uni_hebrew_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1290,7 +1290,7 @@ uint16 to_uni_hebrew_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin7
-uchar ctype_latin7_estonian_cs[] = {
+static const uchar ctype_latin7_estonian_cs[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1310,7 +1310,7 @@ uchar ctype_latin7_estonian_cs[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin7_estonian_cs[] = {
+static const uchar to_lower_latin7_estonian_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1329,7 +1329,7 @@ uchar to_lower_latin7_estonian_cs[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin7_estonian_cs[] = {
+static const uchar to_upper_latin7_estonian_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1348,7 +1348,7 @@ uchar to_upper_latin7_estonian_cs[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin7_estonian_cs[] = {
+static const uchar sort_order_latin7_estonian_cs[] = {
0x00,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x2E,0x2F,0x30,0x31,0x32,0x0A,0x0B,
0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
0x2C,0x33,0x34,0x35,0x36,0x37,0x38,0x27,0x39,0x3A,0x3B,0x5D,0x3C,0x28,0x3D,0x3E,
@@ -1367,7 +1367,7 @@ uchar sort_order_latin7_estonian_cs[] = {
0xDC,0xC3,0xC5,0xC9,0xCB,0xF3,0xF7,0x65,0xED,0xBD,0xD9,0xEB,0xF9,0xE2,0xE4,0x53
};
-uint16 to_uni_latin7_estonian_cs[] = {
+static const uint16 to_uni_latin7_estonian_cs[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1405,7 +1405,7 @@ uint16 to_uni_latin7_estonian_cs[] = {
#endif
#ifdef HAVE_CHARSET_latin2
-uchar ctype_latin2_hungarian_ci[] = {
+static const uchar ctype_latin2_hungarian_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1425,7 +1425,7 @@ uchar ctype_latin2_hungarian_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin2_hungarian_ci[] = {
+static const uchar to_lower_latin2_hungarian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1444,7 +1444,7 @@ uchar to_lower_latin2_hungarian_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin2_hungarian_ci[] = {
+static const uchar to_upper_latin2_hungarian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1463,7 +1463,7 @@ uchar to_upper_latin2_hungarian_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin2_hungarian_ci[] = {
+static const uchar sort_order_latin2_hungarian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1482,7 +1482,7 @@ uchar sort_order_latin2_hungarian_ci[] = {
0xFF,0x62,0x63,0x64,0x66,0x67,0x67,0xFF,0x6D,0x77,0x75,0x78,0x78,0x7E,0x74,0xFF
};
-uint16 to_uni_latin2_hungarian_ci[] = {
+static const uint16 to_uni_latin2_hungarian_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1520,7 +1520,7 @@ uint16 to_uni_latin2_hungarian_ci[] = {
#endif
#ifdef HAVE_CHARSET_koi8u
-uchar ctype_koi8u_general_ci[] = {
+static const uchar ctype_koi8u_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1540,7 +1540,7 @@ uchar ctype_koi8u_general_ci[] = {
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
};
-uchar to_lower_koi8u_general_ci[] = {
+static const uchar to_lower_koi8u_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1559,7 +1559,7 @@ uchar to_lower_koi8u_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar to_upper_koi8u_general_ci[] = {
+static const uchar to_upper_koi8u_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1578,7 +1578,7 @@ uchar to_upper_koi8u_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_koi8u_general_ci[] = {
+static const uchar sort_order_koi8u_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1597,7 +1597,7 @@ uchar sort_order_koi8u_general_ci[] = {
0x94,0xA4,0x95,0x96,0x97,0x98,0x89,0x82,0xA1,0xA0,0x8A,0x9D,0xA2,0x9E,0x9C,0x9F
};
-uint16 to_uni_koi8u_general_ci[] = {
+static const uint16 to_uni_koi8u_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1635,7 +1635,7 @@ uint16 to_uni_koi8u_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1251
-uchar ctype_cp1251_ukrainian_ci[] = {
+static const uchar ctype_cp1251_ukrainian_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1655,7 +1655,7 @@ uchar ctype_cp1251_ukrainian_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_cp1251_ukrainian_ci[] = {
+static const uchar to_lower_cp1251_ukrainian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1674,7 +1674,7 @@ uchar to_lower_cp1251_ukrainian_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1251_ukrainian_ci[] = {
+static const uchar to_upper_cp1251_ukrainian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1693,7 +1693,7 @@ uchar to_upper_cp1251_ukrainian_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar sort_order_cp1251_ukrainian_ci[] = {
+static const uchar sort_order_cp1251_ukrainian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1712,7 +1712,7 @@ uchar sort_order_cp1251_ukrainian_ci[] = {
0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4
};
-uint16 to_uni_cp1251_ukrainian_ci[] = {
+static const uint16 to_uni_cp1251_ukrainian_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1750,7 +1750,7 @@ uint16 to_uni_cp1251_ukrainian_ci[] = {
#endif
#ifdef HAVE_CHARSET_greek
-uchar ctype_greek_general_ci[] = {
+static const uchar ctype_greek_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1770,7 +1770,7 @@ uchar ctype_greek_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00
};
-uchar to_lower_greek_general_ci[] = {
+static const uchar to_lower_greek_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1789,7 +1789,7 @@ uchar to_lower_greek_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_greek_general_ci[] = {
+static const uchar to_upper_greek_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1808,7 +1808,7 @@ uchar to_upper_greek_general_ci[] = {
0xD0,0xD1,0xD3,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xCF,0xD5,0xD9,0xFF
};
-uchar sort_order_greek_general_ci[] = {
+static const uchar sort_order_greek_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1827,7 +1827,7 @@ uchar sort_order_greek_general_ci[] = {
0xD0,0xD1,0xD3,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xC9,0xD5,0xCF,0xD5,0xD9,0xFF
};
-uint16 to_uni_greek_general_ci[] = {
+static const uint16 to_uni_greek_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1865,7 +1865,7 @@ uint16 to_uni_greek_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1250
-uchar ctype_cp1250_general_ci[] = {
+static const uchar ctype_cp1250_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -1885,7 +1885,7 @@ uchar ctype_cp1250_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_cp1250_general_ci[] = {
+static const uchar to_lower_cp1250_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1904,7 +1904,7 @@ uchar to_lower_cp1250_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1250_general_ci[] = {
+static const uchar to_upper_cp1250_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1923,7 +1923,7 @@ uchar to_upper_cp1250_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_cp1250_general_ci[] = {
+static const uchar sort_order_cp1250_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -1942,7 +1942,7 @@ uchar sort_order_cp1250_general_ci[] = {
0x47,0x53,0x53,0x55,0x55,0x55,0x55,0xF7,0x58,0x5C,0x5C,0x5C,0x5C,0x60,0x5B,0xFF
};
-uint16 to_uni_cp1250_general_ci[] = {
+static const uint16 to_uni_cp1250_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -1980,7 +1980,7 @@ uint16 to_uni_cp1250_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin2
-uchar ctype_latin2_croatian_ci[] = {
+static const uchar ctype_latin2_croatian_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2000,7 +2000,7 @@ uchar ctype_latin2_croatian_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin2_croatian_ci[] = {
+static const uchar to_lower_latin2_croatian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2019,7 +2019,7 @@ uchar to_lower_latin2_croatian_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin2_croatian_ci[] = {
+static const uchar to_upper_latin2_croatian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2038,7 +2038,7 @@ uchar to_upper_latin2_croatian_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin2_croatian_ci[] = {
+static const uchar sort_order_latin2_croatian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2057,7 +2057,7 @@ uchar sort_order_latin2_croatian_ci[] = {
0x4A,0x57,0x57,0x59,0x59,0x59,0x59,0xFE,0x5D,0x64,0x64,0x64,0x64,0x69,0x62,0xFF
};
-uint16 to_uni_latin2_croatian_ci[] = {
+static const uint16 to_uni_latin2_croatian_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2095,7 +2095,7 @@ uint16 to_uni_latin2_croatian_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1257
-uchar ctype_cp1257_lithuanian_ci[] = {
+static const uchar ctype_cp1257_lithuanian_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2115,7 +2115,7 @@ uchar ctype_cp1257_lithuanian_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00
};
-uchar to_lower_cp1257_lithuanian_ci[] = {
+static const uchar to_lower_cp1257_lithuanian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2134,7 +2134,7 @@ uchar to_lower_cp1257_lithuanian_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1257_lithuanian_ci[] = {
+static const uchar to_upper_cp1257_lithuanian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2153,7 +2153,7 @@ uchar to_upper_cp1257_lithuanian_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_cp1257_lithuanian_ci[] = {
+static const uchar sort_order_cp1257_lithuanian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2172,7 +2172,7 @@ uchar sort_order_cp1257_lithuanian_ci[] = {
0x5A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5E,0xFF,0xFF,0x5D,0xFF,0xFF,0xFF,0xFF
};
-uint16 to_uni_cp1257_lithuanian_ci[] = {
+static const uint16 to_uni_cp1257_lithuanian_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2210,7 +2210,7 @@ uint16 to_uni_cp1257_lithuanian_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin5
-uchar ctype_latin5_turkish_ci[] = {
+static const uchar ctype_latin5_turkish_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2230,7 +2230,7 @@ uchar ctype_latin5_turkish_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin5_turkish_ci[] = {
+static const uchar to_lower_latin5_turkish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2249,7 +2249,7 @@ uchar to_lower_latin5_turkish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin5_turkish_ci[] = {
+static const uchar to_upper_latin5_turkish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2268,7 +2268,7 @@ uchar to_upper_latin5_turkish_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0x49,0xDE,0xFF
};
-uchar sort_order_latin5_turkish_ci[] = {
+static const uchar sort_order_latin5_turkish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2287,7 +2287,7 @@ uchar sort_order_latin5_turkish_ci[] = {
0x49,0x51,0x52,0x52,0x52,0x52,0x53,0xFA,0x52,0x5A,0x5A,0x5A,0x5B,0x4B,0x58,0x5F
};
-uint16 to_uni_latin5_turkish_ci[] = {
+static const uint16 to_uni_latin5_turkish_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2325,7 +2325,7 @@ uint16 to_uni_latin5_turkish_ci[] = {
#endif
#ifdef HAVE_CHARSET_armscii8
-uchar ctype_armscii8_general_ci[] = {
+static const uchar ctype_armscii8_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2345,7 +2345,7 @@ uchar ctype_armscii8_general_ci[] = {
0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x10,0x10
};
-uchar to_lower_armscii8_general_ci[] = {
+static const uchar to_lower_armscii8_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2364,7 +2364,7 @@ uchar to_lower_armscii8_general_ci[] = {
0xF1,0xF1,0xF3,0xF3,0xF5,0xF5,0xF7,0xF7,0xF9,0xF9,0xFB,0xFB,0xFD,0xFD,0xFE,0xFF
};
-uchar to_upper_armscii8_general_ci[] = {
+static const uchar to_upper_armscii8_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2383,7 +2383,7 @@ uchar to_upper_armscii8_general_ci[] = {
0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF
};
-uchar sort_order_armscii8_general_ci[] = {
+static const uchar sort_order_armscii8_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2402,7 +2402,7 @@ uchar sort_order_armscii8_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_armscii8_general_ci[] = {
+static const uint16 to_uni_armscii8_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2440,7 +2440,7 @@ uint16 to_uni_armscii8_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp866
-uchar ctype_cp866_general_ci[] = {
+static const uchar ctype_cp866_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2460,7 +2460,7 @@ uchar ctype_cp866_general_ci[] = {
0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48
};
-uchar to_lower_cp866_general_ci[] = {
+static const uchar to_lower_cp866_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2479,7 +2479,7 @@ uchar to_lower_cp866_general_ci[] = {
0xF1,0xF1,0xF3,0xF3,0xF5,0xF5,0xF7,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp866_general_ci[] = {
+static const uchar to_upper_cp866_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2498,7 +2498,7 @@ uchar to_upper_cp866_general_ci[] = {
0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_cp866_general_ci[] = {
+static const uchar sort_order_cp866_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2517,7 +2517,7 @@ uchar sort_order_cp866_general_ci[] = {
0x81,0x81,0x83,0x83,0x8B,0x8B,0xA3,0xA3,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2
};
-uint16 to_uni_cp866_general_ci[] = {
+static const uint16 to_uni_cp866_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2555,7 +2555,7 @@ uint16 to_uni_cp866_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_keybcs2
-uchar ctype_keybcs2_general_ci[] = {
+static const uchar ctype_keybcs2_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2575,7 +2575,7 @@ uchar ctype_keybcs2_general_ci[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48
};
-uchar to_lower_keybcs2_general_ci[] = {
+static const uchar to_lower_keybcs2_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2594,7 +2594,7 @@ uchar to_lower_keybcs2_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_keybcs2_general_ci[] = {
+static const uchar to_upper_keybcs2_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2613,7 +2613,7 @@ uchar to_upper_keybcs2_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_keybcs2_general_ci[] = {
+static const uchar sort_order_keybcs2_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2632,7 +2632,7 @@ uchar sort_order_keybcs2_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_keybcs2_general_ci[] = {
+static const uint16 to_uni_keybcs2_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2670,7 +2670,7 @@ uint16 to_uni_keybcs2_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_macce
-uchar ctype_macce_general_ci[] = {
+static const uchar ctype_macce_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2690,7 +2690,7 @@ uchar ctype_macce_general_ci[] = {
0x02,0x01,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x02,0x01,0x01,0x02,0x01,0x00
};
-uchar to_lower_macce_general_ci[] = {
+static const uchar to_lower_macce_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2709,7 +2709,7 @@ uchar to_lower_macce_general_ci[] = {
0xF0,0xF3,0x9C,0xF3,0xF5,0xF5,0xF7,0xF7,0xF9,0xF9,0xFA,0xFD,0xB8,0xFD,0xAE,0xFF
};
-uchar to_upper_macce_general_ci[] = {
+static const uchar to_upper_macce_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2728,7 +2728,7 @@ uchar to_upper_macce_general_ci[] = {
0xED,0xF1,0xF2,0xF1,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xB5,0xFB,0xFC,0xFB,0xFE,0xFF
};
-uchar sort_order_macce_general_ci[] = {
+static const uchar sort_order_macce_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2747,7 +2747,7 @@ uchar sort_order_macce_general_ci[] = {
0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x8B,0x8B,0x5B,0x8D,0x5D,0x8D,0x53,0xFF
};
-uint16 to_uni_macce_general_ci[] = {
+static const uint16 to_uni_macce_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2785,7 +2785,7 @@ uint16 to_uni_macce_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_macroman
-uchar ctype_macroman_general_ci[] = {
+static const uchar ctype_macroman_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2805,7 +2805,7 @@ uchar ctype_macroman_general_ci[] = {
0x00,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_macroman_general_ci[] = {
+static const uchar to_lower_macroman_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2824,7 +2824,7 @@ uchar to_lower_macroman_general_ci[] = {
0xF0,0x98,0x9C,0x9E,0x9D,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_macroman_general_ci[] = {
+static const uchar to_upper_macroman_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2843,7 +2843,7 @@ uchar to_upper_macroman_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_macroman_general_ci[] = {
+static const uchar sort_order_macroman_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2862,7 +2862,7 @@ uchar sort_order_macroman_general_ci[] = {
0xF0,0x72,0x85,0x85,0x85,0x61,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_macroman_general_ci[] = {
+static const uint16 to_uni_macroman_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2900,7 +2900,7 @@ uint16 to_uni_macroman_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp852
-uchar ctype_cp852_general_ci[] = {
+static const uchar ctype_cp852_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -2920,7 +2920,7 @@ uchar ctype_cp852_general_ci[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x02,0x00,0x48
};
-uchar to_lower_cp852_general_ci[] = {
+static const uchar to_lower_cp852_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2939,7 +2939,7 @@ uchar to_lower_cp852_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp852_general_ci[] = {
+static const uchar to_upper_cp852_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2958,7 +2958,7 @@ uchar to_upper_cp852_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF
};
-uchar sort_order_cp852_general_ci[] = {
+static const uchar sort_order_cp852_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -2977,7 +2977,7 @@ uchar sort_order_cp852_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0x74,0x69,0x69,0xFE,0xFF
};
-uint16 to_uni_cp852_general_ci[] = {
+static const uint16 to_uni_cp852_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3015,7 +3015,7 @@ uint16 to_uni_cp852_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin7
-uchar ctype_latin7_general_ci[] = {
+static const uchar ctype_latin7_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3035,7 +3035,7 @@ uchar ctype_latin7_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin7_general_ci[] = {
+static const uchar to_lower_latin7_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3054,7 +3054,7 @@ uchar to_lower_latin7_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin7_general_ci[] = {
+static const uchar to_upper_latin7_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3073,7 +3073,7 @@ uchar to_upper_latin7_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin7_general_ci[] = {
+static const uchar sort_order_latin7_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x30,0x32,0x33,0x34,0x35,0x36,0x37,0x2B,0x38,0x39,0x3A,0x5C,0x3B,0x2C,0x3C,0x3D,
@@ -3092,7 +3092,7 @@ uchar sort_order_latin7_general_ci[] = {
0xE1,0xC4,0xC6,0xCA,0xCE,0xD0,0xCC,0x64,0xEC,0xBC,0xDE,0xEA,0xE8,0xFA,0xFC,0x52
};
-uint16 to_uni_latin7_general_ci[] = {
+static const uint16 to_uni_latin7_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3130,7 +3130,7 @@ uint16 to_uni_latin7_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin7
-uchar ctype_latin7_general_cs[] = {
+static const uchar ctype_latin7_general_cs[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3150,7 +3150,7 @@ uchar ctype_latin7_general_cs[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin7_general_cs[] = {
+static const uchar to_lower_latin7_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3169,7 +3169,7 @@ uchar to_lower_latin7_general_cs[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin7_general_cs[] = {
+static const uchar to_upper_latin7_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3188,7 +3188,7 @@ uchar to_upper_latin7_general_cs[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin7_general_cs[] = {
+static const uchar sort_order_latin7_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x30,0x32,0x33,0x34,0x35,0x36,0x37,0x2B,0x38,0x39,0x3A,0x5C,0x3B,0x2C,0x3C,0x3D,
@@ -3207,7 +3207,7 @@ uchar sort_order_latin7_general_cs[] = {
0xE2,0xC5,0xC7,0xCB,0xCF,0xD1,0xCD,0x64,0xED,0xBD,0xDF,0xEB,0xE9,0xFB,0xFD,0x52
};
-uint16 to_uni_latin7_general_cs[] = {
+static const uint16 to_uni_latin7_general_cs[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3245,7 +3245,7 @@ uint16 to_uni_latin7_general_cs[] = {
#endif
#ifdef HAVE_CHARSET_macce
-uchar ctype_macce_bin[] = {
+static const uchar ctype_macce_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3265,7 +3265,7 @@ uchar ctype_macce_bin[] = {
0x02,0x01,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x02,0x01,0x01,0x02,0x01,0x00
};
-uchar to_lower_macce_bin[] = {
+static const uchar to_lower_macce_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3284,7 +3284,7 @@ uchar to_lower_macce_bin[] = {
0xF0,0xF3,0x9C,0xF3,0xF5,0xF5,0xF7,0xF7,0xF9,0xF9,0xFA,0xFD,0xB8,0xFD,0xAE,0xFF
};
-uchar to_upper_macce_bin[] = {
+static const uchar to_upper_macce_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3303,7 +3303,7 @@ uchar to_upper_macce_bin[] = {
0xED,0xF1,0xF2,0xF1,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xB5,0xFB,0xFC,0xFB,0xFE,0xFF
};
-uint16 to_uni_macce_bin[] = {
+static const uint16 to_uni_macce_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3341,7 +3341,7 @@ uint16 to_uni_macce_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp1250
-uchar ctype_cp1250_croatian_ci[] = {
+static const uchar ctype_cp1250_croatian_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3361,7 +3361,7 @@ uchar ctype_cp1250_croatian_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_cp1250_croatian_ci[] = {
+static const uchar to_lower_cp1250_croatian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3380,7 +3380,7 @@ uchar to_lower_cp1250_croatian_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1250_croatian_ci[] = {
+static const uchar to_upper_cp1250_croatian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3399,7 +3399,7 @@ uchar to_upper_cp1250_croatian_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_cp1250_croatian_ci[] = {
+static const uchar sort_order_cp1250_croatian_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3418,7 +3418,7 @@ uchar sort_order_cp1250_croatian_ci[] = {
0x4A,0x57,0x57,0x59,0x59,0x59,0x59,0xC9,0x5D,0x64,0x64,0x64,0x64,0x69,0x62,0xFF
};
-uint16 to_uni_cp1250_croatian_ci[] = {
+static const uint16 to_uni_cp1250_croatian_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3456,7 +3456,7 @@ uint16 to_uni_cp1250_croatian_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin1
-uchar ctype_latin1_general_ci[] = {
+static const uchar ctype_latin1_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3476,7 +3476,7 @@ uchar ctype_latin1_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin1_general_ci[] = {
+static const uchar to_lower_latin1_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3495,7 +3495,7 @@ uchar to_lower_latin1_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin1_general_ci[] = {
+static const uchar to_upper_latin1_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3514,7 +3514,7 @@ uchar to_upper_latin1_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin1_general_ci[] = {
+static const uchar sort_order_latin1_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3533,7 +3533,7 @@ uchar sort_order_latin1_general_ci[] = {
0x59,0x7F,0x83,0x85,0x87,0x89,0x8B,0xBE,0x8D,0x9C,0x9E,0xA0,0xA2,0xAC,0xB1,0xAE
};
-uint16 to_uni_latin1_general_ci[] = {
+static const uint16 to_uni_latin1_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3571,7 +3571,7 @@ uint16 to_uni_latin1_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_latin1
-uchar ctype_latin1_general_cs[] = {
+static const uchar ctype_latin1_general_cs[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3591,7 +3591,7 @@ uchar ctype_latin1_general_cs[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin1_general_cs[] = {
+static const uchar to_lower_latin1_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3610,7 +3610,7 @@ uchar to_lower_latin1_general_cs[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin1_general_cs[] = {
+static const uchar to_upper_latin1_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3629,7 +3629,7 @@ uchar to_upper_latin1_general_cs[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin1_general_cs[] = {
+static const uchar sort_order_latin1_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3648,7 +3648,7 @@ uchar sort_order_latin1_general_cs[] = {
0x5A,0x80,0x84,0x86,0x88,0x8A,0x8C,0xBE,0x8E,0x9D,0x9F,0xA1,0xA3,0xAD,0xB2,0xAE
};
-uint16 to_uni_latin1_general_cs[] = {
+static const uint16 to_uni_latin1_general_cs[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3686,7 +3686,7 @@ uint16 to_uni_latin1_general_cs[] = {
#endif
#ifdef HAVE_CHARSET_cp1251
-uchar ctype_cp1251_bin[] = {
+static const uchar ctype_cp1251_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3706,7 +3706,7 @@ uchar ctype_cp1251_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_cp1251_bin[] = {
+static const uchar to_lower_cp1251_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3725,7 +3725,7 @@ uchar to_lower_cp1251_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1251_bin[] = {
+static const uchar to_upper_cp1251_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3744,7 +3744,7 @@ uchar to_upper_cp1251_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uint16 to_uni_cp1251_bin[] = {
+static const uint16 to_uni_cp1251_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3782,7 +3782,7 @@ uint16 to_uni_cp1251_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp1251
-uchar ctype_cp1251_general_ci[] = {
+static const uchar ctype_cp1251_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3802,7 +3802,7 @@ uchar ctype_cp1251_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_cp1251_general_ci[] = {
+static const uchar to_lower_cp1251_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3821,7 +3821,7 @@ uchar to_lower_cp1251_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1251_general_ci[] = {
+static const uchar to_upper_cp1251_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3840,7 +3840,7 @@ uchar to_upper_cp1251_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar sort_order_cp1251_general_ci[] = {
+static const uchar sort_order_cp1251_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3859,7 +3859,7 @@ uchar sort_order_cp1251_general_ci[] = {
0xAD,0xAF,0xB1,0xB5,0xB9,0xBB,0xBD,0xBF,0xC3,0xC5,0xC7,0xC9,0xCB,0xCD,0xCF,0xD1
};
-uint16 to_uni_cp1251_general_ci[] = {
+static const uint16 to_uni_cp1251_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3897,7 +3897,7 @@ uint16 to_uni_cp1251_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1251
-uchar ctype_cp1251_general_cs[] = {
+static const uchar ctype_cp1251_general_cs[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -3917,7 +3917,7 @@ uchar ctype_cp1251_general_cs[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_cp1251_general_cs[] = {
+static const uchar to_lower_cp1251_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3936,7 +3936,7 @@ uchar to_lower_cp1251_general_cs[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1251_general_cs[] = {
+static const uchar to_upper_cp1251_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3955,7 +3955,7 @@ uchar to_upper_cp1251_general_cs[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar sort_order_cp1251_general_cs[] = {
+static const uchar sort_order_cp1251_general_cs[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -3974,7 +3974,7 @@ uchar sort_order_cp1251_general_cs[] = {
0xAE,0xB0,0xB2,0xB6,0xBA,0xBC,0xBE,0xC0,0xC4,0xC6,0xC8,0xCA,0xCC,0xCE,0xD0,0xD2
};
-uint16 to_uni_cp1251_general_cs[] = {
+static const uint16 to_uni_cp1251_general_cs[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4012,7 +4012,7 @@ uint16 to_uni_cp1251_general_cs[] = {
#endif
#ifdef HAVE_CHARSET_macroman
-uchar ctype_macroman_bin[] = {
+static const uchar ctype_macroman_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4032,7 +4032,7 @@ uchar ctype_macroman_bin[] = {
0x00,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_macroman_bin[] = {
+static const uchar to_lower_macroman_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4051,7 +4051,7 @@ uchar to_lower_macroman_bin[] = {
0xF0,0x98,0x9C,0x9E,0x9D,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_macroman_bin[] = {
+static const uchar to_upper_macroman_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4070,7 +4070,7 @@ uchar to_upper_macroman_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_macroman_bin[] = {
+static const uint16 to_uni_macroman_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4108,7 +4108,7 @@ uint16 to_uni_macroman_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp1256
-uchar ctype_cp1256_general_ci[] = {
+static const uchar ctype_cp1256_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4128,7 +4128,7 @@ uchar ctype_cp1256_general_ci[] = {
0x03,0x03,0x03,0x03,0x02,0x03,0x03,0x00,0x03,0x02,0x03,0x02,0x02,0x00,0x00,0x00
};
-uchar to_lower_cp1256_general_ci[] = {
+static const uchar to_lower_cp1256_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4147,7 +4147,7 @@ uchar to_lower_cp1256_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1256_general_ci[] = {
+static const uchar to_upper_cp1256_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4166,7 +4166,7 @@ uchar to_upper_cp1256_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_cp1256_general_ci[] = {
+static const uchar sort_order_cp1256_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4185,7 +4185,7 @@ uchar sort_order_cp1256_general_ci[] = {
0xAE,0xAF,0xB0,0xB1,0x69,0xB2,0xB3,0xFC,0xB4,0x78,0xB5,0x79,0x7A,0xFD,0xFE,0xFF
};
-uint16 to_uni_cp1256_general_ci[] = {
+static const uint16 to_uni_cp1256_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4223,7 +4223,7 @@ uint16 to_uni_cp1256_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1257
-uchar ctype_cp1257_bin[] = {
+static const uchar ctype_cp1257_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4243,7 +4243,7 @@ uchar ctype_cp1257_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00
};
-uchar to_lower_cp1257_bin[] = {
+static const uchar to_lower_cp1257_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4262,7 +4262,7 @@ uchar to_lower_cp1257_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1257_bin[] = {
+static const uchar to_upper_cp1257_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4281,7 +4281,7 @@ uchar to_upper_cp1257_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uint16 to_uni_cp1257_bin[] = {
+static const uint16 to_uni_cp1257_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4319,7 +4319,7 @@ uint16 to_uni_cp1257_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp1257
-uchar ctype_cp1257_general_ci[] = {
+static const uchar ctype_cp1257_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4339,7 +4339,7 @@ uchar ctype_cp1257_general_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00
};
-uchar to_lower_cp1257_general_ci[] = {
+static const uchar to_lower_cp1257_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4358,7 +4358,7 @@ uchar to_lower_cp1257_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1257_general_ci[] = {
+static const uchar to_upper_cp1257_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4377,7 +4377,7 @@ uchar to_upper_cp1257_general_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_cp1257_general_ci[] = {
+static const uchar sort_order_cp1257_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4396,7 +4396,7 @@ uchar sort_order_cp1257_general_ci[] = {
0x97,0x7D,0x7D,0x83,0x83,0x83,0x83,0xC3,0xA0,0x75,0x97,0xA0,0xA0,0xB0,0xB0,0xFF
};
-uint16 to_uni_cp1257_general_ci[] = {
+static const uint16 to_uni_cp1257_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4434,7 +4434,7 @@ uint16 to_uni_cp1257_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_armscii8
-uchar ctype_armscii8_bin[] = {
+static const uchar ctype_armscii8_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4454,7 +4454,7 @@ uchar ctype_armscii8_bin[] = {
0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x10,0x10
};
-uchar to_lower_armscii8_bin[] = {
+static const uchar to_lower_armscii8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4473,7 +4473,7 @@ uchar to_lower_armscii8_bin[] = {
0xF1,0xF1,0xF3,0xF3,0xF5,0xF5,0xF7,0xF7,0xF9,0xF9,0xFB,0xFB,0xFD,0xFD,0xFE,0xFF
};
-uchar to_upper_armscii8_bin[] = {
+static const uchar to_upper_armscii8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4492,7 +4492,7 @@ uchar to_upper_armscii8_bin[] = {
0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF
};
-uint16 to_uni_armscii8_bin[] = {
+static const uint16 to_uni_armscii8_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4530,7 +4530,7 @@ uint16 to_uni_armscii8_bin[] = {
#endif
#ifdef HAVE_CHARSET_ascii
-uchar ctype_ascii_bin[] = {
+static const uchar ctype_ascii_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4550,7 +4550,7 @@ uchar ctype_ascii_bin[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_ascii_bin[] = {
+static const uchar to_lower_ascii_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4569,7 +4569,7 @@ uchar to_lower_ascii_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_ascii_bin[] = {
+static const uchar to_upper_ascii_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4588,7 +4588,7 @@ uchar to_upper_ascii_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_ascii_bin[] = {
+static const uint16 to_uni_ascii_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4626,7 +4626,7 @@ uint16 to_uni_ascii_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp1250
-uchar ctype_cp1250_bin[] = {
+static const uchar ctype_cp1250_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4646,7 +4646,7 @@ uchar ctype_cp1250_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_cp1250_bin[] = {
+static const uchar to_lower_cp1250_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4665,7 +4665,7 @@ uchar to_lower_cp1250_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1250_bin[] = {
+static const uchar to_upper_cp1250_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4684,7 +4684,7 @@ uchar to_upper_cp1250_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uint16 to_uni_cp1250_bin[] = {
+static const uint16 to_uni_cp1250_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4722,7 +4722,7 @@ uint16 to_uni_cp1250_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp1256
-uchar ctype_cp1256_bin[] = {
+static const uchar ctype_cp1256_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4742,7 +4742,7 @@ uchar ctype_cp1256_bin[] = {
0x03,0x03,0x03,0x03,0x02,0x03,0x03,0x00,0x03,0x02,0x03,0x02,0x02,0x00,0x00,0x00
};
-uchar to_lower_cp1256_bin[] = {
+static const uchar to_lower_cp1256_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4761,7 +4761,7 @@ uchar to_lower_cp1256_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1256_bin[] = {
+static const uchar to_upper_cp1256_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4780,7 +4780,7 @@ uchar to_upper_cp1256_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_cp1256_bin[] = {
+static const uint16 to_uni_cp1256_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4818,7 +4818,7 @@ uint16 to_uni_cp1256_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp866
-uchar ctype_cp866_bin[] = {
+static const uchar ctype_cp866_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4838,7 +4838,7 @@ uchar ctype_cp866_bin[] = {
0x01,0x02,0x01,0x02,0x01,0x02,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48
};
-uchar to_lower_cp866_bin[] = {
+static const uchar to_lower_cp866_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4857,7 +4857,7 @@ uchar to_lower_cp866_bin[] = {
0xF1,0xF1,0xF3,0xF3,0xF5,0xF5,0xF7,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp866_bin[] = {
+static const uchar to_upper_cp866_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4876,7 +4876,7 @@ uchar to_upper_cp866_bin[] = {
0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_cp866_bin[] = {
+static const uint16 to_uni_cp866_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -4914,7 +4914,7 @@ uint16 to_uni_cp866_bin[] = {
#endif
#ifdef HAVE_CHARSET_dec8
-uchar ctype_dec8_bin[] = {
+static const uchar ctype_dec8_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -4934,7 +4934,7 @@ uchar ctype_dec8_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_dec8_bin[] = {
+static const uchar to_lower_dec8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4953,7 +4953,7 @@ uchar to_lower_dec8_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_dec8_bin[] = {
+static const uchar to_upper_dec8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -4972,7 +4972,7 @@ uchar to_upper_dec8_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uint16 to_uni_dec8_bin[] = {
+static const uint16 to_uni_dec8_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5010,7 +5010,7 @@ uint16 to_uni_dec8_bin[] = {
#endif
#ifdef HAVE_CHARSET_greek
-uchar ctype_greek_bin[] = {
+static const uchar ctype_greek_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5030,7 +5030,7 @@ uchar ctype_greek_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00
};
-uchar to_lower_greek_bin[] = {
+static const uchar to_lower_greek_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5049,7 +5049,7 @@ uchar to_lower_greek_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_greek_bin[] = {
+static const uchar to_upper_greek_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5068,7 +5068,7 @@ uchar to_upper_greek_bin[] = {
0xD0,0xD1,0xD3,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xCF,0xD5,0xD9,0xFF
};
-uint16 to_uni_greek_bin[] = {
+static const uint16 to_uni_greek_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5106,7 +5106,7 @@ uint16 to_uni_greek_bin[] = {
#endif
#ifdef HAVE_CHARSET_hebrew
-uchar ctype_hebrew_bin[] = {
+static const uchar ctype_hebrew_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5126,7 +5126,7 @@ uchar ctype_hebrew_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x20,0x20,0x00
};
-uchar to_lower_hebrew_bin[] = {
+static const uchar to_lower_hebrew_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5145,7 +5145,7 @@ uchar to_lower_hebrew_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_hebrew_bin[] = {
+static const uchar to_upper_hebrew_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5164,7 +5164,7 @@ uchar to_upper_hebrew_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_hebrew_bin[] = {
+static const uint16 to_uni_hebrew_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5202,7 +5202,7 @@ uint16 to_uni_hebrew_bin[] = {
#endif
#ifdef HAVE_CHARSET_hp8
-uchar ctype_hp8_bin[] = {
+static const uchar ctype_hp8_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5222,7 +5222,7 @@ uchar ctype_hp8_bin[] = {
0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x20
};
-uchar to_lower_hp8_bin[] = {
+static const uchar to_lower_hp8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5241,7 +5241,7 @@ uchar to_lower_hp8_bin[] = {
0xF1,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_hp8_bin[] = {
+static const uchar to_upper_hp8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5260,7 +5260,7 @@ uchar to_upper_hp8_bin[] = {
0xF0,0xF0,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_hp8_bin[] = {
+static const uint16 to_uni_hp8_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5298,7 +5298,7 @@ uint16 to_uni_hp8_bin[] = {
#endif
#ifdef HAVE_CHARSET_keybcs2
-uchar ctype_keybcs2_bin[] = {
+static const uchar ctype_keybcs2_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5318,7 +5318,7 @@ uchar ctype_keybcs2_bin[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48
};
-uchar to_lower_keybcs2_bin[] = {
+static const uchar to_lower_keybcs2_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5337,7 +5337,7 @@ uchar to_lower_keybcs2_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_keybcs2_bin[] = {
+static const uchar to_upper_keybcs2_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5356,7 +5356,7 @@ uchar to_upper_keybcs2_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_keybcs2_bin[] = {
+static const uint16 to_uni_keybcs2_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5394,7 +5394,7 @@ uint16 to_uni_keybcs2_bin[] = {
#endif
#ifdef HAVE_CHARSET_koi8r
-uchar ctype_koi8r_bin[] = {
+static const uchar ctype_koi8r_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5414,7 +5414,7 @@ uchar ctype_koi8r_bin[] = {
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
};
-uchar to_lower_koi8r_bin[] = {
+static const uchar to_lower_koi8r_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5433,7 +5433,7 @@ uchar to_lower_koi8r_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar to_upper_koi8r_bin[] = {
+static const uchar to_upper_koi8r_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5452,7 +5452,7 @@ uchar to_upper_koi8r_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_koi8r_bin[] = {
+static const uint16 to_uni_koi8r_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5490,7 +5490,7 @@ uint16 to_uni_koi8r_bin[] = {
#endif
#ifdef HAVE_CHARSET_koi8u
-uchar ctype_koi8u_bin[] = {
+static const uchar ctype_koi8u_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5510,7 +5510,7 @@ uchar ctype_koi8u_bin[] = {
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
};
-uchar to_lower_koi8u_bin[] = {
+static const uchar to_lower_koi8u_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5529,7 +5529,7 @@ uchar to_lower_koi8u_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF
};
-uchar to_upper_koi8u_bin[] = {
+static const uchar to_upper_koi8u_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5548,7 +5548,7 @@ uchar to_upper_koi8u_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_koi8u_bin[] = {
+static const uint16 to_uni_koi8u_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5586,7 +5586,7 @@ uint16 to_uni_koi8u_bin[] = {
#endif
#ifdef HAVE_CHARSET_latin2
-uchar ctype_latin2_bin[] = {
+static const uchar ctype_latin2_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5606,7 +5606,7 @@ uchar ctype_latin2_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin2_bin[] = {
+static const uchar to_lower_latin2_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5625,7 +5625,7 @@ uchar to_lower_latin2_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin2_bin[] = {
+static const uchar to_upper_latin2_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5644,7 +5644,7 @@ uchar to_upper_latin2_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uint16 to_uni_latin2_bin[] = {
+static const uint16 to_uni_latin2_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5682,7 +5682,7 @@ uint16 to_uni_latin2_bin[] = {
#endif
#ifdef HAVE_CHARSET_latin5
-uchar ctype_latin5_bin[] = {
+static const uchar ctype_latin5_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5702,7 +5702,7 @@ uchar ctype_latin5_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin5_bin[] = {
+static const uchar to_lower_latin5_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5721,7 +5721,7 @@ uchar to_lower_latin5_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin5_bin[] = {
+static const uchar to_upper_latin5_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5740,7 +5740,7 @@ uchar to_upper_latin5_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0x49,0xDE,0xFF
};
-uint16 to_uni_latin5_bin[] = {
+static const uint16 to_uni_latin5_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5778,7 +5778,7 @@ uint16 to_uni_latin5_bin[] = {
#endif
#ifdef HAVE_CHARSET_latin7
-uchar ctype_latin7_bin[] = {
+static const uchar ctype_latin7_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5798,7 +5798,7 @@ uchar ctype_latin7_bin[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_latin7_bin[] = {
+static const uchar to_lower_latin7_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5817,7 +5817,7 @@ uchar to_lower_latin7_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin7_bin[] = {
+static const uchar to_upper_latin7_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5836,7 +5836,7 @@ uchar to_upper_latin7_bin[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uint16 to_uni_latin7_bin[] = {
+static const uint16 to_uni_latin7_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5874,7 +5874,7 @@ uint16 to_uni_latin7_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp850
-uchar ctype_cp850_bin[] = {
+static const uchar ctype_cp850_bin[] = {
0x00,
0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x20,0x30,0x30,0x30,0x30,0x30,
@@ -5894,7 +5894,7 @@ uchar ctype_cp850_bin[] = {
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x20
};
-uchar to_lower_cp850_bin[] = {
+static const uchar to_lower_cp850_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5913,7 +5913,7 @@ uchar to_lower_cp850_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp850_bin[] = {
+static const uchar to_upper_cp850_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -5932,7 +5932,7 @@ uchar to_upper_cp850_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_cp850_bin[] = {
+static const uint16 to_uni_cp850_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -5970,7 +5970,7 @@ uint16 to_uni_cp850_bin[] = {
#endif
#ifdef HAVE_CHARSET_cp852
-uchar ctype_cp852_bin[] = {
+static const uchar ctype_cp852_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -5990,7 +5990,7 @@ uchar ctype_cp852_bin[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x02,0x00,0x48
};
-uchar to_lower_cp852_bin[] = {
+static const uchar to_lower_cp852_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6009,7 +6009,7 @@ uchar to_lower_cp852_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp852_bin[] = {
+static const uchar to_upper_cp852_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6028,7 +6028,7 @@ uchar to_upper_cp852_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF
};
-uint16 to_uni_cp852_bin[] = {
+static const uint16 to_uni_cp852_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -6066,7 +6066,7 @@ uint16 to_uni_cp852_bin[] = {
#endif
#ifdef HAVE_CHARSET_swe7
-uchar ctype_swe7_bin[] = {
+static const uchar ctype_swe7_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -6086,7 +6086,7 @@ uchar ctype_swe7_bin[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_swe7_bin[] = {
+static const uchar to_lower_swe7_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6105,7 +6105,7 @@ uchar to_lower_swe7_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_swe7_bin[] = {
+static const uchar to_upper_swe7_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6124,7 +6124,7 @@ uchar to_upper_swe7_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_swe7_bin[] = {
+static const uint16 to_uni_swe7_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -6162,7 +6162,7 @@ uint16 to_uni_swe7_bin[] = {
#endif
#ifdef HAVE_CHARSET_geostd8
-uchar ctype_geostd8_general_ci[] = {
+static const uchar ctype_geostd8_general_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -6182,7 +6182,7 @@ uchar ctype_geostd8_general_ci[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_geostd8_general_ci[] = {
+static const uchar to_lower_geostd8_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6201,7 +6201,7 @@ uchar to_lower_geostd8_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_geostd8_general_ci[] = {
+static const uchar to_upper_geostd8_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6220,7 +6220,7 @@ uchar to_upper_geostd8_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar sort_order_geostd8_general_ci[] = {
+static const uchar sort_order_geostd8_general_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6239,7 +6239,7 @@ uchar sort_order_geostd8_general_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_geostd8_general_ci[] = {
+static const uint16 to_uni_geostd8_general_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -6277,7 +6277,7 @@ uint16 to_uni_geostd8_general_ci[] = {
#endif
#ifdef HAVE_CHARSET_geostd8
-uchar ctype_geostd8_bin[] = {
+static const uchar ctype_geostd8_bin[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -6297,7 +6297,7 @@ uchar ctype_geostd8_bin[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar to_lower_geostd8_bin[] = {
+static const uchar to_lower_geostd8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6316,7 +6316,7 @@ uchar to_lower_geostd8_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_geostd8_bin[] = {
+static const uchar to_upper_geostd8_bin[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6335,7 +6335,7 @@ uchar to_upper_geostd8_bin[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uint16 to_uni_geostd8_bin[] = {
+static const uint16 to_uni_geostd8_bin[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -6373,7 +6373,7 @@ uint16 to_uni_geostd8_bin[] = {
#endif
#ifdef HAVE_CHARSET_latin1
-uchar ctype_latin1_spanish_ci[] = {
+static const uchar ctype_latin1_spanish_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -6393,7 +6393,7 @@ uchar ctype_latin1_spanish_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
};
-uchar to_lower_latin1_spanish_ci[] = {
+static const uchar to_lower_latin1_spanish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6412,7 +6412,7 @@ uchar to_lower_latin1_spanish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_latin1_spanish_ci[] = {
+static const uchar to_upper_latin1_spanish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6431,7 +6431,7 @@ uchar to_upper_latin1_spanish_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_latin1_spanish_ci[] = {
+static const uchar sort_order_latin1_spanish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6450,7 +6450,7 @@ uchar sort_order_latin1_spanish_ci[] = {
0x57,0x7F,0x81,0x81,0x81,0x81,0x81,0xBE,0x81,0x9A,0x9A,0x9A,0x9A,0xAA,0xB1,0xAA
};
-uint16 to_uni_latin1_spanish_ci[] = {
+static const uint16 to_uni_latin1_spanish_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -6488,7 +6488,7 @@ uint16 to_uni_latin1_spanish_ci[] = {
#endif
#ifdef HAVE_CHARSET_cp1250
-uchar ctype_cp1250_polish_ci[] = {
+static const uchar ctype_cp1250_polish_ci[] = {
0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x28,0x28,0x28,0x28,0x28,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
@@ -6508,7 +6508,7 @@ uchar ctype_cp1250_polish_ci[] = {
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10
};
-uchar to_lower_cp1250_polish_ci[] = {
+static const uchar to_lower_cp1250_polish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6527,7 +6527,7 @@ uchar to_lower_cp1250_polish_ci[] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar to_upper_cp1250_polish_ci[] = {
+static const uchar to_upper_cp1250_polish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6546,7 +6546,7 @@ uchar to_upper_cp1250_polish_ci[] = {
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF
};
-uchar sort_order_cp1250_polish_ci[] = {
+static const uchar sort_order_cp1250_polish_ci[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -6565,7 +6565,7 @@ uchar sort_order_cp1250_polish_ci[] = {
0x48,0x58,0x57,0x5A,0x59,0x59,0x59,0xC9,0x5D,0x64,0x64,0x64,0x64,0x69,0x62,0xFF
};
-uint16 to_uni_cp1250_polish_ci[] = {
+static const uint16 to_uni_cp1250_polish_ci[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -6602,7 +6602,7 @@ uint16 to_uni_cp1250_polish_ci[] = {
#endif
-CHARSET_INFO compiled_charsets[] = {
+struct charset_info_st compiled_charsets[] = {
#ifdef HAVE_CHARSET_dec8
{
3,0,0,
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index 0267f35ff5c..641fe2ea24e 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -29,7 +29,7 @@
#ifdef HAVE_CHARSET_gb2312
-static uchar NEAR ctype_gb2312[257] =
+static const uchar NEAR ctype_gb2312[257] =
{
0, /* For standard library */
32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
@@ -50,7 +50,7 @@ static uchar NEAR ctype_gb2312[257] =
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
};
-static uchar NEAR to_lower_gb2312[]=
+static const uchar NEAR to_lower_gb2312[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -86,7 +86,7 @@ static uchar NEAR to_lower_gb2312[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR to_upper_gb2312[]=
+static const uchar NEAR to_upper_gb2312[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -122,7 +122,7 @@ static uchar NEAR to_upper_gb2312[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR sort_order_gb2312[]=
+static const uchar NEAR sort_order_gb2312[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -178,7 +178,7 @@ static uint mbcharlen_gb2312(CHARSET_INFO *cs __attribute__((unused)),uint c)
/* page 0 0x2121-0x2658 */
-static uint16 tab_gb2312_uni0[]={
+static const uint16 tab_gb2312_uni0[]={
0x3000,0x3001,0x3002,0x30FB,0x02C9,0x02C7,0x00A8,0x3003,
0x3005,0x2015,0xFF5E,0x2016,0x2026,0x2018,0x2019,0x201C,
0x201D,0x3014,0x3015,0x3008,0x3009,0x300A,0x300B,0x300C,
@@ -349,7 +349,7 @@ static uint16 tab_gb2312_uni0[]={
};
/* page 1 0x2721-0x296F */
-static uint16 tab_gb2312_uni1[]={
+static const uint16 tab_gb2312_uni1[]={
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,
0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,
@@ -426,7 +426,7 @@ static uint16 tab_gb2312_uni1[]={
0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B};
/* page 2 0x3021-0x777E */
-static uint16 tab_gb2312_uni2[]={
+static const uint16 tab_gb2312_uni2[]={
0x554A,0x963F,0x57C3,0x6328,0x54CE,0x5509,0x54C0,0x7691,
0x764C,0x853C,0x77EE,0x827E,0x788D,0x7231,0x9698,0x978D,
0x6C28,0x5B89,0x4FFA,0x6309,0x6697,0x5CB8,0x80FA,0x6848,
@@ -2724,7 +2724,7 @@ static int func_gb2312_uni_onechar(int code){
/* page 0 0x00A4-0x01DC */
-static uint16 tab_uni_gb23120[]={
+static const uint16 tab_uni_gb23120[]={
0x2168, 0, 0,0x216C,0x2127, 0, 0, 0,
0, 0, 0, 0,0x2163,0x2140, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -2767,7 +2767,7 @@ static uint16 tab_uni_gb23120[]={
0x2838};
/* page 1 0x02C7-0x0451 */
-static uint16 tab_uni_gb23121[]={
+static const uint16 tab_uni_gb23121[]={
0x2126, 0,0x2125, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -2820,7 +2820,7 @@ static uint16 tab_uni_gb23121[]={
0x2771, 0,0x2757};
/* page 2 0x2015-0x2312 */
-static uint16 tab_uni_gb23122[]={
+static const uint16 tab_uni_gb23122[]={
0x212A,0x212C, 0,0x212E,0x212F, 0, 0,0x2130,
0x2131, 0, 0, 0, 0, 0, 0, 0,
0,0x212D, 0, 0, 0, 0, 0, 0,
@@ -2919,7 +2919,7 @@ static uint16 tab_uni_gb23122[]={
0, 0, 0, 0, 0,0x2150};
/* page 3 0x2460-0x2642 */
-static uint16 tab_uni_gb23123[]={
+static const uint16 tab_uni_gb23123[]={
0x2259,0x225A,0x225B,0x225C,0x225D,0x225E,0x225F,0x2260,
0x2261,0x2262, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x2245,0x2246,0x2247,0x2248,
@@ -2983,7 +2983,7 @@ static uint16 tab_uni_gb23123[]={
0x2162, 0,0x2161};
/* page 4 0x3000-0x3129 */
-static uint16 tab_uni_gb23124[]={
+static const uint16 tab_uni_gb23124[]={
0x2121,0x2122,0x2123,0x2128, 0,0x2129, 0, 0,
0x2134,0x2135,0x2136,0x2137,0x2138,0x2139,0x213A,0x213B,
0x213E,0x213F, 0,0x217E,0x2132,0x2133,0x213C,0x213D,
@@ -3024,12 +3024,12 @@ static uint16 tab_uni_gb23124[]={
0x2868,0x2869};
/* page 5 0x3220-0x3229 */
-static uint16 tab_uni_gb23125[]={
+static const uint16 tab_uni_gb23125[]={
0x2265,0x2266,0x2267,0x2268,0x2269,0x226A,0x226B,0x226C,
0x226D,0x226E};
/* page 6 0x4E00-0x9B54 */
-static uint16 tab_uni_gb23126[]={
+static const uint16 tab_uni_gb23126[]={
0x523B,0x3621, 0,0x465F, 0, 0, 0,0x4D72,
0x5549,0x487D,0x494F,0x4F42,0x5822,0x323B,0x536B, 0,
0x5824,0x3373, 0,0x5728,0x4752,0x5827,0x4A40, 0,
@@ -5507,7 +5507,7 @@ static uint16 tab_uni_gb23126[]={
0,0x774E, 0, 0,0x4427};
/* page 7 0x9C7C-0x9CE2 */
-static uint16 tab_uni_gb23127[]={
+static const uint16 tab_uni_gb23127[]={
0x5363, 0, 0,0x764F, 0,0x4233,0x7650, 0,
0,0x7651,0x7652,0x7653,0x7654, 0, 0,0x7656,
0,0x312B,0x7657, 0,0x7658,0x7659,0x765A, 0,
@@ -5523,7 +5523,7 @@ static uint16 tab_uni_gb23127[]={
0x772C,0x772D,0x415B,0x772E, 0, 0,0x772F};
/* page 8 0x9E1F-0x9FA0 */
-static uint16 tab_uni_gb23128[]={
+static const uint16 tab_uni_gb23128[]={
0x4471,0x702F,0x3C26,0x7030,0x4379, 0,0x4538,0x513B,
0,0x7031,0x7032,0x7033,0x7034,0x7035,0x513C, 0,
0x516C, 0,0x7037,0x7036,0x5427, 0,0x4D52,0x7038,
@@ -5575,7 +5575,7 @@ static uint16 tab_uni_gb23128[]={
0x396A,0x595F};
/* page 9 0xFF01-0xFFE5 */
-static uint16 tab_uni_gb23129[]={
+static const uint16 tab_uni_gb23129[]={
0x2321,0x2322,0x2323,0x2167,0x2325,0x2326,0x2327,0x2328,
0x2329,0x232A,0x232B,0x232C,0x232D,0x232E,0x232F,0x2330,
0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,
@@ -5765,7 +5765,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_gb2312_chinese_ci=
+struct charset_info_st my_charset_gb2312_chinese_ci=
{
24,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
@@ -5797,7 +5797,7 @@ CHARSET_INFO my_charset_gb2312_chinese_ci=
&my_collation_ci_handler
};
-CHARSET_INFO my_charset_gb2312_bin=
+struct charset_info_st my_charset_gb2312_bin=
{
86,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 7b8bb85652b..46b711d92be 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -25,7 +25,6 @@
* .configure. mbmaxlen_gbk=2
*/
-
#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
@@ -44,7 +43,7 @@
#define gbkhead(e) ((uchar)(e>>8))
#define gbktail(e) ((uchar)(e&0xff))
-static uchar NEAR ctype_gbk[257] =
+static const uchar NEAR ctype_gbk[257] =
{
0, /* For standard library */
32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
@@ -65,7 +64,7 @@ static uchar NEAR ctype_gbk[257] =
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,
};
-static uchar NEAR to_lower_gbk[]=
+static const uchar NEAR to_lower_gbk[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -101,7 +100,7 @@ static uchar NEAR to_lower_gbk[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR to_upper_gbk[]=
+static const uchar NEAR to_upper_gbk[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -137,7 +136,7 @@ static uchar NEAR to_upper_gbk[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR sort_order_gbk[]=
+static const uchar NEAR sort_order_gbk[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -173,7 +172,7 @@ static uchar NEAR sort_order_gbk[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uint16 NEAR gbk_order[]=
+static const uint16 NEAR gbk_order[]=
{
8653,14277,17116,11482,11160,2751,14613,3913,13337,9827,
19496,1759,8105,7103,7836,5638,2223,21433,5878,8006,
@@ -2782,7 +2781,7 @@ static uint mbcharlen_gbk(CHARSET_INFO *cs __attribute__((unused)),uint c)
}
/* page 0 0x8140-0xFE4F */
-static uint16 tab_gbk_uni0[]={
+static const uint16 tab_gbk_uni0[]={
0x4E02,0x4E04,0x4E05,0x4E06,0x4E0F,0x4E12,0x4E17,0x4E1F,
0x4E20,0x4E21,0x4E23,0x4E26,0x4E29,0x4E2E,0x4E2F,0x4E31,
0x4E33,0x4E35,0x4E37,0x4E3C,0x4E40,0x4E41,0x4E42,0x4E44,
@@ -6796,7 +6795,7 @@ static int func_gbk_uni_onechar(int code){
/* page 0 0x00A4-0x0451 */
-static uint16 tab_uni_gbk0[]={
+static const uint16 tab_uni_gbk0[]={
0xA1E8, 0, 0,0xA1EC,0xA1A7, 0, 0, 0,
0, 0, 0, 0,0xA1E3,0xA1C0, 0, 0,
0, 0, 0,0xA1A4, 0, 0, 0, 0,
@@ -6917,7 +6916,7 @@ static uint16 tab_uni_gbk0[]={
0xA7EE,0xA7EF,0xA7F0,0xA7F1, 0,0xA7D7};
/* page 1 0x2010-0x2312 */
-static uint16 tab_uni_gbk1[]={
+static const uint16 tab_uni_gbk1[]={
0xA95C, 0, 0,0xA843,0xA1AA,0xA844,0xA1AC, 0,
0xA1AE,0xA1AF, 0, 0,0xA1B0,0xA1B1, 0, 0,
0, 0, 0, 0, 0,0xA845,0xA1AD, 0,
@@ -7017,7 +7016,7 @@ static uint16 tab_uni_gbk1[]={
0, 0,0xA1D0};
/* page 2 0x2460-0x2642 */
-static uint16 tab_uni_gbk2[]={
+static const uint16 tab_uni_gbk2[]={
0xA2D9,0xA2DA,0xA2DB,0xA2DC,0xA2DD,0xA2DE,0xA2DF,0xA2E0,
0xA2E1,0xA2E2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0xA2C5,0xA2C6,0xA2C7,0xA2C8,
@@ -7081,7 +7080,7 @@ static uint16 tab_uni_gbk2[]={
0xA1E2, 0,0xA1E1};
/* page 3 0x3000-0x3129 */
-static uint16 tab_uni_gbk3[]={
+static const uint16 tab_uni_gbk3[]={
0xA1A1,0xA1A2,0xA1A3,0xA1A8, 0,0xA1A9,0xA965,0xA996,
0xA1B4,0xA1B5,0xA1B6,0xA1B7,0xA1B8,0xA1B9,0xA1BA,0xA1BB,
0xA1BE,0xA1BF,0xA893,0xA1FE,0xA1B2,0xA1B3,0xA1BC,0xA1BD,
@@ -7122,7 +7121,7 @@ static uint16 tab_uni_gbk3[]={
0xA8E8,0xA8E9};
/* page 4 0x3220-0x32A3 */
-static uint16 tab_uni_gbk4[]={
+static const uint16 tab_uni_gbk4[]={
0xA2E5,0xA2E6,0xA2E7,0xA2E8,0xA2E9,0xA2EA,0xA2EB,0xA2EC,
0xA2ED,0xA2EE, 0, 0, 0, 0, 0, 0,
0,0xA95A, 0, 0, 0, 0, 0, 0,
@@ -7142,7 +7141,7 @@ static uint16 tab_uni_gbk4[]={
0, 0, 0,0xA949};
/* page 5 0x338E-0x33D5 */
-static uint16 tab_uni_gbk5[]={
+static const uint16 tab_uni_gbk5[]={
0xA94A,0xA94B, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0xA94C,0xA94D,
0xA94E, 0, 0,0xA94F, 0, 0, 0, 0,
@@ -7155,7 +7154,7 @@ static uint16 tab_uni_gbk5[]={
};
/* page 6 0x4E00-0x9FA5 */
-static uint16 tab_uni_gbk6[]={
+static const uint16 tab_uni_gbk6[]={
0xD2BB,0xB6A1,0x8140,0xC6DF,0x8141,0x8142,0x8143,0xCDF2,
0xD5C9,0xC8FD,0xC9CF,0xCFC2,0xD8A2,0xB2BB,0xD3EB,0x8144,
0xD8A4,0xB3F3,0x8145,0xD7A8,0xC7D2,0xD8A7,0xCAC0,0x8146,
@@ -9771,7 +9770,7 @@ static uint16 tab_uni_gbk6[]={
0xD9DF,0xFD97,0xFD98,0xFD99,0xFD9A,0xFD9B};
/* page 7 0xF92C-0xFA29 */
-static uint16 tab_uni_gbk7[]={
+static const uint16 tab_uni_gbk7[]={
0xFD9C, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -9806,7 +9805,7 @@ static uint16 tab_uni_gbk7[]={
0xFE4C, 0, 0,0xFE4D,0xFE4E,0xFE4F};
/* page 8 0xFE30-0xFFE5 */
-static uint16 tab_uni_gbk8[]={
+static const uint16 tab_uni_gbk8[]={
0xA955,0xA6F2, 0,0xA6F4,0xA6F5,0xA6E0,0xA6E1,0xA6F0,
0xA6F1,0xA6E2,0xA6E3,0xA6EE,0xA6EF,0xA6E6,0xA6E7,0xA6E4,
0xA6E5,0xA6E8,0xA6E9,0xA6EA,0xA6EB, 0, 0, 0,
@@ -10023,7 +10022,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_gbk_chinese_ci=
+struct charset_info_st my_charset_gbk_chinese_ci=
{
28,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
@@ -10055,7 +10054,7 @@ CHARSET_INFO my_charset_gbk_chinese_ci=
&my_collation_ci_handler
};
-CHARSET_INFO my_charset_gbk_bin=
+struct charset_info_st my_charset_gbk_bin=
{
87,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index e5333c4101b..ebd019754c9 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -17,7 +17,7 @@
#include "m_string.h"
#include "m_ctype.h"
-static uchar ctype_latin1[] = {
+static const uchar ctype_latin1[] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@@ -37,7 +37,7 @@ static uchar ctype_latin1[] = {
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
};
-static uchar to_lower_latin1[] = {
+static const uchar to_lower_latin1[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -56,7 +56,7 @@ static uchar to_lower_latin1[] = {
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
-static uchar to_upper_latin1[] = {
+static const uchar to_upper_latin1[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -75,7 +75,7 @@ static uchar to_upper_latin1[] = {
208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
};
-static uchar sort_order_latin1[] = {
+static const uchar sort_order_latin1[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -116,7 +116,7 @@ static uchar sort_order_latin1[] = {
output doesn't reproduce these undefined characters.
*/
-unsigned short cs_to_uni[256]={
+static unsigned const short cs_to_uni[256]={
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -150,7 +150,7 @@ unsigned short cs_to_uni[256]={
0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,
0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF
};
-uchar pl00[256]={
+static const uchar pl00[256]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
@@ -184,7 +184,7 @@ uchar pl00[256]={
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
};
-uchar pl01[256]={
+static const uchar pl01[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -218,7 +218,7 @@ uchar pl01[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar pl02[256]={
+static const uchar pl02[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -252,7 +252,7 @@ uchar pl02[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar pl20[256]={
+static const uchar pl20[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x96,0x97,0x00,0x00,0x00,
@@ -286,7 +286,7 @@ uchar pl20[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar pl21[256]={
+static const uchar pl21[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -320,7 +320,7 @@ uchar pl21[256]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
-uchar *uni_to_cs[256]={
+static const uchar *const uni_to_cs[256]={
pl00,pl01,pl02,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -374,7 +374,7 @@ int my_wc_mb_latin1(CHARSET_INFO *cs __attribute__((unused)),
uchar *str,
uchar *end __attribute__((unused)))
{
- uchar *pl;
+ const uchar *pl;
if (str >= end)
return MY_CS_TOOSMALL;
@@ -416,7 +416,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_latin1=
+struct charset_info_st my_charset_latin1=
{
8,0,0, /* number */
MY_CS_COMPILED | MY_CS_PRIMARY, /* state */
@@ -471,7 +471,7 @@ CHARSET_INFO my_charset_latin1=
* Ü, ü, Ö, ö, Ä, ä
*/
-static uchar sort_order_latin1_de[] = {
+static const uchar sort_order_latin1_de[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -495,7 +495,7 @@ static uchar sort_order_latin1_de[] = {
same as sort_order_latin_de, but maps ALL accented chars to unaccented ones
*/
-uchar combo1map[]={
+static const uchar combo1map[]={
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -514,7 +514,7 @@ uchar combo1map[]={
68, 78, 79, 79, 79, 79, 79,247,216, 85, 85, 85, 85, 89,222, 89
};
-uchar combo2map[]={
+static const uchar combo2map[]={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -716,7 +716,7 @@ static MY_COLLATION_HANDLER my_collation_german2_ci_handler=
};
-CHARSET_INFO my_charset_latin1_german2_ci=
+struct charset_info_st my_charset_latin1_german2_ci=
{
31,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */
@@ -749,7 +749,7 @@ CHARSET_INFO my_charset_latin1_german2_ci=
};
-CHARSET_INFO my_charset_latin1_bin=
+struct charset_info_st my_charset_latin1_bin=
{
47,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 51f93954bd5..6bb7977c294 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -23,7 +23,7 @@
size_t my_caseup_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register uchar *map= cs->to_upper;
+ register const uchar *map= cs->to_upper;
char *str_orig= str;
while (*str)
@@ -44,7 +44,7 @@ size_t my_caseup_str_mb(CHARSET_INFO * cs, char *str)
size_t my_casedn_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register uchar *map= cs->to_lower;
+ register const uchar *map= cs->to_lower;
char *str_orig= str;
while (*str)
@@ -68,7 +68,7 @@ size_t my_caseup_mb(CHARSET_INFO * cs, char *src, size_t srclen,
{
register uint32 l;
register char *srcend= src + srclen;
- register uchar *map= cs->to_upper;
+ register const uchar *map= cs->to_upper;
DBUG_ASSERT(src == dst && srclen == dstlen);
while (src < srcend)
@@ -91,7 +91,7 @@ size_t my_casedn_mb(CHARSET_INFO * cs, char *src, size_t srclen,
{
register uint32 l;
register char *srcend= src + srclen;
- register uchar *map=cs->to_lower;
+ register const uchar *map=cs->to_lower;
DBUG_ASSERT(src == dst && srclen == dstlen);
while (src < srcend)
@@ -115,7 +115,7 @@ size_t my_casedn_mb(CHARSET_INFO * cs, char *src, size_t srclen,
int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
{
register uint32 l;
- register uchar *map=cs->to_upper;
+ register const uchar *map=cs->to_upper;
while (*s && *t)
{
@@ -794,7 +794,7 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
Data was produced from EastAsianWidth.txt
using utt11-dump utility.
*/
-static char pg11[256]=
+static const char pg11[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -806,7 +806,7 @@ static char pg11[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pg23[256]=
+static const char pg23[256]=
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -818,7 +818,7 @@ static char pg23[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pg2E[256]=
+static const char pg2E[256]=
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -830,7 +830,7 @@ static char pg2E[256]=
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pg2F[256]=
+static const char pg2F[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -842,7 +842,7 @@ static char pg2F[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
};
-static char pg30[256]=
+static const char pg30[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
@@ -854,7 +854,7 @@ static char pg30[256]=
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};
-static char pg31[256]=
+static const char pg31[256]=
{
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -866,7 +866,7 @@ static char pg31[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};
-static char pg32[256]=
+static const char pg32[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -878,7 +878,7 @@ static char pg32[256]=
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
};
-static char pg4D[256]=
+static const char pg4D[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -890,7 +890,7 @@ static char pg4D[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pg9F[256]=
+static const char pg9F[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -902,7 +902,7 @@ static char pg9F[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pgA4[256]=
+static const char pgA4[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -914,7 +914,7 @@ static char pgA4[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pgD7[256]=
+static const char pgD7[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -926,7 +926,7 @@ static char pgD7[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pgFA[256]=
+static const char pgFA[256]=
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -938,7 +938,7 @@ static char pgFA[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pgFE[256]=
+static const char pgFE[256]=
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -950,7 +950,7 @@ static char pgFE[256]=
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static char pgFF[256]=
+static const char pgFF[256]=
{
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -962,7 +962,7 @@ static char pgFF[256]=
1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
-static struct {int page; char *p;} utr11_data[256]=
+static const struct {int page; const char *p;} utr11_data[256]=
{
{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 4f3aaa6f668..2c55137e3a0 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -75,7 +75,7 @@ size_t my_strnxfrm_simple(CHARSET_INFO * cs,
uchar *dest, size_t len,
const uchar *src, size_t srclen)
{
- uchar *map= cs->sort_order;
+ const uchar *map= cs->sort_order;
size_t dstlen= len;
set_if_smaller(len, srclen);
if (dest != src)
@@ -101,7 +101,7 @@ int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, size_t slen,
my_bool t_is_prefix)
{
size_t len = ( slen > tlen ) ? tlen : slen;
- uchar *map= cs->sort_order;
+ const uchar *map= cs->sort_order;
if (t_is_prefix && slen > tlen)
slen=tlen;
while (len--)
@@ -195,7 +195,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, size_t a_length,
size_t my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
{
- register uchar *map= cs->to_upper;
+ register const uchar *map= cs->to_upper;
char *str_orig= str;
while ((*str= (char) map[(uchar) *str]) != 0)
str++;
@@ -205,7 +205,7 @@ size_t my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
size_t my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
{
- register uchar *map= cs->to_lower;
+ register const uchar *map= cs->to_lower;
char *str_orig= str;
while ((*str= (char) map[(uchar) *str]) != 0)
str++;
@@ -218,7 +218,7 @@ size_t my_caseup_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
size_t dstlen __attribute__((unused)))
{
char *end= src + srclen;
- register uchar *map= cs->to_upper;
+ register const uchar *map= cs->to_upper;
DBUG_ASSERT(src == dst && srclen == dstlen);
for ( ; src != end ; src++)
*src= (char) map[(uchar) *src];
@@ -231,7 +231,7 @@ size_t my_casedn_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
size_t dstlen __attribute__((unused)))
{
char *end= src + srclen;
- register uchar *map=cs->to_lower;
+ register const uchar *map=cs->to_lower;
DBUG_ASSERT(src == dst && srclen == dstlen);
for ( ; src != end ; src++)
*src= (char) map[(uchar) *src];
@@ -240,7 +240,7 @@ size_t my_casedn_8bit(CHARSET_INFO * cs, char *src, size_t srclen,
int my_strcasecmp_8bit(CHARSET_INFO * cs,const char *s, const char *t)
{
- register uchar *map=cs->to_upper;
+ register const uchar *map=cs->to_upper;
while (map[(uchar) *s] == map[(uchar) *t++])
if (!*s++) return 0;
return ((int) map[(uchar) s[0]] - (int) map[(uchar) t[-1]]);
@@ -303,7 +303,7 @@ void my_hash_sort_simple(CHARSET_INFO *cs,
const uchar *key, size_t len,
ulong *nr1, ulong *nr2)
{
- register uchar *sort_order=cs->sort_order;
+ register const uchar *sort_order=cs->sort_order;
const uchar *end= key + len;
/*
@@ -1235,7 +1235,7 @@ skip:
typedef struct
{
int nchars;
- MY_UNI_IDX uidx;
+ struct my_uni_idx_st uidx;
} uni_idx;
#define PLANE_SIZE 0x100
@@ -1253,10 +1253,12 @@ static int pcmp(const void * f, const void * s)
return res;
}
-static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(size_t))
+static my_bool create_fromuni(struct charset_info_st *cs,
+ void *(*alloc)(size_t))
{
uni_idx idx[PLANE_NUM];
int i,n;
+ struct my_uni_idx_st *tab_from_uni;
/*
Check that Unicode map is loaded.
@@ -1297,16 +1299,18 @@ static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(size_t))
for (i=0; i < PLANE_NUM; i++)
{
int ch,numchars;
+ uchar *tab;
/* Skip empty plane */
if (!idx[i].nchars)
break;
numchars=idx[i].uidx.to-idx[i].uidx.from+1;
- if (!(idx[i].uidx.tab=(uchar*) alloc(numchars * sizeof(*idx[i].uidx.tab))))
+ if (!(idx[i].uidx.tab= tab= (uchar*)
+ alloc(numchars * sizeof(*idx[i].uidx.tab))))
return TRUE;
- bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
+ bzero(tab,numchars*sizeof(*tab));
for (ch=1; ch < PLANE_SIZE; ch++)
{
@@ -1314,25 +1318,27 @@ static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(size_t))
if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc)
{
int ofs= wc - idx[i].uidx.from;
- idx[i].uidx.tab[ofs]= ch;
+ tab[ofs]= ch;
}
}
}
/* Allocate and fill reverse table for each plane */
n=i;
- if (!(cs->tab_from_uni= (MY_UNI_IDX*) alloc(sizeof(MY_UNI_IDX)*(n+1))))
+ if (!(cs->tab_from_uni= tab_from_uni= (struct my_uni_idx_st*)
+ alloc(sizeof(MY_UNI_IDX)*(n+1))))
return TRUE;
for (i=0; i< n; i++)
- cs->tab_from_uni[i]= idx[i].uidx;
+ tab_from_uni[i]= idx[i].uidx;
/* Set end-of-list marker */
- bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX));
+ bzero(&tab_from_uni[i],sizeof(MY_UNI_IDX));
return FALSE;
}
-static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(size_t))
+static my_bool my_cset_init_8bit(struct charset_info_st *cs,
+ void *(*alloc)(size_t))
{
cs->caseup_multiply= 1;
cs->casedn_multiply= 1;
@@ -1340,7 +1346,7 @@ static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(size_t))
return create_fromuni(cs, alloc);
}
-static void set_max_sort_char(CHARSET_INFO *cs)
+static void set_max_sort_char(struct charset_info_st *cs)
{
uchar max_char;
uint i;
@@ -1359,7 +1365,7 @@ static void set_max_sort_char(CHARSET_INFO *cs)
}
}
-static my_bool my_coll_init_simple(CHARSET_INFO *cs,
+static my_bool my_coll_init_simple(struct charset_info_st *cs,
void *(*alloc)(size_t) __attribute__((unused)))
{
set_max_sort_char(cs);
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index cc7581ffe6e..81d1c57412d 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -31,7 +31,7 @@
* .configure. mbmaxlen_sjis=2
*/
-static uchar NEAR ctype_sjis[257] =
+static const uchar NEAR ctype_sjis[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -68,7 +68,7 @@ static uchar NEAR ctype_sjis[257] =
0020, 0020, 0020, 0020, 0020, 0000, 0000, 0000
};
-static uchar NEAR to_lower_sjis[]=
+static const uchar NEAR to_lower_sjis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -104,7 +104,7 @@ static uchar NEAR to_lower_sjis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR to_upper_sjis[]=
+static const uchar NEAR to_upper_sjis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -140,7 +140,7 @@ static uchar NEAR to_upper_sjis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR sort_order_sjis[]=
+static const uchar NEAR sort_order_sjis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -384,7 +384,7 @@ static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)),
}
/* page 0 0x00A1-0x00DF */
-static uint16 tab_sjis_uni0[]={
+static const uint16 tab_sjis_uni0[]={
0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,0xFF68,
0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F,0xFF70,
0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,0xFF78,
@@ -395,7 +395,7 @@ static uint16 tab_sjis_uni0[]={
0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F};
/* page 1 0x8140-0x84BE */
-static uint16 tab_sjis_uni1[]={
+static const uint16 tab_sjis_uni1[]={
0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
@@ -510,7 +510,7 @@ static uint16 tab_sjis_uni1[]={
0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542};
/* page 2 0x889F-0x9FFC */
-static uint16 tab_sjis_uni2[]={
+static const uint16 tab_sjis_uni2[]={
0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
@@ -1261,7 +1261,7 @@ static uint16 tab_sjis_uni2[]={
0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
/* page 3 0xE040-0xEAA4 */
-static uint16 tab_sjis_uni3[]={
+static const uint16 tab_sjis_uni3[]={
0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
@@ -1608,7 +1608,7 @@ static int func_sjis_uni_onechar(int code){
return(0);
}
/* page 0 0x005C-0x00F7 */
-static uint16 tab_uni_sjis0[]={
+static const uint16 tab_uni_sjis0[]={
0x815F, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -1631,7 +1631,7 @@ static uint16 tab_uni_sjis0[]={
0, 0, 0,0x8180};
/* page 1 0x0391-0x0451 */
-static uint16 tab_uni_sjis1[]={
+static const uint16 tab_uni_sjis1[]={
0x839F,0x83A0,0x83A1,0x83A2,0x83A3,0x83A4,0x83A5,0x83A6,
0x83A7,0x83A8,0x83A9,0x83AA,0x83AB,0x83AC,0x83AD,0x83AE,
0x83AF, 0,0x83B0,0x83B1,0x83B2,0x83B3,0x83B4,0x83B5,
@@ -1659,7 +1659,7 @@ static uint16 tab_uni_sjis1[]={
0x8476};
/* page 2 0x2010-0x2312 */
-static uint16 tab_uni_sjis2[]={
+static const uint16 tab_uni_sjis2[]={
0x815D, 0, 0, 0, 0,0x815C,0x8161, 0,
0x8165,0x8166, 0, 0,0x8167,0x8168, 0, 0,
0x81F5,0x81F6, 0, 0, 0,0x8164,0x8163, 0,
@@ -1759,7 +1759,7 @@ static uint16 tab_uni_sjis2[]={
0, 0,0x81DC};
/* page 3 0x2500-0x266F */
-static uint16 tab_uni_sjis3[]={
+static const uint16 tab_uni_sjis3[]={
0x849F,0x84AA,0x84A0,0x84AB, 0, 0, 0, 0,
0, 0, 0, 0,0x84A1, 0, 0,0x84AC,
0x84A2, 0, 0,0x84AD,0x84A4, 0, 0,0x84AF,
@@ -1809,7 +1809,7 @@ static uint16 tab_uni_sjis3[]={
};
/* page 4 0x3000-0x30FE */
-static uint16 tab_uni_sjis4[]={
+static const uint16 tab_uni_sjis4[]={
0x8140,0x8141,0x8142,0x8156, 0,0x8158,0x8159,0x815A,
0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177,0x8178,
0x8179,0x817A,0x81A7,0x81AC,0x816B,0x816C, 0, 0,
@@ -1844,7 +1844,7 @@ static uint16 tab_uni_sjis4[]={
0, 0, 0,0x8145,0x815B,0x8152,0x8153};
/* page 5 0x4E00-0x9481 */
-static uint16 tab_uni_sjis5[]={
+static const uint16 tab_uni_sjis5[]={
0x88EA,0x929A, 0,0x8EB5, 0, 0, 0,0x969C,
0x8FE4,0x8E4F,0x8FE3,0x89BA, 0,0x9573,0x975E, 0,
0x98A0,0x894E, 0, 0,0x8A8E,0x98A1,0x90A2,0x99C0,
@@ -4104,7 +4104,7 @@ static uint16 tab_uni_sjis5[]={
0,0xE876};
/* page 6 0x9577-0x9FA0 */
-static uint16 tab_uni_sjis6[]={
+static const uint16 tab_uni_sjis6[]={
0x92B7, 0, 0, 0, 0, 0, 0, 0,
0,0x96E5, 0,0xE878,0x914D, 0, 0, 0,
0xE879, 0,0x95C2,0xE87A,0x8A4A, 0, 0, 0,
@@ -4433,7 +4433,7 @@ static uint16 tab_uni_sjis6[]={
0,0xEA9E};
/* page 7 0xFF01-0xFFE5 */
-static uint16 tab_uni_sjis7[]={
+static const uint16 tab_uni_sjis7[]={
0x8149, 0,0x8194,0x8190,0x8193,0x8195, 0,0x8169,
0x816A,0x8196,0x817B,0x8143, 0,0x8144,0x815E,0x824F,
0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257,
@@ -4669,7 +4669,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
};
-CHARSET_INFO my_charset_sjis_japanese_ci=
+struct charset_info_st my_charset_sjis_japanese_ci=
{
13,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_NONASCII, /* state */
@@ -4701,7 +4701,7 @@ CHARSET_INFO my_charset_sjis_japanese_ci=
&my_collation_ci_handler
};
-CHARSET_INFO my_charset_sjis_bin=
+struct charset_info_st my_charset_sjis_bin=
{
88,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_NONASCII, /* state */
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index a8c05dc4fd0..b956f1958e9 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -63,7 +63,7 @@
#define X L_MIDDLE
-static int t_ctype[][TOT_LEVELS] = {
+static const int t_ctype[][TOT_LEVELS] = {
/*0x00*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x01*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x02*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
@@ -416,7 +416,7 @@ static uchar NEAR to_upper_tis620[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
-static uchar NEAR sort_order_tis620[]=
+static const uchar NEAR sort_order_tis620[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -476,7 +476,7 @@ static size_t thai2sortable(uchar *tstr, size_t len)
if (isthai(c))
{
- int *t_ctype0= t_ctype[c];
+ const int *t_ctype0= t_ctype[c];
if (isconsnt(c))
l2bias -= 8;
@@ -647,7 +647,7 @@ size_t my_strnxfrm_tis620(CHARSET_INFO *cs __attribute__((unused)),
}
-static unsigned short cs_to_uni[256]={
+static const unsigned short cs_to_uni[256]={
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -681,7 +681,7 @@ static unsigned short cs_to_uni[256]={
0x0E50,0x0E51,0x0E52,0x0E53,0x0E54,0x0E55,0x0E56,0x0E57,
0x0E58,0x0E59,0x0E5A,0x0E5B,0xFFFD,0xFFFD,0xFFFD,0xFFFD
};
-static uchar pl00[256]={
+static const uchar pl00[256]={
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -715,7 +715,7 @@ static uchar pl00[256]={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-static uchar pl0E[256]={
+static const uchar pl0E[256]={
0x0000,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,
0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF,
0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,
@@ -749,7 +749,7 @@ static uchar pl0E[256]={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-static uchar plFF[256]={
+static const uchar plFF[256]={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -783,7 +783,7 @@ static uchar plFF[256]={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x00FF,0x0000,0x0000
};
-static uchar *uni_to_cs[256]={
+static const uchar *const uni_to_cs[256]={
pl00,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,pl0E,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
@@ -838,7 +838,7 @@ int my_wc_mb_tis620(CHARSET_INFO *cs __attribute__((unused)),
uchar *str,
uchar *end __attribute__((unused)))
{
- uchar *pl;
+ const uchar *pl;
if (str >= end)
return MY_CS_TOOSMALL;
@@ -897,7 +897,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
-CHARSET_INFO my_charset_tis620_thai_ci=
+struct charset_info_st my_charset_tis620_thai_ci=
{
18,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
@@ -929,7 +929,7 @@ CHARSET_INFO my_charset_tis620_thai_ci=
&my_collation_ci_handler
};
-CHARSET_INFO my_charset_tis620_bin=
+struct charset_info_st my_charset_tis620_bin=
{
89,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index b2a60265a0a..7f170ca3b40 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -31,7 +31,6 @@
- No combining marks processing is done
*/
-
#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
@@ -49,7 +48,7 @@
#define MY_UCA_CMASK 255
#define MY_UCA_PSHIFT 8
-uint16 page000data[]= { /* 0000 (4 weights per char) */
+static const uint16 page000data[]= { /* 0000 (4 weights per char) */
0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,
@@ -180,7 +179,7 @@ uint16 page000data[]= { /* 0000 (4 weights per char) */
0x1094,0x0000,0x0000,0x0000, 0x105E,0x0000,0x0000,0x0000
};
-uint16 page001data[]= { /* 0100 (3 weights per char) */
+static const uint16 page001data[]= { /* 0100 (3 weights per char) */
0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000,
0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000,
0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000, 0x0E60,0x0000,0x0000,
@@ -268,7 +267,7 @@ uint16 page001data[]= { /* 0100 (3 weights per char) */
0x0E38,0x0000,0x0000, 0x0E38,0x0000,0x0000, 0x0F8D,0x0000,0x0000,
0x0F8D,0x0000,0x0000 };
-uint16 page002data[]= { /* 0200 (3 weights per char) */
+static const uint16 page002data[]= { /* 0200 (3 weights per char) */
0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000,
0x0E33,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000,
0x0E8B,0x0000,0x0000, 0x0E8B,0x0000,0x0000, 0x0EFB,0x0000,0x0000,
@@ -356,7 +355,7 @@ uint16 page002data[]= { /* 0200 (3 weights per char) */
0x0346,0x0000,0x0000, 0x0347,0x0000,0x0000, 0x0348,0x0000,0x0000,
0x0349,0x0000,0x0000 };
-uint16 page003data[]= { /* 0300 (4 weights per char) */
+static const uint16 page003data[]= { /* 0300 (4 weights per char) */
0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,
@@ -487,7 +486,7 @@ uint16 page003data[]= { /* 0300 (4 weights per char) */
0xFBC0,0x83FE,0x0000,0x0000, 0xFBC0,0x83FF,0x0000,0x0000
};
-uint16 page004data[]= { /* 0400 (3 weights per char) */
+static const uint16 page004data[]= { /* 0400 (3 weights per char) */
0x1152,0x0000,0x0000, 0x1152,0x0000,0x0000, 0x1145,0x0000,0x0000,
0x114A,0x0000,0x0000, 0x115A,0x0000,0x0000, 0x1173,0x0000,0x0000,
0x1188,0x0000,0x0000, 0x118C,0x0000,0x0000, 0x1194,0x0000,0x0000,
@@ -575,7 +574,7 @@ uint16 page004data[]= { /* 0400 (3 weights per char) */
0xFBC0,0x84FC,0x0000, 0xFBC0,0x84FD,0x0000, 0xFBC0,0x84FE,0x0000,
0xFBC0,0x84FF,0x0000 };
-uint16 page005data[]= { /* 0500 (3 weights per char) */
+static const uint16 page005data[]= { /* 0500 (3 weights per char) */
0x1144,0x0000,0x0000, 0x1144,0x0000,0x0000, 0x1149,0x0000,0x0000,
0x1149,0x0000,0x0000, 0x116E,0x0000,0x0000, 0x116E,0x0000,0x0000,
0x117B,0x0000,0x0000, 0x117B,0x0000,0x0000, 0x11BD,0x0000,0x0000,
@@ -663,7 +662,7 @@ uint16 page005data[]= { /* 0500 (3 weights per char) */
0xFBC0,0x85FC,0x0000, 0xFBC0,0x85FD,0x0000, 0xFBC0,0x85FE,0x0000,
0xFBC0,0x85FF,0x0000 };
-uint16 page006data[]= { /* 0600 (3 weights per char) */
+static const uint16 page006data[]= { /* 0600 (3 weights per char) */
0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0xFBC0,0x8604,0x0000, 0xFBC0,0x8605,0x0000,
0xFBC0,0x8606,0x0000, 0xFBC0,0x8607,0x0000, 0xFBC0,0x8608,0x0000,
@@ -751,7 +750,7 @@ uint16 page006data[]= { /* 0600 (3 weights per char) */
0x1392,0x0000,0x0000, 0x1347,0x0000,0x0000, 0x13B0,0x0000,0x0000,
0x13BB,0x0000,0x0000 };
-uint16 page007data[]= { /* 0700 (3 weights per char) */
+static const uint16 page007data[]= { /* 0700 (3 weights per char) */
0x0270,0x0000,0x0000, 0x0260,0x0000,0x0000, 0x0261,0x0000,0x0000,
0x023F,0x0000,0x0000, 0x0240,0x0000,0x0000, 0x0241,0x0000,0x0000,
0x0242,0x0000,0x0000, 0x0243,0x0000,0x0000, 0x0244,0x0000,0x0000,
@@ -839,7 +838,7 @@ uint16 page007data[]= { /* 0700 (3 weights per char) */
0xFBC0,0x87FC,0x0000, 0xFBC0,0x87FD,0x0000, 0xFBC0,0x87FE,0x0000,
0xFBC0,0x87FF,0x0000 };
-uint16 page009data[]= { /* 0900 (3 weights per char) */
+static const uint16 page009data[]= { /* 0900 (3 weights per char) */
0xFBC0,0x8900,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0x155A,0x0000,0x0000, 0x155B,0x0000,0x0000,
0x155C,0x0000,0x0000, 0x155D,0x0000,0x0000, 0x155E,0x0000,0x0000,
@@ -927,7 +926,7 @@ uint16 page009data[]= { /* 0900 (3 weights per char) */
0xFBC0,0x89FC,0x0000, 0xFBC0,0x89FD,0x0000, 0xFBC0,0x89FE,0x0000,
0xFBC0,0x89FF,0x0000 };
-uint16 page00Adata[]= { /* 0A00 (3 weights per char) */
+static const uint16 page00Adata[]= { /* 0A00 (3 weights per char) */
0xFBC0,0x8A00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0xFBC0,0x8A04,0x0000, 0x15E7,0x0000,0x0000,
0x15E8,0x0000,0x0000, 0x15EC,0x0000,0x0000, 0x15ED,0x0000,0x0000,
@@ -1015,7 +1014,7 @@ uint16 page00Adata[]= { /* 0A00 (3 weights per char) */
0xFBC0,0x8AFC,0x0000, 0xFBC0,0x8AFD,0x0000, 0xFBC0,0x8AFE,0x0000,
0xFBC0,0x8AFF,0x0000 };
-uint16 page00Bdata[]= { /* 0B00 (3 weights per char) */
+static const uint16 page00Bdata[]= { /* 0B00 (3 weights per char) */
0xFBC0,0x8B00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0xFBC0,0x8B04,0x0000, 0x165D,0x0000,0x0000,
0x165E,0x0000,0x0000, 0x165F,0x0000,0x0000, 0x1660,0x0000,0x0000,
@@ -1103,7 +1102,7 @@ uint16 page00Bdata[]= { /* 0B00 (3 weights per char) */
0xFBC0,0x8BFC,0x0000, 0xFBC0,0x8BFD,0x0000, 0xFBC0,0x8BFE,0x0000,
0xFBC0,0x8BFF,0x0000 };
-uint16 page00Cdata[]= { /* 0C00 (3 weights per char) */
+static const uint16 page00Cdata[]= { /* 0C00 (3 weights per char) */
0xFBC0,0x8C00,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0xFBC0,0x8C04,0x0000, 0x16CD,0x0000,0x0000,
0x16CE,0x0000,0x0000, 0x16CF,0x0000,0x0000, 0x16D0,0x0000,0x0000,
@@ -1191,7 +1190,7 @@ uint16 page00Cdata[]= { /* 0C00 (3 weights per char) */
0xFBC0,0x8CFC,0x0000, 0xFBC0,0x8CFD,0x0000, 0xFBC0,0x8CFE,0x0000,
0xFBC0,0x8CFF,0x0000 };
-uint16 page00Ddata[]= { /* 0D00 (3 weights per char) */
+static const uint16 page00Ddata[]= { /* 0D00 (3 weights per char) */
0xFBC0,0x8D00,0x0000, 0xFBC0,0x8D01,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0xFBC0,0x8D04,0x0000, 0x1755,0x0000,0x0000,
0x1756,0x0000,0x0000, 0x1757,0x0000,0x0000, 0x1758,0x0000,0x0000,
@@ -1279,7 +1278,7 @@ uint16 page00Ddata[]= { /* 0D00 (3 weights per char) */
0xFBC0,0x8DFC,0x0000, 0xFBC0,0x8DFD,0x0000, 0xFBC0,0x8DFE,0x0000,
0xFBC0,0x8DFF,0x0000 };
-uint16 page00Edata[]= { /* 0E00 (3 weights per char) */
+static const uint16 page00Edata[]= { /* 0E00 (3 weights per char) */
0xFBC0,0x8E00,0x0000, 0x17E4,0x0000,0x0000, 0x17E5,0x0000,0x0000,
0x17E6,0x0000,0x0000, 0x17E7,0x0000,0x0000, 0x17E8,0x0000,0x0000,
0x17E9,0x0000,0x0000, 0x17EA,0x0000,0x0000, 0x17EB,0x0000,0x0000,
@@ -1367,7 +1366,7 @@ uint16 page00Edata[]= { /* 0E00 (3 weights per char) */
0xFBC0,0x8EFC,0x0000, 0xFBC0,0x8EFD,0x0000, 0xFBC0,0x8EFE,0x0000,
0xFBC0,0x8EFF,0x0000 };
-uint16 page00Fdata[]= { /* 0F00 (3 weights per char) */
+static const uint16 page00Fdata[]= { /* 0F00 (3 weights per char) */
0x189A,0x18AD,0x0000, 0x035A,0x0000,0x0000, 0x035B,0x0000,0x0000,
0x035C,0x0000,0x0000, 0x02FE,0x0000,0x0000, 0x02FF,0x0000,0x0000,
0x0300,0x0000,0x0000, 0x0301,0x0000,0x0000, 0x0302,0x0000,0x0000,
@@ -1455,7 +1454,7 @@ uint16 page00Fdata[]= { /* 0F00 (3 weights per char) */
0xFBC0,0x8FFC,0x0000, 0xFBC0,0x8FFD,0x0000, 0xFBC0,0x8FFE,0x0000,
0xFBC0,0x8FFF,0x0000 };
-uint16 page010data[]= { /* 1000 (3 weights per char) */
+static const uint16 page010data[]= { /* 1000 (3 weights per char) */
0x1931,0x0000,0x0000, 0x1932,0x0000,0x0000, 0x1933,0x0000,0x0000,
0x1934,0x0000,0x0000, 0x1935,0x0000,0x0000, 0x1936,0x0000,0x0000,
0x1937,0x0000,0x0000, 0x1938,0x0000,0x0000, 0x1939,0x0000,0x0000,
@@ -1543,7 +1542,7 @@ uint16 page010data[]= { /* 1000 (3 weights per char) */
0xFBC0,0x90FC,0x0000, 0xFBC0,0x90FD,0x0000, 0xFBC0,0x90FE,0x0000,
0xFBC0,0x90FF,0x0000 };
-uint16 page011data[]= { /* 1100 (3 weights per char) */
+static const uint16 page011data[]= { /* 1100 (3 weights per char) */
0x1D62,0x0000,0x0000, 0x1D63,0x0000,0x0000, 0x1D64,0x0000,0x0000,
0x1D65,0x0000,0x0000, 0x1D66,0x0000,0x0000, 0x1D67,0x0000,0x0000,
0x1D68,0x0000,0x0000, 0x1D69,0x0000,0x0000, 0x1D6A,0x0000,0x0000,
@@ -1631,7 +1630,7 @@ uint16 page011data[]= { /* 1100 (3 weights per char) */
0xFBC0,0x91FC,0x0000, 0xFBC0,0x91FD,0x0000, 0xFBC0,0x91FE,0x0000,
0xFBC0,0x91FF,0x0000 };
-uint16 page012data[]= { /* 1200 (3 weights per char) */
+static const uint16 page012data[]= { /* 1200 (3 weights per char) */
0x141C,0x0000,0x0000, 0x141D,0x0000,0x0000, 0x141E,0x0000,0x0000,
0x141F,0x0000,0x0000, 0x1420,0x0000,0x0000, 0x1421,0x0000,0x0000,
0x1422,0x0000,0x0000, 0xFBC0,0x9207,0x0000, 0x1423,0x0000,0x0000,
@@ -1719,7 +1718,7 @@ uint16 page012data[]= { /* 1200 (3 weights per char) */
0x1500,0x0000,0x0000, 0x1501,0x0000,0x0000, 0x1502,0x0000,0x0000,
0x1503,0x0000,0x0000 };
-uint16 page013data[]= { /* 1300 (3 weights per char) */
+static const uint16 page013data[]= { /* 1300 (3 weights per char) */
0x1504,0x0000,0x0000, 0x1505,0x0000,0x0000, 0x1506,0x0000,0x0000,
0x1507,0x0000,0x0000, 0x1508,0x0000,0x0000, 0x1509,0x0000,0x0000,
0x150A,0x0000,0x0000, 0x150B,0x0000,0x0000, 0x150C,0x0000,0x0000,
@@ -1807,7 +1806,7 @@ uint16 page013data[]= { /* 1300 (3 weights per char) */
0xFBC0,0x93FC,0x0000, 0xFBC0,0x93FD,0x0000, 0xFBC0,0x93FE,0x0000,
0xFBC0,0x93FF,0x0000 };
-uint16 page014data[]= { /* 1400 (3 weights per char) */
+static const uint16 page014data[]= { /* 1400 (3 weights per char) */
0xFBC0,0x9400,0x0000, 0x1AAE,0x0000,0x0000, 0x1AAF,0x0000,0x0000,
0x1AB0,0x0000,0x0000, 0x1AB1,0x0000,0x0000, 0x1AB2,0x0000,0x0000,
0x1AB3,0x0000,0x0000, 0x1AB4,0x0000,0x0000, 0x1AB5,0x0000,0x0000,
@@ -1895,7 +1894,7 @@ uint16 page014data[]= { /* 1400 (3 weights per char) */
0x1BA9,0x0000,0x0000, 0x1BAA,0x0000,0x0000, 0x1BAB,0x0000,0x0000,
0x1BAC,0x0000,0x0000 };
-uint16 page015data[]= { /* 1500 (2 weights per char) */
+static const uint16 page015data[]= { /* 1500 (2 weights per char) */
0x1BAD,0x0000, 0x1BAE,0x0000, 0x1BAF,0x0000, 0x1BB0,0x0000,
0x1BB1,0x0000, 0x1BB2,0x0000, 0x1BB3,0x0000, 0x1BB4,0x0000,
0x1BB5,0x0000, 0x1BB6,0x0000, 0x1BB7,0x0000, 0x1BB8,0x0000,
@@ -1962,7 +1961,7 @@ uint16 page015data[]= { /* 1500 (2 weights per char) */
0x1CB1,0x0000, 0x1CB2,0x0000, 0x1CB3,0x0000, 0x1CB4,0x0000
};
-uint16 page016data[]= { /* 1600 (3 weights per char) */
+static const uint16 page016data[]= { /* 1600 (3 weights per char) */
0x1CB5,0x0000,0x0000, 0x1CB6,0x0000,0x0000, 0x1CB7,0x0000,0x0000,
0x1CB8,0x0000,0x0000, 0x1CB9,0x0000,0x0000, 0x1CBA,0x0000,0x0000,
0x1CBB,0x0000,0x0000, 0x1CBC,0x0000,0x0000, 0x1CBD,0x0000,0x0000,
@@ -2050,7 +2049,7 @@ uint16 page016data[]= { /* 1600 (3 weights per char) */
0xFBC0,0x96FC,0x0000, 0xFBC0,0x96FD,0x0000, 0xFBC0,0x96FE,0x0000,
0xFBC0,0x96FF,0x0000 };
-uint16 page017data[]= { /* 1700 (3 weights per char) */
+static const uint16 page017data[]= { /* 1700 (3 weights per char) */
0x18E2,0x0000,0x0000, 0x18E3,0x0000,0x0000, 0x18E4,0x0000,0x0000,
0x18E5,0x0000,0x0000, 0x18E6,0x0000,0x0000, 0x18E7,0x0000,0x0000,
0x18E8,0x0000,0x0000, 0x18E9,0x0000,0x0000, 0x18EA,0x0000,0x0000,
@@ -2138,7 +2137,7 @@ uint16 page017data[]= { /* 1700 (3 weights per char) */
0xFBC0,0x97FC,0x0000, 0xFBC0,0x97FD,0x0000, 0xFBC0,0x97FE,0x0000,
0xFBC0,0x97FF,0x0000 };
-uint16 page018data[]= { /* 1800 (3 weights per char) */
+static const uint16 page018data[]= { /* 1800 (3 weights per char) */
0x02F8,0x0000,0x0000, 0x025E,0x0000,0x0000, 0x0235,0x0000,0x0000,
0x0263,0x0000,0x0000, 0x024A,0x0000,0x0000, 0x024B,0x0000,0x0000,
0x0223,0x0000,0x0000, 0x0224,0x0000,0x0000, 0x0236,0x0000,0x0000,
@@ -2226,7 +2225,7 @@ uint16 page018data[]= { /* 1800 (3 weights per char) */
0xFBC0,0x98FC,0x0000, 0xFBC0,0x98FD,0x0000, 0xFBC0,0x98FE,0x0000,
0xFBC0,0x98FF,0x0000 };
-uint16 page019data[]= { /* 1900 (3 weights per char) */
+static const uint16 page019data[]= { /* 1900 (3 weights per char) */
0x18B0,0x0000,0x0000, 0x18B1,0x0000,0x0000, 0x18B2,0x0000,0x0000,
0x18B3,0x0000,0x0000, 0x18B4,0x0000,0x0000, 0x18B5,0x0000,0x0000,
0x18B6,0x0000,0x0000, 0x18B7,0x0000,0x0000, 0x18B8,0x0000,0x0000,
@@ -2314,7 +2313,7 @@ uint16 page019data[]= { /* 1900 (3 weights per char) */
0x0397,0x0000,0x0000, 0x0398,0x0000,0x0000, 0x0399,0x0000,0x0000,
0x039A,0x0000,0x0000 };
-uint16 page01Ddata[]= { /* 1D00 (3 weights per char) */
+static const uint16 page01Ddata[]= { /* 1D00 (3 weights per char) */
0x0E37,0x0000,0x0000, 0x0E3C,0x0000,0x0000, 0x0E3D,0x0000,0x0000,
0x0E57,0x0000,0x0000, 0x0E64,0x0000,0x0000, 0x0E71,0x0000,0x0000,
0x0E8A,0x0000,0x0000, 0x0E8F,0x0000,0x0000, 0x0EA8,0x0000,0x0000,
@@ -2402,7 +2401,7 @@ uint16 page01Ddata[]= { /* 1D00 (3 weights per char) */
0xFBC0,0x9DFC,0x0000, 0xFBC0,0x9DFD,0x0000, 0xFBC0,0x9DFE,0x0000,
0xFBC0,0x9DFF,0x0000 };
-uint16 page01Edata[]= { /* 1E00 (3 weights per char) */
+static const uint16 page01Edata[]= { /* 1E00 (3 weights per char) */
0x0E33,0x0000,0x0000, 0x0E33,0x0000,0x0000, 0x0E4A,0x0000,0x0000,
0x0E4A,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E4A,0x0000,0x0000,
0x0E4A,0x0000,0x0000, 0x0E4A,0x0000,0x0000, 0x0E60,0x0000,0x0000,
@@ -2490,7 +2489,7 @@ uint16 page01Edata[]= { /* 1E00 (3 weights per char) */
0xFBC0,0x9EFC,0x0000, 0xFBC0,0x9EFD,0x0000, 0xFBC0,0x9EFE,0x0000,
0xFBC0,0x9EFF,0x0000 };
-uint16 page01Fdata[]= { /* 1F00 (3 weights per char) */
+static const uint16 page01Fdata[]= { /* 1F00 (3 weights per char) */
0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000,
0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000,
0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000, 0x10E8,0x0000,0x0000,
@@ -2578,7 +2577,7 @@ uint16 page01Fdata[]= { /* 1F00 (3 weights per char) */
0x1109,0x0000,0x0000, 0x020D,0x0000,0x0000, 0x0218,0x0000,0x0000,
0xFBC0,0x9FFF,0x0000 };
-uint16 page020data[]= { /* 2000 (5 weights per char) */
+static const uint16 page020data[]= { /* 2000 (5 weights per char) */
0x0209,0x0000,0x0000,0x0000,0x0000,
0x0209,0x0000,0x0000,0x0000,0x0000,
0x0209,0x0000,0x0000,0x0000,0x0000,
@@ -2837,7 +2836,7 @@ uint16 page020data[]= { /* 2000 (5 weights per char) */
0xFBC0,0xA0FF,0x0000,0x0000,0x0000
};
-uint16 page021data[]= { /* 2100 (5 weights per char) */
+static const uint16 page021data[]= { /* 2100 (5 weights per char) */
0x0E33,0x02CC,0x0E60,0x0000,0x0000,
0x0E33,0x02CC,0x0FEA,0x0000,0x0000,
0x0E60,0x0000,0x0000,0x0000,0x0000,
@@ -3096,7 +3095,7 @@ uint16 page021data[]= { /* 2100 (5 weights per char) */
0x0417,0x0000,0x0000,0x0000,0x0000
};
-uint16 page022data[]= { /* 2200 (4 weights per char) */
+static const uint16 page022data[]= { /* 2200 (4 weights per char) */
0x0418,0x0000,0x0000,0x0000, 0x0419,0x0000,0x0000,0x0000,
0x041A,0x0000,0x0000,0x0000, 0x041B,0x0000,0x0000,0x0000,
0x041B,0x0000,0x0000,0x0000, 0x041C,0x0000,0x0000,0x0000,
@@ -3227,7 +3226,7 @@ uint16 page022data[]= { /* 2200 (4 weights per char) */
0x04F9,0x0000,0x0000,0x0000, 0x04FA,0x0000,0x0000,0x0000
};
-uint16 page023data[]= { /* 2300 (3 weights per char) */
+static const uint16 page023data[]= { /* 2300 (3 weights per char) */
0x04FB,0x0000,0x0000, 0x04FC,0x0000,0x0000, 0x04FD,0x0000,0x0000,
0x04FE,0x0000,0x0000, 0x04FF,0x0000,0x0000, 0x0500,0x0000,0x0000,
0x0501,0x0000,0x0000, 0x0502,0x0000,0x0000, 0x0503,0x0000,0x0000,
@@ -3315,7 +3314,7 @@ uint16 page023data[]= { /* 2300 (3 weights per char) */
0xFBC0,0xA3FC,0x0000, 0xFBC0,0xA3FD,0x0000, 0xFBC0,0xA3FE,0x0000,
0xFBC0,0xA3FF,0x0000 };
-uint16 page024data[]= { /* 2400 (5 weights per char) */
+static const uint16 page024data[]= { /* 2400 (5 weights per char) */
0x05CA,0x0000,0x0000,0x0000,0x0000,
0x05CB,0x0000,0x0000,0x0000,0x0000,
0x05CC,0x0000,0x0000,0x0000,0x0000,
@@ -3574,7 +3573,7 @@ uint16 page024data[]= { /* 2400 (5 weights per char) */
0x0E29,0x0000,0x0000,0x0000,0x0000
};
-uint16 page025data[]= { /* 2500 (2 weights per char) */
+static const uint16 page025data[]= { /* 2500 (2 weights per char) */
0x05FC,0x0000, 0x05FD,0x0000, 0x05FE,0x0000, 0x05FF,0x0000,
0x0600,0x0000, 0x0601,0x0000, 0x0602,0x0000, 0x0603,0x0000,
0x0604,0x0000, 0x0605,0x0000, 0x0606,0x0000, 0x0607,0x0000,
@@ -3641,7 +3640,7 @@ uint16 page025data[]= { /* 2500 (2 weights per char) */
0x06F8,0x0000, 0x06F9,0x0000, 0x06FA,0x0000, 0x06FB,0x0000
};
-uint16 page026data[]= { /* 2600 (3 weights per char) */
+static const uint16 page026data[]= { /* 2600 (3 weights per char) */
0x06FC,0x0000,0x0000, 0x06FD,0x0000,0x0000, 0x06FE,0x0000,0x0000,
0x06FF,0x0000,0x0000, 0x0700,0x0000,0x0000, 0x0701,0x0000,0x0000,
0x0702,0x0000,0x0000, 0x0703,0x0000,0x0000, 0x0704,0x0000,0x0000,
@@ -3729,7 +3728,7 @@ uint16 page026data[]= { /* 2600 (3 weights per char) */
0xFBC0,0xA6FC,0x0000, 0xFBC0,0xA6FD,0x0000, 0xFBC0,0xA6FE,0x0000,
0xFBC0,0xA6FF,0x0000 };
-uint16 page027data[]= { /* 2700 (3 weights per char) */
+static const uint16 page027data[]= { /* 2700 (3 weights per char) */
0xFBC0,0xA700,0x0000, 0x077C,0x0000,0x0000, 0x077D,0x0000,0x0000,
0x077E,0x0000,0x0000, 0x077F,0x0000,0x0000, 0xFBC0,0xA705,0x0000,
0x0780,0x0000,0x0000, 0x0781,0x0000,0x0000, 0x0782,0x0000,0x0000,
@@ -3817,7 +3816,7 @@ uint16 page027data[]= { /* 2700 (3 weights per char) */
0x0834,0x0000,0x0000, 0x0835,0x0000,0x0000, 0x0836,0x0000,0x0000,
0x0837,0x0000,0x0000 };
-uint16 page028data[]= { /* 2800 (2 weights per char) */
+static const uint16 page028data[]= { /* 2800 (2 weights per char) */
0x0A29,0x0000, 0x0A2A,0x0000, 0x0A2B,0x0000, 0x0A2C,0x0000,
0x0A2D,0x0000, 0x0A2E,0x0000, 0x0A2F,0x0000, 0x0A30,0x0000,
0x0A31,0x0000, 0x0A32,0x0000, 0x0A33,0x0000, 0x0A34,0x0000,
@@ -3884,7 +3883,7 @@ uint16 page028data[]= { /* 2800 (2 weights per char) */
0x0B25,0x0000, 0x0B26,0x0000, 0x0B27,0x0000, 0x0B28,0x0000
};
-uint16 page029data[]= { /* 2900 (2 weights per char) */
+static const uint16 page029data[]= { /* 2900 (2 weights per char) */
0x0838,0x0000, 0x0839,0x0000, 0x083A,0x0000, 0x083B,0x0000,
0x083C,0x0000, 0x083D,0x0000, 0x083E,0x0000, 0x083F,0x0000,
0x0840,0x0000, 0x0841,0x0000, 0x0842,0x0000, 0x0843,0x0000,
@@ -3951,7 +3950,7 @@ uint16 page029data[]= { /* 2900 (2 weights per char) */
0x0296,0x0000, 0x0297,0x0000, 0x091E,0x0000, 0x091F,0x0000
};
-uint16 page02Adata[]= { /* 2A00 (5 weights per char) */
+static const uint16 page02Adata[]= { /* 2A00 (5 weights per char) */
0x0920,0x0000,0x0000,0x0000,0x0000,
0x0921,0x0000,0x0000,0x0000,0x0000,
0x0922,0x0000,0x0000,0x0000,0x0000,
@@ -4210,7 +4209,7 @@ uint16 page02Adata[]= { /* 2A00 (5 weights per char) */
0x0A1A,0x0000,0x0000,0x0000,0x0000
};
-uint16 page02Bdata[]= { /* 2B00 (3 weights per char) */
+static const uint16 page02Bdata[]= { /* 2B00 (3 weights per char) */
0x0A1B,0x0000,0x0000, 0x0A1C,0x0000,0x0000, 0x0A1D,0x0000,0x0000,
0x0A1E,0x0000,0x0000, 0x0A1F,0x0000,0x0000, 0x0A20,0x0000,0x0000,
0x0A21,0x0000,0x0000, 0x0A22,0x0000,0x0000, 0x0A23,0x0000,0x0000,
@@ -4298,7 +4297,7 @@ uint16 page02Bdata[]= { /* 2B00 (3 weights per char) */
0xFBC0,0xABFC,0x0000, 0xFBC0,0xABFD,0x0000, 0xFBC0,0xABFE,0x0000,
0xFBC0,0xABFF,0x0000 };
-uint16 page02Edata[]= { /* 2E00 (3 weights per char) */
+static const uint16 page02Edata[]= { /* 2E00 (3 weights per char) */
0xFBC0,0xAE00,0x0000, 0xFBC0,0xAE01,0x0000, 0xFBC0,0xAE02,0x0000,
0xFBC0,0xAE03,0x0000, 0xFBC0,0xAE04,0x0000, 0xFBC0,0xAE05,0x0000,
0xFBC0,0xAE06,0x0000, 0xFBC0,0xAE07,0x0000, 0xFBC0,0xAE08,0x0000,
@@ -4386,7 +4385,7 @@ uint16 page02Edata[]= { /* 2E00 (3 weights per char) */
0xFBC0,0xAEFC,0x0000, 0xFBC0,0xAEFD,0x0000, 0xFBC0,0xAEFE,0x0000,
0xFBC0,0xAEFF,0x0000 };
-uint16 page02Fdata[]= { /* 2F00 (3 weights per char) */
+static const uint16 page02Fdata[]= { /* 2F00 (3 weights per char) */
0xFB40,0xCE00,0x0000, 0xFB40,0xCE28,0x0000, 0xFB40,0xCE36,0x0000,
0xFB40,0xCE3F,0x0000, 0xFB40,0xCE59,0x0000, 0xFB40,0xCE85,0x0000,
0xFB40,0xCE8C,0x0000, 0xFB40,0xCEA0,0x0000, 0xFB40,0xCEBA,0x0000,
@@ -4474,7 +4473,7 @@ uint16 page02Fdata[]= { /* 2F00 (3 weights per char) */
0xFBC0,0xAFFC,0x0000, 0xFBC0,0xAFFD,0x0000, 0xFBC0,0xAFFE,0x0000,
0xFBC0,0xAFFF,0x0000 };
-uint16 page030data[]= { /* 3000 (3 weights per char) */
+static const uint16 page030data[]= { /* 3000 (3 weights per char) */
0x0209,0x0000,0x0000, 0x0237,0x0000,0x0000, 0x0266,0x0000,0x0000,
0x02E2,0x0000,0x0000, 0x0DBB,0x0000,0x0000, 0x0E05,0x0000,0x0000,
0x1E5D,0x1E73,0x0000, 0x0E29,0x0000,0x0000, 0x02AE,0x0000,0x0000,
@@ -4562,7 +4561,7 @@ uint16 page030data[]= { /* 3000 (3 weights per char) */
0x0E0B,0x0000,0x0000, 0x0E0C,0x0000,0x0000, 0x0E0C,0x0000,0x0000,
0x1E5B,0x1E65,0x0000 };
-uint16 page031data[]= { /* 3100 (3 weights per char) */
+static const uint16 page031data[]= { /* 3100 (3 weights per char) */
0xFBC0,0xB100,0x0000, 0xFBC0,0xB101,0x0000, 0xFBC0,0xB102,0x0000,
0xFBC0,0xB103,0x0000, 0xFBC0,0xB104,0x0000, 0x1E82,0x0000,0x0000,
0x1E83,0x0000,0x0000, 0x1E84,0x0000,0x0000, 0x1E85,0x0000,0x0000,
@@ -4650,7 +4649,7 @@ uint16 page031data[]= { /* 3100 (3 weights per char) */
0x1E79,0x0000,0x0000, 0x1E7A,0x0000,0x0000, 0x1E7B,0x0000,0x0000,
0x1E7C,0x0000,0x0000 };
-uint16 page032data[]= { /* 3200 (8 weights per char) */
+static const uint16 page032data[]= { /* 3200 (8 weights per char) */
0x0288,0x1D62,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0288,0x1D64,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0288,0x1D65,0x0289,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -4909,7 +4908,7 @@ uint16 page032data[]= { /* 3200 (8 weights per char) */
0xFBC0,0xB2FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-uint16 page033data[]= { /* 3300 (9 weights per char) */
+static const uint16 page033data[]= { /* 3300 (9 weights per char) */
0x1E52,0x1E6B,0x0E0B,0x1E65,0x0000,0x0000,0x0000,0x0000,0x0000,
0x1E52,0x1E7A,0x1E6D,0x1E52,0x0000,0x0000,0x0000,0x0000,0x0000,
0x1E52,0x1E81,0x1E6E,0x1E52,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -5168,7 +5167,7 @@ uint16 page033data[]= { /* 3300 (9 weights per char) */
0x0EC1,0x0E33,0x0F2E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-uint16 page04Ddata[]= { /* 4D00 (3 weights per char) */
+static const uint16 page04Ddata[]= { /* 4D00 (3 weights per char) */
0xFB80,0xCD00,0x0000, 0xFB80,0xCD01,0x0000, 0xFB80,0xCD02,0x0000,
0xFB80,0xCD03,0x0000, 0xFB80,0xCD04,0x0000, 0xFB80,0xCD05,0x0000,
0xFB80,0xCD06,0x0000, 0xFB80,0xCD07,0x0000, 0xFB80,0xCD08,0x0000,
@@ -5256,7 +5255,7 @@ uint16 page04Ddata[]= { /* 4D00 (3 weights per char) */
0x0B73,0x0000,0x0000, 0x0B74,0x0000,0x0000, 0x0B75,0x0000,0x0000,
0x0B76,0x0000,0x0000 };
-uint16 page0A0data[]= { /* A000 (2 weights per char) */
+static const uint16 page0A0data[]= { /* A000 (2 weights per char) */
0x1EB1,0x0000, 0x1EB2,0x0000, 0x1EB3,0x0000, 0x1EB4,0x0000,
0x1EB5,0x0000, 0x1EB6,0x0000, 0x1EB7,0x0000, 0x1EB8,0x0000,
0x1EB9,0x0000, 0x1EBA,0x0000, 0x1EBB,0x0000, 0x1EBC,0x0000,
@@ -5323,7 +5322,7 @@ uint16 page0A0data[]= { /* A000 (2 weights per char) */
0x1FAD,0x0000, 0x1FAE,0x0000, 0x1FAF,0x0000, 0x1FB0,0x0000
};
-uint16 page0A1data[]= { /* A100 (2 weights per char) */
+static const uint16 page0A1data[]= { /* A100 (2 weights per char) */
0x1FB1,0x0000, 0x1FB2,0x0000, 0x1FB3,0x0000, 0x1FB4,0x0000,
0x1FB5,0x0000, 0x1FB6,0x0000, 0x1FB7,0x0000, 0x1FB8,0x0000,
0x1FB9,0x0000, 0x1FBA,0x0000, 0x1FBB,0x0000, 0x1FBC,0x0000,
@@ -5390,7 +5389,7 @@ uint16 page0A1data[]= { /* A100 (2 weights per char) */
0x20AD,0x0000, 0x20AE,0x0000, 0x20AF,0x0000, 0x20B0,0x0000
};
-uint16 page0A2data[]= { /* A200 (2 weights per char) */
+static const uint16 page0A2data[]= { /* A200 (2 weights per char) */
0x20B1,0x0000, 0x20B2,0x0000, 0x20B3,0x0000, 0x20B4,0x0000,
0x20B5,0x0000, 0x20B6,0x0000, 0x20B7,0x0000, 0x20B8,0x0000,
0x20B9,0x0000, 0x20BA,0x0000, 0x20BB,0x0000, 0x20BC,0x0000,
@@ -5457,7 +5456,7 @@ uint16 page0A2data[]= { /* A200 (2 weights per char) */
0x21AD,0x0000, 0x21AE,0x0000, 0x21AF,0x0000, 0x21B0,0x0000
};
-uint16 page0A3data[]= { /* A300 (2 weights per char) */
+static const uint16 page0A3data[]= { /* A300 (2 weights per char) */
0x21B1,0x0000, 0x21B2,0x0000, 0x21B3,0x0000, 0x21B4,0x0000,
0x21B5,0x0000, 0x21B6,0x0000, 0x21B7,0x0000, 0x21B8,0x0000,
0x21B9,0x0000, 0x21BA,0x0000, 0x21BB,0x0000, 0x21BC,0x0000,
@@ -5524,7 +5523,7 @@ uint16 page0A3data[]= { /* A300 (2 weights per char) */
0x22AD,0x0000, 0x22AE,0x0000, 0x22AF,0x0000, 0x22B0,0x0000
};
-uint16 page0A4data[]= { /* A400 (3 weights per char) */
+static const uint16 page0A4data[]= { /* A400 (3 weights per char) */
0x22B1,0x0000,0x0000, 0x22B2,0x0000,0x0000, 0x22B3,0x0000,0x0000,
0x22B4,0x0000,0x0000, 0x22B5,0x0000,0x0000, 0x22B6,0x0000,0x0000,
0x22B7,0x0000,0x0000, 0x22B8,0x0000,0x0000, 0x22B9,0x0000,0x0000,
@@ -5612,7 +5611,7 @@ uint16 page0A4data[]= { /* A400 (3 weights per char) */
0xFBC1,0xA4FC,0x0000, 0xFBC1,0xA4FD,0x0000, 0xFBC1,0xA4FE,0x0000,
0xFBC1,0xA4FF,0x0000 };
-uint16 page0F9data[]= { /* F900 (3 weights per char) */
+static const uint16 page0F9data[]= { /* F900 (3 weights per char) */
0xFB41,0x8C48,0x0000, 0xFB40,0xE6F4,0x0000, 0xFB41,0x8ECA,0x0000,
0xFB41,0x8CC8,0x0000, 0xFB40,0xEED1,0x0000, 0xFB40,0xCE32,0x0000,
0xFB40,0xD3E5,0x0000, 0xFB41,0x9F9C,0x0000, 0xFB41,0x9F9C,0x0000,
@@ -5700,7 +5699,7 @@ uint16 page0F9data[]= { /* F900 (3 weights per char) */
0xFB41,0x8B58,0x0000, 0xFB40,0xCEC0,0x0000, 0xFB41,0x8336,0x0000,
0xFB40,0xD23A,0x0000 };
-uint16 page0FAdata[]= { /* FA00 (3 weights per char) */
+static const uint16 page0FAdata[]= { /* FA00 (3 weights per char) */
0xFB40,0xD207,0x0000, 0xFB40,0xDEA6,0x0000, 0xFB40,0xE2D3,0x0000,
0xFB40,0xFCD6,0x0000, 0xFB40,0xDB85,0x0000, 0xFB40,0xED1E,0x0000,
0xFB40,0xE6B4,0x0000, 0xFB41,0x8F3B,0x0000, 0xFB41,0x884C,0x0000,
@@ -5788,7 +5787,7 @@ uint16 page0FAdata[]= { /* FA00 (3 weights per char) */
0xFBC1,0xFAFC,0x0000, 0xFBC1,0xFAFD,0x0000, 0xFBC1,0xFAFE,0x0000,
0xFBC1,0xFAFF,0x0000 };
-uint16 page0FBdata[]= { /* FB00 (4 weights per char) */
+static const uint16 page0FBdata[]= { /* FB00 (4 weights per char) */
0x0EB9,0x0EB9,0x0000,0x0000, 0x0EB9,0x0EFB,0x0000,0x0000,
0x0EB9,0x0F2E,0x0000,0x0000, 0x0EB9,0x0EB9,0x0EFB,0x0000,
0x0EB9,0x0EB9,0x0F2E,0x0000, 0x0FEA,0x1002,0x0000,0x0000,
@@ -5919,7 +5918,7 @@ uint16 page0FBdata[]= { /* FB00 (4 weights per char) */
0x13C9,0x0000,0x0000,0x0000, 0x13C9,0x0000,0x0000,0x0000
};
-uint16 page0FCdata[]= { /* FC00 (3 weights per char) */
+static const uint16 page0FCdata[]= { /* FC00 (3 weights per char) */
0x134F,0x135E,0x0000, 0x134F,0x1364,0x0000, 0x134F,0x13B0,0x0000,
0x134F,0x13C7,0x0000, 0x134F,0x13C8,0x0000, 0x1352,0x135E,0x0000,
0x1352,0x1364,0x0000, 0x1352,0x1365,0x0000, 0x1352,0x13B0,0x0000,
@@ -6007,7 +6006,7 @@ uint16 page0FCdata[]= { /* FC00 (3 weights per char) */
0x1381,0x13C8,0x0000, 0x1382,0x13C7,0x0000, 0x1382,0x13C8,0x0000,
0x1364,0x13C7,0x0000 };
-uint16 page0FDdata[]= { /* FD00 (9 weights per char) */
+static const uint16 page0FDdata[]= { /* FD00 (9 weights per char) */
0x1364,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x135E,0x13C7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x135E,0x13C8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -6266,7 +6265,7 @@ uint16 page0FDdata[]= { /* FD00 (9 weights per char) */
0xFBC1,0xFDFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-uint16 page0FEdata[]= { /* FE00 (3 weights per char) */
+static const uint16 page0FEdata[]= { /* FE00 (3 weights per char) */
0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,
@@ -6354,7 +6353,7 @@ uint16 page0FEdata[]= { /* FE00 (3 weights per char) */
0x13AB,0x1350,0x0000, 0xFBC1,0xFEFD,0x0000, 0xFBC1,0xFEFE,0x0000,
0x0000,0x0000,0x0000 };
-uint16 page0FFdata[]= { /* FF00 (3 weights per char) */
+static const uint16 page0FFdata[]= { /* FF00 (3 weights per char) */
0xFBC1,0xFF00,0x0000, 0x0251,0x0000,0x0000, 0x027E,0x0000,0x0000,
0x02D2,0x0000,0x0000, 0x0E0F,0x0000,0x0000, 0x02D3,0x0000,0x0000,
0x02CF,0x0000,0x0000, 0x0277,0x0000,0x0000, 0x0288,0x0000,0x0000,
@@ -6442,7 +6441,7 @@ uint16 page0FFdata[]= { /* FF00 (3 weights per char) */
0x0DC5,0x0000,0x0000, 0x0DC6,0x0000,0x0000, 0xFBC1,0xFFFE,0x0000,
0xFBC1,0xFFFF,0x0000 };
-uchar uca_length[256]={
+static const uchar uca_length[256]={
4,3,3,4,3,3,3,3,0,3,3,3,3,3,3,3,
3,3,3,3,3,2,3,3,3,3,0,0,0,3,3,3,
5,5,4,3,5,2,3,3,2,2,5,3,0,0,3,3,
@@ -6460,7 +6459,8 @@ uchar uca_length[256]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,3,3,4,3,9,3,3
};
-uint16 *uca_weight[256]={
+
+static const uint16 *const uca_weight[256]={
page000data,page001data,page002data,page003data,
page004data,page005data,page006data,page007data,
NULL ,page009data,page00Adata,page00Bdata,
@@ -6740,9 +6740,9 @@ typedef struct my_uca_scanner_st
const uint16 *wbeg; /* Beginning of the current weight string */
const uchar *sbeg; /* Beginning of the input string */
const uchar *send; /* End of the input string */
- uchar *uca_length;
- uint16 **uca_weight;
- MY_CONTRACTIONS *contractions;
+ const uchar *uca_length;
+ const uint16 * const *uca_weight;
+ const MY_CONTRACTIONS *contractions;
uint16 implicit[2];
int page;
int code;
@@ -6760,7 +6760,7 @@ typedef struct my_uca_scanner_handler_st
int (*next)(my_uca_scanner *scanner);
} my_uca_scanner_handler;
-static uint16 nochar[]= {0,0};
+static const uint16 nochar[]= {0,0};
/********** Helper functions to handle contraction ************/
@@ -6792,10 +6792,10 @@ my_uca_add_contraction_flag(CHARSET_INFO *cs, my_wc_t wc, int flag)
*/
static MY_CONTRACTION *
-my_uca_add_contraction(CHARSET_INFO *cs,
+my_uca_add_contraction(struct charset_info_st *cs,
my_wc_t *wc, int len __attribute__((unused)))
{
- MY_CONTRACTIONS *list= cs->contractions;
+ MY_CONTRACTIONS *list= (MY_CONTRACTIONS*) cs->contractions;
MY_CONTRACTION *next= &list->item[list->nitems];
DBUG_ASSERT(len == 2); /* We currently support only contraction2 */
next->ch[0]= wc[0];
@@ -6818,20 +6818,24 @@ my_uca_add_contraction(CHARSET_INFO *cs,
*/
static my_bool
-my_uca_alloc_contractions(CHARSET_INFO *cs, void *(*alloc)(size_t), size_t n)
+my_uca_alloc_contractions(struct charset_info_st *cs,
+ void *(*alloc)(size_t), size_t n)
{
uint size= n * sizeof(MY_CONTRACTION);
- if (!(cs->contractions= (*alloc)(sizeof(MY_CONTRACTIONS))))
+ MY_CONTRACTIONS *contractions;
+
+ if (!(cs->contractions= contractions= (*alloc)(sizeof(MY_CONTRACTIONS))))
return 1;
- bzero(cs->contractions, sizeof(MY_CONTRACTIONS));
- if (!(cs->contractions->item= (*alloc)(size)) ||
- !(cs->contractions->flags= (char*) (*alloc)(MY_UCA_CNT_FLAG_SIZE)))
+ bzero(contractions, sizeof(MY_CONTRACTIONS));
+ if (!(contractions->item= (*alloc)(size)) ||
+ !(contractions->flags= (char*) (*alloc)(MY_UCA_CNT_FLAG_SIZE)))
return 1;
- bzero((void*) cs->contractions->item, size);
- bzero((void*) cs->contractions->flags, MY_UCA_CNT_FLAG_SIZE);
+ bzero(contractions->item, size);
+ bzero(contractions->flags, MY_UCA_CNT_FLAG_SIZE);
return 0;
}
+
#ifdef HAVE_CHARSET_ucs2
/*
Initialize collation weight scanner
@@ -6939,8 +6943,8 @@ static int my_uca_scanner_next_ucs2(my_uca_scanner *scanner)
do
{
- uint16 **ucaw= scanner->uca_weight;
- uchar *ucal= scanner->uca_length;
+ const uint16 *const *ucaw= scanner->uca_weight;
+ const uchar *ucal= scanner->uca_length;
if (scanner->sbeg > scanner->send)
return -1;
@@ -6955,7 +6959,7 @@ static int my_uca_scanner_next_ucs2(my_uca_scanner *scanner)
if (my_uca_can_be_contraction_head(scanner->cs, wc1))
{
- uint16 *cweight;
+ const uint16 *cweight;
my_wc_t wc2= (((my_wc_t) scanner->sbeg[0]) << 8) | scanner->sbeg[1];
if (my_uca_can_be_contraction_tail(scanner->cs, wc2) &&
(cweight= my_uca_contraction2_weight(scanner->cs,
@@ -7036,8 +7040,8 @@ static int my_uca_scanner_next_any(my_uca_scanner *scanner)
do
{
- uint16 **ucaw= scanner->uca_weight;
- uchar *ucal= scanner->uca_length;
+ const uint16 *const *ucaw= scanner->uca_weight;
+ const uchar *ucal= scanner->uca_length;
my_wc_t wc;
int mb_len;
@@ -7054,7 +7058,7 @@ static int my_uca_scanner_next_any(my_uca_scanner *scanner)
my_uca_can_be_contraction_head(scanner->cs, wc))
{
my_wc_t wc2;
- uint16 *cweight;
+ const uint16 *cweight;
if (((mb_len= scanner->cs->cset->mb_wc(scanner->cs, &wc2,
scanner->sbeg,
@@ -7117,14 +7121,14 @@ static my_uca_scanner_handler my_any_uca_scanner_handler=
or NULL if this page does not have implicit weights.
*/
-static inline uint16 *
+static inline const uint16 *
my_char_weight_addr(CHARSET_INFO *cs, uint wc)
{
uint page= (wc >> 8);
uint ofst= wc & 0xFF;
- return cs->sort_order_big[page] ?
- cs->sort_order_big[page] + ofst * cs->sort_order[page] :
- NULL;
+ return (cs->sort_order_big[page] ?
+ cs->sort_order_big[page] + ofst * cs->sort_order[page] :
+ 0);
}
@@ -7414,12 +7418,12 @@ static int my_uca_charcmp(CHARSET_INFO *cs, my_wc_t wc1, my_wc_t wc2)
{
size_t page1= wc1 >> MY_UCA_PSHIFT;
size_t page2= wc2 >> MY_UCA_PSHIFT;
- uchar *ucal= cs->sort_order;
- uint16 **ucaw= cs->sort_order_big;
+ const uchar *ucal= cs->sort_order;
+ const uint16 *const *ucaw= cs->sort_order_big;
size_t length1= ucal[page1];
size_t length2= ucal[page2];
- uint16 *weight1= ucaw[page1] + (wc1 & MY_UCA_CMASK) * ucal[page1];
- uint16 *weight2= ucaw[page2] + (wc2 & MY_UCA_CMASK) * ucal[page2];
+ const uint16 *weight1= ucaw[page1] + (wc1 & MY_UCA_CMASK) * ucal[page1];
+ const uint16 *weight2= ucaw[page2] + (wc2 & MY_UCA_CMASK) * ucal[page2];
if (!weight1 || !weight2)
return wc1 != wc2;
@@ -7451,9 +7455,7 @@ int my_wildcmp_uca(CHARSET_INFO *cs,
int result= -1; /* Not found, using wildcards */
my_wc_t s_wc, w_wc;
int scan;
- int (*mb_wc)(struct charset_info_st *, my_wc_t *,
- const uchar *, const uchar *);
- mb_wc= cs->cset->mb_wc;
+ my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc;
while (wildstr != wildend)
{
@@ -7948,7 +7950,8 @@ static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems,
default weights.
*/
-static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t))
+static my_bool create_tailoring(struct charset_info_st *cs,
+ void *(*alloc)(size_t))
{
MY_COLL_RULE rule[MY_MAX_COLL_RULE];
MY_COLL_RULE *r, *rfirst, *rlast;
@@ -7956,7 +7959,7 @@ static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t))
uchar *newlengths;
uint16 **newweights;
const uchar *deflengths= uca_length;
- uint16 **defweights= uca_weight;
+ const uint16 *const *defweights= uca_weight;
int rc, i;
int ncontractions= 0;
@@ -8052,11 +8055,11 @@ static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t))
for (i= 0; i < 256 ; i++)
{
if (!newweights[i])
- newweights[i]= defweights[i];
+ ((const uint16**) newweights)[i]= defweights[i];
}
cs->sort_order= newlengths;
- cs->sort_order_big= newweights;
+ cs->sort_order_big= (const uint16**) newweights;
cs->contractions= NULL;
/* Now process contractions */
@@ -8090,7 +8093,8 @@ static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t))
Should work for any character set.
*/
-static my_bool my_coll_init_uca(CHARSET_INFO *cs, void *(*alloc)(size_t))
+static my_bool my_coll_init_uca(struct charset_info_st *cs,
+ void *(*alloc)(size_t))
{
cs->pad_char= ' ';
cs->ctype= my_charset_utf8_unicode_ci.ctype;
@@ -8185,7 +8189,7 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler =
my_propagate_complex
};
-CHARSET_INFO my_charset_ucs2_unicode_ci=
+struct charset_info_st my_charset_ucs2_unicode_ci=
{
128,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8217,7 +8221,7 @@ CHARSET_INFO my_charset_ucs2_unicode_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
+struct charset_info_st my_charset_ucs2_icelandic_uca_ci=
{
129,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8249,7 +8253,7 @@ CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
+struct charset_info_st my_charset_ucs2_latvian_uca_ci=
{
130,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8281,7 +8285,7 @@ CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
+struct charset_info_st my_charset_ucs2_romanian_uca_ci=
{
131,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8313,7 +8317,7 @@ CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
+struct charset_info_st my_charset_ucs2_slovenian_uca_ci=
{
132,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8345,7 +8349,7 @@ CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_polish_uca_ci=
+struct charset_info_st my_charset_ucs2_polish_uca_ci=
{
133,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8377,7 +8381,7 @@ CHARSET_INFO my_charset_ucs2_polish_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
+struct charset_info_st my_charset_ucs2_estonian_uca_ci=
{
134,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8409,7 +8413,7 @@ CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
+struct charset_info_st my_charset_ucs2_spanish_uca_ci=
{
135,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8441,7 +8445,7 @@ CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
+struct charset_info_st my_charset_ucs2_swedish_uca_ci=
{
136,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8473,7 +8477,7 @@ CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
+struct charset_info_st my_charset_ucs2_turkish_uca_ci=
{
137,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8505,7 +8509,7 @@ CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_czech_uca_ci=
+struct charset_info_st my_charset_ucs2_czech_uca_ci=
{
138,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8538,7 +8542,7 @@ CHARSET_INFO my_charset_ucs2_czech_uca_ci=
};
-CHARSET_INFO my_charset_ucs2_danish_uca_ci=
+struct charset_info_st my_charset_ucs2_danish_uca_ci=
{
139,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8570,7 +8574,7 @@ CHARSET_INFO my_charset_ucs2_danish_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
+struct charset_info_st my_charset_ucs2_lithuanian_uca_ci=
{
140,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8602,7 +8606,7 @@ CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
+struct charset_info_st my_charset_ucs2_slovak_uca_ci=
{
141,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8634,7 +8638,7 @@ CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
&my_collation_ucs2_uca_handler
};
-CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
+struct charset_info_st my_charset_ucs2_spanish2_uca_ci=
{
142,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8667,7 +8671,7 @@ CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
};
-CHARSET_INFO my_charset_ucs2_roman_uca_ci=
+struct charset_info_st my_charset_ucs2_roman_uca_ci=
{
143,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8700,7 +8704,7 @@ CHARSET_INFO my_charset_ucs2_roman_uca_ci=
};
-CHARSET_INFO my_charset_ucs2_persian_uca_ci=
+struct charset_info_st my_charset_ucs2_persian_uca_ci=
{
144,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8733,7 +8737,7 @@ CHARSET_INFO my_charset_ucs2_persian_uca_ci=
};
-CHARSET_INFO my_charset_ucs2_esperanto_uca_ci=
+struct charset_info_st my_charset_ucs2_esperanto_uca_ci=
{
145,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8766,7 +8770,7 @@ CHARSET_INFO my_charset_ucs2_esperanto_uca_ci=
};
-CHARSET_INFO my_charset_ucs2_hungarian_uca_ci=
+struct charset_info_st my_charset_ucs2_hungarian_uca_ci=
{
146,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -8799,7 +8803,7 @@ CHARSET_INFO my_charset_ucs2_hungarian_uca_ci=
};
-CHARSET_INFO my_charset_ucs2_croatian_uca_ci=
+struct charset_info_st my_charset_ucs2_croatian_uca_ci=
{
149,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -8879,7 +8883,7 @@ static uchar ctype_utf8[] = {
extern MY_CHARSET_HANDLER my_charset_utf8_handler;
-CHARSET_INFO my_charset_utf8_unicode_ci=
+struct charset_info_st my_charset_utf8_unicode_ci=
{
192,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -8912,7 +8916,7 @@ CHARSET_INFO my_charset_utf8_unicode_ci=
};
-CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
+struct charset_info_st my_charset_utf8_icelandic_uca_ci=
{
193,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -8944,7 +8948,7 @@ CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_latvian_uca_ci=
+struct charset_info_st my_charset_utf8_latvian_uca_ci=
{
194,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -8976,7 +8980,7 @@ CHARSET_INFO my_charset_utf8_latvian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_romanian_uca_ci=
+struct charset_info_st my_charset_utf8_romanian_uca_ci=
{
195,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9008,7 +9012,7 @@ CHARSET_INFO my_charset_utf8_romanian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
+struct charset_info_st my_charset_utf8_slovenian_uca_ci=
{
196,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9040,7 +9044,7 @@ CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_polish_uca_ci=
+struct charset_info_st my_charset_utf8_polish_uca_ci=
{
197,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9072,7 +9076,7 @@ CHARSET_INFO my_charset_utf8_polish_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_estonian_uca_ci=
+struct charset_info_st my_charset_utf8_estonian_uca_ci=
{
198,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9104,7 +9108,7 @@ CHARSET_INFO my_charset_utf8_estonian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_spanish_uca_ci=
+struct charset_info_st my_charset_utf8_spanish_uca_ci=
{
199,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9136,7 +9140,7 @@ CHARSET_INFO my_charset_utf8_spanish_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_swedish_uca_ci=
+struct charset_info_st my_charset_utf8_swedish_uca_ci=
{
200,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9168,7 +9172,7 @@ CHARSET_INFO my_charset_utf8_swedish_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_turkish_uca_ci=
+struct charset_info_st my_charset_utf8_turkish_uca_ci=
{
201,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9200,7 +9204,7 @@ CHARSET_INFO my_charset_utf8_turkish_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_czech_uca_ci=
+struct charset_info_st my_charset_utf8_czech_uca_ci=
{
202,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9233,7 +9237,7 @@ CHARSET_INFO my_charset_utf8_czech_uca_ci=
};
-CHARSET_INFO my_charset_utf8_danish_uca_ci=
+struct charset_info_st my_charset_utf8_danish_uca_ci=
{
203,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9265,7 +9269,7 @@ CHARSET_INFO my_charset_utf8_danish_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
+struct charset_info_st my_charset_utf8_lithuanian_uca_ci=
{
204,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9297,7 +9301,7 @@ CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_slovak_uca_ci=
+struct charset_info_st my_charset_utf8_slovak_uca_ci=
{
205,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9329,7 +9333,7 @@ CHARSET_INFO my_charset_utf8_slovak_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
+struct charset_info_st my_charset_utf8_spanish2_uca_ci=
{
206,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9361,7 +9365,7 @@ CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_roman_uca_ci=
+struct charset_info_st my_charset_utf8_roman_uca_ci=
{
207,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9393,7 +9397,7 @@ CHARSET_INFO my_charset_utf8_roman_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_persian_uca_ci=
+struct charset_info_st my_charset_utf8_persian_uca_ci=
{
208,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9425,7 +9429,7 @@ CHARSET_INFO my_charset_utf8_persian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_esperanto_uca_ci=
+struct charset_info_st my_charset_utf8_esperanto_uca_ci=
{
209,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9457,7 +9461,7 @@ CHARSET_INFO my_charset_utf8_esperanto_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_hungarian_uca_ci=
+struct charset_info_st my_charset_utf8_hungarian_uca_ci=
{
210,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9489,7 +9493,7 @@ CHARSET_INFO my_charset_utf8_hungarian_uca_ci=
&my_collation_any_uca_handler
};
-CHARSET_INFO my_charset_utf8_croatian_uca_ci=
+struct charset_info_st my_charset_utf8_croatian_uca_ci=
{
213,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
@@ -9584,11 +9588,11 @@ my_uca_can_be_contraction_tail(CHARSET_INFO *cs, my_wc_t wc)
@retval ptr - contraction weight array
*/
-uint16 *
+const uint16 *
my_uca_contraction2_weight(CHARSET_INFO *cs, my_wc_t wc1, my_wc_t wc2)
{
- MY_CONTRACTIONS *list= cs->contractions;
- MY_CONTRACTION *c, *last;
+ const MY_CONTRACTIONS *list= cs->contractions;
+ const MY_CONTRACTION *c, *last;
for (c= list->item, last= &list->item[list->nitems]; c < last; c++)
{
if (c->ch[0] == wc1 && c->ch[1] == wc2)
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 9e37518fb1b..d76cbb6e64c 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -32,7 +32,7 @@
#endif
-static uchar ctype_ucs2[] = {
+static const uchar ctype_ucs2[] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@@ -52,7 +52,7 @@ static uchar ctype_ucs2[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static uchar to_lower_ucs2[] = {
+static const uchar to_lower_ucs2[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -71,7 +71,7 @@ static uchar to_lower_ucs2[] = {
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
-static uchar to_upper_ucs2[] = {
+static const uchar to_upper_ucs2[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -120,7 +120,7 @@ static size_t my_caseup_ucs2(CHARSET_INFO *cs, char *src, size_t srclen,
my_wc_t wc;
int res;
char *srcend= src + srclen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
DBUG_ASSERT(src == dst && srclen == dstlen);
while ((src < srcend) &&
@@ -142,7 +142,7 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, size_t slen,
my_wc_t wc;
int res;
const uchar *e=s+slen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while (e > s+1 && e[-1] == ' ' && e[-2] == '\0')
e-= 2;
@@ -174,7 +174,7 @@ static size_t my_casedn_ucs2(CHARSET_INFO *cs, char *src, size_t srclen,
my_wc_t wc;
int res;
char *srcend= src + srclen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
DBUG_ASSERT(src == dst && srclen == dstlen);
while ((src < srcend) &&
@@ -206,7 +206,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -270,7 +270,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
{
const uchar *se, *te;
size_t minlen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
/* extra safety to make sure the lengths are even numbers */
slen&= ~1;
@@ -320,7 +320,7 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs,
my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const char *se=s+len;
const char *te=t+len;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -369,7 +369,7 @@ static size_t my_strnxfrm_ucs2(CHARSET_INFO *cs,
int plane;
uchar *de = dst + dstlen;
const uchar *se = src + srclen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while( src < se && dst < de )
{
@@ -1360,7 +1360,7 @@ int my_wildcmp_ucs2_ci(CHARSET_INFO *cs,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many)
{
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
escape,w_one,w_many,uni_plane);
}
@@ -1708,7 +1708,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler=
};
-CHARSET_INFO my_charset_ucs2_general_ci=
+struct charset_info_st my_charset_ucs2_general_ci=
{
35,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
@@ -1740,7 +1740,7 @@ CHARSET_INFO my_charset_ucs2_general_ci=
&my_collation_ucs2_general_ci_handler
};
-CHARSET_INFO my_charset_ucs2_bin=
+struct charset_info_st my_charset_ucs2_bin=
{
90,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE|MY_CS_NONASCII,
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 1a872a92595..3adee2cff07 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -32,7 +32,7 @@
#ifdef HAVE_CHARSET_ujis
-static uchar NEAR ctype_ujis[257] =
+static const uchar NEAR ctype_ujis[257] =
{
0, /* For standard library */
0040, 0040, 0040, 0040, 0040, 0040, 0040, 0040, /* NUL ^A - ^G */
@@ -69,7 +69,7 @@ static uchar NEAR ctype_ujis[257] =
0020, 0020, 0020, 0020, 0020, 0020, 0020, 0000,
};
-static uchar NEAR to_lower_ujis[]=
+static const uchar NEAR to_lower_ujis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -105,7 +105,7 @@ static uchar NEAR to_lower_ujis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR to_upper_ujis[]=
+static const uchar NEAR to_upper_ujis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -141,7 +141,7 @@ static uchar NEAR to_upper_ujis[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377'
};
-static uchar NEAR sort_order_ujis[]=
+static const uchar NEAR sort_order_ujis[]=
{
'\000','\001','\002','\003','\004','\005','\006','\007',
'\010','\011','\012','\013','\014','\015','\016','\017',
@@ -200,7 +200,7 @@ static uint mbcharlen_ujis(CHARSET_INFO *cs __attribute__((unused)),uint c)
}
-static uint16 tab_jisx0201_uni[256]={
+static const uint16 tab_jisx0201_uni[256]={
0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -269,7 +269,7 @@ my_wc_mb_jisx0201(CHARSET_INFO *cs __attribute__((unused)),
/* page 0 0x2121-0x217E */
-static uint16 tab_jisx0208_uni0[]={
+static const uint16 tab_jisx0208_uni0[]={
0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
@@ -284,7 +284,7 @@ static uint16 tab_jisx0208_uni0[]={
0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7};
/* page 1 0x2221-0x227E */
-static uint16 tab_jisx0208_uni1[]={
+static const uint16 tab_jisx0208_uni1[]={
0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x203B,
0x3012,0x2192,0x2190,0x2191,0x2193,0x3013, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -299,7 +299,7 @@ static uint16 tab_jisx0208_uni1[]={
0x00B6, 0, 0, 0, 0,0x25EF};
/* page 2 0x2330-0x237A */
-static uint16 tab_jisx0208_uni2[]={
+static const uint16 tab_jisx0208_uni2[]={
0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,
0xFF18,0xFF19, 0, 0, 0, 0, 0, 0,
0,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,
@@ -312,7 +312,7 @@ static uint16 tab_jisx0208_uni2[]={
0xFF58,0xFF59,0xFF5A};
/* page 3 0x2421-0x2473 */
-static uint16 tab_jisx0208_uni3[]={
+static const uint16 tab_jisx0208_uni3[]={
0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
@@ -326,7 +326,7 @@ static uint16 tab_jisx0208_uni3[]={
0x3091,0x3092,0x3093};
/* page 4 0x2521-0x2576 */
-static uint16 tab_jisx0208_uni4[]={
+static const uint16 tab_jisx0208_uni4[]={
0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
@@ -340,7 +340,7 @@ static uint16 tab_jisx0208_uni4[]={
0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6};
/* page 5 0x2621-0x2658 */
-static uint16 tab_jisx0208_uni5[]={
+static const uint16 tab_jisx0208_uni5[]={
0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
@@ -351,7 +351,7 @@ static uint16 tab_jisx0208_uni5[]={
};
/* page 6 0x2721-0x2771 */
-static uint16 tab_jisx0208_uni6[]={
+static const uint16 tab_jisx0208_uni6[]={
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,
0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,
@@ -365,7 +365,7 @@ static uint16 tab_jisx0208_uni6[]={
0x044F};
/* page 7 0x2821-0x2840 */
-static uint16 tab_jisx0208_uni7[]={
+static const uint16 tab_jisx0208_uni7[]={
0x2500,0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,
0x2524,0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,
0x2517,0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,
@@ -373,7 +373,7 @@ static uint16 tab_jisx0208_uni7[]={
};
/* page 8 0x3021-0x307E */
-static uint16 tab_jisx0208_uni8[]={
+static const uint16 tab_jisx0208_uni8[]={
0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
@@ -388,7 +388,7 @@ static uint16 tab_jisx0208_uni8[]={
0x59FB,0x5F15,0x98F2,0x6DEB,0x80E4,0x852D};
/* page 9 0x3121-0x317E */
-static uint16 tab_jisx0208_uni9[]={
+static const uint16 tab_jisx0208_uni9[]={
0x9662,0x9670,0x96A0,0x97FB,0x540B,0x53F3,0x5B87,0x70CF,
0x7FBD,0x8FC2,0x96E8,0x536F,0x9D5C,0x7ABA,0x4E11,0x7893,
0x81FC,0x6E26,0x5618,0x5504,0x6B1D,0x851A,0x9C3B,0x59E5,
@@ -403,7 +403,7 @@ static uint16 tab_jisx0208_uni9[]={
0x7525,0x51F9,0x592E,0x5965,0x5F80,0x5FDC};
/* page 10 0x3221-0x327E */
-static uint16 tab_jisx0208_uni10[]={
+static const uint16 tab_jisx0208_uni10[]={
0x62BC,0x65FA,0x6A2A,0x6B27,0x6BB4,0x738B,0x7FC1,0x8956,
0x9D2C,0x9D0E,0x9EC4,0x5CA1,0x6C96,0x837B,0x5104,0x5C4B,
0x61B6,0x81C6,0x6876,0x7261,0x4E59,0x4FFA,0x5378,0x6069,
@@ -418,7 +418,7 @@ static uint16 tab_jisx0208_uni10[]={
0x6094,0x6062,0x61D0,0x6212,0x62D0,0x6539};
/* page 11 0x3321-0x337E */
-static uint16 tab_jisx0208_uni11[]={
+static const uint16 tab_jisx0208_uni11[]={
0x9B41,0x6666,0x68B0,0x6D77,0x7070,0x754C,0x7686,0x7D75,
0x82A5,0x87F9,0x958B,0x968E,0x8C9D,0x51F1,0x52BE,0x5916,
0x54B3,0x5BB3,0x5D16,0x6168,0x6982,0x6DAF,0x788D,0x84CB,
@@ -433,7 +433,7 @@ static uint16 tab_jisx0208_uni11[]={
0x938C,0x565B,0x9D28,0x6822,0x8305,0x8431};
/* page 12 0x3421-0x347E */
-static uint16 tab_jisx0208_uni12[]={
+static const uint16 tab_jisx0208_uni12[]={
0x7CA5,0x5208,0x82C5,0x74E6,0x4E7E,0x4F83,0x51A0,0x5BD2,
0x520A,0x52D8,0x52E7,0x5DFB,0x559A,0x582A,0x59E6,0x5B8C,
0x5B98,0x5BDB,0x5E72,0x5E79,0x60A3,0x611F,0x6163,0x61BE,
@@ -448,7 +448,7 @@ static uint16 tab_jisx0208_uni12[]={
0x673A,0x65D7,0x65E2,0x671F,0x68CB,0x68C4};
/* page 13 0x3521-0x357E */
-static uint16 tab_jisx0208_uni13[]={
+static const uint16 tab_jisx0208_uni13[]={
0x6A5F,0x5E30,0x6BC5,0x6C17,0x6C7D,0x757F,0x7948,0x5B63,
0x7A00,0x7D00,0x5FBD,0x898F,0x8A18,0x8CB4,0x8D77,0x8ECC,
0x8F1D,0x98E2,0x9A0E,0x9B3C,0x4E80,0x507D,0x5100,0x5993,
@@ -463,7 +463,7 @@ static uint16 tab_jisx0208_uni13[]={
0x6F01,0x79A6,0x9B5A,0x4EA8,0x4EAB,0x4EAC};
/* page 14 0x3621-0x367E */
-static uint16 tab_jisx0208_uni14[]={
+static const uint16 tab_jisx0208_uni14[]={
0x4F9B,0x4FA0,0x50D1,0x5147,0x7AF6,0x5171,0x51F6,0x5354,
0x5321,0x537F,0x53EB,0x55AC,0x5883,0x5CE1,0x5F37,0x5F4A,
0x602F,0x6050,0x606D,0x631F,0x6559,0x6A4B,0x6CC1,0x72C2,
@@ -478,7 +478,7 @@ static uint16 tab_jisx0208_uni14[]={
0x9685,0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48};
/* page 15 0x3721-0x377E */
-static uint16 tab_jisx0208_uni15[]={
+static const uint16 tab_jisx0208_uni15[]={
0x6398,0x7A9F,0x6C93,0x9774,0x8F61,0x7AAA,0x718A,0x9688,
0x7C82,0x6817,0x7E70,0x6851,0x936C,0x52F2,0x541B,0x85AB,
0x8A13,0x7FA4,0x8ECD,0x90E1,0x5366,0x8888,0x7941,0x4FC2,
@@ -493,7 +493,7 @@ static uint16 tab_jisx0208_uni15[]={
0x5ACC,0x5EFA,0x61B2,0x61F8,0x62F3,0x6372};
/* page 16 0x3821-0x387E */
-static uint16 tab_jisx0208_uni16[]={
+static const uint16 tab_jisx0208_uni16[]={
0x691C,0x6A29,0x727D,0x72AC,0x732E,0x7814,0x786F,0x7D79,
0x770C,0x80A9,0x898B,0x8B19,0x8CE2,0x8ED2,0x9063,0x9375,
0x967A,0x9855,0x9A13,0x9E78,0x5143,0x539F,0x53B3,0x5E7B,
@@ -508,7 +508,7 @@ static uint16 tab_jisx0208_uni16[]={
0x529F,0x52B9,0x52FE,0x539A,0x53E3,0x5411};
/* page 17 0x3921-0x397E */
-static uint16 tab_jisx0208_uni17[]={
+static const uint16 tab_jisx0208_uni17[]={
0x540E,0x5589,0x5751,0x57A2,0x597D,0x5B54,0x5B5D,0x5B8F,
0x5DE5,0x5DE7,0x5DF7,0x5E78,0x5E83,0x5E9A,0x5EB7,0x5F18,
0x6052,0x614C,0x6297,0x62D8,0x63A7,0x653B,0x6602,0x6643,
@@ -523,7 +523,7 @@ static uint16 tab_jisx0208_uni17[]={
0x7511,0x5FFD,0x60DA,0x9AA8,0x72DB,0x8FBC};
/* page 18 0x3A21-0x3A7E */
-static uint16 tab_jisx0208_uni18[]={
+static const uint16 tab_jisx0208_uni18[]={
0x6B64,0x9803,0x4ECA,0x56F0,0x5764,0x58BE,0x5A5A,0x6068,
0x61C7,0x660F,0x6606,0x6839,0x68B1,0x6DF7,0x75D5,0x7D3A,
0x826E,0x9B42,0x4E9B,0x4F50,0x53C9,0x5506,0x5D6F,0x5DE6,
@@ -538,7 +538,7 @@ static uint16 tab_jisx0208_uni18[]={
0x685C,0x9BAD,0x7B39,0x5319,0x518A,0x5237};
/* page 19 0x3B21-0x3B7E */
-static uint16 tab_jisx0208_uni19[]={
+static const uint16 tab_jisx0208_uni19[]={
0x5BDF,0x62F6,0x64AE,0x64E6,0x672D,0x6BBA,0x85A9,0x96D1,
0x7690,0x9BD6,0x634C,0x9306,0x9BAB,0x76BF,0x6652,0x4E09,
0x5098,0x53C2,0x5C71,0x60E8,0x6492,0x6563,0x685F,0x71E6,
@@ -553,7 +553,7 @@ static uint16 tab_jisx0208_uni19[]={
0x5150,0x5B57,0x5BFA,0x6148,0x6301,0x6642};
/* page 20 0x3C21-0x3C7E */
-static uint16 tab_jisx0208_uni20[]={
+static const uint16 tab_jisx0208_uni20[]={
0x6B21,0x6ECB,0x6CBB,0x723E,0x74BD,0x75D4,0x78C1,0x793A,
0x800C,0x8033,0x81EA,0x8494,0x8F9E,0x6C50,0x9E7F,0x5F0F,
0x8B58,0x9D2B,0x7AFA,0x8EF8,0x5B8D,0x96EB,0x4E03,0x53F1,
@@ -568,7 +568,7 @@ static uint16 tab_jisx0208_uni20[]={
0x6A39,0x7DAC,0x9700,0x56DA,0x53CE,0x5468};
/* page 21 0x3D21-0x3D7E */
-static uint16 tab_jisx0208_uni21[]={
+static const uint16 tab_jisx0208_uni21[]={
0x5B97,0x5C31,0x5DDE,0x4FEE,0x6101,0x62FE,0x6D32,0x79C0,
0x79CB,0x7D42,0x7E4D,0x7FD2,0x81ED,0x821F,0x8490,0x8846,
0x8972,0x8B90,0x8E74,0x8F2F,0x9031,0x914B,0x916C,0x96C6,
@@ -583,7 +583,7 @@ static uint16 tab_jisx0208_uni21[]={
0x5F90,0x6055,0x92E4,0x9664,0x50B7,0x511F};
/* page 22 0x3E21-0x3E7E */
-static uint16 tab_jisx0208_uni22[]={
+static const uint16 tab_jisx0208_uni22[]={
0x52DD,0x5320,0x5347,0x53EC,0x54E8,0x5546,0x5531,0x5617,
0x5968,0x59BE,0x5A3C,0x5BB5,0x5C06,0x5C0F,0x5C11,0x5C1A,
0x5E84,0x5E8A,0x5EE0,0x5F70,0x627F,0x6284,0x62DB,0x638C,
@@ -598,7 +598,7 @@ static uint16 tab_jisx0208_uni22[]={
0x8B72,0x91B8,0x9320,0x5631,0x57F4,0x98FE};
/* page 23 0x3F21-0x3F7E */
-static uint16 tab_jisx0208_uni23[]={
+static const uint16 tab_jisx0208_uni23[]={
0x62ED,0x690D,0x6B96,0x71ED,0x7E54,0x8077,0x8272,0x89E6,
0x98DF,0x8755,0x8FB1,0x5C3B,0x4F38,0x4FE1,0x4FB5,0x5507,
0x5A20,0x5BDD,0x5BE9,0x5FC3,0x614E,0x632F,0x65B0,0x664B,
@@ -613,7 +613,7 @@ static uint16 tab_jisx0208_uni23[]={
0x6749,0x6919,0x83C5,0x9817,0x96C0,0x88FE};
/* page 24 0x4021-0x407E */
-static uint16 tab_jisx0208_uni24[]={
+static const uint16 tab_jisx0208_uni24[]={
0x6F84,0x647A,0x5BF8,0x4E16,0x702C,0x755D,0x662F,0x51C4,
0x5236,0x52E2,0x59D3,0x5F81,0x6027,0x6210,0x653F,0x6574,
0x661F,0x6674,0x68F2,0x6816,0x6B63,0x6E05,0x7272,0x751F,
@@ -628,7 +628,7 @@ static uint16 tab_jisx0208_uni24[]={
0x714E,0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA};
/* page 25 0x4121-0x417E */
-static uint16 tab_jisx0208_uni25[]={
+static const uint16 tab_jisx0208_uni25[]={
0x7E4A,0x7FA8,0x817A,0x821B,0x8239,0x85A6,0x8A6E,0x8CCE,
0x8DF5,0x9078,0x9077,0x92AD,0x9291,0x9583,0x9BAE,0x524D,
0x5584,0x6F38,0x7136,0x5168,0x7985,0x7E55,0x81B3,0x7CCE,
@@ -643,7 +643,7 @@ static uint16 tab_jisx0208_uni25[]={
0x9397,0x971C,0x9A12,0x50CF,0x5897,0x618E};
/* page 26 0x4221-0x427E */
-static uint16 tab_jisx0208_uni26[]={
+static const uint16 tab_jisx0208_uni26[]={
0x81D3,0x8535,0x8D08,0x9020,0x4FC3,0x5074,0x5247,0x5373,
0x606F,0x6349,0x675F,0x6E2C,0x8DB3,0x901F,0x4FD7,0x5C5E,
0x8CCA,0x65CF,0x7D9A,0x5352,0x8896,0x5176,0x63C3,0x5B58,
@@ -658,7 +658,7 @@ static uint16 tab_jisx0208_uni26[]={
0x6FC1,0x8AFE,0x8338,0x51E7,0x86F8,0x53EA};
/* page 27 0x4321-0x437E */
-static uint16 tab_jisx0208_uni27[]={
+static const uint16 tab_jisx0208_uni27[]={
0x53E9,0x4F46,0x9054,0x8FB0,0x596A,0x8131,0x5DFD,0x7AEA,
0x8FBF,0x68DA,0x8C37,0x72F8,0x9C48,0x6A3D,0x8AB0,0x4E39,
0x5358,0x5606,0x5766,0x62C5,0x63A2,0x65E6,0x6B4E,0x6DE1,
@@ -673,7 +673,7 @@ static uint16 tab_jisx0208_uni27[]={
0x8CAF,0x4E01,0x5146,0x51CB,0x558B,0x5BF5};
/* page 28 0x4421-0x447E */
-static uint16 tab_jisx0208_uni28[]={
+static const uint16 tab_jisx0208_uni28[]={
0x5E16,0x5E33,0x5E81,0x5F14,0x5F35,0x5F6B,0x5FB4,0x61F2,
0x6311,0x66A2,0x671D,0x6F6E,0x7252,0x753A,0x773A,0x8074,
0x8139,0x8178,0x8776,0x8ABF,0x8ADC,0x8D85,0x8DF3,0x929A,
@@ -688,7 +688,7 @@ static uint16 tab_jisx0208_uni28[]={
0x7DE0,0x8247,0x8A02,0x8AE6,0x8E44,0x9013};
/* page 29 0x4521-0x457E */
-static uint16 tab_jisx0208_uni29[]={
+static const uint16 tab_jisx0208_uni29[]={
0x90B8,0x912D,0x91D8,0x9F0E,0x6CE5,0x6458,0x64E2,0x6575,
0x6EF4,0x7684,0x7B1B,0x9069,0x93D1,0x6EBA,0x54F2,0x5FB9,
0x64A4,0x8F4D,0x8FED,0x9244,0x5178,0x586B,0x5929,0x5C55,
@@ -703,7 +703,7 @@ static uint16 tab_jisx0208_uni29[]={
0x7B49,0x7B54,0x7B52,0x7CD6,0x7D71,0x5230};
/* page 30 0x4621-0x467E */
-static uint16 tab_jisx0208_uni30[]={
+static const uint16 tab_jisx0208_uni30[]={
0x8463,0x8569,0x85E4,0x8A0E,0x8B04,0x8C46,0x8E0F,0x9003,
0x900F,0x9419,0x9676,0x982D,0x9A30,0x95D8,0x50CD,0x52D5,
0x540C,0x5802,0x5C0E,0x61A7,0x649E,0x6D1E,0x77B3,0x7AE5,
@@ -718,7 +718,7 @@ static uint16 tab_jisx0208_uni30[]={
0x8089,0x8679,0x5EFF,0x65E5,0x4E73,0x5165};
/* page 31 0x4721-0x477E */
-static uint16 tab_jisx0208_uni31[]={
+static const uint16 tab_jisx0208_uni31[]={
0x5982,0x5C3F,0x97EE,0x4EFB,0x598A,0x5FCD,0x8A8D,0x6FE1,
0x79B0,0x7962,0x5BE7,0x8471,0x732B,0x71B1,0x5E74,0x5FF5,
0x637B,0x649A,0x71C3,0x7C98,0x4E43,0x5EFC,0x4E4B,0x57DC,
@@ -733,7 +733,7 @@ static uint16 tab_jisx0208_uni31[]={
0x6F20,0x7206,0x7E1B,0x83AB,0x99C1,0x9EA6};
/* page 32 0x4821-0x487E */
-static uint16 tab_jisx0208_uni32[]={
+static const uint16 tab_jisx0208_uni32[]={
0x51FD,0x7BB1,0x7872,0x7BB8,0x8087,0x7B48,0x6AE8,0x5E61,
0x808C,0x7551,0x7560,0x516B,0x9262,0x6E8C,0x767A,0x9197,
0x9AEA,0x4F10,0x7F70,0x629C,0x7B4F,0x95A5,0x9CE9,0x567A,
@@ -748,7 +748,7 @@ static uint16 tab_jisx0208_uni32[]={
0x5FAE,0x6787,0x6BD8,0x7435,0x7709,0x7F8E};
/* page 33 0x4921-0x497E */
-static uint16 tab_jisx0208_uni33[]={
+static const uint16 tab_jisx0208_uni33[]={
0x9F3B,0x67CA,0x7A17,0x5339,0x758B,0x9AED,0x5F66,0x819D,
0x83F1,0x8098,0x5F3C,0x5FC5,0x7562,0x7B46,0x903C,0x6867,
0x59EB,0x5A9B,0x7D10,0x767E,0x8B2C,0x4FF5,0x5F6A,0x6A19,
@@ -763,7 +763,7 @@ static uint16 tab_jisx0208_uni33[]={
0x8557,0x4F0F,0x526F,0x5FA9,0x5E45,0x670D};
/* page 34 0x4A21-0x4A7E */
-static uint16 tab_jisx0208_uni34[]={
+static const uint16 tab_jisx0208_uni34[]={
0x798F,0x8179,0x8907,0x8986,0x6DF5,0x5F17,0x6255,0x6CB8,
0x4ECF,0x7269,0x9B92,0x5206,0x543B,0x5674,0x58B3,0x61A4,
0x626E,0x711A,0x596E,0x7C89,0x7CDE,0x7D1B,0x96F0,0x6587,
@@ -778,7 +778,7 @@ static uint16 tab_jisx0208_uni34[]={
0x5E96,0x62B1,0x6367,0x653E,0x65B9,0x670B};
/* page 35 0x4B21-0x4B7E */
-static uint16 tab_jisx0208_uni35[]={
+static const uint16 tab_jisx0208_uni35[]={
0x6CD5,0x6CE1,0x70F9,0x7832,0x7E2B,0x80DE,0x82B3,0x840C,
0x84EC,0x8702,0x8912,0x8A2A,0x8C4A,0x90A6,0x92D2,0x98FD,
0x9CF3,0x9D6C,0x4E4F,0x4EA1,0x508D,0x5256,0x574A,0x59A8,
@@ -793,7 +793,7 @@ static uint16 tab_jisx0208_uni35[]={
0x4FAD,0x7E6D,0x9EBF,0x4E07,0x6162,0x6E80};
/* page 36 0x4C21-0x4C7E */
-static uint16 tab_jisx0208_uni36[]={
+static const uint16 tab_jisx0208_uni36[]={
0x6F2B,0x8513,0x5473,0x672A,0x9B45,0x5DF3,0x7B95,0x5CAC,
0x5BC6,0x871C,0x6E4A,0x84D1,0x7A14,0x8108,0x5999,0x7C8D,
0x6C11,0x7720,0x52D9,0x5922,0x7121,0x725F,0x77DB,0x9727,
@@ -808,7 +808,7 @@ static uint16 tab_jisx0208_uni36[]={
0x85AE,0x9453,0x6109,0x6108,0x6CB9,0x7652};
/* page 37 0x4D21-0x4D7E */
-static uint16 tab_jisx0208_uni37[]={
+static const uint16 tab_jisx0208_uni37[]={
0x8AED,0x8F38,0x552F,0x4F51,0x512A,0x52C7,0x53CB,0x5BA5,
0x5E7D,0x60A0,0x6182,0x63D6,0x6709,0x67DA,0x6E67,0x6D8C,
0x7336,0x7337,0x7531,0x7950,0x88D5,0x8A98,0x904A,0x9091,
@@ -823,7 +823,7 @@ static uint16 tab_jisx0208_uni37[]={
0x540F,0x5C65,0x674E,0x68A8,0x7406,0x7483};
/* page 38 0x4E21-0x4E7E */
-static uint16 tab_jisx0208_uni38[]={
+static const uint16 tab_jisx0208_uni38[]={
0x75E2,0x88CF,0x88E1,0x91CC,0x96E2,0x9678,0x5F8B,0x7387,
0x7ACB,0x844E,0x63A0,0x7565,0x5289,0x6D41,0x6E9C,0x7409,
0x7559,0x786B,0x7C92,0x9686,0x7ADC,0x9F8D,0x4FB6,0x616E,
@@ -838,7 +838,7 @@ static uint16 tab_jisx0208_uni38[]={
0x6190,0x6F23,0x7149,0x7C3E,0x7DF4,0x806F};
/* page 39 0x4F21-0x4F53 */
-static uint16 tab_jisx0208_uni39[]={
+static const uint16 tab_jisx0208_uni39[]={
0x84EE,0x9023,0x932C,0x5442,0x9B6F,0x6AD3,0x7089,0x8CC2,
0x8DEF,0x9732,0x52B4,0x5A41,0x5ECA,0x5F04,0x6717,0x697C,
0x6994,0x6D6A,0x6F0F,0x7262,0x72FC,0x7BED,0x8001,0x807E,
@@ -848,7 +848,7 @@ static uint16 tab_jisx0208_uni39[]={
0x6E7E,0x7897,0x8155};
/* page 40 0x5021-0x507E */
-static uint16 tab_jisx0208_uni40[]={
+static const uint16 tab_jisx0208_uni40[]={
0x5F0C,0x4E10,0x4E15,0x4E2A,0x4E31,0x4E36,0x4E3C,0x4E3F,
0x4E42,0x4E56,0x4E58,0x4E82,0x4E85,0x8C6B,0x4E8A,0x8212,
0x5F0D,0x4E8E,0x4E9E,0x4E9F,0x4EA0,0x4EA2,0x4EB0,0x4EB3,
@@ -863,7 +863,7 @@ static uint16 tab_jisx0208_uni40[]={
0x5078,0x5080,0x509A,0x5085,0x50B4,0x50B2};
/* page 41 0x5121-0x517E */
-static uint16 tab_jisx0208_uni41[]={
+static const uint16 tab_jisx0208_uni41[]={
0x50C9,0x50CA,0x50B3,0x50C2,0x50D6,0x50DE,0x50E5,0x50ED,
0x50E3,0x50EE,0x50F9,0x50F5,0x5109,0x5101,0x5102,0x5116,
0x5115,0x5114,0x511A,0x5121,0x513A,0x5137,0x513C,0x513B,
@@ -878,7 +878,7 @@ static uint16 tab_jisx0208_uni41[]={
0x5294,0x5292,0x5271,0x5288,0x5291,0x8FA8};
/* page 42 0x5221-0x527E */
-static uint16 tab_jisx0208_uni42[]={
+static const uint16 tab_jisx0208_uni42[]={
0x8FA7,0x52AC,0x52AD,0x52BC,0x52B5,0x52C1,0x52CD,0x52D7,
0x52DE,0x52E3,0x52E6,0x98ED,0x52E0,0x52F3,0x52F5,0x52F8,
0x52F9,0x5306,0x5308,0x7538,0x530D,0x5310,0x530F,0x5315,
@@ -893,7 +893,7 @@ static uint16 tab_jisx0208_uni42[]={
0x54B8,0x54A5,0x54AC,0x54C4,0x54C8,0x54A8};
/* page 43 0x5321-0x537E */
-static uint16 tab_jisx0208_uni43[]={
+static const uint16 tab_jisx0208_uni43[]={
0x54AB,0x54C2,0x54A4,0x54BE,0x54BC,0x54D8,0x54E5,0x54E6,
0x550F,0x5514,0x54FD,0x54EE,0x54ED,0x54FA,0x54E2,0x5539,
0x5540,0x5563,0x554C,0x552E,0x555C,0x5545,0x5556,0x5557,
@@ -908,7 +908,7 @@ static uint16 tab_jisx0208_uni43[]={
0x56EE,0x56F9,0x5700,0x56FF,0x5704,0x5709};
/* page 44 0x5421-0x547E */
-static uint16 tab_jisx0208_uni44[]={
+static const uint16 tab_jisx0208_uni44[]={
0x5708,0x570B,0x570D,0x5713,0x5718,0x5716,0x55C7,0x571C,
0x5726,0x5737,0x5738,0x574E,0x573B,0x5740,0x574F,0x5769,
0x57C0,0x5788,0x5761,0x577F,0x5789,0x5793,0x57A0,0x57B3,
@@ -923,7 +923,7 @@ static uint16 tab_jisx0208_uni44[]={
0x5958,0x5962,0x5960,0x5967,0x596C,0x5969};
/* page 45 0x5521-0x557E */
-static uint16 tab_jisx0208_uni45[]={
+static const uint16 tab_jisx0208_uni45[]={
0x5978,0x5981,0x599D,0x4F5E,0x4FAB,0x59A3,0x59B2,0x59C6,
0x59E8,0x59DC,0x598D,0x59D9,0x59DA,0x5A25,0x5A1F,0x5A11,
0x5A1C,0x5A09,0x5A1A,0x5A40,0x5A6C,0x5A49,0x5A35,0x5A36,
@@ -938,7 +938,7 @@ static uint16 tab_jisx0208_uni45[]={
0x5C38,0x5C39,0x5C41,0x5C46,0x5C4E,0x5C53};
/* page 46 0x5621-0x567E */
-static uint16 tab_jisx0208_uni46[]={
+static const uint16 tab_jisx0208_uni46[]={
0x5C50,0x5C4F,0x5B71,0x5C6C,0x5C6E,0x4E62,0x5C76,0x5C79,
0x5C8C,0x5C91,0x5C94,0x599B,0x5CAB,0x5CBB,0x5CB6,0x5CBC,
0x5CB7,0x5CC5,0x5CBE,0x5CC7,0x5CD9,0x5CE9,0x5CFD,0x5CFA,
@@ -953,7 +953,7 @@ static uint16 tab_jisx0208_uni46[]={
0x5EA0,0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF};
/* page 47 0x5721-0x577E */
-static uint16 tab_jisx0208_uni47[]={
+static const uint16 tab_jisx0208_uni47[]={
0x5ED6,0x5EE3,0x5EDD,0x5EDA,0x5EDB,0x5EE2,0x5EE1,0x5EE8,
0x5EE9,0x5EEC,0x5EF1,0x5EF3,0x5EF0,0x5EF4,0x5EF8,0x5EFE,
0x5F03,0x5F09,0x5F5D,0x5F5C,0x5F0B,0x5F11,0x5F16,0x5F29,
@@ -968,7 +968,7 @@ static uint16 tab_jisx0208_uni47[]={
0x6059,0x6081,0x608D,0x60E7,0x6083,0x609A};
/* page 48 0x5821-0x587E */
-static uint16 tab_jisx0208_uni48[]={
+static const uint16 tab_jisx0208_uni48[]={
0x6084,0x609B,0x6096,0x6097,0x6092,0x60A7,0x608B,0x60E1,
0x60B8,0x60E0,0x60D3,0x60B4,0x5FF0,0x60BD,0x60C6,0x60B5,
0x60D8,0x614D,0x6115,0x6106,0x60F6,0x60F7,0x6100,0x60F4,
@@ -983,7 +983,7 @@ static uint16 tab_jisx0208_uni48[]={
0x6208,0x6209,0x620D,0x620C,0x6214,0x621B};
/* page 49 0x5921-0x597E */
-static uint16 tab_jisx0208_uni49[]={
+static const uint16 tab_jisx0208_uni49[]={
0x621E,0x6221,0x622A,0x622E,0x6230,0x6232,0x6233,0x6241,
0x624E,0x625E,0x6263,0x625B,0x6260,0x6268,0x627C,0x6282,
0x6289,0x627E,0x6292,0x6293,0x6296,0x62D4,0x6283,0x6294,
@@ -998,7 +998,7 @@ static uint16 tab_jisx0208_uni49[]={
0x6495,0x6493,0x64A5,0x64A9,0x6488,0x64BC};
/* page 50 0x5A21-0x5A7E */
-static uint16 tab_jisx0208_uni50[]={
+static const uint16 tab_jisx0208_uni50[]={
0x64DA,0x64D2,0x64C5,0x64C7,0x64BB,0x64D8,0x64C2,0x64F1,
0x64E7,0x8209,0x64E0,0x64E1,0x62AC,0x64E3,0x64EF,0x652C,
0x64F6,0x64F4,0x64F2,0x64FA,0x6500,0x64FD,0x6518,0x651C,
@@ -1013,7 +1013,7 @@ static uint16 tab_jisx0208_uni50[]={
0x669D,0x66C1,0x66B9,0x66C9,0x66BE,0x66BC};
/* page 51 0x5B21-0x5B7E */
-static uint16 tab_jisx0208_uni51[]={
+static const uint16 tab_jisx0208_uni51[]={
0x66C4,0x66B8,0x66D6,0x66DA,0x66E0,0x663F,0x66E6,0x66E9,
0x66F0,0x66F5,0x66F7,0x670F,0x6716,0x671E,0x6726,0x6727,
0x9738,0x672E,0x673F,0x6736,0x6741,0x6738,0x6737,0x6746,
@@ -1028,7 +1028,7 @@ static uint16 tab_jisx0208_uni51[]={
0x68D8,0x6922,0x6926,0x68E1,0x690C,0x68CD};
/* page 52 0x5C21-0x5C7E */
-static uint16 tab_jisx0208_uni52[]={
+static const uint16 tab_jisx0208_uni52[]={
0x68D4,0x68E7,0x68D5,0x6936,0x6912,0x6904,0x68D7,0x68E3,
0x6925,0x68F9,0x68E0,0x68EF,0x6928,0x692A,0x691A,0x6923,
0x6921,0x68C6,0x6979,0x6977,0x695C,0x6978,0x696B,0x6954,
@@ -1043,7 +1043,7 @@ static uint16 tab_jisx0208_uni52[]={
0x6A90,0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3};
/* page 53 0x5D21-0x5D7E */
-static uint16 tab_jisx0208_uni53[]={
+static const uint16 tab_jisx0208_uni53[]={
0x6A97,0x8617,0x6ABB,0x6AC3,0x6AC2,0x6AB8,0x6AB3,0x6AAC,
0x6ADE,0x6AD1,0x6ADF,0x6AAA,0x6ADA,0x6AEA,0x6AFB,0x6B05,
0x8616,0x6AFA,0x6B12,0x6B16,0x9B31,0x6B1F,0x6B38,0x6B37,
@@ -1058,7 +1058,7 @@ static uint16 tab_jisx0208_uni53[]={
0x6CD7,0x6CC5,0x6CDD,0x6CAE,0x6CB1,0x6CBE};
/* page 54 0x5E21-0x5E7E */
-static uint16 tab_jisx0208_uni54[]={
+static const uint16 tab_jisx0208_uni54[]={
0x6CBA,0x6CDB,0x6CEF,0x6CD9,0x6CEA,0x6D1F,0x884D,0x6D36,
0x6D2B,0x6D3D,0x6D38,0x6D19,0x6D35,0x6D33,0x6D12,0x6D0C,
0x6D63,0x6D93,0x6D64,0x6D5A,0x6D79,0x6D59,0x6D8E,0x6D95,
@@ -1073,7 +1073,7 @@ static uint16 tab_jisx0208_uni54[]={
0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC};
/* page 55 0x5F21-0x5F7E */
-static uint16 tab_jisx0208_uni55[]={
+static const uint16 tab_jisx0208_uni55[]={
0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
@@ -1088,7 +1088,7 @@ static uint16 tab_jisx0208_uni55[]={
0x71CE,0x71E0,0x71EC,0x71E7,0x71F5,0x71FC};
/* page 56 0x6021-0x607E */
-static uint16 tab_jisx0208_uni56[]={
+static const uint16 tab_jisx0208_uni56[]={
0x71F9,0x71FF,0x720D,0x7210,0x721B,0x7228,0x722D,0x722C,
0x7230,0x7232,0x723B,0x723C,0x723F,0x7240,0x7246,0x724B,
0x7258,0x7274,0x727E,0x7282,0x7281,0x7287,0x7292,0x7296,
@@ -1103,7 +1103,7 @@ static uint16 tab_jisx0208_uni56[]={
0x749E,0x74A7,0x74CA,0x74CF,0x74D4,0x73F1};
/* page 57 0x6121-0x617E */
-static uint16 tab_jisx0208_uni57[]={
+static const uint16 tab_jisx0208_uni57[]={
0x74E0,0x74E3,0x74E7,0x74E9,0x74EE,0x74F2,0x74F0,0x74F1,
0x74F8,0x74F7,0x7504,0x7503,0x7505,0x750C,0x750E,0x750D,
0x7515,0x7513,0x751E,0x7526,0x752C,0x753C,0x7544,0x754D,
@@ -1118,7 +1118,7 @@ static uint16 tab_jisx0208_uni57[]={
0x7668,0x7669,0x766A,0x7667,0x766C,0x7670};
/* page 58 0x6221-0x627E */
-static uint16 tab_jisx0208_uni58[]={
+static const uint16 tab_jisx0208_uni58[]={
0x7672,0x7676,0x7678,0x767C,0x7680,0x7683,0x7688,0x768B,
0x768E,0x7696,0x7693,0x7699,0x769A,0x76B0,0x76B4,0x76B8,
0x76B9,0x76BA,0x76C2,0x76CD,0x76D6,0x76D2,0x76DE,0x76E1,
@@ -1133,7 +1133,7 @@ static uint16 tab_jisx0208_uni58[]={
0x78D4,0x78BE,0x78BC,0x78C5,0x78CA,0x78EC};
/* page 59 0x6321-0x637E */
-static uint16 tab_jisx0208_uni59[]={
+static const uint16 tab_jisx0208_uni59[]={
0x78E7,0x78DA,0x78FD,0x78F4,0x7907,0x7912,0x7911,0x7919,
0x792C,0x792B,0x7940,0x7960,0x7957,0x795F,0x795A,0x7955,
0x7953,0x797A,0x797F,0x798A,0x799D,0x79A7,0x9F4B,0x79AA,
@@ -1148,7 +1148,7 @@ static uint16 tab_jisx0208_uni59[]={
0x7B19,0x7B1E,0x7B35,0x7B28,0x7B36,0x7B50};
/* page 60 0x6421-0x647E */
-static uint16 tab_jisx0208_uni60[]={
+static const uint16 tab_jisx0208_uni60[]={
0x7B7A,0x7B04,0x7B4D,0x7B0B,0x7B4C,0x7B45,0x7B75,0x7B65,
0x7B74,0x7B67,0x7B70,0x7B71,0x7B6C,0x7B6E,0x7B9D,0x7B98,
0x7B9F,0x7B8D,0x7B9C,0x7B9A,0x7B8B,0x7B92,0x7B8F,0x7B5D,
@@ -1163,7 +1163,7 @@ static uint16 tab_jisx0208_uni60[]={
0x7CEF,0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06};
/* page 61 0x6521-0x657E */
-static uint16 tab_jisx0208_uni61[]={
+static const uint16 tab_jisx0208_uni61[]={
0x7D02,0x7D1C,0x7D15,0x7D0A,0x7D45,0x7D4B,0x7D2E,0x7D32,
0x7D3F,0x7D35,0x7D46,0x7D73,0x7D56,0x7D4E,0x7D72,0x7D68,
0x7D6E,0x7D4F,0x7D63,0x7D93,0x7D89,0x7D5B,0x7D8F,0x7D7D,
@@ -1178,7 +1178,7 @@ static uint16 tab_jisx0208_uni61[]={
0x7E96,0x7E8E,0x7E9B,0x7E9C,0x7F38,0x7F3A};
/* page 62 0x6621-0x667E */
-static uint16 tab_jisx0208_uni62[]={
+static const uint16 tab_jisx0208_uni62[]={
0x7F45,0x7F4C,0x7F4D,0x7F4E,0x7F50,0x7F51,0x7F55,0x7F54,
0x7F58,0x7F5F,0x7F60,0x7F68,0x7F69,0x7F67,0x7F78,0x7F82,
0x7F86,0x7F83,0x7F88,0x7F87,0x7F8C,0x7F94,0x7F9E,0x7F9D,
@@ -1193,7 +1193,7 @@ static uint16 tab_jisx0208_uni62[]={
0x80F1,0x811B,0x8129,0x8123,0x812F,0x814B};
/* page 63 0x6721-0x677E */
-static uint16 tab_jisx0208_uni63[]={
+static const uint16 tab_jisx0208_uni63[]={
0x968B,0x8146,0x813E,0x8153,0x8151,0x80FC,0x8171,0x816E,
0x8165,0x8166,0x8174,0x8183,0x8188,0x818A,0x8180,0x8182,
0x81A0,0x8195,0x81A4,0x81A3,0x815F,0x8193,0x81A9,0x81B0,
@@ -1208,7 +1208,7 @@ static uint16 tab_jisx0208_uni63[]={
0x82F9,0x82DE,0x8306,0x82DC,0x8309,0x82D9};
/* page 64 0x6821-0x687E */
-static uint16 tab_jisx0208_uni64[]={
+static const uint16 tab_jisx0208_uni64[]={
0x8335,0x8334,0x8316,0x8332,0x8331,0x8340,0x8339,0x8350,
0x8345,0x832F,0x832B,0x8317,0x8318,0x8385,0x839A,0x83AA,
0x839F,0x83A2,0x8396,0x8323,0x838E,0x8387,0x838A,0x837C,
@@ -1223,7 +1223,7 @@ static uint16 tab_jisx0208_uni64[]={
0x8514,0x84FC,0x8540,0x8563,0x8558,0x8548};
/* page 65 0x6921-0x697E */
-static uint16 tab_jisx0208_uni65[]={
+static const uint16 tab_jisx0208_uni65[]={
0x8541,0x8602,0x854B,0x8555,0x8580,0x85A4,0x8588,0x8591,
0x858A,0x85A8,0x856D,0x8594,0x859B,0x85EA,0x8587,0x859C,
0x8577,0x857E,0x8590,0x85C9,0x85BA,0x85CF,0x85B9,0x85D0,
@@ -1238,7 +1238,7 @@ static uint16 tab_jisx0208_uni65[]={
0x874E,0x8774,0x8757,0x8768,0x876E,0x8759};
/* page 66 0x6A21-0x6A7E */
-static uint16 tab_jisx0208_uni66[]={
+static const uint16 tab_jisx0208_uni66[]={
0x8753,0x8763,0x876A,0x8805,0x87A2,0x879F,0x8782,0x87AF,
0x87CB,0x87BD,0x87C0,0x87D0,0x96D6,0x87AB,0x87C4,0x87B3,
0x87C7,0x87C6,0x87BB,0x87EF,0x87F2,0x87E0,0x880F,0x880D,
@@ -1253,7 +1253,7 @@ static uint16 tab_jisx0208_uni66[]={
0x8936,0x8938,0x894C,0x891D,0x8960,0x895E};
/* page 67 0x6B21-0x6B7E */
-static uint16 tab_jisx0208_uni67[]={
+static const uint16 tab_jisx0208_uni67[]={
0x8966,0x8964,0x896D,0x896A,0x896F,0x8974,0x8977,0x897E,
0x8983,0x8988,0x898A,0x8993,0x8998,0x89A1,0x89A9,0x89A6,
0x89AC,0x89AF,0x89B2,0x89BA,0x89BD,0x89BF,0x89C0,0x89DA,
@@ -1268,7 +1268,7 @@ static uint16 tab_jisx0208_uni67[]={
0x8B4E,0x8B49,0x8B56,0x8B5B,0x8B5A,0x8B6B};
/* page 68 0x6C21-0x6C7E */
-static uint16 tab_jisx0208_uni68[]={
+static const uint16 tab_jisx0208_uni68[]={
0x8B5F,0x8B6C,0x8B6F,0x8B74,0x8B7D,0x8B80,0x8B8C,0x8B8E,
0x8B92,0x8B93,0x8B96,0x8B99,0x8B9A,0x8C3A,0x8C41,0x8C3F,
0x8C48,0x8C4C,0x8C4E,0x8C50,0x8C55,0x8C62,0x8C6C,0x8C78,
@@ -1283,7 +1283,7 @@ static uint16 tab_jisx0208_uni68[]={
0x8E1F,0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A};
/* page 69 0x6D21-0x6D7E */
-static uint16 tab_jisx0208_uni69[]={
+static const uint16 tab_jisx0208_uni69[]={
0x8E47,0x8E49,0x8E4C,0x8E50,0x8E48,0x8E59,0x8E64,0x8E60,
0x8E2A,0x8E63,0x8E55,0x8E76,0x8E72,0x8E7C,0x8E81,0x8E87,
0x8E85,0x8E84,0x8E8B,0x8E8A,0x8E93,0x8E91,0x8E94,0x8E99,
@@ -1298,7 +1298,7 @@ static uint16 tab_jisx0208_uni69[]={
0x900B,0x9027,0x9036,0x9035,0x9039,0x8FF8};
/* page 70 0x6E21-0x6E7E */
-static uint16 tab_jisx0208_uni70[]={
+static const uint16 tab_jisx0208_uni70[]={
0x904F,0x9050,0x9051,0x9052,0x900E,0x9049,0x903E,0x9056,
0x9058,0x905E,0x9068,0x906F,0x9076,0x96A8,0x9072,0x9082,
0x907D,0x9081,0x9080,0x908A,0x9089,0x908F,0x90A8,0x90AF,
@@ -1313,7 +1313,7 @@ static uint16 tab_jisx0208_uni70[]={
0x92B7,0x92E9,0x930F,0x92FA,0x9344,0x932E};
/* page 71 0x6F21-0x6F7E */
-static uint16 tab_jisx0208_uni71[]={
+static const uint16 tab_jisx0208_uni71[]={
0x9319,0x9322,0x931A,0x9323,0x933A,0x9335,0x933B,0x935C,
0x9360,0x937C,0x936E,0x9356,0x93B0,0x93AC,0x93AD,0x9394,
0x93B9,0x93D6,0x93D7,0x93E8,0x93E5,0x93D8,0x93C3,0x93DD,
@@ -1328,7 +1328,7 @@ static uint16 tab_jisx0208_uni71[]={
0x964C,0x964F,0x964B,0x9677,0x965C,0x965E};
/* page 72 0x7021-0x707E */
-static uint16 tab_jisx0208_uni72[]={
+static const uint16 tab_jisx0208_uni72[]={
0x965D,0x965F,0x9666,0x9672,0x966C,0x968D,0x9698,0x9695,
0x9697,0x96AA,0x96A7,0x96B1,0x96B2,0x96B0,0x96B4,0x96B6,
0x96B8,0x96B9,0x96CE,0x96CB,0x96C9,0x96CD,0x894D,0x96DC,
@@ -1343,7 +1343,7 @@ static uint16 tab_jisx0208_uni72[]={
0x9846,0x984F,0x984B,0x986B,0x986F,0x9870};
/* page 73 0x7121-0x717E */
-static uint16 tab_jisx0208_uni73[]={
+static const uint16 tab_jisx0208_uni73[]={
0x9871,0x9874,0x9873,0x98AA,0x98AF,0x98B1,0x98B6,0x98C4,
0x98C3,0x98C6,0x98E9,0x98EB,0x9903,0x9909,0x9912,0x9914,
0x9918,0x9921,0x991D,0x991E,0x9924,0x9920,0x992C,0x992E,
@@ -1358,7 +1358,7 @@ static uint16 tab_jisx0208_uni73[]={
0x9AEF,0x9AEB,0x9AEE,0x9AF4,0x9AF1,0x9AF7};
/* page 74 0x7221-0x727E */
-static uint16 tab_jisx0208_uni74[]={
+static const uint16 tab_jisx0208_uni74[]={
0x9AFB,0x9B06,0x9B18,0x9B1A,0x9B1F,0x9B22,0x9B23,0x9B25,
0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2E,0x9B2F,0x9B32,0x9B44,
0x9B43,0x9B4F,0x9B4D,0x9B4E,0x9B51,0x9B58,0x9B74,0x9B93,
@@ -1373,7 +1373,7 @@ static uint16 tab_jisx0208_uni74[]={
0x9D12,0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48};
/* page 75 0x7321-0x737E */
-static uint16 tab_jisx0208_uni75[]={
+static const uint16 tab_jisx0208_uni75[]={
0x9D5D,0x9D5E,0x9D64,0x9D51,0x9D50,0x9D59,0x9D72,0x9D89,
0x9D87,0x9DAB,0x9D6F,0x9D7A,0x9D9A,0x9DA4,0x9DA9,0x9DB2,
0x9DC4,0x9DC1,0x9DBB,0x9DB8,0x9DBA,0x9DC6,0x9DCF,0x9DC2,
@@ -1388,7 +1388,7 @@ static uint16 tab_jisx0208_uni75[]={
0x9F77,0x9F72,0x9F76,0x9F95,0x9F9C,0x9FA0};
/* page 76 0x7421-0x7426 */
-static uint16 tab_jisx0208_uni76[]={
+static const uint16 tab_jisx0208_uni76[]={
0x582F,0x69C7,0x9059,0x7464,0x51DC,0x7199};
static int
@@ -1552,25 +1552,25 @@ my_jisx0208_uni_onechar(int code){
/* page 0 0x005C-0x005C */
-static uint16 tab_uni_jisx02080[]={
+static const uint16 tab_uni_jisx02080[]={
0x2140};
/* page 1 0x00A2-0x00B6 */
-static uint16 tab_uni_jisx02081[]={
+static const uint16 tab_uni_jisx02081[]={
0x2171,0x2172, 0, 0, 0,0x2178,0x212F, 0,
0, 0,0x224C, 0, 0, 0,0x216B,0x215E,
0, 0,0x212D, 0,0x2279};
/* page 2 0x00D7-0x00D7 */
-static uint16 tab_uni_jisx02082[]={
+static const uint16 tab_uni_jisx02082[]={
0x215F};
/* page 3 0x00F7-0x00F7 */
-static uint16 tab_uni_jisx02083[]={
+static const uint16 tab_uni_jisx02083[]={
0x2160};
/* page 4 0x0391-0x03C9 */
-static uint16 tab_uni_jisx02084[]={
+static const uint16 tab_uni_jisx02084[]={
0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,0x2628,
0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F,0x2630,
0x2631, 0,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637,
@@ -1581,7 +1581,7 @@ static uint16 tab_uni_jisx02084[]={
0x2658};
/* page 5 0x0401-0x0451 */
-static uint16 tab_uni_jisx02085[]={
+static const uint16 tab_uni_jisx02085[]={
0x2727, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x2721,
0x2722,0x2723,0x2724,0x2725,0x2726,0x2728,0x2729,0x272A,
@@ -1595,7 +1595,7 @@ static uint16 tab_uni_jisx02085[]={
0x2757};
/* page 6 0x2010-0x203B */
-static uint16 tab_uni_jisx02086[]={
+static const uint16 tab_uni_jisx02086[]={
0x213E, 0, 0, 0, 0,0x213D,0x2142, 0,
0x2146,0x2147, 0, 0,0x2148,0x2149, 0, 0,
0x2277,0x2278, 0, 0, 0,0x2145,0x2144, 0,
@@ -1604,23 +1604,23 @@ static uint16 tab_uni_jisx02086[]={
0, 0, 0,0x2228};
/* page 7 0x2103-0x2103 */
-static uint16 tab_uni_jisx02087[]={
+static const uint16 tab_uni_jisx02087[]={
0x216E};
/* page 8 0x212B-0x212B */
-static uint16 tab_uni_jisx02088[]={
+static const uint16 tab_uni_jisx02088[]={
0x2272};
/* page 9 0x2190-0x2193 */
-static uint16 tab_uni_jisx02089[]={
+static const uint16 tab_uni_jisx02089[]={
0x222B,0x222C,0x222A,0x222D};
/* page 10 0x21D2-0x21D4 */
-static uint16 tab_uni_jisx020810[]={
+static const uint16 tab_uni_jisx020810[]={
0x224D, 0,0x224E};
/* page 11 0x2200-0x223D */
-static uint16 tab_uni_jisx020811[]={
+static const uint16 tab_uni_jisx020811[]={
0x224F, 0,0x225F,0x2250, 0, 0, 0,0x2260,
0x223A, 0, 0,0x223B, 0, 0, 0, 0,
0, 0,0x215D, 0, 0, 0, 0, 0,
@@ -1631,26 +1631,26 @@ static uint16 tab_uni_jisx020811[]={
0, 0, 0, 0, 0,0x2266};
/* page 12 0x2252-0x226B */
-static uint16 tab_uni_jisx020812[]={
+static const uint16 tab_uni_jisx020812[]={
0x2262, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x2162,0x2261,
0, 0, 0, 0,0x2165,0x2166, 0, 0,
0x2263,0x2264};
/* page 13 0x2282-0x2287 */
-static uint16 tab_uni_jisx020813[]={
+static const uint16 tab_uni_jisx020813[]={
0x223E,0x223F, 0, 0,0x223C,0x223D};
/* page 14 0x22A5-0x22A5 */
-static uint16 tab_uni_jisx020814[]={
+static const uint16 tab_uni_jisx020814[]={
0x225D};
/* page 15 0x2312-0x2312 */
-static uint16 tab_uni_jisx020815[]={
+static const uint16 tab_uni_jisx020815[]={
0x225E};
/* page 16 0x2500-0x254B */
-static uint16 tab_uni_jisx020816[]={
+static const uint16 tab_uni_jisx020816[]={
0x2821,0x282C,0x2822,0x282D, 0, 0, 0, 0,
0, 0, 0, 0,0x2823, 0, 0,0x282E,
0x2824, 0, 0,0x282F,0x2826, 0, 0,0x2831,
@@ -1663,7 +1663,7 @@ static uint16 tab_uni_jisx020816[]={
0, 0, 0,0x2836};
/* page 17 0x25A0-0x25CF */
-static uint16 tab_uni_jisx020817[]={
+static const uint16 tab_uni_jisx020817[]={
0x2223,0x2222, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0,0x2225,0x2224, 0, 0, 0, 0,
@@ -1673,30 +1673,30 @@ static uint16 tab_uni_jisx020817[]={
};
/* page 18 0x25EF-0x25EF */
-static uint16 tab_uni_jisx020818[]={
+static const uint16 tab_uni_jisx020818[]={
0x227E};
/* page 19 0x2605-0x2606 */
-static uint16 tab_uni_jisx020819[]={
+static const uint16 tab_uni_jisx020819[]={
0x217A,0x2179};
/* page 20 0x2640-0x2642 */
-static uint16 tab_uni_jisx020820[]={
+static const uint16 tab_uni_jisx020820[]={
0x216A, 0,0x2169};
/* page 21 0x266A-0x266F */
-static uint16 tab_uni_jisx020821[]={
+static const uint16 tab_uni_jisx020821[]={
0x2276, 0, 0,0x2275, 0,0x2274};
/* page 22 0x3000-0x301C */
-static uint16 tab_uni_jisx020822[]={
+static const uint16 tab_uni_jisx020822[]={
0x2121,0x2122,0x2123,0x2137, 0,0x2139,0x213A,0x213B,
0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,
0x215A,0x215B,0x2229,0x222E,0x214C,0x214D, 0, 0,
0, 0, 0, 0,0x2141};
/* page 23 0x3041-0x30FE */
-static uint16 tab_uni_jisx020823[]={
+static const uint16 tab_uni_jisx020823[]={
0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,0x2428,
0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,0x2430,
0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,0x2438,
@@ -1723,7 +1723,7 @@ static uint16 tab_uni_jisx020823[]={
0, 0,0x2126,0x213C,0x2133,0x2134};
/* page 24 0x4E00-0x5516 */
-static uint16 tab_uni_jisx020824[]={
+static const uint16 tab_uni_jisx020824[]={
0x306C,0x437A, 0,0x3C37, 0, 0, 0,0x4B7C,
0x3E66,0x3B30,0x3E65,0x323C, 0,0x4954,0x4D3F, 0,
0x5022,0x312F, 0, 0,0x336E,0x5023,0x4024,0x5242,
@@ -1953,7 +1953,7 @@ static uint16 tab_uni_jisx020824[]={
0x4562, 0, 0, 0,0x532A, 0,0x3022};
/* page 25 0x552E-0x5563 */
-static uint16 tab_uni_jisx020825[]={
+static const uint16 tab_uni_jisx020825[]={
0x5334,0x4D23, 0,0x3E27, 0,0x533A, 0, 0,
0, 0,0x5339,0x5330, 0, 0, 0, 0,
0x4243, 0,0x5331, 0, 0, 0,0x426F,0x5336,
@@ -1963,7 +1963,7 @@ static uint16 tab_uni_jisx020825[]={
0, 0, 0, 0, 0,0x5332};
/* page 26 0x557B-0x576A */
-static uint16 tab_uni_jisx020826[]={
+static const uint16 tab_uni_jisx020826[]={
0x5341,0x5346, 0,0x5342, 0,0x533D, 0, 0,
0x5347,0x4131, 0, 0,0x5349, 0,0x3922,0x533F,
0x437D, 0, 0, 0, 0, 0, 0, 0,
@@ -2029,7 +2029,7 @@ static uint16 tab_uni_jisx020826[]={
};
/* page 27 0x577F-0x5A9B */
-static uint16 tab_uni_jisx020827[]={
+static const uint16 tab_uni_jisx020827[]={
0x5434, 0, 0,0x3F62, 0, 0, 0, 0,
0,0x5432,0x5435, 0,0x373F, 0, 0, 0,
0, 0, 0, 0,0x5436, 0, 0, 0,
@@ -2132,7 +2132,7 @@ static uint16 tab_uni_jisx020827[]={
0, 0, 0,0x553B,0x4932};
/* page 28 0x5ABC-0x5D29 */
-static uint16 tab_uni_jisx020828[]={
+static const uint16 tab_uni_jisx020828[]={
0x553C,0x5540,0x553D, 0, 0,0x3247,0x553F, 0,
0, 0, 0, 0, 0,0x3C3B, 0,0x553E,
0x3779, 0, 0, 0,0x554C, 0, 0, 0,
@@ -2213,7 +2213,7 @@ static uint16 tab_uni_jisx020828[]={
0, 0, 0, 0, 0,0x4A78};
/* page 29 0x5D4B-0x6BF3 */
-static uint16 tab_uni_jisx020829[]={
+static const uint16 tab_uni_jisx020829[]={
0x564B,0x5648, 0,0x564A, 0,0x4D72, 0,0x5649,
0, 0, 0, 0, 0, 0, 0, 0,
0,0x563F, 0, 0, 0, 0, 0, 0,
@@ -2686,7 +2686,7 @@ static uint16 tab_uni_jisx020829[]={
0x5D5E};
/* page 30 0x6C08-0x6CF3 */
-static uint16 tab_uni_jisx020830[]={
+static const uint16 tab_uni_jisx020830[]={
0x5D61, 0, 0, 0, 0, 0, 0,0x3B61,
0,0x4C31, 0,0x5D62,0x5D63, 0, 0,0x3524,
0, 0, 0,0x5D64, 0, 0, 0, 0,
@@ -2719,7 +2719,7 @@ static uint16 tab_uni_jisx020830[]={
0x4259,0x5D76, 0,0x314B};
/* page 31 0x6D0B-0x7409 */
-static uint16 tab_uni_jisx020831[]={
+static const uint16 tab_uni_jisx020831[]={
0x4D4E,0x5E30, 0, 0, 0, 0, 0,0x5E2F,
0, 0, 0, 0,0x4076, 0,0x5E2C, 0,
0x4D6C, 0, 0,0x4636,0x5E26, 0, 0, 0,
@@ -2946,7 +2946,7 @@ static uint16 tab_uni_jisx020831[]={
0x3565, 0,0x6066,0x4D7D, 0, 0,0x4E30};
/* page 32 0x7422-0x7845 */
-static uint16 tab_uni_jisx020832[]={
+static const uint16 tab_uni_jisx020832[]={
0x4276, 0, 0,0x6068, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0x606A,0x4E56,0x3657,0x487C,0x474A, 0, 0, 0,
@@ -3082,7 +3082,7 @@ static uint16 tab_uni_jisx020832[]={
0, 0, 0,0x626B};
/* page 33 0x785D-0x7E9C */
-static uint16 tab_uni_jisx020833[]={
+static const uint16 tab_uni_jisx020833[]={
0x3E4B, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x4E32,0x3945,
0, 0,0x3827, 0, 0,0x4823, 0,0x626D,
@@ -3286,7 +3286,7 @@ static uint16 tab_uni_jisx020833[]={
};
/* page 34 0x7F36-0x8358 */
-static uint16 tab_uni_jisx020834[]={
+static const uint16 tab_uni_jisx020834[]={
0x344C, 0,0x657D, 0,0x657E, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x6621,
0, 0, 0, 0, 0, 0,0x6622,0x6623,
@@ -3422,7 +3422,7 @@ static uint16 tab_uni_jisx020834[]={
0, 0,0x4171};
/* page 35 0x8373-0x8B9A */
-static uint16 tab_uni_jisx020835[]={
+static const uint16 tab_uni_jisx020835[]={
0x683A, 0,0x683B, 0,0x3259, 0, 0, 0,
0x322E,0x6838, 0, 0, 0, 0, 0, 0,
0, 0,0x682E, 0,0x6836, 0,0x683D,0x6837,
@@ -3687,7 +3687,7 @@ static uint16 tab_uni_jisx020835[]={
};
/* page 36 0x8C37-0x8D16 */
-static uint16 tab_uni_jisx020836[]={
+static const uint16 tab_uni_jisx020836[]={
0x432B, 0, 0,0x6C2E, 0, 0, 0, 0,
0x6C30, 0,0x6C2F, 0, 0, 0, 0,0x4626,
0,0x6C31, 0,0x4B2D, 0,0x6C32, 0,0x6C33,
@@ -3719,7 +3719,7 @@ static uint16 tab_uni_jisx020836[]={
};
/* page 37 0x8D64-0x8F64 */
-static uint16 tab_uni_jisx020837[]={
+static const uint16 tab_uni_jisx020837[]={
0x4056, 0,0x3C4F,0x6C5F, 0, 0, 0,0x3352,
0,0x6C60, 0, 0,0x4176,0x6C61, 0,0x6C62,
0x496B, 0, 0,0x352F, 0, 0, 0, 0,
@@ -3787,7 +3787,7 @@ static uint16 tab_uni_jisx020837[]={
0x6D62};
/* page 38 0x8F9B-0x9132 */
-static uint16 tab_uni_jisx020838[]={
+static const uint16 tab_uni_jisx020838[]={
0x3F49,0x6D63, 0,0x3C2D,0x6D64, 0, 0, 0,
0x6D65, 0, 0, 0,0x5221,0x517E, 0, 0,
0, 0,0x6D66,0x6570,0x6D67,0x4324,0x3F2B,0x4740,
@@ -3842,7 +3842,7 @@ static uint16 tab_uni_jisx020838[]={
};
/* page 39 0x9149-0x92B9 */
-static uint16 tab_uni_jisx020839[]={
+static const uint16 tab_uni_jisx020839[]={
0x4653,0x6E44,0x3D36,0x3C60,0x475B,0x4371, 0, 0,
0,0x3C72, 0,0x3F6C, 0,0x6E45, 0,0x6E46,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -3892,7 +3892,7 @@ static uint16 tab_uni_jisx020839[]={
0x6E78};
/* page 40 0x92CF-0x93E8 */
-static uint16 tab_uni_jisx020840[]={
+static const uint16 tab_uni_jisx020840[]={
0x6E77, 0, 0,0x4B2F, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x3D7B, 0, 0,
@@ -3931,7 +3931,7 @@ static uint16 tab_uni_jisx020840[]={
0,0x6F34};
/* page 41 0x9403-0x9481 */
-static uint16 tab_uni_jisx020841[]={
+static const uint16 tab_uni_jisx020841[]={
0x6F3F, 0, 0, 0,0x6F40, 0, 0, 0,
0, 0, 0, 0, 0,0x6F41, 0, 0,
0x6F3E,0x6F3D, 0, 0, 0,0x3E62,0x462A,0x6F3C,
@@ -3950,7 +3950,7 @@ static uint16 tab_uni_jisx020841[]={
0,0x6F55,0x6F53,0x6F56,0x6F58, 0,0x6F57};
/* page 42 0x9577-0x95E5 */
-static uint16 tab_uni_jisx020842[]={
+static const uint16 tab_uni_jisx020842[]={
0x4439, 0, 0, 0, 0, 0, 0, 0,
0,0x4C67, 0,0x6F59,0x412E, 0, 0, 0,
0x6F5A, 0,0x4A44,0x6F5B,0x332B, 0, 0, 0,
@@ -3967,7 +3967,7 @@ static uint16 tab_uni_jisx020842[]={
0, 0,0x6F71,0x6F73, 0, 0,0x6F72};
/* page 43 0x961C-0x9874 */
-static uint16 tab_uni_jisx020843[]={
+static const uint16 tab_uni_jisx020843[]={
0x496C, 0, 0, 0, 0,0x6F74, 0, 0,
0, 0, 0, 0,0x6F75, 0,0x3A65, 0,
0, 0,0x6F76,0x6F77, 0, 0,0x4B49, 0,
@@ -4046,14 +4046,14 @@ static uint16 tab_uni_jisx020843[]={
0x7122};
/* page 44 0x98A8-0x98C6 */
-static uint16 tab_uni_jisx020844[]={
+static const uint16 tab_uni_jisx020844[]={
0x4977, 0,0x7124, 0, 0, 0, 0,0x7125,
0,0x7126, 0, 0, 0, 0,0x7127, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,0x7129,0x7128, 0,0x712A};
/* page 45 0x98DB-0x9957 */
-static uint16 tab_uni_jisx020845[]={
+static const uint16 tab_uni_jisx020845[]={
0x4874,0x664C, 0, 0,0x3F29, 0, 0,0x3532,
0, 0, 0, 0, 0, 0,0x712B, 0,
0x712C, 0,0x522C,0x5D3B,0x4853, 0, 0,0x307B,
@@ -4072,7 +4072,7 @@ static uint16 tab_uni_jisx020845[]={
0, 0,0x7143, 0,0x3642};
/* page 46 0x9996-0x9A6B */
-static uint16 tab_uni_jisx020846[]={
+static const uint16 tab_uni_jisx020846[]={
0x3C73,0x7144,0x7145,0x3961, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x7146,
0, 0,0x333E, 0, 0, 0,0x474F,0x7147,
@@ -4102,7 +4102,7 @@ static uint16 tab_uni_jisx020846[]={
0, 0, 0,0x7169,0x716B,0x716A};
/* page 47 0x9AA8-0x9B5A */
-static uint16 tab_uni_jisx020847[]={
+static const uint16 tab_uni_jisx020847[]={
0x397C, 0, 0, 0, 0,0x716C, 0, 0,
0x716D, 0, 0, 0, 0, 0, 0, 0,
0x333C, 0, 0, 0,0x716E, 0, 0, 0,
@@ -4128,7 +4128,7 @@ static uint16 tab_uni_jisx020847[]={
0x7236, 0,0x357B};
/* page 48 0x9B6F-0x9C78 */
-static uint16 tab_uni_jisx020848[]={
+static const uint16 tab_uni_jisx020848[]={
0x4F25, 0, 0, 0, 0,0x7237, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x7239, 0, 0, 0,
@@ -4165,7 +4165,7 @@ static uint16 tab_uni_jisx020848[]={
0,0x7269};
/* page 49 0x9CE5-0x9DFD */
-static uint16 tab_uni_jisx020849[]={
+static const uint16 tab_uni_jisx020849[]={
0x443B, 0,0x726A, 0,0x4837, 0,0x726F,0x726B,
0, 0, 0,0x726C, 0, 0,0x4B31,0x4C44,
0,0x4650, 0, 0, 0, 0, 0, 0,
@@ -4204,11 +4204,11 @@ static uint16 tab_uni_jisx020849[]={
0x733F};
/* page 50 0x9E1A-0x9E1E */
-static uint16 tab_uni_jisx020850[]={
+static const uint16 tab_uni_jisx020850[]={
0x7340,0x7341, 0, 0,0x7342};
/* page 51 0x9E75-0x9F77 */
-static uint16 tab_uni_jisx020851[]={
+static const uint16 tab_uni_jisx020851[]={
0x7343, 0, 0,0x3834,0x7344, 0, 0, 0,
0x7345, 0,0x3C2F, 0,0x7346, 0, 0, 0,
0, 0, 0,0x7347, 0, 0,0x7348,0x7349,
@@ -4244,13 +4244,13 @@ static uint16 tab_uni_jisx020851[]={
0,0x737B,0x7379};
/* page 52 0x9F8D-0x9FA0 */
-static uint16 tab_uni_jisx020852[]={
+static const uint16 tab_uni_jisx020852[]={
0x4E36, 0, 0, 0, 0, 0, 0, 0,
0x737C, 0, 0, 0, 0, 0, 0,0x737D,
0x6354, 0, 0,0x737E};
/* page 53 0xFF01-0xFF5D */
-static uint16 tab_uni_jisx020853[]={
+static const uint16 tab_uni_jisx020853[]={
0x212A, 0,0x2174,0x2170,0x2173,0x2175, 0,0x214A,
0x214B,0x2176,0x215C,0x2124, 0,0x2125,0x213F,0x2330,
0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,
@@ -4265,7 +4265,7 @@ static uint16 tab_uni_jisx020853[]={
0x2379,0x237A,0x2150,0x2143,0x2151};
/* page 54 0xFFE3-0xFFE5 */
-static uint16 tab_uni_jisx020854[]={
+static const uint16 tab_uni_jisx020854[]={
0x2131, 0,0x216F};
static int
@@ -4386,11 +4386,11 @@ my_uni_jisx0208_onechar(int code){
/* page 0 0x007E-0x007E */
-static uint16 tab_uni_jisx02120[]={
+static const uint16 tab_uni_jisx02120[]={
0x2237};
/* page 1 0x00A1-0x017E */
-static uint16 tab_uni_jisx02121[]={
+static const uint16 tab_uni_jisx02121[]={
0x2242, 0, 0,0x2270, 0,0x2243, 0, 0,
0x226D,0x226C, 0, 0, 0,0x226E,0x2234, 0,
0, 0, 0, 0, 0, 0, 0,0x2231,
@@ -4421,28 +4421,28 @@ static uint16 tab_uni_jisx02121[]={
0x2A75,0x2B75,0x2A77,0x2B77,0x2A76,0x2B76};
/* page 2 0x01CD-0x01DC */
-static uint16 tab_uni_jisx02122[]={
+static const uint16 tab_uni_jisx02122[]={
0x2A26,0x2B26,0x2A43,0x2B43,0x2A55,0x2B55,0x2A67,0x2B67,
0x2A70,0x2B70,0x2A6D,0x2B6D,0x2A6F,0x2B6F,0x2A6E,0x2B6E
};
/* page 3 0x01F5-0x01F5 */
-static uint16 tab_uni_jisx02123[]={
+static const uint16 tab_uni_jisx02123[]={
0x2B39};
/* page 4 0x02C7-0x02DD */
-static uint16 tab_uni_jisx02124[]={
+static const uint16 tab_uni_jisx02124[]={
0x2230, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,0x222F,0x2232,0x2236,0x2235, 0,0x2233};
/* page 5 0x0384-0x0390 */
-static uint16 tab_uni_jisx02125[]={
+static const uint16 tab_uni_jisx02125[]={
0x2238,0x2239,0x2661, 0,0x2662,0x2663,0x2664, 0,
0x2667, 0,0x2669,0x266C,0x2676};
/* page 6 0x03AA-0x03CE */
-static uint16 tab_uni_jisx02126[]={
+static const uint16 tab_uni_jisx02126[]={
0x2665,0x266A,0x2671,0x2672,0x2673,0x2674,0x267B, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -4450,22 +4450,22 @@ static uint16 tab_uni_jisx02126[]={
0x2675,0x267A,0x2677,0x2679,0x267C};
/* page 7 0x0402-0x040F */
-static uint16 tab_uni_jisx02127[]={
+static const uint16 tab_uni_jisx02127[]={
0x2742,0x2743,0x2744,0x2745,0x2746,0x2747,0x2748,0x2749,
0x274A,0x274B,0x274C, 0,0x274D,0x274E};
/* page 8 0x0452-0x045F */
-static uint16 tab_uni_jisx02128[]={
+static const uint16 tab_uni_jisx02128[]={
0x2772,0x2773,0x2774,0x2775,0x2776,0x2777,0x2778,0x2779,
0x277A,0x277B,0x277C, 0,0x277D,0x277E};
/* page 9 0x2116-0x2122 */
-static uint16 tab_uni_jisx02129[]={
+static const uint16 tab_uni_jisx02129[]={
0x2271, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x226F};
/* page 10 0x4E02-0x4F19 */
-static uint16 tab_uni_jisx021210[]={
+static const uint16 tab_uni_jisx021210[]={
0x3021, 0,0x3022,0x3023, 0, 0, 0, 0,
0, 0,0x3024, 0, 0, 0, 0, 0,
0x3025, 0, 0, 0, 0, 0, 0, 0,
@@ -4504,7 +4504,7 @@ static uint16 tab_uni_jisx021210[]={
};
/* page 11 0x4F2E-0x5166 */
-static uint16 tab_uni_jisx021211[]={
+static const uint16 tab_uni_jisx021211[]={
0x305D, 0, 0,0x305E, 0,0x3060, 0,0x3061,
0,0x3062, 0,0x3063, 0,0x3064, 0, 0,
0x3065, 0,0x3066, 0,0x3067, 0, 0, 0,
@@ -4579,7 +4579,7 @@ static uint16 tab_uni_jisx021211[]={
0x326E};
/* page 12 0x517E-0x5515 */
-static uint16 tab_uni_jisx021212[]={
+static const uint16 tab_uni_jisx021212[]={
0x326F, 0, 0, 0, 0,0x3270,0x3271, 0,
0, 0, 0, 0, 0,0x3272, 0, 0,
0x3273, 0, 0, 0, 0, 0, 0, 0,
@@ -4698,7 +4698,7 @@ static uint16 tab_uni_jisx021212[]={
};
/* page 13 0x552A-0x5566 */
-static uint16 tab_uni_jisx021213[]={
+static const uint16 tab_uni_jisx021213[]={
0x354E,0x354F, 0, 0, 0, 0, 0, 0,
0x3550, 0, 0,0x3551,0x3552, 0, 0, 0,
0,0x3553,0x3554,0x3555, 0, 0, 0,0x3556,
@@ -4709,7 +4709,7 @@ static uint16 tab_uni_jisx021213[]={
0, 0,0x3563, 0,0x3564};
/* page 14 0x557F-0x5C36 */
-static uint16 tab_uni_jisx021214[]={
+static const uint16 tab_uni_jisx021214[]={
0x3565, 0,0x3566,0x3567, 0, 0, 0,0x3568,
0,0x3569, 0, 0, 0, 0, 0,0x356A,
0x356B, 0,0x356C,0x356D,0x356E,0x356F, 0, 0,
@@ -4928,7 +4928,7 @@ static uint16 tab_uni_jisx021214[]={
};
/* page 15 0x5C59-0x5EEB */
-static uint16 tab_uni_jisx021215[]={
+static const uint16 tab_uni_jisx021215[]={
0x3A77,0x3A78, 0,0x3A79, 0, 0, 0, 0,
0,0x3A7A,0x3A7B, 0, 0, 0,0x3A7C,0x3A7D,
0x3A7E, 0, 0, 0,0x3B21, 0, 0,0x3B22,
@@ -5014,7 +5014,7 @@ static uint16 tab_uni_jisx021215[]={
0, 0,0x3C5B};
/* page 16 0x5F02-0x6149 */
-static uint16 tab_uni_jisx021216[]={
+static const uint16 tab_uni_jisx021216[]={
0x3C5C, 0, 0, 0,0x3C5D,0x3C5E,0x3C5F, 0,
0, 0, 0, 0,0x3C60, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,0x3C61,
@@ -5091,7 +5091,7 @@ static uint16 tab_uni_jisx021216[]={
};
/* page 17 0x615E-0x6290 */
-static uint16 tab_uni_jisx021217[]={
+static const uint16 tab_uni_jisx021217[]={
0x3E53, 0,0x3E54, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x3E55, 0,
0, 0, 0, 0,0x3E56, 0, 0, 0,
@@ -5133,7 +5133,7 @@ static uint16 tab_uni_jisx021217[]={
0x3F46,0x3F47,0x3F48};
/* page 18 0x62A6-0x679B */
-static uint16 tab_uni_jisx021218[]={
+static const uint16 tab_uni_jisx021218[]={
0x3F49, 0,0x3F4A, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x3F4B, 0, 0,
0x3F4C,0x3F4D, 0, 0,0x3F4E, 0, 0, 0,
@@ -5295,7 +5295,7 @@ static uint16 tab_uni_jisx021218[]={
0x432D, 0,0x432E,0x432F, 0,0x4330};
/* page 19 0x67B0-0x67F9 */
-static uint16 tab_uni_jisx021219[]={
+static const uint16 tab_uni_jisx021219[]={
0x4331,0x4332,0x4333, 0, 0,0x4334, 0, 0,
0, 0, 0,0x4335,0x4336,0x4337, 0, 0,
0x4339, 0,0x433A,0x433B, 0,0x433C, 0, 0,
@@ -5308,7 +5308,7 @@ static uint16 tab_uni_jisx021219[]={
0,0x4338};
/* page 20 0x6814-0x6917 */
-static uint16 tab_uni_jisx021220[]={
+static const uint16 tab_uni_jisx021220[]={
0x434A, 0, 0, 0, 0,0x434B, 0, 0,
0,0x434C, 0,0x434D, 0, 0, 0, 0,
0, 0, 0,0x434F,0x434E, 0, 0, 0,
@@ -5344,7 +5344,7 @@ static uint16 tab_uni_jisx021220[]={
0, 0,0x443B,0x443C};
/* page 21 0x6931-0x6D3F */
-static uint16 tab_uni_jisx021221[]={
+static const uint16 tab_uni_jisx021221[]={
0x443D, 0,0x443E, 0,0x443F, 0, 0,0x4440,
0, 0,0x4441, 0, 0, 0, 0, 0,
0,0x4442, 0, 0,0x4443, 0, 0, 0,
@@ -5477,7 +5477,7 @@ static uint16 tab_uni_jisx021221[]={
0x473A, 0, 0,0x473B, 0, 0,0x473C};
/* page 22 0x6D57-0x6E04 */
-static uint16 tab_uni_jisx021222[]={
+static const uint16 tab_uni_jisx021222[]={
0x473D, 0, 0, 0, 0, 0, 0,0x473E,
0x473F, 0,0x4740, 0, 0, 0,0x4741, 0,
0x4742, 0, 0, 0, 0, 0, 0, 0,
@@ -5502,7 +5502,7 @@ static uint16 tab_uni_jisx021222[]={
0,0x4767, 0, 0, 0,0x4768};
/* page 23 0x6E1E-0x6ECF */
-static uint16 tab_uni_jisx021223[]={
+static const uint16 tab_uni_jisx021223[]={
0x4769, 0, 0, 0,0x476A, 0, 0, 0,
0,0x476B, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x476C, 0, 0, 0,
@@ -5528,7 +5528,7 @@ static uint16 tab_uni_jisx021223[]={
0x4839,0x483A};
/* page 24 0x6EEB-0x70E4 */
-static uint16 tab_uni_jisx021224[]={
+static const uint16 tab_uni_jisx021224[]={
0x483B, 0,0x483C,0x483D, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x483E, 0,
0x483F, 0,0x4840, 0, 0, 0, 0, 0,
@@ -5595,7 +5595,7 @@ static uint16 tab_uni_jisx021224[]={
0,0x4960};
/* page 25 0x70FA-0x71DC */
-static uint16 tab_uni_jisx021225[]={
+static const uint16 tab_uni_jisx021225[]={
0x4961, 0, 0, 0, 0, 0, 0, 0,
0,0x4962,0x4963,0x4964,0x4965,0x4966, 0, 0,
0,0x4967,0x4968, 0, 0,0x4969, 0, 0,
@@ -5627,7 +5627,7 @@ static uint16 tab_uni_jisx021225[]={
0x4A3A, 0,0x4A3B};
/* page 26 0x71F8-0x7E9E */
-static uint16 tab_uni_jisx021226[]={
+static const uint16 tab_uni_jisx021226[]={
0x4A3C, 0, 0, 0, 0, 0,0x4A3D, 0,
0x4A3E, 0, 0, 0, 0, 0, 0,0x4A3F,
0x4A40,0x4A41, 0, 0, 0, 0, 0, 0,
@@ -6035,7 +6035,7 @@ static uint16 tab_uni_jisx021226[]={
0x5467, 0,0x5468, 0, 0,0x5469,0x546A};
/* page 27 0x7F3B-0x8044 */
-static uint16 tab_uni_jisx021227[]={
+static const uint16 tab_uni_jisx021227[]={
0x546C,0x546B,0x546D,0x546E,0x546F, 0, 0, 0,
0x5470,0x5471, 0, 0,0x5472, 0, 0, 0,
0, 0, 0, 0,0x5473, 0, 0,0x5474,
@@ -6072,7 +6072,7 @@ static uint16 tab_uni_jisx021227[]={
0,0x5563};
/* page 28 0x8060-0x8357 */
-static uint16 tab_uni_jisx021228[]={
+static const uint16 tab_uni_jisx021228[]={
0x5564, 0, 0, 0,0x5565, 0,0x5566, 0,
0, 0, 0, 0, 0,0x5567, 0, 0,
0,0x5568, 0, 0, 0,0x5569, 0, 0,
@@ -6171,7 +6171,7 @@ static uint16 tab_uni_jisx021228[]={
};
/* page 29 0x8370-0x8419 */
-static uint16 tab_uni_jisx021229[]={
+static const uint16 tab_uni_jisx021229[]={
0x577D, 0, 0, 0, 0, 0, 0, 0,
0x577E, 0, 0, 0, 0,0x5821, 0,0x5822,
0x5823, 0,0x5824, 0,0x5825, 0,0x5826, 0,
@@ -6196,7 +6196,7 @@ static uint16 tab_uni_jisx021229[]={
0,0x584B};
/* page 30 0x842F-0x8880 */
-static uint16 tab_uni_jisx021230[]={
+static const uint16 tab_uni_jisx021230[]={
0x584D, 0, 0, 0, 0, 0, 0, 0,
0, 0,0x584E, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,0x584F, 0,
@@ -6338,7 +6338,7 @@ static uint16 tab_uni_jisx021230[]={
0,0x5C38};
/* page 31 0x8898-0x89BC */
-static uint16 tab_uni_jisx021231[]={
+static const uint16 tab_uni_jisx021231[]={
0x5C39, 0,0x5C3A,0x5C3B,0x5C3C, 0, 0,0x5C3D,
0x5C3E, 0, 0, 0, 0, 0, 0, 0,
0x5C3F, 0,0x5C40, 0, 0, 0, 0, 0,
@@ -6378,7 +6378,7 @@ static uint16 tab_uni_jisx021231[]={
0, 0, 0, 0,0x5D33};
/* page 32 0x89D4-0x8B9F */
-static uint16 tab_uni_jisx021232[]={
+static const uint16 tab_uni_jisx021232[]={
0x5D34,0x5D35,0x5D36,0x5D37,0x5D38, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,0x5D39, 0, 0, 0,0x5D3A, 0,0x5D3B,
@@ -6439,7 +6439,7 @@ static uint16 tab_uni_jisx021232[]={
0x5E5F, 0,0x5E60,0x5E61};
/* page 33 0x8C38-0x8CA4 */
-static uint16 tab_uni_jisx021233[]={
+static const uint16 tab_uni_jisx021233[]={
0x5E62,0x5E63, 0, 0, 0,0x5E64,0x5E65, 0,
0, 0, 0, 0, 0,0x5E66, 0,0x5E67,
0,0x5E68, 0,0x5E69, 0, 0, 0,0x5E6A,
@@ -6456,7 +6456,7 @@ static uint16 tab_uni_jisx021233[]={
0, 0, 0, 0,0x5F29};
/* page 34 0x8CB9-0x8D1B */
-static uint16 tab_uni_jisx021234[]={
+static const uint16 tab_uni_jisx021234[]={
0x5F2A,0x5F2B, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x5F2C,0x5F2D, 0, 0,
0x5F2E, 0,0x5F2F, 0, 0, 0,0x5F30, 0,
@@ -6472,7 +6472,7 @@ static uint16 tab_uni_jisx021234[]={
0, 0,0x5F45};
/* page 35 0x8D65-0x8F65 */
-static uint16 tab_uni_jisx021235[]={
+static const uint16 tab_uni_jisx021235[]={
0x5F46, 0, 0, 0,0x5F47, 0, 0,0x5F48,
0,0x5F49, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -6540,7 +6540,7 @@ static uint16 tab_uni_jisx021235[]={
0x612C};
/* page 36 0x8F9D-0x9484 */
-static uint16 tab_uni_jisx021236[]={
+static const uint16 tab_uni_jisx021236[]={
0x612D, 0, 0,0x612E,0x612F, 0, 0,0x6130,
0x6131,0x6132, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -6701,7 +6701,7 @@ static uint16 tab_uni_jisx021236[]={
};
/* page 37 0x9578-0x95E6 */
-static uint16 tab_uni_jisx021237[]={
+static const uint16 tab_uni_jisx021237[]={
0x657D,0x657E, 0, 0, 0, 0,0x6621, 0,
0, 0, 0, 0,0x6622, 0, 0, 0,
0x6623, 0, 0, 0,0x6624,0x6625,0x6626, 0,
@@ -6718,7 +6718,7 @@ static uint16 tab_uni_jisx021237[]={
0x6641, 0, 0, 0,0x6642, 0,0x6643};
/* page 38 0x961D-0x986C */
-static uint16 tab_uni_jisx021238[]={
+static const uint16 tab_uni_jisx021238[]={
0x6644,0x6645, 0, 0, 0,0x6646, 0,0x6647,
0x6648,0x6649, 0, 0, 0, 0, 0,0x664A,
0, 0, 0, 0,0x664B, 0,0x664C, 0,
@@ -6796,7 +6796,7 @@ static uint16 tab_uni_jisx021238[]={
};
/* page 39 0x98AB-0x98CC */
-static uint16 tab_uni_jisx021239[]={
+static const uint16 tab_uni_jisx021239[]={
0x683A, 0,0x683B,0x683C, 0,0x683D, 0, 0,
0,0x683E, 0, 0,0x683F,0x6840, 0,0x6841,
0x6842, 0, 0, 0,0x6843, 0, 0,0x6844,
@@ -6804,7 +6804,7 @@ static uint16 tab_uni_jisx021239[]={
0,0x6847};
/* page 40 0x98E1-0x9960 */
-static uint16 tab_uni_jisx021240[]={
+static const uint16 tab_uni_jisx021240[]={
0x6848, 0,0x6849, 0,0x684A,0x684B,0x684C, 0,
0,0x684D, 0, 0, 0, 0, 0, 0,
0, 0,0x684E, 0, 0,0x684F, 0, 0,
@@ -6824,7 +6824,7 @@ static uint16 tab_uni_jisx021240[]={
};
/* page 41 0x999B-0x9A5D */
-static uint16 tab_uni_jisx021241[]={
+static const uint16 tab_uni_jisx021241[]={
0x6877, 0,0x6878, 0,0x6879, 0, 0, 0,
0, 0, 0,0x687A, 0, 0, 0, 0,
0, 0, 0, 0, 0,0x687B,0x687C,0x687D,
@@ -6852,7 +6852,7 @@ static uint16 tab_uni_jisx021241[]={
0, 0,0x6955};
/* page 42 0x9AAA-0x9C7B */
-static uint16 tab_uni_jisx021242[]={
+static const uint16 tab_uni_jisx021242[]={
0x6956, 0,0x6957, 0,0x6958,0x6959, 0, 0,
0x695A, 0,0x695B,0x695C,0x695D, 0, 0,0x695E,
0,0x695F, 0, 0,0x6960,0x6961, 0,0x6962,
@@ -6914,7 +6914,7 @@ static uint16 tab_uni_jisx021242[]={
0,0x6B58};
/* page 43 0x9CE6-0x9E1D */
-static uint16 tab_uni_jisx021243[]={
+static const uint16 tab_uni_jisx021243[]={
0x6B59, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,0x6B5A, 0, 0, 0,
0,0x6B5B, 0,0x6B5C, 0, 0, 0, 0,
@@ -6957,7 +6957,7 @@ static uint16 tab_uni_jisx021243[]={
};
/* page 44 0x9E7A-0x9FA5 */
-static uint16 tab_uni_jisx021244[]={
+static const uint16 tab_uni_jisx021244[]={
0x6C59,0x6C5A,0x6C5B, 0, 0, 0,0x6C5C, 0,
0x6C5D,0x6C5E,0x6C5F,0x6C60, 0,0x6C61, 0, 0,
0, 0, 0, 0,0x6C62,0x6C63, 0, 0,
@@ -7094,34 +7094,34 @@ my_uni_jisx0212_onechar(int code){
/* page 0 0x222F-0x2244 */
-static uint16 tab_jisx0212_uni0[]={
+static const uint16 tab_jisx0212_uni0[]={
0x02D8,0x02C7,0x00B8,0x02D9,0x02DD,0x00AF,0x02DB,0x02DA,
0x007E,0x0384,0x0385, 0, 0, 0, 0, 0,
0, 0, 0,0x00A1,0x00A6,0x00BF};
/* page 1 0x226B-0x2271 */
-static uint16 tab_jisx0212_uni1[]={
+static const uint16 tab_jisx0212_uni1[]={
0x00BA,0x00AA,0x00A9,0x00AE,0x2122,0x00A4,0x2116};
/* page 2 0x2661-0x267C */
-static uint16 tab_jisx0212_uni2[]={
+static const uint16 tab_jisx0212_uni2[]={
0x0386,0x0388,0x0389,0x038A,0x03AA, 0,0x038C, 0,
0x038E,0x03AB, 0,0x038F, 0, 0, 0, 0,
0x03AC,0x03AD,0x03AE,0x03AF,0x03CA,0x0390,0x03CC,0x03C2,
0x03CD,0x03CB,0x03B0,0x03CE};
/* page 3 0x2742-0x274E */
-static uint16 tab_jisx0212_uni3[]={
+static const uint16 tab_jisx0212_uni3[]={
0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,0x0409,
0x040A,0x040B,0x040C,0x040E,0x040F};
/* page 4 0x2772-0x277E */
-static uint16 tab_jisx0212_uni4[]={
+static const uint16 tab_jisx0212_uni4[]={
0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,
0x045A,0x045B,0x045C,0x045E,0x045F};
/* page 5 0x2921-0x2950 */
-static uint16 tab_jisx0212_uni5[]={
+static const uint16 tab_jisx0212_uni5[]={
0x00C6,0x0110, 0,0x0126, 0,0x0132, 0,0x0141,
0x013F, 0,0x014A,0x00D8,0x0152, 0,0x0166,0x00DE,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -7131,7 +7131,7 @@ static uint16 tab_jisx0212_uni5[]={
};
/* page 6 0x2A21-0x2A77 */
-static uint16 tab_jisx0212_uni6[]={
+static const uint16 tab_jisx0212_uni6[]={
0x00C1,0x00C0,0x00C4,0x00C2,0x0102,0x01CD,0x0100,0x0104,
0x00C5,0x00C3,0x0106,0x0108,0x010C,0x00C7,0x010A,0x010E,
0x00C9,0x00C8,0x00CB,0x00CA,0x011A,0x0116,0x0112,0x0118,
@@ -7145,7 +7145,7 @@ static uint16 tab_jisx0212_uni6[]={
0x0174,0x00DD,0x0178,0x0176,0x0179,0x017D,0x017B};
/* page 7 0x2B21-0x2B77 */
-static uint16 tab_jisx0212_uni7[]={
+static const uint16 tab_jisx0212_uni7[]={
0x00E1,0x00E0,0x00E4,0x00E2,0x0103,0x01CE,0x0101,0x0105,
0x00E5,0x00E3,0x0107,0x0109,0x010D,0x00E7,0x010B,0x010F,
0x00E9,0x00E8,0x00EB,0x00EA,0x011B,0x0117,0x0113,0x0119,
@@ -7159,7 +7159,7 @@ static uint16 tab_jisx0212_uni7[]={
0x0175,0x00FD,0x00FF,0x0177,0x017A,0x017E,0x017C};
/* page 8 0x3021-0x307E */
-static uint16 tab_jisx0212_uni8[]={
+static const uint16 tab_jisx0212_uni8[]={
0x4E02,0x4E04,0x4E05,0x4E0C,0x4E12,0x4E1F,0x4E23,0x4E24,
0x4E28,0x4E2B,0x4E2E,0x4E2F,0x4E30,0x4E35,0x4E40,0x4E41,
0x4E44,0x4E47,0x4E51,0x4E5A,0x4E5C,0x4E63,0x4E68,0x4E69,
@@ -7174,7 +7174,7 @@ static uint16 tab_jisx0212_uni8[]={
0x4F7A,0x4F7D,0x4F7E,0x4F81,0x4F82,0x4F84};
/* page 9 0x3121-0x317E */
-static uint16 tab_jisx0212_uni9[]={
+static const uint16 tab_jisx0212_uni9[]={
0x4F85,0x4F89,0x4F8A,0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,
0x4F94,0x4F97,0x4F99,0x4F9A,0x4F9E,0x4F9F,0x4FB2,0x4FB7,
0x4FB9,0x4FBB,0x4FBC,0x4FBD,0x4FBE,0x4FC0,0x4FC1,0x4FC5,
@@ -7189,7 +7189,7 @@ static uint16 tab_jisx0212_uni9[]={
0x5084,0x5086,0x508A,0x508E,0x508F,0x5090};
/* page 10 0x3221-0x327E */
-static uint16 tab_jisx0212_uni10[]={
+static const uint16 tab_jisx0212_uni10[]={
0x5092,0x5093,0x5094,0x5096,0x509B,0x509C,0x509E,0x509F,
0x50A0,0x50A1,0x50A2,0x50AA,0x50AF,0x50B0,0x50B9,0x50BA,
0x50BD,0x50C0,0x50C3,0x50C4,0x50C7,0x50CC,0x50CE,0x50D0,
@@ -7204,7 +7204,7 @@ static uint16 tab_jisx0212_uni10[]={
0x51B8,0x51BA,0x51BC,0x51BE,0x51BF,0x51C2};
/* page 11 0x3321-0x337E */
-static uint16 tab_jisx0212_uni11[]={
+static const uint16 tab_jisx0212_uni11[]={
0x51C8,0x51CF,0x51D1,0x51D2,0x51D3,0x51D5,0x51D8,0x51DE,
0x51E2,0x51E5,0x51EE,0x51F2,0x51F3,0x51F4,0x51F7,0x5201,
0x5202,0x5205,0x5212,0x5213,0x5215,0x5216,0x5218,0x5222,
@@ -7219,7 +7219,7 @@ static uint16 tab_jisx0212_uni11[]={
0x52F6,0x52F7,0x5300,0x5303,0x530A,0x530B};
/* page 12 0x3421-0x347E */
-static uint16 tab_jisx0212_uni12[]={
+static const uint16 tab_jisx0212_uni12[]={
0x530C,0x5311,0x5313,0x5318,0x531B,0x531C,0x531E,0x531F,
0x5325,0x5327,0x5328,0x5329,0x532B,0x532C,0x532D,0x5330,
0x5332,0x5335,0x533C,0x533D,0x533E,0x5342,0x534C,0x534B,
@@ -7234,7 +7234,7 @@ static uint16 tab_jisx0212_uni12[]={
0x5469,0x546B,0x546D,0x546E,0x5474,0x547F};
/* page 13 0x3521-0x357E */
-static uint16 tab_jisx0212_uni13[]={
+static const uint16 tab_jisx0212_uni13[]={
0x5481,0x5483,0x5485,0x5488,0x5489,0x548D,0x5491,0x5495,
0x5496,0x549C,0x549F,0x54A1,0x54A6,0x54A7,0x54A9,0x54AA,
0x54AD,0x54AE,0x54B1,0x54B7,0x54B9,0x54BA,0x54BB,0x54BF,
@@ -7249,7 +7249,7 @@ static uint16 tab_jisx0212_uni13[]={
0x55C9,0x55CB,0x55CC,0x55CE,0x55D1,0x55D2};
/* page 14 0x3621-0x367E */
-static uint16 tab_jisx0212_uni14[]={
+static const uint16 tab_jisx0212_uni14[]={
0x55D3,0x55D7,0x55D8,0x55DB,0x55DE,0x55E2,0x55E9,0x55F6,
0x55FF,0x5605,0x5608,0x560A,0x560D,0x560E,0x560F,0x5610,
0x5611,0x5612,0x5619,0x562C,0x5630,0x5633,0x5635,0x5637,
@@ -7264,7 +7264,7 @@ static uint16 tab_jisx0212_uni14[]={
0x56E6,0x56E7,0x56E8,0x56F1,0x56EB,0x56ED};
/* page 15 0x3721-0x377E */
-static uint16 tab_jisx0212_uni15[]={
+static const uint16 tab_jisx0212_uni15[]={
0x56F6,0x56F7,0x5701,0x5702,0x5707,0x570A,0x570C,0x5711,
0x5715,0x571A,0x571B,0x571D,0x5720,0x5722,0x5723,0x5724,
0x5725,0x5729,0x572A,0x572C,0x572E,0x572F,0x5733,0x5734,
@@ -7279,7 +7279,7 @@ static uint16 tab_jisx0212_uni15[]={
0x57FF,0x5803,0x5804,0x5808,0x5809,0x57E1};
/* page 16 0x3821-0x387E */
-static uint16 tab_jisx0212_uni16[]={
+static const uint16 tab_jisx0212_uni16[]={
0x580C,0x580D,0x581B,0x581E,0x581F,0x5820,0x5826,0x5827,
0x582D,0x5832,0x5839,0x583F,0x5849,0x584C,0x584D,0x584F,
0x5850,0x5855,0x585F,0x5861,0x5864,0x5867,0x5868,0x5878,
@@ -7294,7 +7294,7 @@ static uint16 tab_jisx0212_uni16[]={
0x595E,0x595F,0x5961,0x5963,0x596B,0x596D};
/* page 17 0x3921-0x397E */
-static uint16 tab_jisx0212_uni17[]={
+static const uint16 tab_jisx0212_uni17[]={
0x596F,0x5972,0x5975,0x5976,0x5979,0x597B,0x597C,0x598B,
0x598C,0x598E,0x5992,0x5995,0x5997,0x599F,0x59A4,0x59A7,
0x59AD,0x59AE,0x59AF,0x59B0,0x59B3,0x59B7,0x59BA,0x59BC,
@@ -7309,7 +7309,7 @@ static uint16 tab_jisx0212_uni17[]={
0x5AB3,0x5AB5,0x5AB8,0x5ABA,0x5ABB,0x5ABF};
/* page 18 0x3A21-0x3A7E */
-static uint16 tab_jisx0212_uni18[]={
+static const uint16 tab_jisx0212_uni18[]={
0x5AC4,0x5AC6,0x5AC8,0x5ACF,0x5ADA,0x5ADC,0x5AE0,0x5AE5,
0x5AEA,0x5AEE,0x5AF5,0x5AF6,0x5AFD,0x5B00,0x5B01,0x5B08,
0x5B17,0x5B34,0x5B19,0x5B1B,0x5B1D,0x5B21,0x5B25,0x5B2D,
@@ -7324,7 +7324,7 @@ static uint16 tab_jisx0212_uni18[]={
0x5C5C,0x5C62,0x5C63,0x5C67,0x5C68,0x5C69};
/* page 19 0x3B21-0x3B7E */
-static uint16 tab_jisx0212_uni19[]={
+static const uint16 tab_jisx0212_uni19[]={
0x5C6D,0x5C70,0x5C74,0x5C75,0x5C7A,0x5C7B,0x5C7C,0x5C7D,
0x5C87,0x5C88,0x5C8A,0x5C8F,0x5C92,0x5C9D,0x5C9F,0x5CA0,
0x5CA2,0x5CA3,0x5CA6,0x5CAA,0x5CB2,0x5CB4,0x5CB5,0x5CBA,
@@ -7339,7 +7339,7 @@ static uint16 tab_jisx0212_uni19[]={
0x5DD0,0x5DCE,0x5DD8,0x5DD9,0x5DE0,0x5DE4};
/* page 20 0x3C21-0x3C7E */
-static uint16 tab_jisx0212_uni20[]={
+static const uint16 tab_jisx0212_uni20[]={
0x5DE9,0x5DF8,0x5DF9,0x5E00,0x5E07,0x5E0D,0x5E12,0x5E14,
0x5E15,0x5E18,0x5E1F,0x5E20,0x5E2E,0x5E28,0x5E32,0x5E35,
0x5E3E,0x5E4B,0x5E50,0x5E49,0x5E51,0x5E56,0x5E58,0x5E5B,
@@ -7354,7 +7354,7 @@ static uint16 tab_jisx0212_uni20[]={
0x5F58,0x5F5B,0x5F60,0x5F63,0x5F64,0x5F67};
/* page 21 0x3D21-0x3D7E */
-static uint16 tab_jisx0212_uni21[]={
+static const uint16 tab_jisx0212_uni21[]={
0x5F6F,0x5F72,0x5F74,0x5F75,0x5F78,0x5F7A,0x5F7D,0x5F7E,
0x5F89,0x5F8D,0x5F8F,0x5F96,0x5F9C,0x5F9D,0x5FA2,0x5FA7,
0x5FAB,0x5FA4,0x5FAC,0x5FAF,0x5FB0,0x5FB1,0x5FB8,0x5FC4,
@@ -7369,7 +7369,7 @@ static uint16 tab_jisx0212_uni21[]={
0x60A4,0x60A5,0x60A8,0x60B0,0x60B1,0x60B7};
/* page 22 0x3E21-0x3E7E */
-static uint16 tab_jisx0212_uni22[]={
+static const uint16 tab_jisx0212_uni22[]={
0x60BB,0x60BE,0x60C2,0x60C4,0x60C8,0x60C9,0x60CA,0x60CB,
0x60CE,0x60CF,0x60D4,0x60D5,0x60D9,0x60DB,0x60DD,0x60DE,
0x60E2,0x60E5,0x60F2,0x60F5,0x60F8,0x60FC,0x60FD,0x6102,
@@ -7384,7 +7384,7 @@ static uint16 tab_jisx0212_uni22[]={
0x61DF,0x61E1,0x61E2,0x61E7,0x61E9,0x61E5};
/* page 23 0x3F21-0x3F7E */
-static uint16 tab_jisx0212_uni23[]={
+static const uint16 tab_jisx0212_uni23[]={
0x61EC,0x61ED,0x61EF,0x6201,0x6203,0x6204,0x6207,0x6213,
0x6215,0x621C,0x6220,0x6222,0x6223,0x6227,0x6229,0x622B,
0x6239,0x623D,0x6242,0x6243,0x6244,0x6246,0x624C,0x6250,
@@ -7399,7 +7399,7 @@ static uint16 tab_jisx0212_uni23[]={
0x6366,0x636C,0x636D,0x6371,0x6374,0x6375};
/* page 24 0x4021-0x407E */
-static uint16 tab_jisx0212_uni24[]={
+static const uint16 tab_jisx0212_uni24[]={
0x6378,0x637C,0x637D,0x637F,0x6382,0x6384,0x6387,0x638A,
0x6390,0x6394,0x6395,0x6399,0x639A,0x639E,0x63A4,0x63A6,
0x63AD,0x63AE,0x63AF,0x63BD,0x63C1,0x63C5,0x63C8,0x63CE,
@@ -7414,7 +7414,7 @@ static uint16 tab_jisx0212_uni24[]={
0x64A8,0x64AC,0x64B3,0x64BD,0x64BE,0x64BF};
/* page 25 0x4121-0x417E */
-static uint16 tab_jisx0212_uni25[]={
+static const uint16 tab_jisx0212_uni25[]={
0x64C4,0x64C9,0x64CA,0x64CB,0x64CC,0x64CE,0x64D0,0x64D1,
0x64D5,0x64D7,0x64E4,0x64E5,0x64E9,0x64EA,0x64ED,0x64F0,
0x64F5,0x64F7,0x64FB,0x64FF,0x6501,0x6504,0x6508,0x6509,
@@ -7429,7 +7429,7 @@ static uint16 tab_jisx0212_uni25[]={
0x660D,0x6611,0x6612,0x6615,0x6616,0x661D};
/* page 26 0x4221-0x427E */
-static uint16 tab_jisx0212_uni26[]={
+static const uint16 tab_jisx0212_uni26[]={
0x661E,0x6621,0x6622,0x6623,0x6624,0x6626,0x6629,0x662A,
0x662B,0x662C,0x662E,0x6630,0x6631,0x6633,0x6639,0x6637,
0x6640,0x6645,0x6646,0x664A,0x664C,0x6651,0x664E,0x6657,
@@ -7444,7 +7444,7 @@ static uint16 tab_jisx0212_uni26[]={
0x6747,0x6748,0x674C,0x6754,0x6755,0x675D};
/* page 27 0x4321-0x437E */
-static uint16 tab_jisx0212_uni27[]={
+static const uint16 tab_jisx0212_uni27[]={
0x6766,0x676C,0x676E,0x6774,0x6776,0x677B,0x6781,0x6784,
0x678E,0x678F,0x6791,0x6793,0x6796,0x6798,0x6799,0x679B,
0x67B0,0x67B1,0x67B2,0x67B5,0x67BB,0x67BC,0x67BD,0x67F9,
@@ -7459,7 +7459,7 @@ static uint16 tab_jisx0212_uni27[]={
0x68B2,0x68BB,0x68C5,0x68C8,0x68CC,0x68CF};
/* page 28 0x4421-0x447E */
-static uint16 tab_jisx0212_uni28[]={
+static const uint16 tab_jisx0212_uni28[]={
0x68D0,0x68D1,0x68D3,0x68D6,0x68D9,0x68DC,0x68DD,0x68E5,
0x68E8,0x68EA,0x68EB,0x68EC,0x68ED,0x68F0,0x68F1,0x68F5,
0x68F6,0x68FB,0x68FC,0x68FD,0x6906,0x6909,0x690A,0x6910,
@@ -7474,7 +7474,7 @@ static uint16 tab_jisx0212_uni28[]={
0x6A1D,0x6A20,0x6A24,0x6A28,0x6A30,0x6A32};
/* page 29 0x4521-0x457E */
-static uint16 tab_jisx0212_uni29[]={
+static const uint16 tab_jisx0212_uni29[]={
0x6A34,0x6A37,0x6A3B,0x6A3E,0x6A3F,0x6A45,0x6A46,0x6A49,
0x6A4A,0x6A4E,0x6A50,0x6A51,0x6A52,0x6A55,0x6A56,0x6A5B,
0x6A64,0x6A67,0x6A6A,0x6A71,0x6A73,0x6A7E,0x6A81,0x6A83,
@@ -7489,7 +7489,7 @@ static uint16 tab_jisx0212_uni29[]={
0x6B67,0x6B6B,0x6B6E,0x6B70,0x6B75,0x6B7D};
/* page 30 0x4621-0x467E */
-static uint16 tab_jisx0212_uni30[]={
+static const uint16 tab_jisx0212_uni30[]={
0x6B7E,0x6B82,0x6B85,0x6B97,0x6B9B,0x6B9F,0x6BA0,0x6BA2,
0x6BA3,0x6BA8,0x6BA9,0x6BAC,0x6BAD,0x6BAE,0x6BB0,0x6BB8,
0x6BB9,0x6BBD,0x6BBE,0x6BC3,0x6BC4,0x6BC9,0x6BCC,0x6BD6,
@@ -7504,7 +7504,7 @@ static uint16 tab_jisx0212_uni30[]={
0x6CCF,0x6CD0,0x6CD1,0x6CD2,0x6CD4,0x6CD6};
/* page 31 0x4721-0x477E */
-static uint16 tab_jisx0212_uni31[]={
+static const uint16 tab_jisx0212_uni31[]={
0x6CDA,0x6CDC,0x6CE0,0x6CE7,0x6CE9,0x6CEB,0x6CEC,0x6CEE,
0x6CF2,0x6CF4,0x6D04,0x6D07,0x6D0A,0x6D0E,0x6D0F,0x6D11,
0x6D13,0x6D1A,0x6D26,0x6D27,0x6D28,0x6C67,0x6D2E,0x6D2F,
@@ -7519,7 +7519,7 @@ static uint16 tab_jisx0212_uni31[]={
0x6E53,0x6E54,0x6E57,0x6E5C,0x6E5D,0x6E5E};
/* page 32 0x4821-0x487E */
-static uint16 tab_jisx0212_uni32[]={
+static const uint16 tab_jisx0212_uni32[]={
0x6E62,0x6E63,0x6E68,0x6E73,0x6E7B,0x6E7D,0x6E8D,0x6E93,
0x6E99,0x6EA0,0x6EA7,0x6EAD,0x6EAE,0x6EB1,0x6EB3,0x6EBB,
0x6EBF,0x6EC0,0x6EC1,0x6EC3,0x6EC7,0x6EC8,0x6ECA,0x6ECD,
@@ -7534,7 +7534,7 @@ static uint16 tab_jisx0212_uni32[]={
0x6FB6,0x6FBC,0x6FC5,0x6FC7,0x6FC8,0x6FCA};
/* page 33 0x4921-0x497E */
-static uint16 tab_jisx0212_uni33[]={
+static const uint16 tab_jisx0212_uni33[]={
0x6FDA,0x6FDE,0x6FE8,0x6FE9,0x6FF0,0x6FF5,0x6FF9,0x6FFC,
0x6FFD,0x7000,0x7005,0x7006,0x7007,0x700D,0x7017,0x7020,
0x7023,0x702F,0x7034,0x7037,0x7039,0x703C,0x7043,0x7044,
@@ -7549,7 +7549,7 @@ static uint16 tab_jisx0212_uni33[]={
0x7152,0x7157,0x715A,0x715C,0x715E,0x7160};
/* page 34 0x4A21-0x4A7E */
-static uint16 tab_jisx0212_uni34[]={
+static const uint16 tab_jisx0212_uni34[]={
0x7168,0x7179,0x7180,0x7185,0x7187,0x718C,0x7192,0x719A,
0x719B,0x71A0,0x71A2,0x71AF,0x71B0,0x71B2,0x71B3,0x71BA,
0x71BF,0x71C0,0x71C1,0x71C4,0x71CB,0x71CC,0x71D3,0x71D6,
@@ -7564,7 +7564,7 @@ static uint16 tab_jisx0212_uni34[]={
0x72DF,0x72E5,0x72F3,0x72F4,0x72FA,0x72FB};
/* page 35 0x4B21-0x4B7E */
-static uint16 tab_jisx0212_uni35[]={
+static const uint16 tab_jisx0212_uni35[]={
0x72FE,0x7302,0x7304,0x7305,0x7307,0x730B,0x730D,0x7312,
0x7313,0x7318,0x7319,0x731E,0x7322,0x7324,0x7327,0x7328,
0x732C,0x7331,0x7332,0x7335,0x733A,0x733B,0x733D,0x7343,
@@ -7579,7 +7579,7 @@ static uint16 tab_jisx0212_uni35[]={
0x73F5,0x73F7,0x73F9,0x73FA,0x73FB,0x73FD};
/* page 36 0x4C21-0x4C7E */
-static uint16 tab_jisx0212_uni36[]={
+static const uint16 tab_jisx0212_uni36[]={
0x73FF,0x7400,0x7401,0x7404,0x7407,0x740A,0x7411,0x741A,
0x741B,0x7424,0x7426,0x7428,0x7429,0x742A,0x742B,0x742C,
0x742D,0x742E,0x742F,0x7430,0x7431,0x7439,0x7440,0x7443,
@@ -7594,7 +7594,7 @@ static uint16 tab_jisx0212_uni36[]={
0x74F4,0x74FA,0x74FB,0x74FC,0x74FF,0x7506};
/* page 37 0x4D21-0x4D7E */
-static uint16 tab_jisx0212_uni37[]={
+static const uint16 tab_jisx0212_uni37[]={
0x7512,0x7516,0x7517,0x7520,0x7521,0x7524,0x7527,0x7529,
0x752A,0x752F,0x7536,0x7539,0x753D,0x753E,0x753F,0x7540,
0x7543,0x7547,0x7548,0x754E,0x7550,0x7552,0x7557,0x755E,
@@ -7609,7 +7609,7 @@ static uint16 tab_jisx0212_uni37[]={
0x762D,0x7632,0x7633,0x7635,0x7638,0x7639};
/* page 38 0x4E21-0x4E7E */
-static uint16 tab_jisx0212_uni38[]={
+static const uint16 tab_jisx0212_uni38[]={
0x763A,0x763C,0x764A,0x7640,0x7641,0x7643,0x7644,0x7645,
0x7649,0x764B,0x7655,0x7659,0x765F,0x7664,0x7665,0x766D,
0x766E,0x766F,0x7671,0x7674,0x7681,0x7685,0x768C,0x768D,
@@ -7624,7 +7624,7 @@ static uint16 tab_jisx0212_uni38[]={
0x7757,0x775C,0x775E,0x775F,0x7760,0x7762};
/* page 39 0x4F21-0x4F7E */
-static uint16 tab_jisx0212_uni39[]={
+static const uint16 tab_jisx0212_uni39[]={
0x7764,0x7767,0x776A,0x776C,0x7770,0x7772,0x7773,0x7774,
0x777A,0x777D,0x7780,0x7784,0x778C,0x778D,0x7794,0x7795,
0x7796,0x779A,0x779F,0x77A2,0x77A7,0x77AA,0x77AE,0x77AF,
@@ -7639,7 +7639,7 @@ static uint16 tab_jisx0212_uni39[]={
0x78AC,0x78AD,0x78B0,0x78B1,0x78B2,0x78B3};
/* page 40 0x5021-0x507E */
-static uint16 tab_jisx0212_uni40[]={
+static const uint16 tab_jisx0212_uni40[]={
0x78BB,0x78BD,0x78BF,0x78C7,0x78C8,0x78C9,0x78CC,0x78CE,
0x78D2,0x78D3,0x78D5,0x78D6,0x78E4,0x78DB,0x78DF,0x78E0,
0x78E1,0x78E6,0x78EA,0x78F2,0x78F3,0x7900,0x78F6,0x78F7,
@@ -7654,7 +7654,7 @@ static uint16 tab_jisx0212_uni40[]={
0x79CF,0x79D4,0x79D6,0x79DA,0x79DD,0x79DE};
/* page 41 0x5121-0x517E */
-static uint16 tab_jisx0212_uni41[]={
+static const uint16 tab_jisx0212_uni41[]={
0x79E0,0x79E2,0x79E5,0x79EA,0x79EB,0x79ED,0x79F1,0x79F8,
0x79FC,0x7A02,0x7A03,0x7A07,0x7A09,0x7A0A,0x7A0C,0x7A11,
0x7A15,0x7A1B,0x7A1E,0x7A21,0x7A27,0x7A2B,0x7A2D,0x7A2F,
@@ -7669,7 +7669,7 @@ static uint16 tab_jisx0212_uni41[]={
0x7B2A,0x7B2B,0x7B2D,0x7B2E,0x7B2F,0x7B30};
/* page 42 0x5221-0x527E */
-static uint16 tab_jisx0212_uni42[]={
+static const uint16 tab_jisx0212_uni42[]={
0x7B31,0x7B34,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B47,0x7B4E,
0x7B55,0x7B60,0x7B64,0x7B66,0x7B69,0x7B6A,0x7B6D,0x7B6F,
0x7B72,0x7B73,0x7B77,0x7B84,0x7B89,0x7B8E,0x7B90,0x7B91,
@@ -7684,7 +7684,7 @@ static uint16 tab_jisx0212_uni42[]={
0x7C59,0x7C5A,0x7C5B,0x7C5C,0x7C5D,0x7C5E};
/* page 43 0x5321-0x537E */
-static uint16 tab_jisx0212_uni43[]={
+static const uint16 tab_jisx0212_uni43[]={
0x7C61,0x7C63,0x7C67,0x7C69,0x7C6D,0x7C6E,0x7C70,0x7C72,
0x7C79,0x7C7C,0x7C7D,0x7C86,0x7C87,0x7C8F,0x7C94,0x7C9E,
0x7CA0,0x7CA6,0x7CB0,0x7CB6,0x7CB7,0x7CBA,0x7CBB,0x7CBC,
@@ -7699,7 +7699,7 @@ static uint16 tab_jisx0212_uni43[]={
0x7D8C,0x7D8D,0x7D91,0x7D96,0x7D97,0x7D9D};
/* page 44 0x5421-0x547E */
-static uint16 tab_jisx0212_uni44[]={
+static const uint16 tab_jisx0212_uni44[]={
0x7D9E,0x7DA6,0x7DA7,0x7DAA,0x7DB3,0x7DB6,0x7DB7,0x7DB9,
0x7DC2,0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DCC,0x7DCD,0x7DCE,
0x7DD7,0x7DD9,0x7E00,0x7DE2,0x7DE5,0x7DE6,0x7DEA,0x7DEB,
@@ -7714,7 +7714,7 @@ static uint16 tab_jisx0212_uni44[]={
0x7F61,0x7F63,0x7F64,0x7F65,0x7F66,0x7F6D};
/* page 45 0x5521-0x557E */
-static uint16 tab_jisx0212_uni45[]={
+static const uint16 tab_jisx0212_uni45[]={
0x7F71,0x7F7D,0x7F7E,0x7F7F,0x7F80,0x7F8B,0x7F8D,0x7F8F,
0x7F90,0x7F91,0x7F96,0x7F97,0x7F9C,0x7FA1,0x7FA2,0x7FA6,
0x7FAA,0x7FAD,0x7FB4,0x7FBC,0x7FBF,0x7FC0,0x7FC3,0x7FC8,
@@ -7729,7 +7729,7 @@ static uint16 tab_jisx0212_uni45[]={
0x80D5,0x80D7,0x80D8,0x80E0,0x80ED,0x80EE};
/* page 46 0x5621-0x567E */
-static uint16 tab_jisx0212_uni46[]={
+static const uint16 tab_jisx0212_uni46[]={
0x80F0,0x80F2,0x80F3,0x80F6,0x80F9,0x80FA,0x80FE,0x8103,
0x810B,0x8116,0x8117,0x8118,0x811C,0x811E,0x8120,0x8124,
0x8127,0x812C,0x8130,0x8135,0x813A,0x813C,0x8145,0x8147,
@@ -7744,7 +7744,7 @@ static uint16 tab_jisx0212_uni46[]={
0x8234,0x823A,0x8243,0x8244,0x8245,0x8246};
/* page 47 0x5721-0x577E */
-static uint16 tab_jisx0212_uni47[]={
+static const uint16 tab_jisx0212_uni47[]={
0x824B,0x824E,0x824F,0x8251,0x8256,0x825C,0x8260,0x8263,
0x8267,0x826D,0x8274,0x827B,0x827D,0x827F,0x8280,0x8281,
0x8283,0x8284,0x8287,0x8289,0x828A,0x828E,0x8291,0x8294,
@@ -7759,7 +7759,7 @@ static uint16 tab_jisx0212_uni47[]={
0x8351,0x8355,0x8356,0x8357,0x8370,0x8378};
/* page 48 0x5821-0x587E */
-static uint16 tab_jisx0212_uni48[]={
+static const uint16 tab_jisx0212_uni48[]={
0x837D,0x837F,0x8380,0x8382,0x8384,0x8386,0x838D,0x8392,
0x8394,0x8395,0x8398,0x8399,0x839B,0x839C,0x839D,0x83A6,
0x83A7,0x83A9,0x83AC,0x83BE,0x83BF,0x83C0,0x83C7,0x83C9,
@@ -7774,7 +7774,7 @@ static uint16 tab_jisx0212_uni48[]={
0x84C2,0x84C7,0x84C8,0x84CC,0x84CF,0x84D3};
/* page 49 0x5921-0x597E */
-static uint16 tab_jisx0212_uni49[]={
+static const uint16 tab_jisx0212_uni49[]={
0x84DC,0x84E7,0x84EA,0x84EF,0x84F0,0x84F1,0x84F2,0x84F7,
0x8532,0x84FA,0x84FB,0x84FD,0x8502,0x8503,0x8507,0x850C,
0x850E,0x8510,0x851C,0x851E,0x8522,0x8523,0x8524,0x8525,
@@ -7789,7 +7789,7 @@ static uint16 tab_jisx0212_uni49[]={
0x85E6,0x85E8,0x85ED,0x85F3,0x85F6,0x85FC};
/* page 50 0x5A21-0x5A7E */
-static uint16 tab_jisx0212_uni50[]={
+static const uint16 tab_jisx0212_uni50[]={
0x85FF,0x8600,0x8604,0x8605,0x860D,0x860E,0x8610,0x8611,
0x8612,0x8618,0x8619,0x861B,0x861E,0x8621,0x8627,0x8629,
0x8636,0x8638,0x863A,0x863C,0x863D,0x8640,0x8642,0x8646,
@@ -7804,7 +7804,7 @@ static uint16 tab_jisx0212_uni50[]={
0x8714,0x8719,0x871E,0x871F,0x8721,0x8723};
/* page 51 0x5B21-0x5B7E */
-static uint16 tab_jisx0212_uni51[]={
+static const uint16 tab_jisx0212_uni51[]={
0x8728,0x872E,0x872F,0x8731,0x8732,0x8739,0x873A,0x873C,
0x873D,0x873E,0x8740,0x8743,0x8745,0x874D,0x8758,0x875D,
0x8761,0x8764,0x8765,0x876F,0x8771,0x8772,0x877B,0x8783,
@@ -7819,7 +7819,7 @@ static uint16 tab_jisx0212_uni51[]={
0x8828,0x882D,0x882E,0x8830,0x8832,0x8835};
/* page 52 0x5C21-0x5C7E */
-static uint16 tab_jisx0212_uni52[]={
+static const uint16 tab_jisx0212_uni52[]={
0x883A,0x883C,0x8841,0x8843,0x8845,0x8848,0x8849,0x884A,
0x884B,0x884E,0x8851,0x8855,0x8856,0x8858,0x885A,0x885C,
0x885F,0x8860,0x8864,0x8869,0x8871,0x8879,0x887B,0x8880,
@@ -7834,7 +7834,7 @@ static uint16 tab_jisx0212_uni52[]={
0x896B,0x896E,0x8970,0x8973,0x8975,0x897A};
/* page 53 0x5D21-0x5D7E */
-static uint16 tab_jisx0212_uni53[]={
+static const uint16 tab_jisx0212_uni53[]={
0x897B,0x897C,0x897D,0x8989,0x898D,0x8990,0x8994,0x8995,
0x899B,0x899C,0x899F,0x89A0,0x89A5,0x89B0,0x89B4,0x89B5,
0x89B6,0x89B7,0x89BC,0x89D4,0x89D5,0x89D6,0x89D7,0x89D8,
@@ -7849,7 +7849,7 @@ static uint16 tab_jisx0212_uni53[]={
0x8A9F,0x8AA7,0x8AA9,0x8AAE,0x8AAF,0x8AB3};
/* page 54 0x5E21-0x5E7E */
-static uint16 tab_jisx0212_uni54[]={
+static const uint16 tab_jisx0212_uni54[]={
0x8AB6,0x8AB7,0x8ABB,0x8ABE,0x8AC3,0x8AC6,0x8AC8,0x8AC9,
0x8ACA,0x8AD1,0x8AD3,0x8AD4,0x8AD5,0x8AD7,0x8ADD,0x8ADF,
0x8AEC,0x8AF0,0x8AF4,0x8AF5,0x8AF6,0x8AFC,0x8AFF,0x8B05,
@@ -7864,7 +7864,7 @@ static uint16 tab_jisx0212_uni54[]={
0x8C73,0x8C75,0x8C76,0x8C7B,0x8C7E,0x8C86};
/* page 55 0x5F21-0x5F7E */
-static uint16 tab_jisx0212_uni55[]={
+static const uint16 tab_jisx0212_uni55[]={
0x8C87,0x8C8B,0x8C90,0x8C92,0x8C93,0x8C99,0x8C9B,0x8C9C,
0x8CA4,0x8CB9,0x8CBA,0x8CC5,0x8CC6,0x8CC9,0x8CCB,0x8CCF,
0x8CD6,0x8CD5,0x8CD9,0x8CDD,0x8CE1,0x8CE8,0x8CEC,0x8CEF,
@@ -7879,7 +7879,7 @@ static uint16 tab_jisx0212_uni55[]={
0x8E11,0x8E14,0x8E16,0x8E20,0x8E21,0x8E22};
/* page 56 0x6021-0x607E */
-static uint16 tab_jisx0212_uni56[]={
+static const uint16 tab_jisx0212_uni56[]={
0x8E23,0x8E26,0x8E27,0x8E31,0x8E33,0x8E36,0x8E37,0x8E38,
0x8E39,0x8E3D,0x8E40,0x8E41,0x8E4B,0x8E4D,0x8E4E,0x8E4F,
0x8E54,0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E61,0x8E62,0x8E69,
@@ -7894,7 +7894,7 @@ static uint16 tab_jisx0212_uni56[]={
0x8F35,0x8F36,0x8F37,0x8F3A,0x8F40,0x8F41};
/* page 57 0x6121-0x617E */
-static uint16 tab_jisx0212_uni57[]={
+static const uint16 tab_jisx0212_uni57[]={
0x8F43,0x8F47,0x8F4F,0x8F51,0x8F52,0x8F53,0x8F54,0x8F55,
0x8F58,0x8F5D,0x8F5E,0x8F65,0x8F9D,0x8FA0,0x8FA1,0x8FA4,
0x8FA5,0x8FA6,0x8FB5,0x8FB6,0x8FB8,0x8FBE,0x8FC0,0x8FC1,
@@ -7909,7 +7909,7 @@ static uint16 tab_jisx0212_uni57[]={
0x90B4,0x90B6,0x90BD,0x90CC,0x90BE,0x90C3};
/* page 58 0x6221-0x627E */
-static uint16 tab_jisx0212_uni58[]={
+static const uint16 tab_jisx0212_uni58[]={
0x90C4,0x90C5,0x90C7,0x90C8,0x90D5,0x90D7,0x90D8,0x90D9,
0x90DC,0x90DD,0x90DF,0x90E5,0x90D2,0x90F6,0x90EB,0x90EF,
0x90F0,0x90F4,0x90FE,0x90FF,0x9100,0x9104,0x9105,0x9106,
@@ -7924,7 +7924,7 @@ static uint16 tab_jisx0212_uni58[]={
0x91B3,0x91B6,0x91BB,0x91BC,0x91BD,0x91BF};
/* page 59 0x6321-0x637E */
-static uint16 tab_jisx0212_uni59[]={
+static const uint16 tab_jisx0212_uni59[]={
0x91C2,0x91C3,0x91C5,0x91D3,0x91D4,0x91D7,0x91D9,0x91DA,
0x91DE,0x91E4,0x91E5,0x91E9,0x91EA,0x91EC,0x91ED,0x91EE,
0x91EF,0x91F0,0x91F1,0x91F7,0x91F9,0x91FB,0x91FD,0x9200,
@@ -7939,7 +7939,7 @@ static uint16 tab_jisx0212_uni59[]={
0x9289,0x928A,0x928D,0x928E,0x9292,0x9297};
/* page 60 0x6421-0x647E */
-static uint16 tab_jisx0212_uni60[]={
+static const uint16 tab_jisx0212_uni60[]={
0x9299,0x929F,0x92A0,0x92A4,0x92A5,0x92A7,0x92A8,0x92AB,
0x92AF,0x92B2,0x92B6,0x92B8,0x92BA,0x92BB,0x92BC,0x92BD,
0x92BF,0x92C0,0x92C1,0x92C2,0x92C3,0x92C5,0x92C6,0x92C7,
@@ -7954,7 +7954,7 @@ static uint16 tab_jisx0212_uni60[]={
0x936F,0x9370,0x9371,0x9373,0x9374,0x9376};
/* page 61 0x6521-0x657E */
-static uint16 tab_jisx0212_uni61[]={
+static const uint16 tab_jisx0212_uni61[]={
0x937A,0x937D,0x937F,0x9380,0x9381,0x9382,0x9388,0x938A,
0x938B,0x938D,0x938F,0x9392,0x9395,0x9398,0x939B,0x939E,
0x93A1,0x93A3,0x93A4,0x93A6,0x93A8,0x93AB,0x93B4,0x93B5,
@@ -7969,7 +7969,7 @@ static uint16 tab_jisx0212_uni61[]={
0x9471,0x9472,0x9484,0x9483,0x9578,0x9579};
/* page 62 0x6621-0x667E */
-static uint16 tab_jisx0212_uni62[]={
+static const uint16 tab_jisx0212_uni62[]={
0x957E,0x9584,0x9588,0x958C,0x958D,0x958E,0x959D,0x959E,
0x959F,0x95A1,0x95A6,0x95A9,0x95AB,0x95AC,0x95B4,0x95B6,
0x95BA,0x95BD,0x95BF,0x95C6,0x95C8,0x95C9,0x95CB,0x95D0,
@@ -7984,7 +7984,7 @@ static uint16 tab_jisx0212_uni62[]={
0x96DF,0x96E9,0x96EF,0x96F1,0x96FA,0x9702};
/* page 63 0x6721-0x677E */
-static uint16 tab_jisx0212_uni63[]={
+static const uint16 tab_jisx0212_uni63[]={
0x9703,0x9705,0x9709,0x971A,0x971B,0x971D,0x9721,0x9722,
0x9723,0x9728,0x9731,0x9733,0x9741,0x9743,0x974A,0x974E,
0x974F,0x9755,0x9757,0x9758,0x975A,0x975B,0x9763,0x9767,
@@ -7999,7 +7999,7 @@ static uint16 tab_jisx0212_uni63[]={
0x9816,0x981C,0x981E,0x9820,0x9823,0x9826};
/* page 64 0x6821-0x687E */
-static uint16 tab_jisx0212_uni64[]={
+static const uint16 tab_jisx0212_uni64[]={
0x982B,0x982E,0x982F,0x9830,0x9832,0x9833,0x9835,0x9825,
0x983E,0x9844,0x9847,0x984A,0x9851,0x9852,0x9853,0x9856,
0x9857,0x9859,0x985A,0x9862,0x9863,0x9865,0x9866,0x986A,
@@ -8014,7 +8014,7 @@ static uint16 tab_jisx0212_uni64[]={
0x999F,0x99A6,0x99B0,0x99B1,0x99B2,0x99B5};
/* page 65 0x6921-0x697E */
-static uint16 tab_jisx0212_uni65[]={
+static const uint16 tab_jisx0212_uni65[]={
0x99B9,0x99BA,0x99BD,0x99BF,0x99C3,0x99C9,0x99D3,0x99D4,
0x99D9,0x99DA,0x99DC,0x99DE,0x99E7,0x99EA,0x99EB,0x99EC,
0x99F0,0x99F4,0x99F5,0x99F9,0x99FD,0x99FE,0x9A02,0x9A03,
@@ -8029,7 +8029,7 @@ static uint16 tab_jisx0212_uni65[]={
0x9AFD,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B03};
/* page 66 0x6A21-0x6A7E */
-static uint16 tab_jisx0212_uni66[]={
+static const uint16 tab_jisx0212_uni66[]={
0x9B04,0x9B05,0x9B08,0x9B09,0x9B0B,0x9B0C,0x9B0D,0x9B0E,
0x9B10,0x9B12,0x9B16,0x9B19,0x9B1B,0x9B1C,0x9B20,0x9B26,
0x9B2B,0x9B2D,0x9B33,0x9B34,0x9B35,0x9B37,0x9B39,0x9B3A,
@@ -8044,7 +8044,7 @@ static uint16 tab_jisx0212_uni66[]={
0x9BEA,0x9BEB,0x9BEF,0x9BF3,0x9BF7,0x9BF8};
/* page 67 0x6B21-0x6B7E */
-static uint16 tab_jisx0212_uni67[]={
+static const uint16 tab_jisx0212_uni67[]={
0x9BF9,0x9BFA,0x9BFD,0x9BFF,0x9C00,0x9C02,0x9C0B,0x9C0F,
0x9C11,0x9C16,0x9C18,0x9C19,0x9C1A,0x9C1C,0x9C1E,0x9C22,
0x9C23,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,0x9C31,0x9C35,
@@ -8059,7 +8059,7 @@ static uint16 tab_jisx0212_uni67[]={
0x9D6A,0x9D6B,0x9D70,0x9D76,0x9D77,0x9D7B};
/* page 68 0x6C21-0x6C7E */
-static uint16 tab_jisx0212_uni68[]={
+static const uint16 tab_jisx0212_uni68[]={
0x9D7C,0x9D7E,0x9D83,0x9D84,0x9D86,0x9D8A,0x9D8D,0x9D8E,
0x9D92,0x9D93,0x9D95,0x9D96,0x9D97,0x9D98,0x9DA1,0x9DAA,
0x9DAC,0x9DAE,0x9DB1,0x9DB5,0x9DB9,0x9DBC,0x9DBF,0x9DC3,
@@ -8074,7 +8074,7 @@ static uint16 tab_jisx0212_uni68[]={
0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2,0x9EF5};
/* page 69 0x6D21-0x6D63 */
-static uint16 tab_jisx0212_uni69[]={
+static const uint16 tab_jisx0212_uni69[]={
0x9EF8,0x9EFF,0x9F02,0x9F03,0x9F09,0x9F0F,0x9F10,0x9F11,
0x9F12,0x9F14,0x9F16,0x9F17,0x9F19,0x9F1A,0x9F1B,0x9F1F,
0x9F22,0x9F26,0x9F2A,0x9F2B,0x9F2F,0x9F31,0x9F32,0x9F34,
@@ -8542,7 +8542,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
-CHARSET_INFO my_charset_ujis_japanese_ci=
+struct charset_info_st my_charset_ujis_japanese_ci=
{
12,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
@@ -8575,7 +8575,7 @@ CHARSET_INFO my_charset_ujis_japanese_ci=
};
-CHARSET_INFO my_charset_ujis_bin=
+struct charset_info_st my_charset_ujis_bin=
{
91,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT, /* state */
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index 9cfee43fa36..ae1a7ad0f2e 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1486,7 +1486,7 @@ static MY_UNICASE_INFO planeFF[]={
{0xFFFE,0xFFFE,0xFFFE}, {0xFFFF,0xFFFF,0xFFFF}
};
-MY_UNICASE_INFO *my_unicase_default[256]={
+MY_UNICASE_INFO *const my_unicase_default[256]={
plane00, plane01, plane02, plane03, plane04, plane05, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1665,7 +1665,7 @@ static MY_UNICASE_INFO turk00[]=
-MY_UNICASE_INFO *my_unicase_turkish[256]=
+MY_UNICASE_INFO *const my_unicase_turkish[256]=
{
turk00, plane01, plane02, plane03, plane04, plane05, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1716,14 +1716,12 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
const char *str,const char *str_end,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many,
- MY_UNICASE_INFO **weights)
+ MY_UNICASE_INFO *const *weights)
{
int result= -1; /* Not found, using wildcards */
my_wc_t s_wc, w_wc;
int scan, plane;
- int (*mb_wc)(struct charset_info_st *, my_wc_t *,
- const uchar *, const uchar *);
- mb_wc= cs->cset->mb_wc;
+ my_charset_conv_mb_wc mb_wc= cs->cset->mb_wc;
while (wildstr != wildend)
{
@@ -1873,7 +1871,7 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
expressions. Note, there is no need to mark byte 255 as a
letter, it is illegal byte in UTF8.
*/
-static uchar ctype_utf8[] = {
+static const uchar ctype_utf8[] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@@ -1895,7 +1893,7 @@ static uchar ctype_utf8[] = {
/* The below are taken from usa7 implementation */
-static uchar to_lower_utf8[] = {
+static const uchar to_lower_utf8[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -1914,7 +1912,7 @@ static uchar to_lower_utf8[] = {
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
-static uchar to_upper_utf8[] = {
+static const uchar to_upper_utf8[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -2174,7 +2172,7 @@ static size_t my_caseup_utf8(CHARSET_INFO *cs, char *src, size_t srclen,
my_wc_t wc;
int srcres, dstres;
char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
DBUG_ASSERT(src != dst || cs->caseup_multiply == 1);
while ((src < srcend) &&
@@ -2197,7 +2195,7 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, size_t slen,
my_wc_t wc;
int res;
const uchar *e=s+slen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
/*
Remove end space. We have to do this to be able to compare
@@ -2224,7 +2222,7 @@ static size_t my_caseup_str_utf8(CHARSET_INFO *cs, char *src)
my_wc_t wc;
int srcres, dstres;
char *dst= src, *dst0= src;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
DBUG_ASSERT(cs->caseup_multiply == 1);
while (*src &&
@@ -2248,7 +2246,7 @@ static size_t my_casedn_utf8(CHARSET_INFO *cs, char *src, size_t srclen,
my_wc_t wc;
int srcres, dstres;
char *srcend= src + srclen, *dstend= dst + dstlen, *dst0= dst;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
DBUG_ASSERT(src != dst || cs->casedn_multiply == 1);
while ((src < srcend) &&
@@ -2270,7 +2268,7 @@ static size_t my_casedn_str_utf8(CHARSET_INFO *cs, char *src)
my_wc_t wc;
int srcres, dstres;
char *dst= src, *dst0= src;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
DBUG_ASSERT(cs->casedn_multiply == 1);
while (*src &&
@@ -2313,7 +2311,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se=s+slen;
const uchar *te=t+tlen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -2382,7 +2380,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
int s_res, t_res, res;
my_wc_t UNINIT_VAR(s_wc), UNINIT_VAR(t_wc);
const uchar *se= s+slen, *te= t+tlen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
diff_if_only_endspace_difference= 0;
@@ -2470,7 +2468,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
static
int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t)
{
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while (s[0] && t[0])
{
my_wc_t s_wc,t_wc;
@@ -2555,7 +2553,7 @@ int my_wildcmp_utf8(CHARSET_INFO *cs,
const char *wildstr,const char *wildend,
int escape, int w_one, int w_many)
{
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
return my_wildcmp_unicode(cs,str,str_end,wildstr,wildend,
escape,w_one,w_many,uni_plane);
}
@@ -2579,7 +2577,7 @@ static size_t my_strnxfrm_utf8(CHARSET_INFO *cs,
uchar *de= dst + dstlen;
uchar *de_beg= de - 1;
const uchar *se = src + srclen;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while (dst < de_beg)
{
@@ -2685,7 +2683,7 @@ MY_CHARSET_HANDLER my_charset_utf8_handler=
-CHARSET_INFO my_charset_utf8_general_ci=
+struct charset_info_st my_charset_utf8_general_ci=
{
33,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */
@@ -2718,7 +2716,7 @@ CHARSET_INFO my_charset_utf8_general_ci=
};
-CHARSET_INFO my_charset_utf8_bin=
+struct charset_info_st my_charset_utf8_bin=
{
83,0,0, /* number */
MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE, /* state */
@@ -2770,7 +2768,7 @@ static int my_strnncoll_utf8_cs(CHARSET_INFO *cs,
const uchar *te=t+tlen;
int save_diff = 0;
int diff;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
while ( s < se && t < te )
{
@@ -2815,7 +2813,7 @@ static int my_strnncollsp_utf8_cs(CHARSET_INFO *cs,
const uchar *se= s + slen;
const uchar *te= t + tlen;
int save_diff= 0;
- MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ MY_UNICASE_INFO *const *uni_plane= cs->caseinfo;
#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
diff_if_only_endspace_difference= 0;
@@ -2901,7 +2899,7 @@ static MY_COLLATION_HANDLER my_collation_cs_handler =
my_propagate_simple
};
-CHARSET_INFO my_charset_utf8_general_cs=
+struct charset_info_st my_charset_utf8_general_cs=
{
254,0,0, /* number */
MY_CS_COMPILED|MY_CS_UNICODE, /* state */
@@ -2959,7 +2957,7 @@ All other characters are encoded using five bytes:
*/
-static uint16 touni[5994]=
+static const uint16 touni[5994]=
{
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -3715,7 +3713,7 @@ static uint16 touni[5994]=
/* 00C0-05FF */
-static uint16 uni_0C00_05FF[1344]=
+static const uint16 uni_0C00_05FF[1344]=
{
0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,
0x001F,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,
@@ -3959,7 +3957,7 @@ static uint16 uni_1E00_1FFF[512]=
/* 2160-217F */
-static uint16 uni_2160_217F[32]=
+static const uint16 uni_2160_217F[32]=
{
0x0739,0x0789,0x07D9,0x0829,0x0879,0x08C9,0x0919,0x0969,
0x09B9,0x0A09,0x0A59,0x0AA9,0x0AF9,0x0B49,0x0B99,0x0BE9,
@@ -3969,7 +3967,7 @@ static uint16 uni_2160_217F[32]=
/* 24B0-24EF */
-static uint16 uni_24B0_24EF[64]=
+static const uint16 uni_24B0_24EF[64]=
{
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0511,0x0512,
0x0513,0x0514,0x0515,0x0516,0x0517,0x0518,0x0519,0x051A,
@@ -3983,7 +3981,7 @@ static uint16 uni_24B0_24EF[64]=
/* FF20-FF5F */
-static uint16 uni_FF20_FF5F[64]=
+static const uint16 uni_FF20_FF5F[64]=
{
0x0000,0x0560,0x05B0,0x0600,0x0650,0x06A0,0x06F0,0x0740,
0x0790,0x07E0,0x0830,0x0880,0x08D0,0x0920,0x0970,0x09C0,
@@ -4007,7 +4005,7 @@ static uint16 uni_FF20_FF5F[64]=
static int hexlo(int x)
{
- static char hex_lo_digit[256]=
+ static const char hex_lo_digit[256]=
{
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* ................ */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* ................ */
@@ -4038,7 +4036,7 @@ static int hexlo(int x)
0..9 digits
_ underscore
*/
-static char filename_safe_char[128]=
+static const char filename_safe_char[128]=
{
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */
@@ -4201,7 +4199,7 @@ static MY_CHARSET_HANDLER my_charset_filename_handler=
-CHARSET_INFO my_charset_filename=
+struct charset_info_st my_charset_filename=
{
17,0,0, /* number */
MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_HIDDEN|MY_CS_NONASCII,
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index b22b4364e8a..abef74dd6eb 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -53,7 +53,7 @@
#ifdef HAVE_CHARSET_cp1250
-static uint16 tab_cp1250_uni[256]={
+static const uint16 tab_cp1250_uni[256]={
0,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -90,7 +90,7 @@ static uint16 tab_cp1250_uni[256]={
/* 0000-00FD , 254 chars */
-static uchar tab_uni_cp1250_plane00[]={
+static const uchar tab_uni_cp1250_plane00[]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
@@ -109,7 +109,7 @@ static uchar tab_uni_cp1250_plane00[]={
0x00,0x00,0x00,0xF3,0xF4,0x00,0xF6,0xF7,0x00,0x00,0xFA,0x00,0xFC,0xFD};
/* 0102-017E , 125 chars */
-static uchar tab_uni_cp1250_plane01[]={
+static const uchar tab_uni_cp1250_plane01[]={
0xC3,0xE3,0xA5,0xB9,0xC6,0xE6,0x00,0x00,0x00,0x00,0xC8,0xE8,0xCF,0xEF,0xD0,0xF0,
0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0xEA,0xCC,0xEC,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -120,7 +120,7 @@ static uchar tab_uni_cp1250_plane01[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x9F,0xAF,0xBF,0x8E,0x9E};
/* 2013-20AC , 154 chars */
-static uchar tab_uni_cp1250_plane20[]={
+static const uchar tab_uni_cp1250_plane20[]={
0x96,0x97,0x00,0x00,0x00,0x91,0x92,0x82,0x00,0x93,0x94,0x84,0x00,0x86,0x87,0x95,
0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -133,12 +133,12 @@ static uchar tab_uni_cp1250_plane20[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80};
/* 02C7-02DD , 23 chars */
-static uchar tab_uni_cp1250_plane02[]={
+static const uchar tab_uni_cp1250_plane02[]={
0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xA2,0xFF,0x00,0xB2,0x00,0xBD};
/* 2122-2122 , 1 chars */
-static uchar tab_uni_cp1250_plane21[]={
+static const uchar tab_uni_cp1250_plane21[]={
0x99};
@@ -152,7 +152,7 @@ static MY_UNI_IDX idx_uni_cp1250[]={
};
-static uchar NEAR ctype_win1250ch[] = {
+static const uchar NEAR ctype_win1250ch[] = {
0x00,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x20, 0x20,
@@ -188,7 +188,7 @@ static uchar NEAR ctype_win1250ch[] = {
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10
};
-static uchar NEAR to_lower_win1250ch[] = {
+static const uchar NEAR to_lower_win1250ch[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -223,7 +223,7 @@ static uchar NEAR to_lower_win1250ch[] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
-static uchar NEAR to_upper_win1250ch[] = {
+static const uchar NEAR to_upper_win1250ch[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -260,7 +260,7 @@ static uchar NEAR to_upper_win1250ch[] = {
-static uchar NEAR sort_order_win1250ch[] = {
+static const uchar NEAR sort_order_win1250ch[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -279,7 +279,7 @@ static uchar NEAR sort_order_win1250ch[] = {
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
};
-static uchar NEAR _sort_order_win1250ch1[] = {
+static const uchar NEAR _sort_order_win1250ch1[] = {
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
@@ -404,7 +404,7 @@ struct wordvalue {
uchar pass1;
uchar pass2;
};
-static struct wordvalue doubles[] = {
+static const struct wordvalue doubles[] = {
{ (uchar*) "ch", 0xad, 0x03 },
{ (uchar*) "c", 0xa6, 0x02 },
{ (uchar*) "Ch", 0xad, 0x02 },
@@ -513,7 +513,7 @@ static size_t my_strnxfrm_win1250ch(CHARSET_INFO * cs __attribute__((unused)),
#ifdef REAL_MYSQL
-static uchar NEAR like_range_prefix_min_win1250ch[]=
+static const uchar NEAR like_range_prefix_min_win1250ch[]=
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
@@ -677,7 +677,7 @@ static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
};
-CHARSET_INFO my_charset_cp1250_czech_ci =
+struct charset_info_st my_charset_cp1250_czech_ci =
{
34,0,0, /* number */
MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_CSSORT, /* state */
diff --git a/strings/ctype.c b/strings/ctype.c
index 75d76aceea3..51e97b9eb48 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -76,7 +76,7 @@ struct my_cs_file_section_st
#define _CS_DIFF3 21
-static struct my_cs_file_section_st sec[] =
+static const struct my_cs_file_section_st sec[] =
{
{_CS_MISC, "xml"},
{_CS_MISC, "xml/version"},
@@ -111,9 +111,10 @@ static struct my_cs_file_section_st sec[] =
{0, NULL}
};
-static struct my_cs_file_section_st * cs_file_sec(const char *attr, size_t len)
+static const struct my_cs_file_section_st
+*cs_file_sec(const char *attr, size_t len)
{
- struct my_cs_file_section_st *s;
+ const struct my_cs_file_section_st *s;
for (s=sec; s->str; s++)
{
if (!strncmp(attr,s->str,len))
@@ -137,8 +138,8 @@ typedef struct my_cs_file_info
char comment[MY_CS_CSDESCR_SIZE];
char tailoring[MY_CS_TAILORING_SIZE];
size_t tailoring_length;
- CHARSET_INFO cs;
- int (*add_collation)(CHARSET_INFO *cs);
+ struct charset_info_st cs;
+ int (*add_collation)(struct charset_info_st *cs);
} MY_CHARSET_LOADER;
@@ -181,7 +182,7 @@ static int fill_uint16(uint16 *a,uint size,const char *str, size_t len)
static int cs_enter(MY_XML_PARSER *st,const char *attr, size_t len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
- struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+ const struct my_cs_file_section_st *s= cs_file_sec(attr,len);
if ( s && (s->state == _CS_CHARSET))
bzero(&i->cs,sizeof(i->cs));
@@ -196,7 +197,7 @@ static int cs_enter(MY_XML_PARSER *st,const char *attr, size_t len)
static int cs_leave(MY_XML_PARSER *st,const char *attr, size_t len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
- struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+ const struct my_cs_file_section_st *s= cs_file_sec(attr,len);
int state= s ? s->state : 0;
int rc;
@@ -214,9 +215,9 @@ static int cs_leave(MY_XML_PARSER *st,const char *attr, size_t len)
static int cs_value(MY_XML_PARSER *st,const char *attr, size_t len)
{
struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
- struct my_cs_file_section_st *s;
- int state= (int)((s=cs_file_sec(st->attr, strlen(st->attr))) ? s->state :
- 0);
+ const struct my_cs_file_section_st *s;
+ int state= (int)((s= cs_file_sec(st->attr, strlen(st->attr))) ? s->state :
+ 0);
switch (state) {
case _CS_ID:
@@ -291,7 +292,7 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, size_t len)
my_bool my_parse_charset_xml(const char *buf, size_t len,
- int (*add_collation)(CHARSET_INFO *cs))
+ int (*add_collation)(struct charset_info_st *cs))
{
MY_XML_PARSER p;
struct my_cs_file_info i;
diff --git a/strings/int2str.c b/strings/int2str.c
index fba98aac3f1..411762c38d3 100644
--- a/strings/int2str.c
+++ b/strings/int2str.c
@@ -19,9 +19,9 @@
/*
_dig_vec arrays are public because they are used in several outer places.
*/
-char NEAR _dig_vec_upper[] =
+const char NEAR _dig_vec_upper[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-char NEAR _dig_vec_lower[] =
+const char NEAR _dig_vec_lower[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
@@ -56,7 +56,7 @@ int2str(register long int val, register char *dst, register int radix,
char buffer[65];
register char *p;
long int new_val;
- char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower;
+ const char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower;
ulong uval= (ulong) val;
if (radix < 0)
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index 920022aae91..79267461c47 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -18,61 +18,533 @@
#include <stdarg.h>
#include <m_ctype.h>
-/*
- Limited snprintf() implementations
- SYNOPSIS
- my_vsnprintf()
- to Store result here
- n Store up to n-1 characters, followed by an end 0
- fmt printf format
- ap Arguments
-
- IMPLEMENTION:
- Supports following formats:
- %#[l]d
- %#[l]u
- %#[l]x
- %#.#b Local format; note first # is ignored and second is REQUIRED
- %#.#s Note first # is ignored
+#define MAX_ARGS 32 /* max positional args count*/
+#define MAX_PRINT_INFO 32 /* max print position count */
+
+#define LENGTH_ARG 1
+#define WIDTH_ARG 2
+#define PREZERO_ARG 4
+#define ESCAPED_ARG 8
+
+typedef struct pos_arg_info ARGS_INFO;
+typedef struct print_info PRINT_INFO;
+
+struct pos_arg_info
+{
+ char arg_type; /* argument type */
+ uint have_longlong; /* used from integer values */
+ char *str_arg; /* string value of the arg */
+ longlong longlong_arg; /* integer value of the arg */
+ double double_arg; /* double value of the arg */
+};
+
+
+struct print_info
+{
+ char arg_type; /* argument type */
+ size_t arg_idx; /* index of the positional arg */
+ size_t length; /* print width or arg index */
+ size_t width; /* print width or arg index */
+ uint flags;
+ const char *begin; /**/
+ const char *end; /**/
+};
+
+
+/**
+ Calculates print length or index of positional argument
+
+ @param fmt processed string
+ @param length print length or index of positional argument
+ @param pre_zero returns flags with PREZERO_ARG set if necessary
+
+ @retval
+ string position right after length digits
+*/
+
+static const char *get_length(const char *fmt, size_t *length, uint *pre_zero)
+{
+ for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ {
+ *length= *length * 10 + (uint)(*fmt - '0');
+ if (!*length)
+ *pre_zero|= PREZERO_ARG; /* first digit was 0 */
+ }
+ return fmt;
+}
+
+
+/**
+ Calculates print width or index of positional argument
+
+ @param fmt processed string
+ @param width print width or index of positional argument
+
+ @retval
+ string position right after width digits
+*/
+
+static const char *get_width(const char *fmt, size_t *width)
+{
+ for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ {
+ *width= *width * 10 + (uint)(*fmt - '0');
+ }
+ return fmt;
+}
+
+/**
+ Calculates print width or index of positional argument
+
+ @param fmt processed string
+ @param have_longlong TRUE if longlong is required
+
+ @retval
+ string position right after modifier symbol
+*/
+
+static const char *check_longlong(const char *fmt, uint *have_longlong)
+{
+ *have_longlong= 0;
+ if (*fmt == 'l')
+ {
+ fmt++;
+ if (*fmt != 'l')
+ *have_longlong= (sizeof(long) == sizeof(longlong));
+ else
+ {
+ fmt++;
+ *have_longlong= 1;
+ }
+ }
+ else if (*fmt == 'z')
+ {
+ fmt++;
+ *have_longlong= (sizeof(size_t) == sizeof(longlong));
+ }
+ return fmt;
+}
+
+
+/**
+ Returns escaped string
+
+ @param cs string charset
+ @param to buffer where escaped string will be placed
+ @param end end of buffer
+ @param par string to escape
+ @param par_len string length
+ @param quote_char character for quoting
+
+ @retval
+ position in buffer which points on the end of escaped string
+*/
+
+static char *backtick_string(CHARSET_INFO *cs, char *to, char *end,
+ char *par, size_t par_len, char quote_char)
+{
+ uint char_len;
+ char *start= to;
+ char *par_end= par + par_len;
+ size_t buff_length= (size_t) (end - to);
+
+ if (buff_length <= par_len)
+ goto err;
+ *start++= quote_char;
+
+ for ( ; par < par_end; par+= char_len)
+ {
+ uchar c= *(uchar *) par;
+ if (!(char_len= my_mbcharlen(cs, c)))
+ char_len= 1;
+ if (char_len == 1 && c == (uchar) quote_char )
+ {
+ if (start + 1 >= end)
+ goto err;
+ *start++= quote_char;
+ }
+ if (start + char_len >= end)
+ goto err;
+ start= strnmov(start, par, char_len);
+ }
- RETURN
+ if (start + 1 >= end)
+ goto err;
+ *start++= quote_char;
+ return start;
+
+err:
+ *to='\0';
+ return to;
+}
+
+
+/**
+ Prints string argument
+*/
+
+static char *process_str_arg(CHARSET_INFO *cs, char *to, char *end,
+ size_t width, char *par, uint print_type)
+{
+ int well_formed_error;
+ size_t plen, left_len= (size_t) (end - to) + 1;
+ if (!par)
+ par = (char*) "(null)";
+
+ plen= strnlen(par, width);
+ if (left_len <= plen)
+ plen = left_len - 1;
+ plen= cs->cset->well_formed_len(cs, par, par + plen,
+ width, &well_formed_error);
+ if (print_type & ESCAPED_ARG)
+ to= backtick_string(cs, to, end, par, plen, '`');
+ else
+ to= strnmov(to,par,plen);
+ return to;
+}
+
+
+/**
+ Prints binary argument
+*/
+
+static char *process_bin_arg(char *to, char *end, size_t width, char *par)
+{
+ DBUG_ASSERT(to <= end);
+ if (to + width + 1 > end)
+ width= end - to - 1; /* sign doesn't matter */
+ memmove(to, par, width);
+ to+= width;
+ return to;
+}
+
+
+/**
+ Prints integer argument
+*/
+
+static char *process_int_arg(char *to, char *end, size_t length,
+ longlong par, char arg_type, uint print_type)
+{
+ size_t res_length, to_length;
+ char *store_start= to, *store_end;
+ char buff[32];
+
+ if ((to_length= (size_t) (end-to)) < 16 || length)
+ store_start= buff;
+
+ if (arg_type == 'd')
+ store_end= int10_to_str(par, store_start, -10);
+ else if (arg_type == 'u')
+ store_end= int10_to_str(par, store_start, 10);
+ else if (arg_type == 'p')
+ {
+ store_start[0]= '0';
+ store_start[1]= 'x';
+ store_end= int2str(par, store_start + 2, 16, 0);
+ }
+ else
+ {
+ DBUG_ASSERT(arg_type == 'X' || arg_type =='x');
+ store_end= int2str(par, store_start, 16, (arg_type == 'X'));
+ }
+
+ if ((res_length= (size_t) (store_end - store_start)) > to_length)
+ return to; /* num doesn't fit in output */
+ /* If %#d syntax was used, we have to pre-zero/pre-space the string */
+ if (store_start == buff)
+ {
+ length= min(length, to_length);
+ if (res_length < 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);
+ }
+ to+= res_length;
+ return to;
+}
+
+
+/**
+ Procesed positional arguments.
+
+ @param cs string charset
+ @param to buffer where processed string will be place
+ @param end end of buffer
+ @param par format string
+ @param arg_index arg index of the first occurrence of positional arg
+ @param ap list of parameters
+
+ @retval
+ end of buffer where processed string is placed
+*/
+
+static char *process_args(CHARSET_INFO *cs, char *to, char *end,
+ const char* fmt, size_t arg_index, va_list ap)
+{
+ ARGS_INFO args_arr[MAX_ARGS];
+ PRINT_INFO print_arr[MAX_PRINT_INFO];
+ uint idx= 0, arg_count= arg_index;
+
+start:
+ /* Here we are at the beginning of positional argument, right after $ */
+ arg_index--;
+ print_arr[idx].flags= 0;
+ if (*fmt == '`')
+ {
+ print_arr[idx].flags|= ESCAPED_ARG;
+ fmt++;
+ }
+ if (*fmt == '-')
+ fmt++;
+ print_arr[idx].length= print_arr[idx].width= 0;
+ /* Get print length */
+ if (*fmt == '*')
+ {
+ fmt++;
+ fmt= get_length(fmt, &print_arr[idx].length, &print_arr[idx].flags);
+ print_arr[idx].length--;
+ DBUG_ASSERT(*fmt == '$' && print_arr[idx].length < MAX_ARGS);
+ args_arr[print_arr[idx].length].arg_type= 'd';
+ print_arr[idx].flags|= LENGTH_ARG;
+ arg_count= max(arg_count, print_arr[idx].length + 1);
+ fmt++;
+ }
+ else
+ fmt= get_length(fmt, &print_arr[idx].length, &print_arr[idx].flags);
+
+ if (*fmt == '.')
+ {
+ fmt++;
+ /* 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);
+ args_arr[print_arr[idx].width].arg_type= 'd';
+ print_arr[idx].flags|= WIDTH_ARG;
+ arg_count= max(arg_count, print_arr[idx].width + 1);
+ fmt++;
+ }
+ else
+ fmt= get_width(fmt, &print_arr[idx].width);
+ }
+ else
+ print_arr[idx].width= SIZE_T_MAX;
+
+ fmt= check_longlong(fmt, &args_arr[arg_index].have_longlong);
+ if (*fmt == 'p')
+ args_arr[arg_index].have_longlong= (sizeof(void *) == sizeof(longlong));
+ args_arr[arg_index].arg_type= print_arr[idx].arg_type= *fmt;
+
+ print_arr[idx].arg_idx= arg_index;
+ print_arr[idx].begin= ++fmt;
+
+ while (*fmt && *fmt != '%')
+ fmt++;
+
+ if (!*fmt) /* End of format string */
+ {
+ uint i;
+ print_arr[idx].end= fmt;
+ /* Obtain parameters from the list */
+ for (i= 0 ; i < arg_count; i++)
+ {
+ switch (args_arr[i].arg_type) {
+ case 's':
+ case 'b':
+ args_arr[i].str_arg= va_arg(ap, char *);
+ break;
+ case 'f':
+ case 'g':
+ args_arr[i].double_arg= va_arg(ap, double);
+ break;
+ case 'd':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'p':
+ if (args_arr[i].have_longlong)
+ args_arr[i].longlong_arg= va_arg(ap,longlong);
+ else if (args_arr[i].arg_type == 'd')
+ args_arr[i].longlong_arg= va_arg(ap, int);
+ else
+ args_arr[i].longlong_arg= va_arg(ap, uint);
+ break;
+ case 'c':
+ args_arr[i].longlong_arg= va_arg(ap, int);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ /* Print result string */
+ for (i= 0; i <= idx; i++)
+ {
+ uint width= 0, length= 0;
+ switch (print_arr[i].arg_type) {
+ case 's':
+ {
+ char *par= args_arr[print_arr[i].arg_idx].str_arg;
+ width= ((print_arr[i].flags & WIDTH_ARG) ?
+ (uint) args_arr[print_arr[i].width].longlong_arg :
+ (uint) print_arr[i].width);
+ to= process_str_arg(cs, to, end, width, par, print_arr[i].flags);
+ break;
+ }
+ case 'b':
+ {
+ char *par = args_arr[print_arr[i].arg_idx].str_arg;
+ width= ((print_arr[i].flags & WIDTH_ARG) ?
+ (uint) args_arr[print_arr[i].width].longlong_arg :
+ (uint) print_arr[i].width);
+ to= process_bin_arg(to, end, width, par);
+ break;
+ }
+ case 'c':
+ {
+ if (to == end)
+ break;
+ *to++= (char) args_arr[print_arr[i].arg_idx].longlong_arg;
+ break;
+ }
+ case 'd':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'p':
+ {
+ /* Integer parameter */
+ longlong larg;
+ length= ((print_arr[i].flags & LENGTH_ARG) ?
+ args_arr[print_arr[i].length].longlong_arg :
+ (longlong) print_arr[i].length);
+
+ if (args_arr[print_arr[i].arg_idx].have_longlong)
+ larg = args_arr[print_arr[i].arg_idx].longlong_arg;
+ else if (print_arr[i].arg_type == 'd')
+ larg = (int) args_arr[print_arr[i].arg_idx].longlong_arg;
+ else
+ larg= (uint) args_arr[print_arr[i].arg_idx].longlong_arg;
+
+ to= process_int_arg(to, end, length, larg, print_arr[i].arg_type,
+ print_arr[i].flags);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (to == end)
+ break;
+
+ length= min(end - to , print_arr[i].end - print_arr[i].begin);
+ if (to + length < end)
+ length++;
+ to= strnmov(to, print_arr[i].begin, length);
+ }
+ DBUG_ASSERT(to <= end);
+ *to='\0'; /* End of errmessage */
+ return to;
+ }
+ else
+ {
+ /* Process next positional argument*/
+ DBUG_ASSERT(*fmt == '%');
+ print_arr[idx].end= fmt - 1;
+ idx++;
+ fmt++;
+ arg_index= 0;
+ fmt= get_width(fmt, &arg_index);
+ DBUG_ASSERT(*fmt == '$');
+ fmt++;
+ arg_count= max(arg_count, arg_index);
+ goto start;
+ }
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
+
+/**
+ 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
+ @param par format string
+ @param ap list of parameters
+
+ @retval
length of result string
*/
-size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
+size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
+ const char* fmt, va_list ap)
{
char *start=to, *end=to+n-1;
size_t length, width;
- uint pre_zero, have_long;
+ uint print_type, have_longlong;
for (; *fmt ; fmt++)
{
if (*fmt != '%')
{
- if (to == end) /* End of buffer */
+ if (to == end) /* End of buffer */
break;
- *to++= *fmt; /* Copy ordinary char */
+ *to++= *fmt; /* Copy ordinary char */
continue;
}
fmt++; /* skip '%' */
- /* Read max fill size (only used with %d and %u) */
- if (*fmt == '-')
- fmt++;
+
length= width= 0;
- pre_zero= have_long= 0;
- if (*fmt == '*')
+ print_type= 0;
+
+ /* Read max fill size (only used with %d and %u) */
+ if (my_isdigit(&my_charset_latin1, *fmt))
{
- fmt++;
- length= va_arg(ap, int);
+ fmt= get_length(fmt, &length, &print_type);
+ if (*fmt == '$')
+ {
+ to= process_args(cs, to, end, (fmt+1), length, ap);
+ return (size_t) (to - start);
+ }
}
else
- for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ {
+ if (*fmt == '`')
+ {
+ print_type|= ESCAPED_ARG;
+ fmt++;
+ }
+ if (*fmt == '-')
+ fmt++;
+ if (*fmt == '*')
{
- length= length * 10 + (uint)(*fmt - '0');
- if (!length)
- pre_zero= 1; /* first digit was 0 */
+ fmt++;
+ length= va_arg(ap, int);
}
+ else
+ fmt= get_length(fmt, &length, &print_type);
+ }
+
if (*fmt == '.')
{
fmt++;
@@ -82,75 +554,41 @@ size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
width= va_arg(ap, int);
}
else
- for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
- width= width * 10 + (uint)(*fmt - '0');
+ fmt= get_width(fmt, &width);
}
else
- width= ~0;
- if (*fmt == 'l')
- {
- fmt++;
- have_long= 1;
- }
+ width= SIZE_T_MAX;
+
+ fmt= check_longlong(fmt, &have_longlong);
+
if (*fmt == 's') /* String parameter */
{
- reg2 char *par = va_arg(ap, char *);
- size_t plen,left_len = (size_t) (end - to) + 1;
- if (!par) par = (char*)"(null)";
- plen= (uint) strnlen(par, width);
- if (left_len <= plen)
- plen = left_len - 1;
- to=strnmov(to,par,plen);
+ reg2 char *par= va_arg(ap, char *);
+ to= process_str_arg(cs, to, end, width, par, print_type);
continue;
}
else if (*fmt == 'b') /* Buffer parameter */
{
char *par = va_arg(ap, char *);
- DBUG_ASSERT(to <= end);
- if (to + abs(width) + 1 > end)
- width= (uint) (end - to - 1); /* sign doesn't matter */
- memmove(to, par, abs(width));
- to+= width;
+ to= process_bin_arg(to, end, width, par);
continue;
}
- else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x') /* Integer parameter */
+ else if (*fmt == 'd' || *fmt == 'u' || *fmt == 'x' || *fmt == 'X' ||
+ *fmt == 'p')
{
- register long larg;
- size_t res_length, to_length;
- char *store_start= to, *store_end;
- char buff[32];
-
- if ((to_length= (size_t) (end-to)) < 16 || length)
- store_start= buff;
- if (have_long)
- larg = va_arg(ap, long);
- else
- if (*fmt == 'd')
- larg = va_arg(ap, int);
- else
- larg= (long) (uint) va_arg(ap, int);
- if (*fmt == 'd')
- store_end= int10_to_str(larg, store_start, -10);
+ /* Integer parameter */
+ longlong larg;
+ if (*fmt == 'p')
+ have_longlong= (sizeof(void *) == sizeof(longlong));
+
+ if (have_longlong)
+ larg = va_arg(ap,longlong);
+ else if (*fmt == 'd')
+ larg = va_arg(ap, int);
else
- if (*fmt== 'u')
- store_end= int10_to_str(larg, store_start, 10);
- else
- store_end= int2str(larg, store_start, 16, 0);
- if ((res_length= (size_t) (store_end - store_start)) > to_length)
- break; /* num doesn't fit in output */
- /* If %#d syntax was used, we have to pre-zero/pre-space the string */
- if (store_start == buff)
- {
- length= min(length, to_length);
- if (res_length < length)
- {
- size_t diff= (length- res_length);
- bfill(to, diff, pre_zero ? '0' : ' ');
- to+= diff;
- }
- bmove(to, store_start, res_length);
- }
- to+= res_length;
+ larg= va_arg(ap, uint);
+
+ to= process_int_arg(to, end, length, larg, *fmt, print_type);
continue;
}
else if (*fmt == 'c') /* Character parameter */
@@ -174,6 +612,19 @@ size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
}
+/*
+ Limited snprintf() implementations
+
+ exported to plugins as a service, see the detailed documentation
+ around my_snprintf_service_st
+*/
+
+size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
+{
+ return my_vsnprintf_ex(&my_charset_latin1, to, n, fmt, ap);
+}
+
+
size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
{
size_t result;
@@ -184,42 +635,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);
- return 0;
-}
-#endif
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 6647074bd2f..47ab569b725 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -34,6 +34,7 @@
#include <m_string.h>
#include <mysqld_error.h>
#include <my_handler.h>
+#include <sql_common.h>
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am
index 115eeb8df7a..e9ec6210e20 100644
--- a/unittest/mysys/Makefile.am
+++ b/unittest/mysys/Makefile.am
@@ -24,7 +24,8 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \
$(top_builddir)/strings/libmystrings.a
EXTRA_DIST = CMakeLists.txt
-noinst_PROGRAMS = bitmap-t base64-t my_atomic-t lf-t waiting_threads-t
+noinst_PROGRAMS = bitmap-t base64-t my_atomic-t lf-t waiting_threads-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/win/Makefile.am b/win/Makefile.am
index fceebb07a59..18bfe8ddf81 100644
--- a/win/Makefile.am
+++ b/win/Makefile.am
@@ -17,7 +17,8 @@
EXTRA_DIST = build-vs71.bat build-vs8.bat build-vs8_x64.bat build-vs9.bat \
build-vs9_x64.bat configure.js README mysql_manifest.cmake \
create_manifest.js create_def_file.js build-nmake.bat \
- build-nmake-x64.bat configure-mariadb.sh make_mariadb_win_dist
+ build-nmake-x64.bat configure-mariadb.sh make_mariadb_win_dist \
+ build-vs10.bat build-vs10_x64.bat
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/win/build-vs10.bat b/win/build-vs10.bat
new file mode 100644
index 00000000000..b67ac7e9753
--- /dev/null
+++ b/win/build-vs10.bat
@@ -0,0 +1,18 @@
+@echo off
+
+REM Copyright (C) 2010 Monty Program AB
+REM
+REM This program is free software; you can redistribute it and/or modify
+REM it under the terms of the GNU General Public License as published by
+REM the Free Software Foundation; version 2 of the License.
+REM
+REM This program is distributed in the hope that it will be useful,
+REM but WITHOUT ANY WARRANTY; without even the implied warranty of
+REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+REM GNU General Public License for more details.
+REM
+REM You should have received a copy of the GNU General Public License
+REM along with this program; if not, write to the Free Software
+REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+cmake -G "Visual Studio 10"
+
diff --git a/win/build-vs10_x64.bat b/win/build-vs10_x64.bat
new file mode 100644
index 00000000000..f84e826ac65
--- /dev/null
+++ b/win/build-vs10_x64.bat
@@ -0,0 +1,18 @@
+@echo off
+
+REM Copyright (C) 2010 Monty Program AB
+REM
+REM This program is free software; you can redistribute it and/or modify
+REM it under the terms of the GNU General Public License as published by
+REM the Free Software Foundation; version 2 of the License.
+REM
+REM This program is distributed in the hope that it will be useful,
+REM but WITHOUT ANY WARRANTY; without even the implied warranty of
+REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+REM GNU General Public License for more details.
+REM
+REM You should have received a copy of the GNU General Public License
+REM along with this program; if not, write to the Free Software
+REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+cmake -G "Visual Studio 10 Win64"
+
diff --git a/win/configure-mariadb.sh b/win/configure-mariadb.sh
index 294b1530788..b6063a20dc4 100644
--- a/win/configure-mariadb.sh
+++ b/win/configure-mariadb.sh
@@ -15,9 +15,7 @@ cscript win/configure.js \
WITH_FEDERATED_STORAGE_ENGINE \
WITH_MERGE_STORAGE_ENGINE \
WITH_PARTITION_STORAGE_ENGINE \
- WITH_MARIA_STORAGE_ENGINE \
- WITH_PBXT_STORAGE_ENGINE \
- WITH_XTRADB_STORAGE_ENGINE \
+ WITH_MARIA_STORAGE_ENGINE \
+ WITH_PBXT_STORAGE_ENGINE \
+ WITH_XTRADB_STORAGE_ENGINE \
WITH_EMBEDDED_SERVER
-
-